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

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

談?wù)勱P(guān)于PHP的代碼安全相關(guān)的一些致命知識

瀏覽:97日期:2022-09-14 09:51:44
目標(biāo)本教程講解如何防御最常見的安全威脅:SQL 注入、操縱 GET 和 POST 變量、緩沖區(qū)溢出攻擊、跨站點(diǎn)腳本攻擊、瀏覽器內(nèi)的數(shù)據(jù)操縱和遠(yuǎn)程表單提交。前提條件本教程是為至少有一年編程經(jīng)驗(yàn)的 PHP 開發(fā)人員編寫的。您應(yīng)該了解 PHP 的語法和約定;這里不解釋這些內(nèi)容。有使用其他語言(比如 Ruby、Python 和 Perl)的經(jīng)驗(yàn)的開發(fā)人員也能夠從本教程中受益,因?yàn)檫@里討論的許多規(guī)則也適用于其他語言和環(huán)境。安全性快速簡介Web 應(yīng)用程序最重要的部分是什么?根據(jù)回答問題的人不同,對這個問題的答案可能是五花八門。業(yè)務(wù)人員需要可靠性和可伸縮性。IT 支持團(tuán)隊(duì)需要健壯的可維護(hù)的代碼。最終用戶需要漂亮的用戶界面和執(zhí)行任務(wù)時的高性能。但是,如果回答 “安全性”,那么每個人都會同意這對 Web 應(yīng)用程序很重要。但是,大多數(shù)討論到此就打住了。盡管安全性在項(xiàng)目的檢查表中,但是往往到了項(xiàng)目交付之前才開始考慮解決安全性問題。采用這種方式的 Web 應(yīng)用程序項(xiàng)目的數(shù)量多得驚人。開發(fā)人員工作幾個月,只在最后才添加安全特性,從而讓 Web 應(yīng)用程序能夠向公眾開放。結(jié)果往往是一片混亂,甚至需要返工,因?yàn)榇a已經(jīng)經(jīng)過檢驗(yàn)、單元測試并集成為更大的框架,之后才在其中添加安全特性。添加安全性之后,主要組件可能會停止工作。安全性的集成使得原本順暢(但不安全)的過程增加額外負(fù)擔(dān)或步驟。本教程提供一種將安全性集成到 PHP Web 應(yīng)用程序中的好方法。它討論幾個一般性安全主題,然后深入討論主要的安全漏洞以及如何堵住它們。在學(xué)完本教程之后,您會對安全性有更好的理解。主題包括:SQL 注入攻擊操縱 GET 字符串緩沖區(qū)溢出攻擊跨站點(diǎn)腳本攻擊(XSS)瀏覽器內(nèi)的數(shù)據(jù)操縱遠(yuǎn)程表單提交Web 安全性 101在討論實(shí)現(xiàn)安全性的細(xì)節(jié)之前,最好從比較高的角度討論 Web 應(yīng)用程序安全性。本節(jié)介紹安全哲學(xué)的一些基本信條,無論正在創(chuàng)建何種 Web 應(yīng)用程序,都應(yīng)該牢記這些信條。這些思想的一部分來自 Chris Shiflett(他關(guān)于 PHP 安全性的書是無價的寶庫),一些來自 Simson Garfinkel(參見 參考資料),還有一些來自多年積累的知識。規(guī)則 1:絕不要信任外部數(shù)據(jù)或輸入關(guān)于 Web 應(yīng)用程序安全性,必須認(rèn)識到的第一件事是不應(yīng)該信任外部數(shù)據(jù)。外部數(shù)據(jù)(outside data) 包括不是由程序員在 PHP 代碼中直接輸入的任何數(shù)據(jù)。在采取措施確保安全之前,來自任何其他來源(比如 GET 變量、表單 POST、數(shù)據(jù)庫、配置文件、會話變量或 cookie)的任何數(shù)據(jù)都是不可信任的。例如,下面的數(shù)據(jù)元素可以被認(rèn)為是安全的,因?yàn)樗鼈兪窃?PHP 中設(shè)置的。清單 1. 安全無暇的代碼 [php]$myUsername = ‘tmyer’;$arrayUsers = array(’tmyer’, ‘tom’, ‘tommy’);define(”GREETING”, ‘hello there’ . $myUsername); [/php]但是,下面的數(shù)據(jù)元素都是有瑕疵的。清單 2. 不安全、有瑕疵的代碼 [php]$myUsername = $_POST[’username’]; //tainted!$arrayUsers = array($myUsername, ‘tom’, ‘tommy’); //tainted!define(”GREETING”, ‘hello there’ . $myUsername); //tainted! [/php]為什么第一個變量 $myUsername 是有瑕疵的?因?yàn)樗苯觼碜员韱?POST。用戶可以在這個輸入域中輸入任何字符串,包括用來清除文件或運(yùn)行以前上傳的文件的惡意命令。您可能會問,“難道不能使用只接受字母 A-Z 的客戶端(JavaScript)表單檢驗(yàn)?zāi)_本來避免這種危險嗎?”是的,這總是一個有好處的步驟,但是正如在后面會看到的,任何人都可以將任何表單下載到自己的機(jī)器上,修改它,然后重新提交他們需要的任何內(nèi)容。解決方案很簡單:必須對 $_POST[’username’] 運(yùn)行清理代碼。如果不這么做,那么在使用 $myUsername 的任何其他時候(比如在數(shù)組或常量中),就可能污染這些對象。對用戶輸入進(jìn)行清理的一個簡單方法是,使用正則表達(dá)式來處理它。在這個示例中,只希望接受字母。將字符串限制為特定數(shù)量的字符,或者要求所有字母都是小寫的,這可能也是個好主意。清單 3. 使用戶輸入變得安全 [php]$myUsername = cleanInput($_POST[’username’]); //clean!$arrayUsers = array($myUsername, ‘tom’, ‘tommy’); //clean!define(”GREETING”, ‘hello there’ . $myUsername); //clean!function cleanInput($input){$clean = strtolower($input);$clean = preg_replace(”/[^a-z]/”, “”, $clean);$clean = substr($clean,0,12);return $clean;}[/php]規(guī)則 2:禁用那些使安全性難以實(shí)施的 PHP 設(shè)置已經(jīng)知道了不能信任用戶輸入,還應(yīng)該知道不應(yīng)該信任機(jī)器上配置 PHP 的方式。例如,要確保禁用 register_globals。如果啟用了 register_globals,就可能做一些粗心的事情,比如使用 $variable 替換同名的 GET 或 POST 字符串。通過禁用這個設(shè)置,PHP 強(qiáng)迫您在正確的名稱空間中引用正確的變量。要使用來自表單 POST 的變量,應(yīng)該引用 $_POST[’variable’]。這樣就不會將這個特定變量誤會成 cookie、會話或 GET 變量。要檢查的第二個設(shè)置是錯誤報告級別。在開發(fā)期間,希望獲得盡可能多的錯誤報告,但是在交付項(xiàng)目時,希望將錯誤記錄到日志文件中,而不是顯示在屏幕上。為什么呢?因?yàn)閻阂獾暮诳蜁褂缅e誤報告信息(比如 SQL 錯誤)來猜測應(yīng)用程序正在做什么。這種偵察可以幫助黑客突破應(yīng)用程序。為了堵住這個漏洞,需要編輯 php.ini 文件,為 error_log 條目提供合適的目的地,并將 display_errors 設(shè)置為 Off。規(guī)則 3:如果不能理解它,就不能保護(hù)它一些開發(fā)人員使用奇怪的語法,或者將語句組織得很緊湊,形成簡短但是含義模糊的代碼。這種方式可能效率高,但是如果您不理解代碼正在做什么,那么就無法決定如何保護(hù)它。例如,您喜歡下面兩段代碼中的哪一段?清單 4. 使代碼容易得到保護(hù) [php]//obfuscated code$input = (isset($_POST[’username’]) ? $_POST[’username’]:”);//unobfuscated code$input = ”;if (isset($_POST[’username’])){$input = $_POST[’username’];}else{$input = ”;}[/php]在第二個比較清晰的代碼段中,很容易看出 $input 是有瑕疵的,需要進(jìn)行清理,然后才能安全地處理。規(guī)則 4:“縱深防御” 是新的法寶本教程將用示例來說明如何保護(hù)在線表單,同時在處理表單的 PHP 代碼中采用必要的措施。同樣,即使使用 PHP regex 來確保 GET 變量完全是數(shù)字的,仍然可以采取措施確保 SQL 查詢使用轉(zhuǎn)義的用戶輸入??v深防御不只是一種好思想,它可以確保您不會陷入嚴(yán)重的麻煩。既然已經(jīng)討論了基本規(guī)則,現(xiàn)在就來研究第一種威脅:SQL 注入攻擊。防止 SQL 注入攻擊在 SQL 注入攻擊 中,用戶通過操縱表單或 GET 查詢字符串,將信息添加到數(shù)據(jù)庫查詢中。例如,假設(shè)有一個簡單的登錄數(shù)據(jù)庫。這個數(shù)據(jù)庫中的每個記錄都有一個用戶名字段和一個密碼字段。構(gòu)建一個登錄表單,讓用戶能夠登錄。清單 5. 簡單的登錄表單 [php]Login

Username

Password

[/php] 這個表單接受用戶輸入的用戶名和密碼,并將用戶輸入提交給名為 verify.php 的文件。在這個文件中,PHP 處理來自登錄表單的數(shù)據(jù),如下所示:清單 6. 不安全的 PHP 表單處理代碼 [php] $okay = 0;$username = $_POST[’user’];$pw = $_POST[’pw’];$sql = “select count(*) as ctr from users whereusername=’”.$username.”‘ and password=’”. $pw.”‘ limit 1″;$result = mysql_query($sql);while ($data = mysql_fetch_object($result)){if ($data->ctr == 1){ //they’re okay to enter the application! $okay = 1;}}if ($okay){$_SESSION[’loginokay’] = true;header(”index.php”);}else{header(”login.php”);}?> [/php]這段代碼看起來沒問題,對嗎?世界各地成百(甚至成千)的 PHP/MySQL 站點(diǎn)都在使用這樣的代碼。它錯在哪里?好,記住 “不能信任用戶輸入”。這里沒有對來自用戶的任何信息進(jìn)行轉(zhuǎn)義,因此使應(yīng)用程序容易受到攻擊。具體來說,可能會出現(xiàn)任何類型的 SQL 注入攻擊。例如,如果用戶輸入 foo 作為用戶名,輸入 ‘ or ‘1′=’1 作為密碼,那么實(shí)際上會將以下字符串傳遞給 PHP,然后將查詢傳遞給 MySQL:$sql = “select count(*) as ctr from users where username=’foo’ and password=” or ‘1′=’1′ limit 1″; 這個查詢總是返回計數(shù)值 1,因此 PHP 會允許進(jìn)行訪問。通過在密碼字符串的末尾注入某些惡意 SQL,黑客就能裝扮成合法的用戶。解決這個問題的辦法是,將 PHP 的內(nèi)置 mysql_real_escape_string() 函數(shù)用作任何用戶輸入的包裝器。這個函數(shù)對字符串中的字符進(jìn)行轉(zhuǎn)義,使字符串不可能傳遞撇號等特殊字符并讓 MySQL 根據(jù)特殊字符進(jìn)行操作。清單 7 展示了帶轉(zhuǎn)義處理的代碼。清單 7. 安全的 PHP 表單處理代碼 [php] $okay = 0;$username = $_POST[’user’];$pw = $_POST[’pw’];$sql = “select count(*) as ctr from users where username=’”.mysql_real_escape_string($username).”‘ and password=’”. mysql_real_escape_string($pw).”‘ limit 1″; $result = mysql_query($sql);while ($data = mysql_fetch_object($result)){if ($data->ctr == 1){ //they’re okay to enter the application! $okay = 1;}}if ($okay){$_SESSION[’loginokay’] = true;header(”index.php”);}else{header(”login.php”);}?>[/php]使用 mysql_real_escape_string() 作為用戶輸入的包裝器,就可以避免用戶輸入中的任何惡意 SQL 注入。如果用戶嘗試通過 SQL 注入傳遞畸形的密碼,那么會將以下查詢傳遞給數(shù)據(jù)庫:select count(*) as ctr from users where username=’foo’ and password=’’ or ’1’=’1′ limit 1″ 數(shù)據(jù)庫中沒有任何東西與這樣的密碼匹配。僅僅采用一個簡單的步驟,就堵住了 Web 應(yīng)用程序中的一個大漏洞。這里得出的經(jīng)驗(yàn)是,總是應(yīng)該對 SQL 查詢的用戶輸入進(jìn)行轉(zhuǎn)義。但是,還有幾個安全漏洞需要堵住。下一項(xiàng)是操縱 GET 變量。防止用戶操縱 變量在前一節(jié)中,防止了用戶使用畸形的密碼進(jìn)行登錄。如果您很聰明,應(yīng)該應(yīng)用您學(xué)到的方法,確保對 SQL 語句的所有用戶輸入進(jìn)行轉(zhuǎn)義。但是,用戶現(xiàn)在已經(jīng)安全地登錄了。用戶擁有有效的密碼,并不意味著他將按照規(guī)則行事 —— 他有很多機(jī)會能夠造成損害。例如,應(yīng)用程序可能允許用戶查看特殊的內(nèi)容。所有鏈接指向 template.php?pid=33 或 template.php?pid=321 這樣的位置。URL 中問號后面的部分稱為查詢字符串。因?yàn)椴樵冏址苯臃旁?URL 中,所以也稱為 GET 查詢字符串。在 PHP 中,如果禁用了 register_globals,那么可以用 $_GET[’pid’] 訪問這個字符串。在 template.php 頁面中,可能會執(zhí)行與清單 8 相似的操作。清單 8. 示例 template.php [php] $pid = $_GET[’pid’];//we create an object of a fictional class Page$obj = new Page;$content = $obj->fetchPage($pid);//and now we have a bunch of PHP that displays the page//……//……?> [/php]這里有什么錯嗎?首先,這里隱含地相信來自瀏覽器的 GET 變量 pid 是安全的。這會怎么樣呢?大多數(shù)用戶沒那么聰明,無法構(gòu)造出語義攻擊。但是,如果他們注意到瀏覽器的 URL 位置域中的 pid=33,就可能開始搗亂。如果他們輸入另一個數(shù)字,那么可能沒問題;但是如果輸入別的東西,比如輸入 SQL 命令或某個文件的名稱(比如 /etc/passwd),或者搞別的惡作劇,比如輸入長達(dá) 3,000 個字符的數(shù)值,那么會發(fā)生什么呢?在這種情況下,要記住基本規(guī)則,不要信任用戶輸入。應(yīng)用程序開發(fā)人員知道 template.php 接受的個人標(biāo)識符(PID)應(yīng)該是數(shù)字,所以可以使用 PHP 的 is_numeric() 函數(shù)確保不接受非數(shù)字的 PID,如下所示:清單 9. 使用 is_numeric() 來限制 GET 變量 [php] $pid = $_GET[’pid’];if (is_numeric($pid)){//we create an object of a fictional class Page$obj = new Page;$content = $obj->fetchPage($pid);//and now we have a bunch of PHP that displays the page //……//……}else{//didn’t pass the is_numeric() test, do something else!}?> [/php]這個方法似乎是有效的,但是以下這些輸入都能夠輕松地通過 is_numeric() 的檢查:100 (有效)100.1 (不應(yīng)該有小數(shù)位)+0123.45e6 (科學(xué)計數(shù)法 —— 不好)0xff33669f (十六進(jìn)制 —— 危險!危險!)那么,有安全意識的 PHP 開發(fā)人員應(yīng)該怎么做呢?多年的經(jīng)驗(yàn)表明,最好的做法是使用正則表達(dá)式來確保整個 GET 變量由數(shù)字組成,如下所示:清單 10. 使用正則表達(dá)式限制 GET 變量 [php] $pid = $_GET[’pid’];if (strlen($pid)){if (!ereg(”^[0-9]+$”,$pid)){ //do something appropriate, like maybe logging them out or sending them back to home page}}else{//empty $pid, so send them back to the home page}//we create an object of a fictional class Page, which is now//moderately protected from evil user input$obj = new Page;$content = $obj->fetchPage($pid);//and now we have a bunch of PHP that displays the page //……//……?>[/php]需要做的只是使用 strlen() 檢查變量的長度是否非零;如果是,就使用一個全數(shù)字正則表達(dá)式來確保數(shù)據(jù)元素是有效的。如果 PID 包含字母、斜線、點(diǎn)號或任何與十六進(jìn)制相似的內(nèi)容,那么這個例程捕獲它并將頁面從用戶活動中屏蔽。如果看一下 Page 類幕后的情況,就會看到有安全意識的 PHP 開發(fā)人員已經(jīng)對用戶輸入 $pid 進(jìn)行了轉(zhuǎn)義,從而保護(hù)了 fetchPage() 方法,如下所示:清單 11. 對 fetchPage() 方法進(jìn)行轉(zhuǎn)義 [php] class Page{ function fetchPage($pid){ $sql = “select pid,title,desc,kw,content, status from page where pid=’ ”.mysql_real_escape_string($pid).”‘”; //etc, etc….}}?> [/php]您可能會問,“既然已經(jīng)確保 PID 是數(shù)字,那么為什么還要進(jìn)行轉(zhuǎn)義?” 因?yàn)椴恢涝诙嗌俨煌纳舷挛暮颓闆r中會使用 fetchPage() 方法。必須在調(diào)用這個方法的所有地方進(jìn)行保護(hù),而方法中的轉(zhuǎn)義體現(xiàn)了縱深防御的意義。如果用戶嘗試輸入非常長的數(shù)值,比如長達(dá) 1000 個字符,試圖發(fā)起緩沖區(qū)溢出攻擊,那么會發(fā)生什么呢?下一節(jié)更詳細(xì)地討論這個問題,但是目前可以添加另一個檢查,確保輸入的 PID 具有正確的長度。您知道數(shù)據(jù)庫的 pid 字段的最大長度是 5 位,所以可以添加下面的檢查。清單 12. 使用正則表達(dá)式和長度檢查來限制 GET 變量 [php] $pid = $_GET[’pid’];if (strlen($pid)){if (!ereg(”^[0-9]+$”,$pid) && strlen($pid) > 5){ //do something appropriate, like maybe logging them out or sending them back to home page}}else{//empty $pid, so send them back to the home page}//we create an object of a fictional class Page, which is now//even more protected from evil user input$obj = new Page;$content = $obj->fetchPage($pid);//and now we have a bunch of PHP that displays the page //……//……?> [/php]現(xiàn)在,任何人都無法在數(shù)據(jù)庫應(yīng)用程序中塞進(jìn)一個 5,000 位的數(shù)值 —— 至少在涉及 GET 字符串的地方不會有這種情況。想像一下黑客在試圖突破您的應(yīng)用程序而遭到挫折時咬牙切齒的樣子吧!而且因?yàn)殛P(guān)閉了錯誤報告,黑客更難進(jìn)行偵察。緩沖區(qū)溢出攻擊緩沖區(qū)溢出攻擊 試圖使 PHP 應(yīng)用程序中(或者更精確地說,在 Apache 或底層操作系統(tǒng)中)的內(nèi)存分配緩沖區(qū)發(fā)生溢出。請記住,您可能是使用 PHP 這樣的高級語言來編寫 Web 應(yīng)用程序,但是最終還是要調(diào)用 C(在 Apache 的情況下)。與大多數(shù)低級語言一樣,C 對于內(nèi)存分配有嚴(yán)格的規(guī)則。緩沖區(qū)溢出攻擊向緩沖區(qū)發(fā)送大量數(shù)據(jù),使部分?jǐn)?shù)據(jù)溢出到相鄰的內(nèi)存緩沖區(qū),從而破壞緩沖區(qū)或者重寫邏輯。這樣就能夠造成拒絕服務(wù)、破壞數(shù)據(jù)或者在遠(yuǎn)程服務(wù)器上執(zhí)行惡意代碼。防止緩沖區(qū)溢出攻擊的惟一方法是檢查所有用戶輸入的長度。例如,如果有一個表單元素要求輸入用戶的名字,那么在這個域上添加值為 40 的 maxlength 屬性,并在后端使用 substr() 進(jìn)行檢查。清單 13 給出表單和 PHP 代碼的簡短示例。清單 13. 檢查用戶輸入的長度 [php] if ($_POST[’submit’] == “go”){$name = substr($_POST[’name’],0,40);//continue processing….}?>
標(biāo)簽: PHP
相關(guān)文章:
主站蜘蛛池模板: 亚洲国产精品视频 | 久久99爰这里有精品国产 | 日本在线观看不卡免费视频 | ririai99在线视频观看 | 中文字幕精品一区二区三区视频 | 国产日产高清欧美一区二区三区 | 91精品国产91久久久久久青草 | 成人久久18免费软件 | 91久久夜色精品国产网站 | 欧美视频免费一区二区三区 | 亚洲一区二区三区免费看 | 亚洲女精品一区二区三区 | 伊人久久在线 | 97国产免费全部免费观看 | 免费公开视频人人人人人人人 | 交videos人妖| 一区二区三区国产美女在线播放 | 国产精品不卡在线 | 国产永久在线观看 | 国产精品1区2区3区在线播放 | 一本色道久久综合 | 美女黄色一级毛片 | 久草免费在线视频 | 欧美α一级毛片 | 免费观看成年的网站 | 欧美日韩一区二区三区视频 | 久久久一区二区三区不卡 | 中文字幕视频网站 | 国内精品久久久久影院不卡 | 国产欧美精品一区二区三区四区 | 欧美一级看片 | 日鲁夜鲁鲁狠狠综合视频 | 欧美成人中文字幕 | 免费视频久久久 | 中文字幕亚洲高清综合 | 欧美日韩精品一区二区另类 | 国产一级精品高清一级毛片 | 久热国产视频 | 91porny九色国产首页在线 | 91久久青草精品38国产 | 毛片免费全部免费播放 |