PHP安全-函數(shù)
在我寫(xiě)作本書(shū)的時(shí)候,http://php.net/quickref.php列出了共3917個(gè)函數(shù),其中包括一些類似函數(shù)的語(yǔ)法結(jié)構(gòu),在此我不準(zhǔn)備把它們從函數(shù)中區(qū)分開(kāi)來(lái),而是把它作為函數(shù)看待。
由于函數(shù)數(shù)量很大,一一說(shuō)明它們的正確及安全用法是不太可能的。在此我選出了我認(rèn)為最需要注意的函數(shù)。選擇的標(biāo)準(zhǔn)包括使用的頻繁度、使用時(shí)的危險(xiǎn)(安全)度及我本人的經(jīng)驗(yàn)。
對(duì)于每一個(gè)列出的函數(shù),我都會(huì)提供推薦的使用方法。在提出這些方法時(shí),我會(huì)把安全作為重點(diǎn)考慮。請(qǐng)?jiān)趯?shí)際使用時(shí)根據(jù)你的需求進(jìn)行相應(yīng)調(diào)整。
當(dāng)一個(gè)函數(shù)與另一個(gè)有相同的風(fēng)險(xiǎn)時(shí),我會(huì)給出參見(jiàn)另一個(gè)函數(shù)的信息,而不是多余地再次描述一遍。
B.1. eval( )
eval( )函數(shù)用于對(duì)一個(gè)字符串以PHP語(yǔ)句方式解析運(yùn)行。如:
<?php
$name = ’Chris’;
$string = ’echo 'Hello, $name';’;
eval($string);
?>
上例中會(huì)把$string作為PHP語(yǔ)句來(lái)運(yùn)行,因此等價(jià)于:
<?php
$name = ’Chris’;
echo 'Hello, $name';
?>
雖然eval( )非常有用,但是當(dāng)使用了被污染數(shù)據(jù)時(shí)會(huì)非常危險(xiǎn)。例如,在下例中,如果$name是被污染的,攻擊者可以任意運(yùn)行PHP代碼:
<?php
$name = $_GET[’name’];
eval($name);
?>
當(dāng)你無(wú)法確信以PHP方式解釋的字符串是否使用被污染數(shù)據(jù)時(shí),以及在可能的情況下,我推薦你避免使用eval( )。在安全審查和同行評(píng)審中,應(yīng)重點(diǎn)檢查該函數(shù)。
B.2. exec( )
第6章中已提到,執(zhí)行shell命令是非常危險(xiǎn)的操作,在構(gòu)造shell命令時(shí)使用被污染數(shù)據(jù)會(huì)導(dǎo)致命令注入漏洞。
盡量避免使用shell命令函數(shù),但當(dāng)你需要用它們時(shí),請(qǐng)確信構(gòu)造shell命令時(shí)只使用過(guò)濾及轉(zhuǎn)義過(guò)的數(shù)據(jù)。
<?php
$clean = array();
$shell = array();
/* Filter Input ($command, $argument) */
$shell[’command’] = escapeshellcmd($clean[’command’]);
$shell[’argument’] = escapeshellarg($clean[’argument’]);
$last = exec('{$shell[’command’]} {$shell[’argument’]}', $output, $return);
?>
B.3. file( )
file( )函數(shù)是我喜歡使用的讀文件方法之一。它會(huì)讀取文件的每一行作為返回?cái)?shù)組的元素。特別方便的一點(diǎn)是,你不需要提供一個(gè)文件句柄——你提供文件名,它會(huì)為你做好一切:
<?php
$contents = file(’/tmp/file.txt’);
print_r($contents);
?>
如果上面的文件有兩行,則會(huì)產(chǎn)生類似如下的輸出:
Array
(
[0] => This is line one.
[1] => This is line two.
)
使用file( )函數(shù)不是特別危險(xiǎn),但當(dāng)你在allow_url_fopen選項(xiàng)打開(kāi)的情況下使用時(shí),它就能讀取許多不同類型的資源如一個(gè)遠(yuǎn)程網(wǎng)站的內(nèi)容:
<?php
$contents = file(’http://example.org/’);
print_r($contents);
?>
輸出如下 (有刪節(jié)):
Array
(
[0] => <html>
[1] => <head>
[2] => <title>Example Web Page</title>
[3] => </head>
[4] => <body>
...
[11] => </body>
[12] => </html>
)
如果file()函數(shù)調(diào)用的文件名是由被污染數(shù)據(jù)構(gòu)造的,則其內(nèi)容也應(yīng)被看成是被污染的。這是因?yàn)槭褂帽晃廴緮?shù)據(jù)構(gòu)造文件名可能會(huì)導(dǎo)致你打開(kāi)一個(gè)有惡意數(shù)據(jù)的遠(yuǎn)程網(wǎng)站。一旦你把數(shù)據(jù)保存在一個(gè)變量中,危險(xiǎn)就大幅增加了:
<?php
$tainted = file($_POST[’filename’]);
?>
$tainted數(shù)組中的每個(gè)元素與$_POST[’filename’]有相同的危險(xiǎn)性——它是輸入并必須要進(jìn)行過(guò)濾。
在這里,其行為有可能是意想不到的——$_POST[’filename’]的誤用可以改變file()函數(shù)的行為,因此它可以指向一個(gè)遠(yuǎn)程資源而不是本地文件。
B.4. file_get_contents( )
參見(jiàn) 'file( ).'
B.5. fopen( )
參見(jiàn) 'file( ).'
B.6. include
如第5章所述,include在組織化與模塊化的軟件設(shè)計(jì)中被普遍使用,是非常有必要的。但是,不正確的使用include會(huì)造成一個(gè)重大的代碼注入安全漏洞。
在include語(yǔ)句中只使用已過(guò)濾數(shù)據(jù)是非常有必要的。在安全審查和同行評(píng)審中,應(yīng)重點(diǎn)檢查該函數(shù)。
B.7. passthru( )
見(jiàn)'exec( ).'
B.8. phpinfo( )
phpinfo( )會(huì)輸出有關(guān)PHP信息的頁(yè)面——運(yùn)行的版本號(hào),配置信息等等。由于phpinfo( )的輸出提供了非常多的信息,我建議限制對(duì)任何使用該函數(shù)的資源的訪問(wèn)。
如果你使用的第八章中的技巧來(lái)保護(hù)數(shù)據(jù)庫(kù)驗(yàn)證信息,則需要確認(rèn)訪問(wèn)者不能看到由phpinfo( )形成的輸出信息,這是由于它會(huì)暴露超級(jí)全局?jǐn)?shù)組$_SERVER的內(nèi)容。
B.9. popen( )
參見(jiàn)'exec( ).'
B.10. preg_replace( )
preg_replace( )用于對(duì)符合正則表達(dá)式的字符串進(jìn)行替換。在某些情況下,使用被污染數(shù)據(jù)構(gòu)造正則表達(dá)式部分會(huì)非常危險(xiǎn),因?yàn)樗膃修飾符會(huì)導(dǎo)致在替換時(shí)把用于替換的參數(shù)作為PHP代碼來(lái)對(duì)待。例如(本例為譯者所加):
<?php
$str = 'abcdef';
$se = 'len';
$reg = '/abc/e';
echo preg_replace($reg,'strlen($se)',$str);
?>
會(huì)輸出如下字串:
3def
當(dāng)使用了e修飾符,不管是否有意為之,它會(huì)帶來(lái)與eval()相同的風(fēng)險(xiǎn)。在安全審查和同行評(píng)審中,應(yīng)重點(diǎn)檢查該函數(shù)。
B.11. proc_open( )
參見(jiàn) 'exec( ).'
B.12. readfile( )
參見(jiàn) 'file( ).'
B.13. require
參見(jiàn) 'include.'
B.14. shell_exec( )
參見(jiàn) 'exec( ).'
B.15. system( )
參見(jiàn) 'exec( ).'
相關(guān)文章:
1. idea導(dǎo)入maven項(xiàng)目的方法2. idea設(shè)置代碼格式化的方法步驟3. Spring+Http請(qǐng)求+HttpClient實(shí)現(xiàn)傳參4. PHP處理Ajax請(qǐng)求與Ajax跨域5. java構(gòu)建OAuth2授權(quán)服務(wù)器6. asp文件如何打開(kāi)7. ASP 信息提示函數(shù)并作返回或者轉(zhuǎn)向8. Java中的== 和equals()有什么方法實(shí)例9. PHP中為什么使用file_get_contents("php://input")接收微信通知10. IntelliJ IDEA 2020.3通過(guò)重命名內(nèi)聯(lián)重構(gòu)代碼
