2009-12-11 127 views
0

我已經作出如下功能的URL的安全性。我只是想知道是否有什麼我需要重新考慮或更改下面的代碼。在閱讀了關於各種來源的安全性的文章之後,我已經完成了這個功能。的URL安全

下面是函數:

// filters possible malacious stuff from URLs 
private function filter_url($url) 
{ 
    if (is_array($url)) 
    { 
    foreach($url as $key => $value) 
    { 
     // recurssion 
     $url[$key] = filter_url($value); 
    } 

    return $url; 
} 
else 
{ 
    // Allow only one ? in URLs 
    $total_question_marks = substr_count($url, '?'); 

    if ($total_question_marks >= 2) 
    { 
     exit('You can not use 2 question marks (?) in URLs for security reasons!!'); 
    } 

    // decode URLs 
    $url = rawurldecode($url); 
    $url = urldecode($url); 
    // remove bad stuff 
    $url = str_replace('../', '', $url); 
    $url = str_replace('..\\', '', $url); 
    $url = str_replace('..%5C', '', $url); 
    $url = str_replace('%00', '', $url); 
    $url = str_ireplace('http', '', $url); 
    $url = str_ireplace('https', '', $url); 
    $url = str_ireplace('ftp', '', $url); 
    $url = str_ireplace('smb', '', $url); 
    $url = str_replace('://', '', $url); 
    $url = str_replace(':\\\\', '', $url); 
    $url = str_replace(array('<', '>'), array('&lt;', '&gt;'), $url); 

    // Allow only a-zA-Z0-9_/.-?=& 
    $url = preg_replace("/[^a-zA-Z0-9_\-\/\.\?=&]+/", "", $url); 

    //print $url; 
    return $url; 
    } 
} 

我可以簡單地使用此功能是這樣的:

$_GET = filter_url($_GET); 

甚至是這樣的:

$_SERVER['QUERY_STRING'] = filter_url($_SERVER['QUERY_STRING']); 
+0

你想要保護什麼?一個URL本身並不是可以防範的。應用程序如何處理輸入是發生可能的入侵的地方,而這個簡單的過濾器不會自動保護每個後續層。 – deceze 2009-12-11 09:14:50

+0

基本上我做了一個框架MVC,在它所有的URL都重新路由。 – Sarfraz 2009-12-11 14:34:20

回答

5

任何企圖,試圖建立某種形式的包羅萬象的這樣的過濾器總是會失敗,此外,因爲你總是「腐敗」的數據,你就會有麻煩的時候,你真的需要接受一段數據帶有「不合格」字符或字符序列。

你真的需要圍繞網絡安全的主題閱讀了一下,充分了解常見的攻擊,如(最小的)跨站點腳本,跨站請求僞造和SQL注入。

你需要採取2方面入手,以安全的方式使用用戶提供的數據。這是

這樣想的過程:

  1. 驗證並拒絕對數據的方式上的出路

輸入驗證 檢查

  • 編碼數據。每一塊的輸入,以確保它僅包含正確的數據類型和長度以及範圍邊界之內適合 - 根據數據的每個INIDIVIDUAL PIECE的含義 - 。即確保號碼只包含數字。確保年份在合理的範圍內,確保字符串不會過長或空白,確保文件名不會傳送目錄,確保ID僅包含合法字符。 etc.etc。等等。這裏最重要的是,儘可能說明什麼是允許的;不要說明什麼是泄露。測試什麼是允許的,否則拒絕一切被稱爲白名單和是一件好事,因爲你知道你會得到乾淨的數據(或接近它是明智的)。尋找不好的模式並拒絕它們被稱爲黑名單,並且是不太安全的想法。要使黑名單成功,您需要確保您的黑名單已完成,而且這通常是一項不可能完成的任務。在一些有限的情況下,黑名單方法可能是有益的,但只有當你確信清單是詳盡無遺的時候。

    存儲數據 一旦您只有可接受的乾淨數據,請將其保存在變量或會話中。也許採取變量命名的方法,指出這個數據現在是乾淨的。這裏最重要的是,當我們保存這些數據時,我們還沒有改變它。這意味着數據可以在任何環境中使用而無需我們有「扔任何東西」

    輸出編碼 當您將數據發送到外部系統 - 如文件名,餅乾,網頁,文件或保存在您自己的數據庫中 - 您必須對數據進行編碼,以確保不會中斷輸出中使用的語言語法或文件格式。數據可以在這裏轉換。

    你需要對數據進行轉換將根據您如何以及在何處使用數據是不同的。轉換用於Windows文件名的字符串對於linux文件名是不同的,如果插入到PDF文檔或網頁或數據庫等等中,則再次不同。但是,讓我們更詳細地查看2個示例:

    輸出爲HTML 在將字符串插入某些HTML的最常見情況下,您需要確保不允許用戶向頁面中注入任意內容,這不僅允許他們編輯頁面另一個用戶可以看到,但他們也可以注入JavaScript形式的代碼,可以做任何他們想要的。該腳本將以查看頁面的用戶身份運行,並可能允許攻擊者竊取他們的信息和登錄憑據。這被稱爲跨站腳本。 HTML和Javascript的語法規則意味着您需要進行不同的編碼,具體取決於您在HTML中插入用戶數據的位置。在http://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet有一個非常有價值的頁面,它解釋瞭如何轉換6種不同類別的地方的數據,您可以在其中插入字符串到HTML頁面。

    輸出到數據庫 如果用戶的數據保存到數據庫中,您有效地必須包括在SQL語句中的字符串。您必須確保不允許用戶更改SQL語句的含義,並且只能更改數據值。如果他們可以更改語句的含義,則稱爲SQL注入。

    這是一個特殊的情況下,雖然可以使用輸出編碼是解決這個問題,你最好使用一個名爲「綁定參數」技術。這可確保您的數據始終用作數據,而不會在與數據庫交談時用作代碼。 PHP支持包括「PDO」(跨數據庫)和「Mysqli」(MySQL)在內的許多數據庫庫中的綁定參數。應該指出,「Mysql」庫不支持綁定參數。

    有更多的信息遍佈網絡和StackOverflow的有關跨站點腳本(XSS)和和SQL注入(SQLI),這是很值得一讀圍繞的主題。當然還有許多其他類型的攻擊,但如果按照上述流程進行操作,應該儘量減少風險。數據驗證和編碼例程構成安全Web應用程序的重要組成部分並非不合理。但是您必須將安全方法學融入您的標準工作流程中。添加它作爲事後的想法要困難得多。有時候回頭看看你的驗證代碼,看看是否可以添加更多的規則。總會有你第一次錯過的東西。

  • +0

    哎感謝這麼好的解釋,學到了很多:) – Sarfraz 2009-12-11 13:32:00

    3

    過濾器依靠黑名單失敗。如果您認真檢測攻擊模式,請檢查PHPIDS

    +0

    嘿謝謝你讓我知道 – Sarfraz 2009-12-11 09:55:53

    +1

    請注意,所有Web應用程序IDS設備只能捕獲極少數的惡意攻擊媒介,它們通常很微不足道。只有使用這樣的IDS方法作爲額外的安全層,並且永遠不要期望它爲您開發的自己的應用程序提供任何真正的安全性。他們可能阻止一些常見的蠕蟲,但對人類攻擊者沒有真正的威脅。 – Cheekysoft 2009-12-11 13:27:17

    +0

    嘿謝謝你讓我知道這件事。 – Sarfraz 2009-12-11 13:32:33