赞
踩
网络对抗实验二
1. 搭建 mysql 数据库,建立数据库 test,数据表 student,包含 id、name、score 三列。
2、环境:nginx+php-fpm
3、接口程序按老师给的资料里的php文件略微修改一下
手工sql注入:得到全部信息
id=1、2、3均显示exist,其他显示inexistence
改完后去前面查询
从日志里可以看到操作命令正确
现在的student表:
4、UNION query
sqlmap找注入点,指定注入点,-p指定存在SQL注入点的参数id
找到了一些注入点,
利用注入点查询到其他所有的数据库
还可以得到users
得到current-db
看一看test数据库里有哪些表
查询到了student表
sqlmap是一款用来检测与利用SQL注入漏洞的免费开源工具,做到这里似乎还没有深入到对sql注入底层的理解,只是工具的利用。需要搞懂sqlmap是怎么利用sql注入漏洞的,接下来尝试搞清楚sqlmap的原理,清楚技术细节,本质上也就搞懂了sql注入。
1、打开ZAP,在sqlmap命令里加上代理,先从简单的current-db开始
得到
在ZAP抓到的包里,发现两个包
第一个是sqlmap发出的正常的请求,好像对于查询到current-db没什么用处
那么,真正有用的是第二个请求:
http://127.0.0.2:80/sql_injection/1.php?id=1%27%20UNION%20ALL%20SELECT%20CONCAT%280x716b786a71%2CIFNULL%28CAST%28DATABASE%28%29%20AS%20NCHAR%29%2C0x20%29%2C0x7162766a71%29%2CNULL--%20-&submit=submit
所以,我们可以自己在浏览器上新开一个窗口输入上述请求。
结果输出了一个正常的name、score和一个没见过的name。仔细观察这个qkxjqtestqbvjq,其实包含了test。
下面对
1' UNION ALL SELECT CONCAT(0x716b786a71%2CIFNULL(CAST(DATABASE() AS NCHAR)%2C0x20)%2C0x7162766a71)%2CNULL-- -
用做一个解码,用老师常用的网站:bianma.911cha.com
得到文本格式:
1' UNION ALL SELECT CONCAT(0x716b786a71,IFNULL(CAST(DATABASE() AS NCHAR),0x20),0x7162766a71),NULL-- -
把这个文本输入查询id框,得到的结果与上面的url一样。
那么,对这个解码后的命令做一个分析。
1’及之前就是简单的查询命令
UNION ALL 就是把后边的语句跟之前拼接起来。
SELECT是查询命令
CONCAT是字符串拼接函数
0x716b786a71、0x7162766a71分别是前缀和后缀,也就是qkxjq、qbvjq
IFNULL(CAST(DATABASE() AS NCHAR是核心语句,利用DATABASE()函数。
-- -是把后边的语句注释掉
在MySQL query log里也可以看到执行的命令的完整版
在mysql里输入上面的命令得到同样结果
再换一个,查询current-user
还是两个请求,第二个请求里找到GET,分析
http://127.0.0.2:80/sql_injection/1.php?id=1%27%20UNION%20ALL%20SELECT%20CONCAT%280x716b786a71%2CIFNULL%28CAST%28CURRENT_USER%28%29%20AS%20NCHAR%29%2C0x20%29%2C0x7162766a71%29%2CNULL--%20-&submit=submit
在浏览器里输入,与上一个例子相似,可以看到想要的结果。
解码得到:
1' UNION ALL SELECT CONCAT(0x716b786a71,IFNULL(CAST(CURRENT_USER() AS NCHAR),0x20),0x7162766a71),NULL-- -
可以知道,核心语句是CURRENT_USER()
query log的记录
输入到mysql
结论:从以上的实践可以大致了解一些sql注入的原理,当然,这只是一些简单的实验,都是利用UNION SELECT。如果改一下接口程序,比如在1.php里的输出后加入一个break,就可以使UNION 失效。
值得一提的是,sqlmap依然可以通过UNION查询到所有信息。
接下来学习更高级的sql注入技术。
对于返回不属于数据库的信息,如查询学生是否存在。
尝试union select查询
没有注入点。
在网页里直接输入1' OR 'a'='b ,注入依然成功,id=1变为不存在
问题是结果里只有存在与不存在,无法得到想要的数据表信息。
尝试构造:1' AND *** -- -
***部分的真假直接决定返回值的存在与不存在,编写***部分可以得到数据库的一些信息。
分析是这么分析的,但是可能我写的接口程序的问题,查询学生存在不存在的程序只有基于时间的盲注。
那我正好都检测一遍,发现5.php可以,也就是检查学生分数是否大于60,因为这个返回的也是不属于数据库的信息。那就用这个做布尔盲注。
5、基于布尔的盲注,boolean-based blind
同样是先用sqlmap
但是运行了两次,结果均不正确。
拖库也不成功。
把5.php改一下,把随机内容去掉
又成功了
拖库也成功了
那么,看来这个插入两段随机内容的语句,让sqlmap布尔盲注失效了。
原理还不太懂。
继续用修改后5.php布尔盲注,了解原理。
抓current-db命令的包分析
复制上面网页到浏览器,没有出现current-db
对1%27%20AND%20ORD%28MID%28%28IFNULL%28CAST%28DATABASE%28%29%20AS%20NCHAR%29%2C0x20%29%29%2C1%2C1%29%29%3E64%20AND%20%27foFD%27%3D%27foFD&submit=submit
作解码处理得到
1' AND ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),1,1))>64 AND 'foFD'='foFD&submit=submit
与query log里记录的一样
来分析一下这个命令
1' AND略
(IFNULL(CAST(DATABASE() AS NCHAR),0x20))
MID(……,n,1)看图秒懂,就是求第n位字符
ORD求ASCII码的十进制
AND 'foFD'='foFD略
所以整个命令就是判断数据库名字的第一个字符的ASCII码十进制值是否大于64。大于64则表达式成立。
以第二个字符e为例,就是一系列逼近101的过程,判断结果依次为>64、>96、<=112、<=104、>100、<=102、<=101
结论:所以布尔盲注就是逐字符比对,不断逼近答案。
那这样就解开了上面加入随机字符能避免sql注入的疑问。因为布尔盲注是逐字符比对,每次都要得到比对结果yes或者no,但加入的字符串使结果不再只有固定的对立两面,无法判断。
为了验证这个结论,先恢复5.php的随机内容
然后在sqlmap命令里加上条件:--string='(score <= 60)'
成功注入得到current-db
6、基于时间的盲注,time-based blind
对于6.php,不论输入id是什么,都会输出“query ok“,显然UNION ALL和基于布尔的盲注不能用于对6.php的sql注入。先扫描一下6.php
得到只有time-based blind
输入命令:
成功得到current-db,但是可以看出,得到的过程很慢
在ZAP里找到抓到的包
复制这个URL在网页里执行一下
把网页解码
分析这个命令:
id=1' AND (SELECT 3689 FROM (SELECT(SLEEP(5-(IF(ORD(MID((IFNULL(CAST(DATABASE() AS NCHAR),0x20)),1,1))>64,0,5)))))YdwL) AND 'POac'='POac&submit=submit
看一下query log里的记录
这些命令放到MySQL里执行
结论:DATABASE的第一个字符的ASCII码值满足了大于64、96、115,不满足116,所以第一个字符为“t“。表达式成立则sleep长时间,如果不成立,则命令立刻执行,故很快出结果。所以可以说,sleep命令是关键。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。