题目描述
纯粹的SQL注入题
随意传入
name=abc&pw=a
返回 wrong user
尝试传入
name=1%27&pw=a
发现闭合方式为'
,同时给出了一个可疑字符串
把这段字符串丢进ChatGPT,告诉我们可能是Base32编码的,对其进行Base32解码得到字符串
c2VsZWN0ICogZnJvbSB1c2VyIHdoZXJlIHVzZXJuYW1lID0gJyRuYW1lJw==
这显然是Base64编码的,再对其解码,得到明文
select * from user where username = '$name'
显然这道题的注入点就是name
题解
在尝试的过程中发现以下字符串被过滤
or = ( )
但是由于对大小写不敏感,or
可以使用大小写方式进行绕过
传参:
name=1' Or 1#&pw=a
返回 wrong pass
说明name
已经注入成功了,但是却要校验pw
参数。
由于当name
的值为1'
时,会返回错误的语句,正常的思路是使用报错注入,得到数据库的信息,但是过滤了(
和)
,因此也无法进行数据库的查询。
题目给了源代码,点入search.php
的源代码,关键代码如下:
其登录逻辑是,根据name
到数据库中查找,将查找到的用户名对应的md5加密的密码与传入的pw
的md5值进行比较(即存储在数据库中的是密码的md5值),若相等,则登录成功。这与CTF比赛中常见的直接对用户名参数进行注入不同。
当我们传入name=1' Or 1#&pw=a
时,查询的结果是用户admin的用户名和密码,即$arr[1]
的值是admin
,$arr[2]
的值是admin用户的密码。当pw
的md5值与$arr[2]
的值相等时,就返回flag。而admin用户的密码是我们无法得到的。
因此我们需要控制$arr[2]
的值,将其赋值为pw
参数的md5值。当传参如下时:
name=1' union select 1,"admin",3#&pw=a
返回也是 wrong pass,说明用户名存储在表中的第二列,猜测密码存储在第三列,传参:
name=1' union select 1,"admin","0cc175b9c0f1b6a831c399e269772661"#&pw=a
其中0cc175b9c0f1b6a831c399e269772661
是a 的md5值,这样传参,$arr[1]
的值为admin
,$arr[2]
的值为0cc175b9c0f1b6a831c399e269772661
总结
本题的登录逻辑与一般的题目不同,源码中的查询语句并非是
select * from user where username = '$name' && password = '$pw'
而是
select * from user where username = '$name'
先选择与用户名匹配的记录,记录中存储的是用户名和密码的md5值 ,再将查询到的密码的md5值与传入参数的md5值进行比较。