转载自:http://lightless.me/archives/zero-to-n-sqli-2.html
0x00 废话
又是废话环节,今天我们就开始实战吧。当然这是不可能的,在开始之前我还要废话一些东西,不过离实战不远了。
0x01 理解SQL注入
怎么又是理解SQL注入,作者你是出来坑爹的吧!
不要慌,上一次我们只是通俗的讲了什么是SQL注入,大家只是有了一个很简单的概念,如果真的要进行SQL注入的话,只有这些概念还是不够的,不过没关系,我们一边实践一边学习,这样学起来更容易被接受。
好的,上一节我们的环境派上用场了。我们打开Less-1
在我这里的地址是这个:http://127.0.0.1/sqli-labs/Less-1/?id=1
现在我们尝试改变一下参数试试,例如id=2
你会发现他显示了一个不同的用户名密码,这就是我们上次讲到的,向服务器请求了2号记录,于是服务器从数据库中取出2号记录返回给了我们,你可以试着看看一共有多少条记录。
接下来我们要做什么呢,没错,我们要做熊孩子了,不过不用删掉数据库就是了。
我们试着给他传递点“不一样”的参数看看,来传递个id=1'
,对,你没看错,1后面加个单引号,也许你会说“这条记录根本没有啊!怎么会有第1'条记录!”,先看看服务器给我们返回了什么。
英语不好的看官自己解决一下语言障碍吧,你会发现这个是数据库告诉我们的错误,意思是你的SQL语句中出现了问题,在'1'' LIMIT 0,1
的位置,为什么会这样呢。我们仔细分析一下,如果你的SQL语句是SELECT * FROM table WHERE id='1'
,这自然是没问题,但是如果多了一个单引号会怎么样呢?
没错!就会出现语法错误:单引号不匹配。有人会说“不就是报了个错误么,有什么大不了的。”,其实这是个很严重的问题,那就是服务器没有对我们输入的数据进行检查,直接代入了SQL语句进行数据库查询,这样就会出现上一节中熊孩子的问题(如果不记得了,可以翻回去看看),那就是我们可以输入指令,服务器也不会当做数据,而是当做指令去执行。这样就引发了SQL注入问题。
很多人还没有认识到SQL注入的危害,觉得不是严重的安全漏洞,其实这是很不对的!SQL注入的危害小则获取数据库中的内容,大到可以控制整台服务器进而危害整个内网。
0x02 识别SQL注入
好了,上面说了这么多废话,很多人可能已经迫不及待的想要尝试一下SQL注入到底有多厉害了。很重要的一件事就是识别SQL注入,我们怎么才能判断某处有SQL注入呢。聪明的小伙伴可能发现了,在传递参数的时候给他加个单引号,报错了就说明没有过滤参数。这的确是一种方法,但有时并不可靠。什么?你不信?
我们现在打开Less-4,访问http://127.0.0.1/sqli-labs/Less-4/?id=1
,没问题,返回了正常的信息。继续尝试单引号大法http://127.0.0.1/sqli-labs/Less-4/?id=1'
,怎么没报错?!所以说,单引号大法并不是万能的。
那么应该怎么去判断一个位置是否可控并具有SQL注入漏洞呢?
我们来看两个SQL语句:
SELECT * FROM table WHERE news_id = $id
SELECT * FROM table WHERE news_id = '$id'
有什么区别呢,上面的1号代码中的$id直接代入SQL语句了,而下面的2号代码中用单引号包裹了之后才代入查询的。我们将上面一种类型的注入点称为“数字型”,将下面一种类型的注入点称为“字符型”(其实很多不是单引号包裹的也这么叫)。
为什么这么叫呢,很简单,1号代码中你可以认为传递的就是个数字,而2号代码中传递的其实是个字符串。于是就这么区分开了。
其实还有一种类型的SQL注入,我在某些资料上看到的是叫做“内联SQL注入”,我们考虑下面的情况,有一个用户登陆的地方,后端处理的时候可能是类似下面这个样子的
SELECT * FROM user WHERE username = $_POST['username'] AND password = $_POST['password']
我们注入了自己的SQL代码后,原来的SQL语句仍然会执行,这个就叫做内联注入,不过不用太过关注它,因为我们很容易用注释的方法干掉他。:)
0x03 先来说说数字型吧
下面讲到的大部分方法都是我听说的或常见的,一定不完整,所以只是抛砖引玉罢了。
我们用Less-2来做示范,这个是数字型的,可以看看他的源码。
首先就是我们的单引号大法(http://127.0.0.1/sqli-labs/Less-2/?id=1'
)了,这个没的说,肯定会报错的,可是一旦服务器过滤了单引号怎么办呢?
好了,既然是数字型的话,那肯定可以做一些加减乘除吧!我们记住id=1,id=2,id=3分别是什么内容。下面就是见证奇迹的时候:我们测试:http://127.0.0.1/sqli-labs/Less-2/?id=2-1
。
竟然显示了第一条记录的内容,服务器看到了2-1,就自己计算出来了是1,然后查询了第一条数据,那么服务器并没有对我们输入的数据进行彻底的过滤,也就是说,即便服务端过滤了单引号,我们也可以通过其他的方法来判断是否有注入点。
接下来你肯定会喜滋滋的尝试1+1
了,so,我们试一试:http://127.0.0.1/sqli-labs/Less-2/?id=1+1
纳尼,怎么报错了!是的,他并没有计算1+1的值,而是直接报错了。这是为什么呢?因为+
会被SQL解析成空格,于是原有的SQL语句就被破坏了。那么怎么样才能让他进行加法运算呢,那就是URL编码,我们尝试传递参数id=1%2b1
,你会发现成功的显示了第二条记录的值。这个%2b
就是加号的URL编码,这样就会计算1+1了。
我们开个脑洞,运算符符号真的只有加减乘除么,逻辑运算的符号也算哦~
这样一来我们就有了很多种判断这里是否有注入点的方法。其实在讲到单引号的时候,你应该马上就想到双引号,括号啊什么的配对括号。对于数字型的,只要传入一个非数字类型的参数就会引发错误了。
只有这些还是不够的,还有另一种方法,就是构造True and False条件。我们先来测试几个payload吧。
http://127.0.0.1/sqli-labs/Less-2/?id=1 and 1=1
http://127.0.0.1/sqli-labs/Less-2/?id=1 and 1=2
尝试一下上面的两个,发现了什么,第一个返回了正常的数据,第二个返回异常,这又是为什么呢。老方法,我们把传入的参数代入SQL语句中看一下是什么样子。
SELECT * FROM table WHERE id = 1 and 1=1
SELECT * FROM table WHERE id = 1 and 1=2
结果一目了然,第一条因为AND
两边有一个1=1
构成了永真条件,所以会返回正确的数据。第二条语句因为AND
两边有1=2
导致了WHERE
子句永假(不明白的话想想AND
的逻辑),所以不会返回正常的结果了。
通过这种方法也可以判断是否有注入点。
继续开脑洞,只有AND可以这么判断么,结合上前面的符号问题呢?更多的猥琐技巧可以看这里:http://lightless.me/archives/SQL-Injection-weisuo-Skill.html
0x04 必须要有的总结
乱七八糟讲了一大堆,我们来总结下都有啥东西吧。
首先是理解SQL注入,具体怎么理解呢还是要看各位读者自己了。
接下来有数字型、字符型、以及莫名的内联注入型。
然后就是如何识别注入点了,从数字型列举了几个常见的情况
字符型的嘛~下一节再继续~