PHP函數漏洞審計之addslashes函數-實例分析蘋果CMS

2021-02-19 看雪學院

本文為看雪論壇優秀文章

看雪論壇作者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=1

1. 漏洞位於\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

  *本文由看雪論壇 洪七公. 原創,轉載請註明來自看雪社區。

相關焦點

  • php代碼審計學習之函數缺陷
    弱類型比較時,6php會轉換為6,6在1-24中間,所以可以進行上傳piwigo2.7.1實例分析漏洞分析case 'rate' : { include_once(PHPWG_ROOT_PATH.'
  • 代碼審計入門實戰
    下面進入文章的重點部分——PHP函數的代碼審計,通過具體實例分析PHP部分函數,包括in_array函數、filter_var函數、escapeshellarg與escapeshellcmd函數、parse_str函數及addslashes函數,學習上述函數缺陷引發的漏洞及利用方式,結合CTF練習掌握PHP函數漏洞審計流程。
  • 代碼審計Day9 - str_replace函數過濾不當
    前言大家好,我們是紅日安全-代碼審計小組。最近我們小組正在做一個PHP代碼審計的項目,供大家學習交流,我們給這個項目起了一個名字叫 PHP-Audit-Labs 。 :這一題考察的是一個 str_replace 函數過濾不當造成的任意文件包含漏洞。
  • 看代碼學PHP滲透(3) - 實例化任意對象漏洞
    第一個是文件包含漏洞,上圖第8行中使用了 class_exists() 函數來判斷用戶傳過來的控制器是否存在,默認情況下,如果程序存在 __autoload 函數,那麼在使用 class_exists() 函數就會自動調用本程序中的 __autoload 函數,這題的文件包含漏洞就出現在這個地方
  • 搜索 PHP代碼審計之旅
    白盒測試流程——BlueCMS1.6由於初學代碼審計,通過BlueCMS1.6來進行練習,這裡重點寫一些白盒測試如何進行分析0x00:了解目錄結構,利用Seay原始碼審計系統工具發現這麼多漏洞,但要注意只是可能存在,有的不一定就是可以利用的。
  • PHP一些常見的漏洞梳理
    file=…/…/…/…/var/log/httpd/acess_log,getshell實例:ekucms某版本存在文件包含漏洞①通過訪問該url,將一句話木馬寫入日誌文件中http://192.168.1.3/ekucms2.4.1/?
  • 【作者投稿】PHP代碼審計-sprintf函數中的安全問題
    新媒體管家看到一篇WorldPress注入漏洞分析,其中sprintf單引號逃逸的思路很巧妙
  • 全網最詳細的常見PHP漏洞全方面解析
    magic quotes 為 On,它會影響 HTTP 請求的數據(GET、POST、Cookies)程式設計師也可以使用 addslashes 來轉義提交的 HTTP 請求數據,或者用 stripslashes 來刪除轉義PHP 漏洞全解(二)-命令注入攻擊命令注入攻擊PHP 中可以使用下列 5 個函數來執行外部的應用程式或函數
  • ZZZPHP1.61 代碼審計-從SQL注入到Getshell
    近期有很多小夥伴在後臺留言想看關於代碼審計的文章,其實有關審計的文章網上資源是比較多的,但是從代碼審計開始到結束的這類文章卻少之甚少。
  • 看代碼學安全(8 )preg_replace函數之命令執行
    實例分析本次實例分析,我們選取的是 CmsEasy 5.5 版本,漏洞入口文件為 /lib/tool/form.php ,我們可以看到下圖第7行處引用了通過搜索,我們可以發現在 Cache/template/default/manage/guestadd.php 程序中,調用了此函數。
  • pbootcms最新版本前臺撿的rce-論如何繞廢正則
    本文轉載自先知社區:https://xz.aliyun.com/t/8663本文作者:Decade 本文涉及知識點實操練習-命令注入漏洞的代碼審計
  • PHP 繞過禁用函數漏洞的原理與利用分析
    PHP 發布公告,舊版本的 php_array_merge_recursive 函數中存在UAF風險,被利用可能導致用來繞過禁用函數。受影響的版本PHP 7.2 - 7.4.9安全專家建議用戶儘快升級到安全版本,以解決風險。
  • PHP sprintf格式化字符串漏洞
    定義和用法 sprintf() 函數把格式化的字符串寫入變量中。arg1、arg2、++ 參數將被插入到主字符串中的百分號(%)符號處。該函數是逐步執行的。在第一個 % 符號處,插入 arg1,在第二個 % 符號處,插入 arg2,依此類推。注釋:如果 % 符號多於 arg 參數,則您必須使用佔位符。佔位符位於 % 符號之後,由數字和 "\$" 組成。
  • php中函數禁用繞過的原理與利用
    ec=ECID172.19.104.182014092310094200001&pk_campaign=baijia-wemedia(通過本實驗學會通過寬字節方式繞過mysql_real_escape_string()、addslashes()這兩個函數。)
  • 看代碼學安全(9 )str_replace函數過濾不當
    前言大家好,我們是紅日安全-代碼審計小組。最近我們小組正在做一個PHP代碼審計的項目,供大家學習交流,我們給這個項目起了一個名字叫 PHP-Audit-Labs 。現在大家所看到的系列文章,屬於項目 第一階段 的內容,本階段的內容題目均來自 PHP SECURITY CALENDAR 2017 。對於每一道題目,我們均給出對應的分析,並結合實際CMS進行解說。
  • PHP配置函數ini_get()的具體用法介紹
    PHP配置函數ini_get()的具體用法介紹 PHP配置函數ini_get()的主要功能就是獲取配置文件中的選項值。如果我們能合理運用,還可以發揮出它的許多功能供我們使用。
  • PHP代碼審計四
    通常結合程序的其它漏洞實現完整的攻擊,比如文件上傳頁面,覆蓋掉原來白名單的列表,導致任意文件上傳;用戶註冊頁面控制沒覆蓋的未初始化變量導致SQL思路$$extract()函數parse_str()函數執行import_request_variables()函數如下代碼
  • 看代碼學安全(11) - unserialize反序列化漏洞
    大家好,我們是紅日安全-代碼審計小組。最近我們小組正在做一個PHP代碼審計的項目,供大家學習交流,我們給這個項目起了一個名字叫 PHP-Audit-Labs 。現在大家所看到的系列文章,屬於項目 第一階段 的內容,本階段的內容題目均來自 PHP SECURITY CALENDAR 2017 。對於每一道題目,我們均給出對應的分析,並結合實際CMS進行解說。
  • CTF中常見的PHP漏洞小結
    在做ctf題的時候經常會遇到一些PHP代碼審計的題目,這裡將我遇到過的常見漏洞做一個小結。md5()漏洞  PHP在處理哈希字符串時,會利用」!=」或」==」來對哈希值進行比較,它把每一個以」0E」開頭的哈希值都解釋為0,所以如果兩個不同的密碼經過哈希以後,其哈希值都是以」0E」開頭的,那麼PHP將會認為他們相同,都是0。
  • PHP 文件包含漏洞姿勢總結
    原理文件包含漏洞的產生原因是在通過 PHP 的函數引入文件時,由於傳入的文件名沒有經過合理的校驗,從而操作了預想之外的文件,就可能導致意外的文件洩露甚至惡意的代碼注入。php 中引發文件包含漏洞的通常是以下四個函數:1、include() 當使用該函數包含文件時,只有代碼執行到 include() 函數時才將文件包含進來,發生錯誤時只給出一個警告,繼續向下執行。2、include_once() 功能和 include() 相同,區別在於當重複調用同一文件時,程序只調用一次。