高級PHP應(yīng)用程序漏洞審核技術(shù)
?
- 高級PHP應(yīng)用程序漏洞審核技術(shù)
- 前言
- 傳統(tǒng)的代碼審計技術(shù)
- PHP版本與應(yīng)用代碼審計
- 其他的因素與應(yīng)用代碼審計
- 擴(kuò)展我們的字典
- 變量本身的key
- 變量覆蓋
- 遍歷初始化變量
- parse_str()變量覆蓋漏洞
- import_request_variables()變量覆蓋漏洞
- PHP5 Globals
- magic_quotes_gpc與代碼安全
- 什么是magic_quotes_gpc
- 哪些地方?jīng)]有魔術(shù)引號的保護(hù)
- 變量的編碼與解碼
- 二次攻擊
- 魔術(shù)引號帶來的新的安全問題
- 變量key與魔術(shù)引號
- 代碼注射
- PHP中可能導(dǎo)致代碼注射的函數(shù)
- 變量函數(shù)與雙引號
- PHP自身函數(shù)漏洞及缺陷
- PHP函數(shù)的溢出漏洞
- PHP函數(shù)的其他漏洞
- session_destroy()刪除文件漏洞
- 隨機(jī)函數(shù)
- 特殊字符
- 截斷
- include截斷
- 數(shù)據(jù)截斷
- 文件操作里的特殊字符
- 怎么進(jìn)一步尋找新的字典
- DEMO
- 后話
- 附錄
?
前言
PHP是一種被廣泛使用的腳本語言,尤其適合于web開發(fā)。具有跨平臺,容易學(xué)習(xí),功能強(qiáng)大等特點(diǎn),據(jù)統(tǒng)計全世界有超過34%的網(wǎng)站有php的應(yīng)用,包括Yahoo、sina、163、sohu等大型門戶網(wǎng)站。而且很多具名的web應(yīng)用系統(tǒng)(包括bbs,blog,wiki,cms等等)都是使用php開發(fā)的,Discuz、phpwind、phpbb、vbb、wordpress、boblog等等。隨著web安全的熱點(diǎn)升級,php應(yīng)用程序的代碼安全問題也逐步興盛起來,越來越多的安全人員投入到這個領(lǐng)域,越來越多的應(yīng)用程序代碼漏洞被披露。針對這樣一個狀況,很多應(yīng)用程序的官方都成立了安全部門,或者雇傭安全人員進(jìn)行代碼審計,因此出現(xiàn)了很多自動化商業(yè)化的代碼審計工具。也就是這樣的形勢導(dǎo)致了一個局面:大公司的產(chǎn)品安全系數(shù)大大的提高,那些很明顯的漏洞基本滅絕了,那些大家都知道的審計技術(shù)都無用武之地了。我們面對很多工具以及大牛掃描過n遍的代碼,有很多的安全人員有點(diǎn)悲觀,而有的官方安全人員也非常的放心自己的代碼,但是不要忘記了“沒有絕對的安全”,我們應(yīng)該去尋找新的途徑挖掘新的漏洞。本文就給介紹了一些非傳統(tǒng)的技術(shù)經(jīng)驗(yàn)和大家分享。
另外在這里特別說明一下本文里面很多漏洞都是來源于網(wǎng)絡(luò)上牛人和朋友們的分享,在這里需要感謝他們 :)
傳統(tǒng)的代碼審計技術(shù)
WEB應(yīng)用程序漏洞查找基本上是圍繞兩個元素展開:變量與函數(shù)。也就是說一漏洞的利用必須把你提交的惡意代碼通過變量經(jīng)過n次變量轉(zhuǎn)換傳遞,最終傳遞給目標(biāo)函數(shù)執(zhí)行,還記得MS那句經(jīng)典的名言嗎?“一切輸入都是有害的”。這句話只強(qiáng)調(diào)了變量輸入,很多程序員把“輸入”理解為只是gpc[$_GET,$_POST,$_COOKIE],但是變量在傳遞過程產(chǎn)生了n多的變化。導(dǎo)致很多過濾只是個“紙老虎”!我們換句話來描敘下代碼安全:“一切進(jìn)入函數(shù)的變量是有害的”。
PHP代碼審計技術(shù)用的最多也是目前的主力方法:靜態(tài)分析,主要也是通過查找容易導(dǎo)致安全漏洞的危險函數(shù),常用的如grep,findstr等搜索工具,很多自動化工具也是使用正則來搜索這些函數(shù)。下面列舉一些常用的函數(shù),也就是下文說的字典(暫略)。但是目前基本已有的字典很難找到漏洞,所以我們需要擴(kuò)展我們的字典,這些字典也是本文主要探討的。
其他的方法有:通過修改PHP源代碼來分析變量流程,或者h(yuǎn)ook危險的函數(shù)來實(shí)現(xiàn)對應(yīng)用程序代碼的審核,但是這些也依靠了我們上面提到的字典。
PHP版本與應(yīng)用代碼審計
到目前為止,PHP主要有3個版本: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 | ? | 目前還在測試階段,變化很多做了大量的修改,取消了很多安全選項(xiàng)如magic_quotes_gpc(這個不是今天討論的范圍) |
?
由于php缺少自動升級的機(jī)制,導(dǎo)致目前PHP版本并存,也導(dǎo)致很多存在漏洞沒有被修補(bǔ)。這些有漏洞的函數(shù)也是我們進(jìn)行WEB應(yīng)用程序代碼審計的重點(diǎn)對象,也是我們字典重要來源。
其他的因素與應(yīng)用代碼審計
很多代碼審計者拿到代碼就看,他們忽視了“安全是一個整體”,代碼安全很多的其他因素有關(guān)系,比如上面我們談到的PHP版本的問題,比較重要的還有操作系統(tǒng)類型(主要是兩大陣營win/*nix),WEB服務(wù)端軟件(主要是iis/apache兩大類型)等因素。這是由于不同的系統(tǒng)不同的WEB SERVER有著不同的安全特點(diǎn)或特性,下文有些部分會涉及。
所以我們在做某個公司W(wǎng)EB應(yīng)用代碼審計時,應(yīng)該了解他們使用的系統(tǒng),WEB服務(wù)端軟件,PHP版本等信息。
擴(kuò)展我們的字典
下面將詳細(xì)介紹一些非傳統(tǒng)PHP應(yīng)用代碼審計一些漏洞類型和利用技巧。
變量本身的key
說到變量的提交很多人只是看到了GET/POST/COOKIE等提交的變量的值,但是忘記了有的程序把變量本身的key也當(dāng)變量提取給函數(shù)處理。
<span style="color: #666600;" class="pun"><?</span><span class="pln">php</span><span style="color: #880000;" class="com">//key.php?aaaa'aaa=1&bb'b=2 </span><span class="pln"></span><span style="color: #880000;" class="com">//print_R($_GET); </span><span class="pln">?</span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET AS $key </span><span style="color: #666600;" class="pun">=></span><span class="pln"> $value</span><span style="color: #666600;" class="pun">)</span><span class="pln"></span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? </span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $key</span><span style="color: #666600;" class="pun">.</span><span style="color: #008800;" class="str">"\n"</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #666600;" class="pun">?></span>
上面的代碼就提取了變量本身的key顯示出來,單純對于上面的代碼,如果我們提交URL:
<span class="pln">key</span><span style="color: #666600;" class="pun">.</span><span class="pln">php</span><span style="color: #666600;" class="pun">?<</span><span class="pln">script</span><span style="color: #666600;" class="pun">></span><span class="pln">alert</span><span style="color: #666600;" class="pun">(</span><span style="color: #006666;" class="lit">1</span><span style="color: #666600;" class="pun">);</</span><span class="pln">script</span><span style="color: #666600;" class="pun">>=</span><span style="color: #006666;" class="lit">1</span><span style="color: #666600;" class="pun">&</span><span class="pln">bbb</span><span style="color: #666600;" class="pun">=</span><span style="color: #006666;" class="lit">2</span>
那么就導(dǎo)致一個xss的漏洞,擴(kuò)展一下如果這個key提交給include()等函數(shù)或者sql查詢呢?:)
?
漏洞審計策略 |
PHP版本要求:無 系統(tǒng)要求:無 審計策略:通讀代碼 |
?
變量覆蓋
很多的漏洞查找者都知道extract()這個函數(shù)在指定參數(shù)為EXTR_OVERWRITE或者沒有指定函數(shù)可以導(dǎo)致變量覆蓋,但是還有很多其他情況導(dǎo)致變量覆蓋的如:
遍歷初始化變量
請看如下代碼:
<span style="color: #666600;" class="pun"><?</span><span class="pln">php</span><span style="color: #880000;" class="com">//var.php?a=fuck</span><span class="pln">$a</span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'hi'</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET </span><span style="color: #000088;" class="kwd">as</span><span class="pln"> $key </span><span style="color: #666600;" class="pun">=></span><span class="pln"> $value</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? $$key </span><span style="color: #666600;" class="pun">=</span><span class="pln"> $value</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $a</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #666600;" class="pun">?></span>
很多的WEB應(yīng)用都使用上面的方式(注意循環(huán)不一定是foreach),如Discuz!4.1的WAP部分的代碼:
<span class="pln">$chs </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">''</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_POST </span><span style="color: #666600;" class="pun">&&</span><span class="pln"> $charset </span><span style="color: #666600;" class="pun">!=</span><span style="color: #008800;" class="str">'utf-8'</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? $chs </span><span style="color: #666600;" class="pun">=</span><span style="color: #000088;" class="kwd">new</span><span style="color: #660066;" class="typ">Chinese</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'UTF-8'</span><span style="color: #666600;" class="pun">,</span><span class="pln"> $charset</span><span style="color: #666600;" class="pun">);</span><span class="pln">? ? ? ? </span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_POST </span><span style="color: #000088;" class="kwd">as</span><span class="pln"> $key </span><span style="color: #666600;" class="pun">=></span><span class="pln"> $value</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? ? ? ? ? $$key </span><span style="color: #666600;" class="pun">=</span><span class="pln"> $chs</span><span style="color: #666600;" class="pun">-></span><span style="color: #660066;" class="typ">Convert</span><span style="color: #666600;" class="pun">(</span><span class="pln">$value</span><span style="color: #666600;" class="pun">);</span><span class="pln">? ? ? ? </span><span style="color: #666600;" class="pun">}</span><span class="pln">? ? ? ? unset</span><span style="color: #666600;" class="pun">(</span><span class="pln">$chs</span><span style="color: #666600;" class="pun">);</span>
?
漏洞審計策略 |
PHP版本要求:無 系統(tǒng)要求:無 審計策略:通讀代碼 |
?
parse_str()變量覆蓋漏洞
<span style="color: #880000;" class="com">//var.php?var=new</span><span class="pln">$var </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'init'</span><span style="color: #666600;" class="pun">;</span><span class="pln"> ? ? ? ? ? ? ? ? ? ? parse_str</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_SERVER</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'QUERY_STRING'</span><span style="color: #666600;" class="pun">]);</span><span class="pln"> </span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $var</span><span style="color: #666600;" class="pun">;</span>
該函數(shù)一樣可以覆蓋數(shù)組變量,上面的代碼是通過$_SERVER['QUERY_STRING']來提取變量的,對于指定了變量名的我們可以通過注射“=”來實(shí)現(xiàn)覆蓋其他的變量:
<span style="color: #880000;" class="com">//var.php?var=1&a[1]=var1%3d222</span><span class="pln">$var1 </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'init'</span><span style="color: #666600;" class="pun">;</span><span class="pln">parse_str</span><span style="color: #666600;" class="pun">(</span><span class="pln">$a</span><span style="color: #666600;" class="pun">[</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'var'</span><span style="color: #666600;" class="pun">]]);</span><span class="pln"></span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $var1</span><span style="color: #666600;" class="pun">;</span>
上面的代碼通過提交$var來實(shí)現(xiàn)對$var1的覆蓋。
?
漏洞審計策略(parse_str) |
PHP版本要求:無 系統(tǒng)要求:無 審計策略:查找字符parse_str |
?
?
漏洞審計策略(mb_parse_str) |
PHP版本要求:php4<4.4.7 php5<5.2.2 系統(tǒng)要求:無 審計策略:查找字符mb_parse_str |
?
import_request_variables()變量覆蓋漏洞
<span style="color: #880000;" class="com">//var.php?_SERVER[REMOTE_ADDR]=10.1.1.1</span><span class="pln">echo </span><span style="color: #008800;" class="str">'GLOBALS '</span><span style="color: #666600;" class="pun">.(</span><span style="color: #000088;" class="kwd">int</span><span style="color: #666600;" class="pun">)</span><span class="pln">ini_get</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">"register_globals"</span><span style="color: #666600;" class="pun">).</span><span style="color: #008800;" class="str">"n"</span><span style="color: #666600;" class="pun">;</span><span class="pln">import_request_variables</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'GPC'</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_SERVER</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'REMOTE_ADDR'</span><span style="color: #666600;" class="pun">]</span><span style="color: #666600;" class="pun">!=</span><span style="color: #008800;" class="str">'10.1.1.1'</span><span style="color: #666600;" class="pun">)</span><span style="color: #000088;" class="kwd">die</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'Go away!'</span><span style="color: #666600;" class="pun">);</span><span class="pln">echo </span><span style="color: #008800;" class="str">'Hello admin!'</span><span style="color: #666600;" class="pun">;</span>
?
漏洞審計策略(import_request_variables) |
PHP版本要求:php4<4.4.1 php5<5.2.2 系統(tǒng)要求:無 審計策略:查找字符import_request_variables |
?
PHP5 Globals
從嚴(yán)格意義上來說這個不可以算是PHP的漏洞,只能算是一個特性,測試代碼:
<span style="color: #666600;" class="pun"><?</span><span class="pln"></span><span style="color: #880000;" class="com">// register_globals =ON</span><span class="pln"></span><span style="color: #880000;" class="com">//foo.php?GLOBALS[foobar]=HELLO</span><span class="pln">php echo $foobar</span><span style="color: #666600;" class="pun">;</span><span class="pln"> </span><span style="color: #666600;" class="pun">?></span>
但是很多的程序沒有考慮到這點(diǎn),請看如下代碼:
<span style="color: #880000;" class="com">//為了安全取消全局變量</span><span class="pln"></span><span style="color: #880000;" class="com">//var.php?GLOBALS[a]=aaaa&b=111</span><span class="pln"></span><span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(</span><span class="pln">ini_get</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'register_globals'</span><span style="color: #666600;" class="pun">))</span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_REQUEST </span><span style="color: #000088;" class="kwd">as</span><span class="pln"> $k</span><span style="color: #666600;" class="pun">=></span><span class="pln">$v</span><span style="color: #666600;" class="pun">)</span><span class="pln"> unset</span><span style="color: #666600;" class="pun">(</span><span class="pln">$</span><span style="color: #666600;" class="pun">{</span><span class="pln">$k</span><span style="color: #666600;" class="pun">});</span><span class="pln"></span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $a</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $_GET</span><span style="color: #666600;" class="pun">[</span><span class="pln">b</span><span style="color: #666600;" class="pun">];</span>
如果熟悉WEB2.0的攻擊的同學(xué),很容易想到上面的代碼我們可以利用這個特性進(jìn)行crsf攻擊。
?
漏洞審計策略 |
PHP版本要求:無 系統(tǒng)要求:無 審計策略:通讀代碼 |
?
magic_quotes_gpc與代碼安全
?
什么是magic_quotes_gpc
當(dāng)打開時,所有的 '(單引號),"(雙引號),\(反斜線)和 NULL 字符都會被自動加上一個反斜線進(jìn)行轉(zhuǎn)義。還有很多函數(shù)有類似的作用 如:addslashes()、mysql_escape_string()、mysql_real_escape_string()等,另外還有parse_str()后的變量也受magic_quotes_gpc的影響。目前大多數(shù)的主機(jī)都打開了這個選項(xiàng),并且很多程序員也注意使用上面那些函數(shù)去過濾變量,這看上去很安全。很多漏洞查找者或者工具遇到些函數(shù)過濾后的變量直接就放棄,但是就在他們放棄的同時也放過很多致命的安全漏洞。 :)
哪些地方?jīng)]有魔術(shù)引號的保護(hù)
1) $_SERVER變量
PHP5的$_SERVER變量缺少magic_quotes_gpc的保護(hù),導(dǎo)致近年來X-Forwarded-For的漏洞猛暴,所以很多程序員考慮過濾X-Forwarded-For,但是其他的變量呢?
?
漏洞審計策略($_SERVER變量) |
PHP版本要求:無 系統(tǒng)要求:無 審計策略:查找字符_SERVER |
?
2) getenv()得到的變量(使用類似$_SERVER變量)
?
漏洞審計策略(getenv()) |
PHP版本要求:無 系統(tǒng)要求:無 審計策略:查找字符getenv |
?
3) $HTTP_RAW_POST_DATA與PHP輸入、輸出流
主要應(yīng)用與soap/xmlrpc/webpublish功能里,請看如下代碼:
<span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(</span><span style="color: #666600;" class="pun">!</span><span class="pln">isset</span><span style="color: #666600;" class="pun">(</span><span class="pln"> $HTTP_RAW_POST_DATA </span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? $HTTP_RAW_POST_DATA </span><span style="color: #666600;" class="pun">=</span><span class="pln"> file_get_contents</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'php://input'</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(</span><span class="pln"> isset</span><span style="color: #666600;" class="pun">(</span><span class="pln">$HTTP_RAW_POST_DATA</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">)</span><span class="pln">? ? ? ? $HTTP_RAW_POST_DATA </span><span style="color: #666600;" class="pun">=</span><span class="pln"> trim</span><span style="color: #666600;" class="pun">(</span><span class="pln">$HTTP_RAW_POST_DATA</span><span style="color: #666600;" class="pun">);</span>
?
漏洞審計策略(數(shù)據(jù)流) |
PHP版本要求:無 系統(tǒng)要求:無 審計策略:查找字符HTTP_RAW_POST_DATA或者php://input |
?
4) 數(shù)據(jù)庫操作容易忘記'的地方如:in()/limit/order by/group by
如Discuz!<5.0的pm.php:
<span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(</span><span class="pln">is_array</span><span style="color: #666600;" class="pun">(</span><span class="pln">$msgtobuddys</span><span style="color: #666600;" class="pun">))</span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? $msgto </span><span style="color: #666600;" class="pun">=</span><span class="pln"> array_merge</span><span style="color: #666600;" class="pun">(</span><span class="pln">$msgtobuddys</span><span style="color: #666600;" class="pun">,</span><span class="pln"> array</span><span style="color: #666600;" class="pun">(</span><span class="pln">$msgtoid</span><span style="color: #666600;" class="pun">));</span><span class="pln">? ? ? ? ? ? ? ? </span><span style="color: #666600;" class="pun">......</span><span class="pln"></span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$msgto </span><span style="color: #000088;" class="kwd">as</span><span class="pln"> $uid</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? $uids </span><span style="color: #666600;" class="pun">.=</span><span class="pln"> $comma</span><span style="color: #666600;" class="pun">.</span><span class="pln">$uid</span><span style="color: #666600;" class="pun">;</span><span class="pln">? ? ? ? $comma </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">','</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #666600;" class="pun">......</span><span class="pln">$query </span><span style="color: #666600;" class="pun">=</span><span class="pln"> $db</span><span style="color: #666600;" class="pun">-></span><span class="pln">query</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">"SELECT m.username, mf.ignorepm FROM {$tablepre}members m? ? ? ? LEFT JOIN {$tablepre}memberfields mf USING(uid)? ? ? ? WHERE m.uid IN ($uids)"</span><span style="color: #666600;" class="pun">);</span>
?
漏洞審計策略 |
PHP版本要求:無 系統(tǒng)要求:無 審計策略:查找數(shù)據(jù)庫操作字符(select,update,insert等等) |
?
變量的編碼與解碼
一個WEB程序很多功能的實(shí)現(xiàn)都需要變量的編碼解碼,而且就在這一轉(zhuǎn)一解的傳遞過程中就悄悄的繞過你的過濾的安全防線。
這個類型的主要函數(shù)有:
1) stripslashes() 這個其實(shí)就是一個decode-addslashes()
2) 其他字符串轉(zhuǎn)換函數(shù):
?
base64_decode | 對使用 MIME base64 編碼的數(shù)據(jù)進(jìn)行解碼 |
base64_encode | 使用 MIME base64 對數(shù)據(jù)進(jìn)行編碼 |
rawurldecode | 對已編碼的 URL 字符串進(jìn)行解碼 |
rawurlencode | 按照 RFC 1738 對 URL 進(jìn)行編碼 |
urldecode | 解碼已編碼的 URL 字符串 |
urlencode | 編碼 URL 字符串 |
... | ... |
?
另外一個 unserialize/serialize
3) 字符集函數(shù)(GKB,UTF7/8...)如iconv()/mb_convert_encoding()等
目前很多漏洞挖掘者開始注意這一類型的漏洞了,如典型的urldecode:
<span class="pln">$sql </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">"SELECT * FROM article WHERE articleid='"</span><span style="color: #666600;" class="pun">.</span><span class="pln">urldecode</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">[</span><span class="pln">id</span><span style="color: #666600;" class="pun">]).</span><span style="color: #008800;" class="str">"'"</span><span style="color: #666600;" class="pun">;</span>
當(dāng)magic_quotes_gpc=on時,我們提交?id=%2527,得到sql語句為:
<span class="pln">SELECT </span><span style="color: #666600;" class="pun">*</span><span class="pln"> FROM article WHERE articleid</span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'''</span>
?
漏洞審計策略 |
PHP版本要求:無 系統(tǒng)要求:無 審計策略:查找對應(yīng)的編碼函數(shù) |
?
二次攻擊
詳細(xì)見附錄[1]
1)數(shù)據(jù)庫出來的變量沒有進(jìn)行過濾
2)數(shù)據(jù)庫的轉(zhuǎn)義符號:
- mysql/oracle轉(zhuǎn)義符號同樣是\(我們提交'通過魔術(shù)引號變化為\',當(dāng)我們update進(jìn)入數(shù)據(jù)庫時,通過轉(zhuǎn)義變?yōu)?)
- mssql的轉(zhuǎn)義字符為'(所以我們提交'通過魔術(shù)引號變化為\',mssql會把它當(dāng)為一個字符串直接處理,所以魔術(shù)引號對于mssql的注射沒有任何意義)
從這里我們可以思考得到一個結(jié)論:一切進(jìn)入函數(shù)的變量都是有害的,另外利用二次攻擊我們可以實(shí)現(xiàn)一個webrootkit,把我們的惡意構(gòu)造直接放到數(shù)據(jù)庫里。我們應(yīng)當(dāng)把這樣的代碼看成一個vul?
?
漏洞審計策略 |
PHP版本要求:無 系統(tǒng)要求:無 審計策略:通讀代碼 |
?
魔術(shù)引號帶來的新的安全問題
首先我們看下魔術(shù)引號的處理機(jī)制:
<span style="color: #666600;" class="pun">[\-->\\,</span><span style="color: #008800;" class="str">'-->\',"-->\",null-->\0]</span>
這給我們引進(jìn)了一個非常有用的符號“\”,“\”符號不僅僅是轉(zhuǎn)義符號,在WIN系統(tǒng)下也是目錄轉(zhuǎn)跳的符號。這個特點(diǎn)可能導(dǎo)致php應(yīng)用程序里產(chǎn)生非常有意思的漏洞:
1)得到原字符(',\,",null])
<span class="pln">$order_sn</span><span style="color: #666600;" class="pun">=</span><span class="pln">substr</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'order_sn'</span><span style="color: #666600;" class="pun">],</span><span style="color: #006666;" class="lit">1</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #880000;" class="com">//提交 ? ? ? ? ? ? ? ? '</span><span class="pln"></span><span style="color: #880000;" class="com">//魔術(shù)引號處理 ? ? ? ? \'</span><span class="pln"></span><span style="color: #880000;" class="com">//substr ? ? ? ? ? ? ? '</span><span class="pln">$sql </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">"SELECT order_id, order_status, shipping_status, pay_status, "</span><span style="color: #666600;" class="pun">.</span><span class="pln">? ?</span><span style="color: #008800;" class="str">" shipping_time, shipping_id, invoice_no, user_id "</span><span style="color: #666600;" class="pun">.</span><span class="pln">? ?</span><span style="color: #008800;" class="str">" FROM "</span><span style="color: #666600;" class="pun">.</span><span class="pln"> $ecs</span><span style="color: #666600;" class="pun">-></span><span class="pln">table</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'order_info'</span><span style="color: #666600;" class="pun">).</span><span class="pln">? ?</span><span style="color: #008800;" class="str">" WHERE order_sn = '$order_sn' LIMIT 1"</span><span style="color: #666600;" class="pun">;</span>
2)得到“\”字符
<span class="pln">$order_sn</span><span style="color: #666600;" class="pun">=</span><span class="pln">substr</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'order_sn'</span><span style="color: #666600;" class="pun">],</span><span style="color: #006666;" class="lit">0</span><span style="color: #666600;" class="pun">,</span><span style="color: #006666;" class="lit">1</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #880000;" class="com">//提交 ? ? ? ? ? ? ? ? '</span><span class="pln"></span><span style="color: #880000;" class="com">//魔術(shù)引號處理 ? ? ? ? \'</span><span class="pln"></span><span style="color: #880000;" class="com">//substr ? ? ? ? ? ? ? \ ? ?</span><span class="pln">$sql </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">"SELECT order_id, order_status, shipping_status, pay_status, "</span><span style="color: #666600;" class="pun">.</span><span class="pln">? ?</span><span style="color: #008800;" class="str">" shipping_time, shipping_id, invoice_no, user_id "</span><span style="color: #666600;" class="pun">.</span><span class="pln">? ?</span><span style="color: #008800;" class="str">" FROM "</span><span style="color: #666600;" class="pun">.</span><span class="pln"> $ecs</span><span style="color: #666600;" class="pun">-></span><span class="pln">table</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'order_info'</span><span style="color: #666600;" class="pun">).</span><span class="pln">? ?</span><span style="color: #008800;" class="str">" WHERE order_sn = '$order_sn' and order_tn='"</span><span style="color: #666600;" class="pun">.</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'order_tn'</span><span style="color: #666600;" class="pun">].</span><span style="color: #008800;" class="str">"'"</span><span style="color: #666600;" class="pun">;</span>
提交內(nèi)容:
<span style="color: #666600;" class="pun">?</span><span class="pln">order_sn</span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'&order_tn=%20and%201=1/* </span>
執(zhí)行的SQL語句為:
<span class="pln">SELECT order_id</span><span style="color: #666600;" class="pun">,</span><span class="pln"> order_status</span><span style="color: #666600;" class="pun">,</span><span class="pln"> shipping_status</span><span style="color: #666600;" class="pun">,</span><span class="pln"> pay_status</span><span style="color: #666600;" class="pun">,</span><span class="pln"> shipping_time</span><span style="color: #666600;" class="pun">,</span><span class="pln"> shipping_id</span><span style="color: #666600;" class="pun">,</span><span class="pln"> invoice_no</span><span style="color: #666600;" class="pun">,</span><span class="pln"> user_id FROM order_info WHERE order_sn </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'\' and order_tn='</span><span style="color: #000088;" class="kwd">and</span><span style="color: #006666;" class="lit">1</span><span style="color: #666600;" class="pun">=</span><span style="color: #006666;" class="lit">1</span><span style="color: #880000;" class="com">/*'</span>
?
漏洞審計策略 |
PHP版本要求:無 系統(tǒng)要求:無 審計策略:查找字符串處理函數(shù)如substr或者通讀代碼 |
?
變量key與魔術(shù)引號
我們最在這一節(jié)的開頭就提到了變量key,PHP的魔術(shù)引號對它有什么影響呢?
<span style="color: #666600;" class="pun"><?</span><span class="pln">php</span><span style="color: #880000;" class="com">//key.php?aaaa'aaa=1&bb'b=2 </span><span class="pln"></span><span style="color: #880000;" class="com">//print_R($_GET); </span><span class="pln">?</span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET AS $key </span><span style="color: #666600;" class="pun">=></span><span class="pln"> $value</span><span style="color: #666600;" class="pun">)</span><span class="pln">? ? ? ? </span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? </span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $key</span><span style="color: #666600;" class="pun">.</span><span style="color: #008800;" class="str">"\n"</span><span style="color: #666600;" class="pun">;</span><span class="pln">? ? ? ? </span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #666600;" class="pun">?></span>
1)當(dāng)magic_quotes_gpc = On時,在php5.24下測試顯示:
<span class="pln">aaaa</span><span style="color: #666600;" class="pun">\</span><span style="color: #008800;" class="str">'aaabb\'b</span>
從上面結(jié)果可以看出來,在設(shè)置了magic_quotes_gpc = On下,變量key受魔術(shù)引號影響。但是在php4和php<5.2.1的版本中,不處理數(shù)組第一維變量的key,測試代碼如下:
<span style="color: #666600;" class="pun"><?</span><span class="pln">php</span><span style="color: #880000;" class="com">//key.php?aaaa'aaa[bb']=1 </span><span class="pln">print_R</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">);</span><span class="pln"> </span><span style="color: #666600;" class="pun">?></span>
結(jié)果顯示:
<span style="color: #660066;" class="typ">Array</span><span style="color: #666600;" class="pun">(</span><span style="color: #666600;" class="pun">[</span><span class="pln">aaaa</span><span style="color: #008800;" class="str">'aaa] => Array ( [bb\'] => 1 ) ) </span>
數(shù)組第一維變量的key不受魔術(shù)引號的影響。
?
漏洞審計策略 |
PHP版本要求:php4和php<5.2.1 系統(tǒng)要求:無 審計策略:通讀代碼 |
?
2)當(dāng)magic_quotes_gpc = Off時,在php5.24下測試顯示:
<span class="pln">aaaa</span><span style="color: #008800;" class="str">'aaabb'</span><span class="pln">b</span>
對于magic_quotes_gpc = Off時所有的變量都是不安全的,考慮到這個,很多程序都通過addslashes等函數(shù)來實(shí)現(xiàn)魔術(shù)引號對變量的過濾,示例代碼如下:
<span style="color: #666600;" class="pun"><?</span><span class="pln">php </span><span style="color: #880000;" class="com">//keyvul.php?aaa'aa=1'</span><span class="pln"></span><span style="color: #880000;" class="com">//magic_quotes_gpc = Off</span><span class="pln">?</span><span style="color: #000088;" class="kwd">if</span><span style="color: #666600;" class="pun">(!</span><span class="pln">get_magic_quotes_gpc</span><span style="color: #666600;" class="pun">())</span><span class="pln"></span><span style="color: #666600;" class="pun">{</span><span class="pln">?$_GET ?</span><span style="color: #666600;" class="pun">=</span><span class="pln"> addslashes_array</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #000088;" class="kwd">function</span><span class="pln"> addslashes_array</span><span style="color: #666600;" class="pun">(</span><span class="pln">$value</span><span style="color: #666600;" class="pun">)</span><span class="pln"></span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? </span><span style="color: #000088;" class="kwd">return</span><span class="pln"> is_array</span><span style="color: #666600;" class="pun">(</span><span class="pln">$value</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">?</span><span class="pln"> array_map</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'addslashes_array'</span><span style="color: #666600;" class="pun">,</span><span class="pln"> $value</span><span style="color: #666600;" class="pun">)</span><span style="color: #666600;" class="pun">:</span><span class="pln"> addslashes</span><span style="color: #666600;" class="pun">(</span><span class="pln">$value</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln">print_R</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">);</span><span class="pln"></span><span style="color: #000088;" class="kwd">foreach</span><span style="color: #666600;" class="pun">(</span><span class="pln">$_GET AS $key </span><span style="color: #666600;" class="pun">=></span><span class="pln"> $value</span><span style="color: #666600;" class="pun">)</span><span class="pln"></span><span style="color: #666600;" class="pun">{</span><span class="pln">? ? ? ? </span><span style="color: #000088;" class="kwd">print</span><span class="pln"> $key</span><span style="color: #666600;" class="pun">;</span><span class="pln"></span><span style="color: #666600;" class="pun">}</span><span class="pln"></span><span style="color: #666600;" class="pun">?></span>
以上的代碼看上去很完美,但是他這個代碼里addslashes($value)只處理了變量的具體的值,但是沒有處理變量本身的key,上面的代碼顯示結(jié)果如下:
<span style="color: #660066;" class="typ">Array</span><span class="pln"></span><span style="color: #666600;" class="pun">(</span><span class="pln">? ? </span><span style="color: #666600;" class="pun">[</span><span class="pln">aaa</span><span style="color: #008800;" class="str">'aa] => 1\')aaa'</span><span class="pln">aa</span>
?
漏洞審計策略 |
PHP版本要求:無 系統(tǒng)要求:無 審計策略:通讀代碼 |
?
代碼注射
PHP中可能導(dǎo)致代碼注射的函數(shù)
很多人都知道eval、preg_replace+/e可以執(zhí)行代碼,但是不知道php還有很多的函數(shù)可以執(zhí)行代碼如:
?
assert() |
call_user_func() |
call_user_func_array() |
create_function() |
變量函數(shù) |
... |
?
這里我們看看最近出現(xiàn)的幾個關(guān)于create_function()代碼執(zhí)行漏洞的代碼:
<span style="color: #666600;" class="pun"></span><span class="pln">php</span><span style="color: #880000;" class="com">//how to exp this code</span><span class="pln">$sort_by</span><span style="color: #666600;" class="pun">=</span><span class="pln">$_GET</span><span style="color: #666600;" class="pun">[</span><span style="color: #008800;" class="str">'sort_by'</span><span style="color: #666600;" class="pun">];</span><span class="pln">$sorter</span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">'strnatcasecmp'</span><span style="color: #666600;" class="pun">;</span><span class="pln">$databases</span><span style="color: #666600;" class="pun">=</span><span class="pln">array</span><span style="color: #666600;" class="pun">(</span><span style="color: #008800;" class="str">'test'</span><span style="color: #666600;" class="pun">,</span><span style="color: #008800;" class="str">'test'</span><span style="color: #666600;" class="pun">);</span><span class="pln">$sort_function </span><span style="color: #666600;" class="pun">=</span><span style="color: #008800;" class="str">' ?return 1 * '</span><span style="color: #666600;" class="pun">.</span><span class="pln"> $sorter </span><span style="color: #666600;" class="pun">.</span><span style="color: #008800;" class="str">'($a["'</span><span style="color: #666600;" class="pun">.</span><span class="pln"> $sort_by </span><span style="color: #666600;" class="pun">.</span><span style="color: #008800;" class="str">'"], $b["'</span><span style="color: #666600;" class="pun">.</span><span class="pln"> $sort_by </span><span style="color: #666600;" class="pun">.</span><span style></span>