本文為看雪論壇優秀文章
看雪論壇作者ID:洪七公.
addslashes() 函數返回在預定義字符之前添加反斜槓的字符串。
(PHP 4, PHP 5, PHP 7)
預定義字符是:
單引號(')
雙引號(")
反斜槓(\)
NULL
提示:該函數可用於為存儲在資料庫中的字符串以及資料庫查詢語句準備字符串。
注釋:默認地,PHP 對所有的 GET、POST 和 COOKIE 數據自動運行 addslashes()。所以您不應對已轉義過的字符串使用 addslashes(),因為這樣會導致雙層轉義。遇到這種情況時可以使用函數 get_magic_quotes_gpc() 進行檢測。
示例1在每個雙引號(")前添加反斜槓:
<!DOCTYPE html><html><body><?php $str = addslashes('Shanghai is the "biggest" city in China.');echo($str); ?> </body></html>示例2
在每個雙引號(")前添加反斜槓:
<!DOCTYPE html><html><body> <?php$str = "Who's Bill Gates?";echo $str . " This is not safe in a database query.<br>";echo addslashes($str) . " This is safe in a database query.";?> </body></html>
以一個用戶登錄程序為例,考察通過SQL注入繞過登錄驗證,代碼如下:
第29行通過POST方式傳入user和passwd兩個參數,通過isValid函數判斷是否合法。isValid函數主要功能代碼在第10~20行,可以看到第11~12行調用sanitizeInput方法對user和passwd進行相關處理。
sanitizeInput主要功能代碼在第22~25行,這裡針對輸入的數據調用addslashes函數進行處理,然後對處理後的內容進行長度判斷,長度大於20則只截取前20個字符。
這道題已經過濾了單引號,正常情況是沒有注入了,為什麼還能導致注入呢?原因實際上出在第24行substr函數這裡,關於substr函數的定義查看相關知識第二條。
關於substr函數一個簡單的例子:
註:substr中的參數0代表從位置為0的字符開始計算,2代表返回的字符串將從0(start)處開始最多包括2(length)個字符。
再回到題目中,我們知道反斜槓可以取消特殊字符的用法,而注入想要通過單引號閉合,必然會引入反斜槓。
將官方提供的payload帶入題目中,拼接第15~17行代碼中的SQL語句:
select count(p) from user u where user ='1234567890123456789\' AND password = '$pass'這裡的SQL語句由於反斜槓的原因,user=』1234567890123456789\』最後這個單引號會失去它的作用,我們讓password=or 1=1#,那麼最後的SQL語句為:
select count(p) from user u where user = '1234567890123456789\' AND password = 'or 1=1此時user值為1234567890123456789\' AND password =,可以保證帶入資料庫執行的結果為true,就能順利地通過驗證。因此使用如下payload即可逃逸出\(反斜槓)注入。
user=1234567890123456789\'&passwd= or 1=11. 漏洞位於\inc\common\template.php:
$lp['wd']變量位置存在字符串拼接,存在SQL注入。
2. 但是這個CMS具有一些通用的注入防護,首先在\inc\module\vod.php文件中:
當$method=search成立的時候,進入了第96行中的be("all","wd"),獲取請求中的wd參數的值,並且使用chkSql函數對wd參數的值進行處理。
3. 跟進be函數,在\inc\common\function.php文件中:
這部分代碼的作用是對GET、POST、REQUEST接收到的參數進行addslashes轉義處理。
4. 跟進\inc\module\vod.php文件中的chkSql函數,具體位置在\inc\common\360_safe3.php文件中:
在第34~38行針對接收到的變量進行循環的urldecode(即url解碼),然後在第41行使用StopAttack函數對解碼後的數據進行處理,將處理後的數據通過htmlEncode方法進行HTML編碼,然後返回編碼後的值。
跟進StopAttack函數:
第18~24行調用正則進行處理,相關的正則表達式是$ArrFiltReq,這裡的$ArrFiltReq變量就是前面傳入的$getfilter(StopAttack函數的第三個參數),語句變成:preg_match("/". $getfilter."/is",1)
跟進$getfilter變量:
這段代碼的功能就是檢測GET、POST、COOKIE中的惡意數據。
5. 在chkSql函數最後有串代碼是return htmlEncode($s),跟進一下htmlEncode函數,在\inc\common\function.php文件中:
這段代碼的功能是針對&、'、空格、"、TAB、回車、換行、大小於號等符號進行實體編碼轉換,但是這裡沒有針對其他的空白字符和反斜槓進行處理。
6. 注入點是\inc\common\template.php,就是分析的第一條。我們繼續看看$lp['wd']的值是怎麼獲取的:
當P["wd"]不為空時,$lp['wd']從P["wd"]中獲取數據。
7. 根據之前的分析,在\inc\module\vod.php文件中存在這樣一行代碼:$tpl->P["wd"] = $wd;(見分析的第二條),而wd可以從REQUEST中獲取到,所以這裡的wd實際上是可控的。
1. 在前面的分析中,我們知道html Encode針對&、』、空格、」、TAB、回車、換行、大小於號等進行了實體編碼轉換,但是這裡的注入類型是字符型注入,需要引入單引號來進行閉合。而htmlEncode函數對單引號進行了處理,因此我們需要換個思路。
2. $lp['wd']參數可以控制SQL語句中的兩個位置,可以通過引入反斜槓進行單引號閉合,而源文件調用了addslashes函數,會對反斜槓進行轉義處理。但是這裡對用戶請求的參數又會進行url解碼(見分析的第四條),因此可以使用雙url編碼繞過addslashes函數。
3. Attack機器使用瀏覽器訪問http://10.1.1.100/maccms-8.0/index.php?m=vod-search並用burpsuite抓包,修改請求包中的內容,go之後會看到response處的響應:
Payload:wd=))||if((select%0b(select(m_name)''from(mac_manager))regexp(0x5e61)),('sleep'(3)),0)#%25%35%63
註:%25%35%63經過兩次url解碼後為\
4. Payload傳到程序裡,經過拼接後的資料庫語句如下所示:
addslashes函數相關ctf練習,繞過WAF並獲取flag。
在做題之前,先了解一些需要用到的基礎知識:
1. 對於傳入的非法$_GET數組參數名,PHP會將其替換成下劃線。
2. 當使用HPP(HTTP參數汙染)傳入多個相同參數給伺服器時,PHP只會接收到後者的值:
解題:
1. Attack機器使用瀏覽器訪問http://10.1.1.100/maccms-8.0/ctf/index.php開始解題。
2. 查看源碼,第一個WAF在第26~28行,採用了dowith_sql函數,其主要功能代碼在第17~24行:
如果$_REQUEST數組中的數據存在select|insert|update|delete等敏感關鍵字或字符,則直接exit();如果不存在則原字符串返回。
3. 第二個WAF源碼:
通過$_SERVER['REQUEST_URI']的方式獲取參數,然後使用explode函數針對&進行分割,獲取每個參數的參數名和參數值,最後針對每個參數值調用dhtmlspecialchars函數進行過濾。
4. 跟進dhtmlspecialchars函數:
主要針對&、」、<、>、(、)等特殊字符進行過濾替換,最後返回替換後的內容。
5. 從第41~42行代碼可以看到,題目的參數通過REQUEST方式獲取:
6. Payload可以根據下面的圖進行構造:
我們通過頁面請求i_d=payload&i.d=123,當數據流到達第一個WAF時,PHP會將參數中的某些特殊符號替換為下劃線。
於是得到了兩個i_d,此時的payload為i_d=payload&i_d=123。
而在參數相同的情況下,默認第二個參數傳入的值會覆蓋第一個參數傳入的值,因此第一個WAF中i_d=123,不存在其他特殊字符,因此繞過了第一個WAF。
當數據流到達第二個WAF時,代碼是通過$_SERVER['REQUEST_URI']的方式獲取參數,而$_SERVER['REQUEST_URI']不會將參數中的特殊符號進行轉換,因此這裡的i.d參數不會被替換為i_d,此時i.d和i_d都能繞過第二個WAF。
繞過第二個WAF中的dhtmlspecialchars函數後,i_d=payload&i.d=123會進入到業務層代碼中,執行SQL語句。這裡的SQL語句採用拼接的方式,因此存在SQL注入。
7. 最後的payload為:
在\inc\common\function.php文件中添補上疏漏的str_replace(chr(92),」<br/>」,$str);即可:
反斜槓\的ASCII碼為92,這裡新增一行代碼處理反斜槓。一個簡單的例子:
看雪ID:洪七公.
https://bbs.pediy.com/user-home-784718.htm
*本文由看雪論壇 洪七公. 原創,轉載請註明來自看雪社區。