当前位置:   article > 正文

网络对抗课程SQL注入实验_(select 6793 from (select(sleep(1-(if(ord(mid((sel

(select 6793 from (select(sleep(1-(if(ord(mid((select ifnull(cast(flag as nc

网络对抗实验二

1. 搭建 mysql 数据库,建立数据库 test,数据表 student,包含 id、name、score 三列。

2、环境:nginx+php-fpm

3、接口程序按老师给的资料里的php文件略微修改一下

  1. 根据输入的参数值,拼接SQL查询语句并执行,将查询结果展示。如根据输入的学号展示姓名和分数。(1.php)

手工sql注入:得到全部信息

  1. 根据输入的参数值,拼接 SQL 查询语句并执行,展示查询结果是否为空。如输入学号,展示是否有该学生存在。(4.php)

id=1、2、3均显示exist,其他显示inexistence

  1. 根据输入的参数值,拼接 SQL 查询语句并执行,将查询结果是否为空展示在两段随机内容之间。(3.php)

  1. 根据输入的参数值,拼接 SQL 查询语句并执行,展示查询结果的条件表达式结果,并将结果展 示在两段随机内容之间。如入学号,展示该学生分数是否大于 60。(5.php)

  1. 根据输入的参数值,拼接 SQL 查询语句并执行,但展示一个固定的结果。如输入学号,查询是否有学生存在,然后输出固定内容。(6.php)

  1. 据输入的参数值,拼接SQL语句并执行,更新数据库。如输入学号和分数,将对应学生的分数更新。(8.php)

改完后去前面查询

从日志里可以看到操作命令正确

现在的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命令是关键。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/573962
推荐阅读
  

闽ICP备14008679号