- 代碼審計(jì):企業(yè)級(jí)Web代碼安全架構(gòu)
- 尹毅
- 2652字
- 2018-12-31 21:29:43
1.3 PHP核心配置詳解
代碼在不同環(huán)境下執(zhí)行的結(jié)果也會(huì)大有不同,可能就因?yàn)橐粋€(gè)配置問(wèn)題,導(dǎo)致一個(gè)非常高危的漏洞能夠利用;也可能你已經(jīng)找到的一個(gè)漏洞就因?yàn)槟愕呐渲脝?wèn)題,導(dǎo)致你鼓搗很久都無(wú)法構(gòu)造成功的漏洞利用代碼。然而,在不同的PHP版本中配置指令也有不一樣的地方,新的版本可能會(huì)增加或者刪除部分指令,改變指令默認(rèn)設(shè)置或者固定設(shè)置指令,因此我們?cè)诖a審計(jì)之前必須要非常熟悉PHP各個(gè)版本中配置文件的核心指令,才能更高效地挖掘到高質(zhì)量的漏洞。
我們?cè)陂喿xPHP官方配置說(shuō)明(http://www.php.net/manual/zh/ini.list.php)之前需要了解幾個(gè)定義值,即PHP_INI_*常量的定義,參見(jiàn)表1-1。
表1-1 PHP_INI_*常量的定義

PHP配置文件指令多達(dá)數(shù)百項(xiàng),為了節(jié)省篇幅,這里不一一對(duì)每個(gè)指令進(jìn)行說(shuō)明,只列出會(huì)影響PHP腳本安全的配置列表以及核心配置選項(xiàng)。
1.register_globals(全局變量注冊(cè)開(kāi)關(guān))
該選項(xiàng)在設(shè)置為on的情況下,會(huì)直接把用戶(hù)GET、POST等方式提交上來(lái)的參數(shù)注冊(cè)成全局變量并初始化值為參數(shù)對(duì)應(yīng)的值,使得提交參數(shù)可以直接在腳本中使用。register_globals在 PHP版本小于等于4.2.3時(shí)設(shè)置為PHP_INI_ALL,從 PHP 5.3.0 起被廢棄,不推薦使用,在PHP 5.4.0中移除了該選項(xiàng)。
當(dāng)register_globals設(shè)置為on且PHP版本低于5.4.0時(shí),如下代碼輸出結(jié)果為true。
測(cè)試代碼:
<?php if($user=='admin') { echo 'true'; //do something }
執(zhí)行結(jié)果如圖1-6所示。

圖1-6
2.allow_url_include(是否允許包含遠(yuǎn)程文件)
這個(gè)配置指令對(duì)PHP安全的影響不可小覷。在該配置為on的情況下,它可以直接包含遠(yuǎn)程文件,當(dāng)存在include ($var)且$var可控的情況下,可以直接控制$var變量來(lái)執(zhí)行PHP代碼。allow_url_include在PHP 5.2.0后默認(rèn)設(shè)置為off,配置范圍是PHP_INI_ALL。與之類(lèi)似的配置有allow_url_fopen,配置是否允許打開(kāi)遠(yuǎn)程文件,不過(guò)該參數(shù)對(duì)安全的影響沒(méi)有allow_url_include大,故這里不詳細(xì)介紹。
配置allow_url_include為on,可以直接包含遠(yuǎn)程文件。測(cè)試代碼如下:
<?php include $_GET['a'];
測(cè)試截圖如圖1-7所示。

圖1-7
3.magic_quotes_gpc(魔術(shù)引號(hào)自動(dòng)過(guò)濾)
magic_quotes_gpc在安全方面做了很大的貢獻(xiàn),只要它被開(kāi)啟,在不存在編碼或者其他特殊繞過(guò)的情況下,可以使得很多漏洞無(wú)法被利用,它也是讓滲透測(cè)試人員很頭疼的一個(gè)東西。當(dāng)該選項(xiàng)設(shè)置為on時(shí),會(huì)自動(dòng)在GET、POST、COOKIE變量中的單引號(hào)(')、雙引號(hào)(")、反斜杠(\)及空字符(NULL)的前面加上反斜杠(\),但是在PHP 5中magic_quotes_gpc并不會(huì)過(guò)濾$_SERVER變量,導(dǎo)致很多類(lèi)似client-ip、referer一類(lèi)的漏洞能夠利用。在PHP 5.3之后的不推薦使用magic_quotes_gpc,PHP 5.4之后干脆被取消,所以你下載PHP 5.4之后的版本并打開(kāi)配置文件會(huì)發(fā)現(xiàn)找不到這個(gè)配置選項(xiàng)。在PHP版本小于4.2.3時(shí),配置范圍是PHP_INI_ALL;在PHP版本大于4.2.3時(shí),是PHP_INI_PERDIR。
測(cè)試代碼如下:
<?php echo $_GET['seay'];
測(cè)試結(jié)果如圖1-8所示。

圖1-8
4.magic_quotes_runtime(魔術(shù)引號(hào)自動(dòng)過(guò)濾)
magic_quotes_runtime也是自動(dòng)在單引號(hào)(')、雙引號(hào)(")、反斜杠(\)及空字符(NULL)的前面加上反斜杠(\)。它跟magic_quotes_gpc的區(qū)別是,處理的對(duì)象不一樣,magic_quotes_runtime只對(duì)從數(shù)據(jù)庫(kù)或者文件中獲取的數(shù)據(jù)進(jìn)行過(guò)濾,它的作用也非常大,因?yàn)楹芏喑绦騿T只對(duì)外部輸入的數(shù)據(jù)進(jìn)行過(guò)濾,卻沒(méi)有想過(guò)從數(shù)據(jù)庫(kù)獲取的數(shù)據(jù)同樣也會(huì)有特殊字符存在,所以攻擊者的做法是先將攻擊代碼寫(xiě)入數(shù)據(jù)庫(kù),在程序讀取、使用到被污染的數(shù)據(jù)后即可觸發(fā)攻擊。同樣,magic_quotes_runtime在PHP 5.4之后也被取消,配置范圍是PHP_INI_ALL。
有一個(gè)點(diǎn)要記住,只有部分函數(shù)受它的影響,所以在某些情況下這個(gè)配置是可以繞過(guò)的,受影響的列表包括get_meta_tags()、file_get_contents()、file()、fgets()、fwrite()、fread()、fputcsv()、stream_socket_recvfrom()、exec()、system()、passthru()、stream_get_contents()、bzread()、gzf ile()、gzgets()、gzwrite()、gzread()、exif_read_data()、dba_insert()、dba_replace()、dba_fetch()、ibase_fetch_row()、ibase_fetch_assoc()、ibase_fetch_object()、mssql_fetch_row()、mssql_fetch_object()、mssql_fetch_array()、mssql_fetch_assoc()、mysqli_fetch_row()、mysqli_fetch_array()、mysqli_fetch_assoc()、mysqli_fetch_object()、pg_fetch_row()、pg_fetch_assoc()、pg_fetch_array()、pg_fetch_object()、pg_fetch_all()、pg_select()、sybase_fetch_object()、sybase_fetch_array()、sybase_fetch_assoc()、SplFileObject::fgets()、SplFileObject::fgetcsv()、SplFileObject::fwrite()。
測(cè)試代碼如下:
#文件1.txt 1'2"3\4 #文件1.php <?php ini_set("magic_quotes_runtime", "1"); echo file_get_contents("1.txt");
測(cè)試結(jié)果如圖1-9所示。

圖1-9
5.magic_quotes_sybase(魔術(shù)引號(hào)自動(dòng)過(guò)濾)
magic_quotes_sybase指令用于自動(dòng)過(guò)濾特殊字符,當(dāng)設(shè)置為on時(shí),它會(huì)覆蓋掉magic_quotes_gpc=on的配置,也就是說(shuō),即使配置了gpc=on也是沒(méi)有效果的。這個(gè)指令與gpc的共同點(diǎn)是處理的對(duì)象一致,即都對(duì)GET、POST、Cookie進(jìn)行處理。而它們之前的區(qū)別在于處理方式不一樣,magic_quotes_sybase僅僅是轉(zhuǎn)義了空字符和把單引號(hào)(')變成了雙引號(hào)('')。與gpc相比,這個(gè)指令使用得更少,它的配置范圍是PHP_INI_ALL,在PHP 5.4.0中移除了該選項(xiàng)。
測(cè)試代碼如下:
<?php echo $_GET['a']; ?>
執(zhí)行結(jié)果如圖1-10所示。

圖1-10
6.safe_mode(安全模式)
安全模式是PHP內(nèi)嵌的一種安全機(jī)制,當(dāng)safe_mode=on時(shí),聯(lián)動(dòng)可以配置的指令有safe_mode_include_dir、safe_mode_exec_dir、safe_mode_allowed_env_vars、safe_mode_protected_env_vars。safe_mode指令的配置范圍為PHP_INI_SYSTEM,PHP 5.4之后被取消。
這個(gè)配置會(huì)出現(xiàn)下面限制:
1)所有文件操作函數(shù)(例如unlink()、file()和include())等都會(huì)受到限制。例如,文件a.php和文件c.txt的文件所有者是用戶(hù)a,文件b.txt的所有者是用戶(hù)b并且與文件a.php不在屬于同一個(gè)用戶(hù)的文件夾中,當(dāng)啟用了安全模式時(shí),使用a用戶(hù)執(zhí)行a.php,刪除文件c.txt可成功刪除,但是刪除文件b.php會(huì)失敗。對(duì)文件操作的include等函數(shù)也一樣,如果有一些腳本文件放在非Web服務(wù)啟動(dòng)用戶(hù)所有的目錄下,需要利用include等函數(shù)來(lái)加載一些類(lèi)或函數(shù),可以使用safe_mode_include_dir指令來(lái)配置可以包含的路徑。
2)通過(guò)函數(shù)popen()、system()以及exec()等函數(shù)執(zhí)行命令或程序會(huì)提示錯(cuò)誤。如果我們需要使用一些外部腳本,可以把它們集中放在一個(gè)目錄下,然后使用safe_mode_exec_dir指令指向腳本的目錄。
下面是啟用safe_mode指令時(shí)受影響的函數(shù)、變量及配置指令的完整列表:
apache_request_headers()、ackticks()、hdir()、hgrp()、chmode()、chown()、copy()、dbase_open()、dbmopen()、dl()、exec()、filepro()、filepro_retrieve()、ilepro_rowcount()、fopen()、header()、highlight_file()、ifx_*、ingres_*、link()、mail()、max_execution_time()、mkdir()、move_uploaded_file()、mysql_*、parse_ini_file()、passthru()、pg_lo_import()、popen()、posix_mkfifo()、putenv()、rename()、zmdir()、set_time_limit()、shell_exec()、show_source()、symlink()、system()、touch()。
安全模式下執(zhí)行命令失敗的提示,如圖1-11所示。

圖1-11
7.open_basedir PHP可訪問(wèn)目錄
open_basedir指令用來(lái)限制PHP只能訪問(wèn)哪些目錄,通常我們只需要設(shè)置Web文件目錄即可,如果需要加載外部腳本,也需要把腳本所在目錄路徑加入到open_basedir指令中,多個(gè)目錄以分號(hào)(;)分割。使用open_basedir需要注意的一點(diǎn)是,指定的限制實(shí)際上是前綴,而不是目錄名。例如,如果配置open_basedir =/www/a,那么目錄/www/a和/www/ab都是可以訪問(wèn)的。所以如果要將訪問(wèn)僅限制在指定的目錄內(nèi),請(qǐng)用斜線(xiàn)結(jié)束路徑名。例如設(shè)置成:open_basedir=/www/a/。
當(dāng)open_basedir配置目錄后,執(zhí)行腳本訪問(wèn)其他文件都需要驗(yàn)證文件路徑,因此在執(zhí)行效率上面也會(huì)有一定的影響。該指令的配置范圍在 PHP版本小于5.2.3時(shí)是PHP_INI_SYSTEM,在PHP版本大于等于5.2.3是PHP_INI_ALL。
8.disable_functions(禁用函數(shù))
在正式的生產(chǎn)環(huán)境中,為了更安全地運(yùn)行PHP,也可以使用disable_functions指令來(lái)禁止一些敏感函數(shù)的使用。當(dāng)你想用本指令禁止一些危險(xiǎn)函數(shù)時(shí),切記要把dl()函數(shù)也加到禁止列表,因?yàn)楣粽呖梢岳胐l()函數(shù)來(lái)加載自定義的PHP擴(kuò)展以突破disable_functions指令的限制。
本指令配置范圍為php.ini only。配置禁用函數(shù)時(shí)使用逗號(hào)分割函數(shù)名,例如:disable_functions=phpinfo,eval,passthru,exec,system。
9.display_errors和error_reporting錯(cuò)誤顯示
display_errors表明是否顯示PHP腳本內(nèi)部錯(cuò)誤的選項(xiàng),在調(diào)試PHP的時(shí)候,通常都把PHP錯(cuò)誤顯示打開(kāi),但是在生產(chǎn)環(huán)境中,建議關(guān)閉PHP錯(cuò)誤回顯,即設(shè)置display_errors=off,以避免帶來(lái)一些安全隱患。在設(shè)置display_errors=on時(shí),還可以配置的一個(gè)指令是error_reporting,這個(gè)選項(xiàng)用來(lái)配置錯(cuò)誤顯示的級(jí)別,可使用數(shù)字也可使用內(nèi)置常量配置,數(shù)字格式與常量格式的詳細(xì)信息如表1-2所示。
表1-2 數(shù)字格式與常量格式

這兩個(gè)指令的配置范圍都是PHP_INI_ALL。
會(huì)影響到安全的指令大致就介紹到這里,表1-3列出一些常用指令以及對(duì)應(yīng)的說(shuō)明。
表1-3 常用指令及說(shuō)明

- 數(shù)據(jù)恢復(fù)方法及案例分析
- Learning Python for Forensics
- Getting Started with FortiGate
- 黑客攻防與無(wú)線(xiàn)安全從新手到高手(超值版)
- 網(wǎng)絡(luò)安全三十六計(jì):人人該懂的防黑客技巧
- 軟件安全保障體系架構(gòu)
- 博弈論與數(shù)據(jù)安全
- 網(wǎng)絡(luò)安全實(shí)戰(zhàn)詳解(企業(yè)專(zhuān)供版)
- 網(wǎng)絡(luò)對(duì)抗的前世今生
- 商用密碼應(yīng)用與安全性評(píng)估
- 精通Metasploit滲透測(cè)試(第3版)
- 網(wǎng)站入侵與腳本技術(shù)快速防殺
- 網(wǎng)絡(luò)安全與維護(hù)
- Web安全與攻防實(shí)戰(zhàn)從新手到高手(微課超值版)
- 攜手構(gòu)建網(wǎng)絡(luò)空間命運(yùn)共同體