[HarekazeCTF2019]Sqlite Voting
[HarekazeCTF2019]Sqlite Voting
考点
sqlite注入
sqlite盲注
sqlite中
abs整数溢出导致盲注
wp
打开靶机,看到投票的页面,并且给了源码

在 schema.sql 中发现了 flag 表
在 vote.php 页面 POST 参数 id ,只能为数字。 vote.php 是查询的功能,但是对参数进行了过滤。
UPDATE 成功与失败分别对应了不同的页面,那么可以进行盲注,但是考虑到它过滤了 ' 和 " 这就无法使用字符进行判断,char 又被过滤也无法使用 ASCII 码判断
可以考虑使用 hex 进行字符判断,将所有的的字符串组合用有限的 36 个字符表示
先考虑对 flag 十六进制长度的判断,假设它的长度为 x,y 表示 2 的 n 次方,那么 x&y 就能表现出 x 二进制为 1 的位置,将这些 y 再进行或运算就可以得到完整的 x 的二进制,也就得到了 flag 的长度,而 1<<n 恰可以表示 2 的 n 次方
那么如何构造报错语句呢?在 sqlite3 中,abs 函数有一个整数溢出的报错,如果 abs 的参数是 -9223372036854775808 就会报错,同样如果是正数也会报错

判断长度的 payload : abs(case(length(hex((select(flag)from(flag))))&{1<<n})when(0)then(0)else(0x8000000000000000)end)
脚本
假设长度是20,20的二进制是10100

然后考虑逐字符进行判断,但是 is_valid() 过滤了大部分截取字符的函数,而且也无法用 ASCII 码判断
这一题对盲注语句的构造很巧妙,首先利用如下语句分别构造出 ABCDEF ,这样十六进制的所有字符都可以使用了,并且使用 trim(0,0) 来表示空字符
然后逐字符进行爆破,已经知道 flag 格式为 flag{} ,hex(b'flag{')==666C61677B ,在其后面逐位添加十六进制字符,构成 paylaod
再利用 replace(length(replace(flag,payload,''))),84,'') 这个语句进行判断
如果 flag 不包含 payload ,那么得到的 length 必为 84 ,最外面的 replace 将返回 false ,通过 case when then else 构造 abs 参数为 0 ,它不报错
如果 flag 包含 payload ,那么 replace(flag, payload, '') 将 flag 中的 payload 替换为空,得到的 length 必不为 84 ,最外面的 replace 将返回 true ,通过 case when then else 构造 abs 参数为 0x8000000000000000 令其报错
以上就可以根据报错爆破出 flag,最后附上出题人脚本
小结
sqlite3 盲注 bypass ,利用 replace() 和 length 进行爆破,trim() 替换空字符,trim() 和 hex() 构造字符,& 特性获取长度等等,在 mysql 中也存在整数溢出的现象
最后更新于