乱七八糟的就不多说了,自己百度去
想要更好的学习SQL注入,那么我们就必须要深入的了解每种数据库的SQL语法及特性。下面通过一个经典的万能密码的例子带大家来拨开一下SQL注入漏洞的神秘面纱。本次环境为:DVWA的第一关(DVWA是一个渗透环境,可以用来当作学习渗透的靶机)。实验环境是PHP+MYSQL
如下图是一个正常登录的表单
输入正确的密码后,php程序会查询数据库,如果存在此用户并且密码是正确的,那么登录肯定是成功的。用户不存在或者密码不正确,则会提示账号或者密码错误
登陆成功
登录失败
我们接下来使用一个比较特殊的用户“ admin’ or ‘1’='1 ”来登录,密码可以随意填写或者不填,在点击登录按钮之后发现是可以登录的。
结果如下
那么问题到底出现在哪里呢?
我们通过查看源代码可以发现,登录处最终调用result来实现登录。
上述SQL语句意思非常清楚:在获取到用户输入的username和password之后,和数据库进行比对。若返回结果==1,那么登陆成功。若返回其他值,那么登陆失败。
看起来这段代码是没有什么错误,现在我们提交账户admin,密码为password,再对应执行语句源代码,发现执行的SQL语句为
SELECT * FROM 'users' WHERE user = 'admin' AND password = 'password'
在数据库中,存在admin用户,并且密码为password,所以此时返回结果为1,所以通过验证,用户可以成功登录。
接下来继续输入特殊用户admin’ or ‘1’='1 ,并对照执行语句,发现:
SELECT * FROM 'users' WHERE user = 'admin' or '1'='1' AND password = ''
终于找到问题的根源了
从开发人员的角度理解,SQL语句的本义是:
username=‘账户’ and password=‘密码’
现在却变为
username=‘账户’ or ‘1’=‘1’ and password=‘密码’
因为在SQL语句中and的优先级比or高,所以先运行’1’=‘1’ and password='密码’判断为假,然后因为username=‘admin’ or false为真,所以result=1即result=true顺利通过验证。
由此可见,SQL注入漏洞的形成原因就是:用户输入的数据被SQL解释器执行。
在测试注入漏洞之前,我们首先要搞清楚注入有哪些分类,这样再去测试注入的时候就将会起到事半功倍的效果。
常见的SQL注入类型一般分为两大类:数字型和字符型。也有人分的更多,但不管注入的类型如何,攻击者的目标只有一个,就是绕过程序限制,使用户输入的数据带入数据库执行,利用数据库的特殊性获取更多的信息或者更大的权限。
数字型注入
当输入的参数为整型的时候,比如ID,年龄,页码等,如果存在注入漏洞,则可以认为是数字型注入,数字型注入是最为简单的一种。假设有URL为http://www.xxser.com/test.php?id=8
,那么我们可以对SQL语句进行猜测。
测试步骤:
http://www.xxser.com/test.php?id=8'
select * from table where id=8'
,这样的语句肯定会出错,导致脚本程序无法从数据库中正常获取数据,从而使原来的页面出现异常。http://www.xxser.com/test.php?id=8 and 1=1
select * from table where id =8 and 1=1
,语句执行正常,返回的数据与原始请求无任何差异http://www.xxser.com/test.php?id=8 and 1=2
select * from table where id=8 and 1=2
语句执行正常,但是无法查询出数据,因为1=2始终为假,返回数据与原始请求有差异。select * from table where id = 8
select * from table where username = 'admin'
字符型注入最关键的就是如何闭合SQL语句以及注释多余语句或者对SQL语句的执行进行逻辑上的更改。
当攻击者进行SQL注入时,如果输入 admin and 1=1 ,则无法进行注入。因为 admin and 1=1 会被数据库当作查询的字符串,SQL语句变为
select * from table where username = 'admin and 1=1'
这时候如果我们想要注入,那么就必须要注意字符串的闭合问题,输入admin’ and 1=1 - - 就可以继续注入,SQL语句如下
select * from table where username ='admin' and 1=1 - -'
只要是字符型的注入,都必须要闭合单引号以及注释多余的代码。
通过翻阅大量的参考资料,张小白比较同意的一种观点是:SQL注入只分为数字型和字符型。
但是很多人可能要问了,那不是还有Cookie注入、POST注入、盲注、延时等注入吗?没错,但是大家可以仔细分析一下就会发现,这些类型的注入其实都是以上两大类二点不同展现形式或者不同的展现位置罢了。
那么怎么去理解上面这段话呢?
我们都知道,对数据库进行数据查询的时候,输入的数据一般只有两种;一个是数字类型,比如where id = 1、where age >20,另外一种是字符串类型,比如where name = ‘root’ 、where datetime > ‘2018-09-22’.
也许不同的数据库的比较方式不一样,但是代入数据库查询时一定是字符串(严格的说,数字也是字符串,在数据库当中进行数据查询时,where id ='1’也是合法的,只不过在查询条件为数字时一般不会加单引号)。所以,无论是POST注入还是其他类型的注入,都可以归纳为数字型或者字符型注入。
那么Cookie注入,POST注入等是怎么一回事呢?其实这类注入主要通过注入的位置来分辨,比如有以下请求
POST /user/login.php HTTP/1.1
Host:www.secbug.org
Proxy-Connection:keep-alive
Content-Length:53
Cache-Control:max-age=0
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.17 (KHTML, like Gecko)
Chrom/24.0.1312.57 Safari/537.17 SE 2.X MetaSr 1.0
Content-type:application/x-www-form-urlencoded
Cookie:_jkb_10667=1
username=admin&password=123456
我想看了张小白的渗透之路(一)——HTTP详解的小伙伴一定能够很轻松的搞清楚上面这块代码想要表达什么意思。
我们可以看到此时呢为POST请求,但是POST数据中的username字段存在漏洞,一般就直接说POST注入,却不再考虑username是什么类型的注入
如果此时的HTTP请求如下:
GET /user/login.php?username=admin&password=123456 HTTP/1.1
Host:www.secbug.org
Proxy-Connection:keep-alive
Content-Length:53
Cache-Control:max-age=0
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.17 (KHTML, like Gecko)
Chrom/24.0.1312.57 Safari/537.17 SE 2.X MetaSr 1.0
Content-type:application/x-www-form-urlencoded
Cookie:_jkb_10667=1
那么是不是应该又叫做GET注入呢?
下面呢是张小白整理的一些注入叫法,大家可以参考一下
对于SQL注入更加深入的了解,大家可以尝试在张小白的渗透之路(三)寻找到属于自己的答案