认识SQL注入的类型

标签: 认识 sql 类型 | 发表时间:2015-11-21 08:00 | 作者:
出处:http://blogkun.com

SQL的注入类型有以下5种:

  1. Boolean-based blind SQL injection(布尔型注入)
  2. Error-based SQL injection(报错型注入)
  3. UNION query SQL injection(可联合查询注入)
  4. Stacked queries SQL injection(可多语句查询注入)
  5. Time-based blind SQL injection(基于时间延迟注入)

下文都是基于PHP、MySQL测试得到的结果。

Boolean-based blind SQL injection(布尔型注入)


通过判断页面返回情况获得想要的信息。

如下SQL注入:

   1 http://hello.com/view?id=1 and substring(version(),1,1)=5

如果服务端MySQL版本是5.X的话,那么页面返回的内容就会跟正常请求一样。攻击者就可以通过这种方式获取到MySQL的各类信息。

Error-based SQL injection(报错型注入)


如果页面能够输出SQL报错信息,则可以从报错信息中获得想要的信息。

典型的就是利用group by的duplicate entry错误。关于这个错误,貌似是MySQL存在的 bug: duplicate key for entry on select?SQL Injection attack - What does this do?

如下SQL注入:

   1 http://hello.com/view?id=1%20AND%20(SELECT%207506%20FROM(SELECT%20COUNT(*),CONCAT(0x717a707a71,(SELECT%20MID((IFNULL(CAST(schema_name%20
2 AS%20CHAR),0x20)),1,54)%20FROM%20INFORMATION_SCHEMA.SCHEMATA%20
3 LIMIT%202,1),0x7178786271,FLOOR(RAND(0)*2))x%20FROM%20INFORMATION_
4 SCHEMA.CHARACTER_SETS%20GROUP%20BY%20x)a)

在抛出的SQL错误中会包含这样的信息: Duplicate entry 'qzpzqttqxxbq1' for key 'group_key',其中qzpzq和qxxbq分别是0x717a707a71和0x7178786271,用这两个字符串包住了tt(即数据库名),是为了方便sql注入程序从返回的错误内容中提取出信息。

UNION query SQL injection(可联合查询注入)


最快捷的方法,通过UNION查询获取到所有想要的数据,前提是请求返回后能输出SQL执行后查询到的所有内容。

如下SQL注入:

   1 http://hello.com/view?id=1 UNION ALL SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.SCHEMATA

Stacked queries SQL injection(可多语句查询注入)


即能够执行多条查询语句,非常危险,因为这意味着能够对数据库直接做更新操作。

如下SQL注入:

   1 http://hello.com/view?id=1;update t1 set content = 'aaaaaaaaa'

在第二次请求 http://hello.com/view?id=1时,会发现所有的content都被设置为aaaaaaaaa了。

Time-based blind SQL injection(基于时间延迟注入)


页面不会返回错误信息,不会输出UNION注入所查出来的泄露的信息。类似搜索这类请求,boolean注入也无能为力,因为搜索返回空也属于正常的,这时就得采用time-based的注入了,即判断请求响应的时间,但该类型注入获取信息的速度非常慢。

如下SQL注入:

   1 http://hello.com/view?q=abc' AND (SELECT * FROM (SELECT(SLEEP(5)))VCVe) OR 1 = '

该请求会使MySQL的查询睡眠5S,攻击者可以通过添加条件判断到SQL中,比如IF(substring(version(),1,1)=5, sleep(5), ‘t’) AS value就能做到类似boolean注入的效果,如果睡眠了5s,那么说明MySQL版本为5,否则不是,但这种方式获取信息的速度就会很慢了,因为要做非常多的判断,并且需要花时间等待,不断地去测试出相应的值出来。

来做个实验


使用SQL注入工具:sqlmap

服务端代码(输出SQL报错信息、输出SQL查出来的所有内容):

   1 <?php
2 $pdo = new PDO("mysql:host=$host;dbname=tt", $db_user, $password);
3 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);                                                                                                                       
4 $res = $pdo->query('select * from t1 where id = ' . $_GET['id']);
5 var_dump($res->fetchAll());
6 ?>

执行sqlmap获取所有数据库名:

   1 sqlmap -u http://host/id\=1\* --dbms=mysql --dbs -v 3 --level=5 --risk=3

查看执行结果:

mysql 从输出结果可以看出支持所有类型的SQL注入。

获取到的数据库名:

mysql

服务端代码去掉SQL报错信息:

   1 <?php
2 $pdo = new PDO("mysql:host=$host;dbname=tt", $db_user, $password);
3 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);                                                                                                                       
4 $res = $pdo->query('select * from t1 where id = ' . $_GET['id']);
5 var_dump($res->fetchAll());
6 ?>

重新执行sqlmap,查看执行结果:

mysql

从输出结果可以看出无法使用error-based注入了。

服务端代码改为去掉任何的输出信息:

   1 <?php
2 $pdo = new PDO("mysql:host=$host;dbname=tt", $db_user, $password);
3 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);                                                                                                          
4 $res = $pdo->query('select * from t1 where id = ' . $_GET['id']);
5 ?>

mysql

从输出结果可以看出只支持stacked注入和time-based注入,但要获得数据库信息只能使用time-based注入获得,且会做非常多次的注入尝试,如下图:

mysql

如何防止SQL注入?


使用MySQL提供的 SQL Syntax for Prepared Statements,即语句预处理,从web开发的角度来讲是参数绑定查询,能够抵挡住上述所说的所有SQL注入= =

   1 <?php
2 $pdo = new PDO('mysql:host=192.168.103.111;dbname=tt', 'test', '19921212');
3 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);                                                                                                                       
4 $res = $pdo->prepare('select * from t1 where id = ?');
5 $res->execute([$_GET['id']]);
6 var_dump($res->fetchAll());
7 ?>

sqlmap执行结果:

mysql

相关 [认识 sql 类型] 推荐:

认识SQL注入的类型

- - 小火箭
SQL的注入类型有以下5种:. Boolean-based blind SQL injection(布尔型注入). Error-based SQL injection(报错型注入). UNION query SQL injection(可联合查询注入). Stacked queries SQL injection(可多语句查询注入).

oracle各类型SQL的操作流程

- - 数据库 - ITeye博客
•Select * from test  where  object_id=200在体系中是如何运转的. 在PGA中把此条SQL语句hash成一个值;. 接下来根据此hash值到SGA的共享池中去匹配,如果没有,首先查询自己的语句语法是否正确,语义是否正确,是否有权限. 如果都通过则通过CBO解析生成执行计划(如走索引还是全表).

SQL 数据类型和 Java 数据类型间的映射关系

- - ITeye博客
由于 SQL 数据类型和 Java 数据类型是不同的,因此需要某种机制在使用 Java 类型的应用程序和使用 SQL 类型的数据库之间来读写数据. 为此,JDBC 提供了 getXXX 和 setXXX 方法集、方法 registerOutParameter 和类 Types. 本章汇集了影响各种类和接口的数据类型的有关信息,并列出所有的对应关系表(这些表显示了 SQL 类型和 Java 类型之间的映射关系)以便于参考.

PL/SQL动态SQL(原创)

- - ITeye博客
使用动态SQL是在编写PL/SQL过程时经常使用的方法之一. 很多情况下,比如根据业务的需要,如果输入不同查询条件,则生成不同的执行SQL查询语句,对于这种情况需要使用动态SQL来完成. 再比如,对于分页的情况,对于不同的表,必定存在不同的字段,因此使用静态SQL则只能针对某几个特定的表来形成分页.

Derby SQL 分页

- - ITeye博客
    之前在网上看到有人问 Derby SQL 分页实现的问题,网上有人给出这样的解决方案,SQL 如下:. 其实,这样的分页查询,性能不理想,我试过在 300W 数据量中采用这种分页方式,需要 20~30秒之久;其实 Derby 10.6 以上版本有更好的分页支持,直接给出 SQL 实现如下:.

SQL Server--索引

- - CSDN博客推荐文章
         1,概念:  数据库索引是对数据表中一个或多个列的值进行排序的结构,就像一本书的目录一样,索引提供了在行中快速查询特定行的能力..             2.1优点:  1,大大加快搜索数据的速度,这是引入索引的主要原因..                             2,创建唯一性索引,保证数据库表中每一行数据的唯一性..

MySql动态SQL

- - SQL - 编程语言 - ITeye博客
13.7. 用于预处理语句的SQL语法. MySQL 5.1对服务器一方的预制语句提供支持. 如果您使用合适的客户端编程界面,则这种支持可以发挥在MySQL 4.1中实施的高效客户端/服务器二进制协议的优势. 候选界面包括MySQL C API客户端库(用于C程序)、MySQL Connector/J(用于Java程序)和MySQL Connector/NET.

sql优化

- - 数据库 - ITeye博客
是对数据库(数据)进行操作的惟一途径;. 消耗了70%~90%的数据库资源;独立于程序设计逻辑,相对于对程序源代码的优化,对SQL语句的优化在时间成本和风险上的代价都很低;. 可以有不同的写法;易学,难精通. 固定的SQL书写习惯,相同的查询尽量保持相同,存储过程的效率较高. 应该编写与其格式一致的语句,包括字母的大小写、标点符号、换行的位置等都要一致.

birt动态SQL

- - ITeye博客
birt动态SQL实现有三种方式:拼接SQL、绑定变量和让应用程序拼接,birt得到返回结果集方式. 在数据集中写SQL,如下:. 选中数据集,点script方式,在beforeOpen事件中写如下SQL:. 然后就可以了,当然,也可以不写第一步,直接所有的SQL都在beforeOpen中拼接. 但是,拼接SQL方式不仅复杂容易错,还会导致SQL注入风险.