2010-04-01 97 views
0

我想讓用戶在我的數據庫中存儲網址我使用的是php mysql和htmlpurifier我想知道在將數據存儲到數據庫之前,以下代碼是否可以過濾掉不良數據?PHP URL安全問題

這是部分PHP代碼。

$url = mysqli_real_escape_string($mysqli, $purifier->purify(htmlspecialchars(strip_tags($_POST['url']))); 
+0

定義「壞數據」 – 2010-04-01 14:23:47

+0

什麼意思是壞數據? – 2010-04-01 14:25:23

+0

XSS和SQL注入。 – TaG 2010-04-01 14:25:27

回答

0

如果你擔心SQL注入,它會清除它並阻止它。否則,不確定你在問什麼。

4

你不需要在數據上調用htmlspecialchars()和​​3210 - 你真的只有一個問題在這裏,這是確保該URL不包含SQL注入 - mysqli_real_escape_string()將排序。

或者,如果您要將數據輸出到頁面/ HTML(而不是將其用作HTTP重定向標頭),則需要使用htmlentities()來防止數據輸出時發生XSS。金科玉律是背景感知:

HTML實體編碼是好的,爲你把 體的HTML文檔的 不可信數據,如 一個標籤內。它甚至可以用於 適用於不可信數據的 屬性,特別是如果您對使用圍繞您的屬性的引用 信仰宗教信仰 。但是,如果您將 不受信任的數據放入任何地方的 標記或處理器屬性(如CSS中的onmouseover或 )或URL中的事件 ,但HTML 實體編碼不起作用。因此,即使您使用的HTML實體編碼方法 無處不在,您仍然最有可能的 容易受到XSS。對於要將不可信數據 置入的HTML 文檔部分,您必須使用 轉義語法。

有關XSS預防的深入參考,請查看OWASP

在使用數據(即針對相關攻擊)之前編碼數據總是最好的(例如,MySQL轉義字符串用於輸入到數據庫以防止SQLi,HTML轉義字符串用於輸出到屏幕以防止XSS,而不是兩者都相同時間)。這使您可以跟蹤通過應用程序的數據流,並且您知道數據庫中的所有數據都可以用於任何目的。例如,如果您在將這些數據放入數據庫之前對其進行了HTML編碼,則在將其用作HTTP標頭之前,您必須對其進行解碼。

如果您必須在數據進入數據庫之前對其進行編碼,請確保列名反映了未來的開發人員/維護人員!

編輯:

按VolkerK的評論,以防止XSS在URL輸出的最好方法是檢查協議 - 如果它不符合您的允許的協議(可能是HTTP/HTTPS)拒絕:

$url = 'http://hostname/path?arg=value#anchor'; 

$parsedUrl = parse_url($url); 

if($parsedUrl['scheme'] != 'http') { 
    // reject URL 
} else { 
    $url = mysqli_real_escape_string($mysqli, $url); 
    $sql = "INSERT INTO table (url) VALUES ('$url')"; 
    // insert query 
} 

這具有防止在<a href="$url">情況javascript:alert('xss')攻擊的優勢。在javascript:alert('xss')上運行htmlentities()沒有任何影響(因爲<>等字符的有限子集不存在被轉義),因此惡意用戶將能夠在您的域上執行JS。

+0

$ url正在被'javascript:alert(「hello」)'?這不是關於文本/內容,而是URL/URI/URN,它是屬性的值。所以htmlenties/htmlspecialchars()不是一個安全的選擇。 – VolkerK 2010-04-01 15:02:07

+0

@VolkerK只能在window.location重定向(即在Javascript標記)中執行,或者當設置爲HTML標記參數時執行,而不是在作爲HTML內容輸出或作爲HTTP標頭的一部分輸出時執行。授予的OP沒有指定數據的使用,所以所有的基地應該被答案覆蓋。在數據庫中存儲數據時,XSS預防不成問題,在輸出編碼時相關。 OWASP參考添加從http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting))_Prevention_Cheat_Sheet – Andy 2010-04-01 15:14:18

+0

無論如何,你打開門「你需要使用htmlentities()」,我認爲不會做(整個)工作,如果URL是例如在href屬性中。我會檢查模式並將其限制爲http,https可能是ftp,不管是否合理。這是在將值存儲在數據庫之前可以執行的操作。 $ url ='skype:whatever'->錯誤(除非這正是你想要允許的---))。 – VolkerK 2010-04-01 16:18:23

1

在將值放入數據庫之前,只需要mysqli_real_escape_string()

爲了防止XSS,htmlspecialchars()應在您顯示的所有數據上顯示時調用(以HTML格式),而不是在存儲之前調用。

想象一下,您可能有一天需要以非HTML格式輸出數據;那麼在將它存儲在數據庫中之前,你會後悔的稱呼它爲htmlspecialchars()

我不知道爲什麼你使用purifierstrip_tags(),也許你有一個特別的原因,但它只是看起來像一起「數據清洗的層數越多我用,精益求精」的行矯枉過正。無論如何,htmlspecialchars()將使任何HTML無害。

0

如果您只需要將網址存儲在數據庫中並將其取回,只需將該字符串傳遞給mysqli_real_escape_string即可。無需其他任何東西。您只需要使用htmlspecialchars當您想要將其輸出回HTML頁面中的用戶。

HTMLPurifier根本不屬於這裏,因爲它清理HTML而不是URL。

0

我在我的數據庫中存儲網址,它只是被xss清除,但是被orm自動轉義。這基本上可以歸結爲:

mysqli_real_escape_string(strip_tags($var)); 

所以你先清洗,然後確保這是確定在數據庫保存,然後保存不變網址。

在它的出路,然而你會拉它,然後在你的模板使用htmlentities(),以防萬一有可能會干擾HTML的任何東西。

你並不需要過度設計這樣的東西。

PS。如果你正在使用POST,你可以這樣做:

$fixed = $_POST; 
$fixed = array_map('strip_tags', $fixed); 
$fixed = array_map('mysqli_real_escape_string', $fixed); 

然後使用$ fixed數組。

0

您需要區分過濾和轉義。當收到數據時,應該過濾它。這意味着剝離不良的角色和有缺陷的數據。

使用過濾器擴展名和適當的過濾器將數據從超全局數組轉換爲應用程序變量。

之後,您可能需要清空$ _POST以避免再次使用未過濾的數據。

然後你將它按摩成你想要的形狀。

轉義是數據發送或保存之前的一步,應根據輸出介質完成。

使用mysqli_real_escape_string進行轉義以存儲在MySQL數據庫中。如果您使用其他DBMS,則應使用其他功能。

更好的是,爲用戶數據使用預先準備好的語句和佔位符。

以HTML格式輸出時,htmlentities可能是明智的。假設您不想在數據中擁有任何HTML代碼。如果這樣做,請使用HTMLPurifier之類的可信庫。

我建議你不要試圖在一行代碼中做所有事情,就像你的例子。這是更難以閱讀和更難維護。

對於URL,htmlentities是避免非轉義字符的好方法。他們當然應該是&它也確保你沒有使用任何引號,因爲你當然使用標誌來引用這些引號 - 對嗎?

但是在存儲數據時不應該使用這個函數。它在發送給用戶時應該應用。

過濾器輸入 - 轉義輸出! (引用Chris Schifflett)