2009-11-28 116 views
2

我有獲取要求的任何其他腳本,這是我寫的消毒用戶輸入一個「走出去」的劇本:PHP/MySQL的:消毒用戶輸入 - 這是一個壞主意?

foreach ($_REQUEST as $key => $value){ 
    if (get_magic_quotes_gpc()) 
    $_REQUEST[$key] = mysql_real_escape_string(stripslashes($value)); 
    else 
    $_REQUEST[$key] = mysql_real_escape_string($value); 
} 

我還沒有看到任何人使用這種方法。有什麼理由不這樣做?

編輯 - 修訂了爲數組工作:

function mysql_escape($thing) { 
    if (is_array($thing)) { 
    $escaped = array(); 
    foreach ($thing as $key => $value) { 
     $escaped[$key] = mysql_escape($value); 
    }   
    return $escaped; 
    } 
    // else 
    if (get_magic_quotes_gpc()) $thing = stripslashes($thing); 
    return mysql_real_escape_string($thing); 
} 

foreach ($_REQUEST as $key => $value){ 
    $_REQUEST[$key] = mysql_escape($value); 
} 

回答

9

我覺得好多了逃避當時的數據是使用,而不是在路上你可能想使用該數據的採集。 JSON,XML,Shell,MySQL,Curl或HTML,並且每種都有自己的轉義數據的方式。


讓有爲什麼需要在不同的上下文中逃逸的快速回顧:

如果你是在一個引號分隔字符串,你需要能夠逃脫引號。 如果你是在XML中,則需要從「標記」 如果你在SQL,你需要的,如果你是在命令行中,從「數據」分離「命令」 單獨的「內容」,你需要單獨從「數據」

「命令」這是計算的一般一個非常基本的方面。因爲其限制數據,就可能出現在數據中的語法,需要有從SYNTAX區分DATA,因此,逸出的方式。

在網頁編程,共同逃逸案件是:1。 輸出文本到HTML 2.輸出數據到HTML屬性 3.輸出HTML的成HTML 4.將數據插入到JavaScript 5.將數據插入SQL 6.將數據插入到外殼命令

如果處理不當每一個都有不同的安全隱患。這非常重要!讓我們回顧一下這個在PHP的背景:

  1. 文成HTML:用htmlspecialchars (...)

  2. 數據轉換成HTML屬性 用htmlspecialchars(...,ENT_QUOTES)

  3. HTML轉換成HTML 使用庫如HTMLPurifier,以確保只有合法的標籤都存在。數據轉換成Javascript 我更喜歡json_encode。如果你把它放在一個屬性中,你仍然需要使用#2,例如

  4. 插入數據到SQL 每個驅動程序都有一個escape()函數。這是最好的。如果您正在使用正常的latin1字符集,則addslashes(...)是合適的。不要忘記在addslashes()調用周圍引用:

    「INSERT INTO table1 SET field1 ='」。 addslashes($ data)。「'」

  5. 數據在命令行 escapeshellarg()和escapeshellcmd()將 - 閱讀手冊

- 把這些對心臟,你會消除常見的95%*網絡安全風險! (*猜測)

+0

不幸的是,我的字符集是UTF-8,而不是僅限於拉丁字符。我已經把它解決了,這樣所有的東西都可以正確地轉義出來,但是我想我只是太偏執了,我會留下一些開放的SQL注入。 – Greg 2009-11-28 07:02:12

+0

mysql_real_escape_characters是清理進入數據庫的用戶輸入的更好選項。 – Residuum 2009-11-28 07:45:04

+0

@Residuum:我似乎無法在手冊中找到。 – Greg 2009-11-28 07:58:05

2

您的方法試圖淨化所有請求數據以插入到數據庫中,但如果您只是想輸出它呢?你的輸出中會有不必要的反斜槓。而且,轉義並不是防止SQL異常的好策略。通過使用參數化查詢(例如在PDO或MySQLi中),您可以將轉義問題「傳遞」到抽象層。

3

如果您在$_REQUEST中有陣列,它們的值將不會被消毒。

+1

+1表示同意。遞歸消毒是必需的。 – mauris 2009-11-28 06:58:17

+0

謝謝你指出。我編輯了我的問題。 – Greg 2009-11-28 07:13:35

2

除了缺乏對數組的遞歸以及不必要的整數轉義之外,此方法還將編碼數據用於消毒前的SQL語句中。 mysql_real_escape_string()轉義數據,它不會消毒它 - 轉義和消毒不是一回事。

消毒是許多PHP腳本在使用前仔細檢查輸入數據的可接受性的任務。我認爲這對未逃脫的數據做得更好。在進入SQL之前,我通常不會轉義數據。那些更喜歡使用Prepared Statements的人也能達到同樣的效果。

還有一件事:如果輸入數據可以包含utf8字符串,看起來這些應該在轉義之前進行驗證。在清理之前,我經常在$ _POST上使用遞歸的utf8清理器。

3

我做了,並用這一個:

<?php 
function _clean($var){ 
    $pattern = array("/0x27/","/%0a/","/%0A/","/%0d/","/%0D/","/0x3a/", 
        "/union/i","/concat/i","/delete/i","/truncate/i","/alter/i","/information_schema/i", 
        "/unhex/i","/load_file/i","/outfile/i","/0xbf27/"); 
    $value = addslashes(preg_replace($pattern, "", $var)); 
    return $value; 
} 

if(isset($_GET)){ 
    foreach($_GET as $k => $v){ 
     $_GET[$k] = _clean($v); 
    } 
} 

if(isset($_POST)){ 
    foreach($_POST as $k => $v){ 
     $_POST[$k] = _clean($v); 
    } 
} 
?>