[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 十六进制长度的判断,假设它的长度为 xy 表示 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,最后附上出题人脚本

小结

  1. sqlite3 盲注 bypass ,利用 replace() 和 length 进行爆破,trim() 替换空字符,trim() 和 hex() 构造字符,& 特性获取长度等等,在 mysql 中也存在整数溢出的现象

最后更新于