2013-01-22 65 views
1

可能重複:
How to prevent SQL injection in PHP?抵禦Mysql的注射用PHP escapestring(任何這樣做的真正的好辦法

我想問問關於防範SQL注入的一些問題。從我一直在讀的內容中,我總會遇到以下三件事:

  • stripslashes
  • 其一起使用magic_quotes_gpc的
  • mysql_real_escape_string(或mysqli的我在較新的PHP的假設?)

的問題是,我應該使用這兩種或將real_escape_string足夠?

例如,我有這行代碼有關的註冊頁面(我知道一個事實是脆弱的,因爲sqli助手讓我找到關於我的數據庫的一切:(因爲我還沒有實現任何上述) :

if(isset($_POST['submit'])){ 
    //cleanup the variables 
    $username = ($_POST['username']); 
    $password = ($_POST['password']); 
    $email = ($_POST['email']); 
    $username = sanitise($username); 
    $password = sanitise($password); 
    $email = sanitise($email); 
    //quick/simple validation 
    if(empty($username)){ $action['result'] = 'error'; array_push($text,'Please type in a username'); } 
    if(empty($password)){ $action['result'] = 'error'; array_push($text,'Please type in a password'); } 
if($action['result'] != 'error'){ 
     $password = md5($password); 
     //add to the database 
     $add = mysql_query("INSERT INTO Users VALUES(NULL,'$username','$password','$email',0, 'First', 'Last', 'Phone Number Here', '...', 'Something about me...')"); 
     if($add){ 
      //get the new user id 
      $userid = mysql_insert_id();  
      //create a random key 
      $key = $username . $email . date('mY'); 
      $key = md5($key); 
      //add confirm row 
      $confirm = mysql_query("INSERT INTO Confirm VALUES(NULL,'$userid','$key','$email')"); 
      if($confirm){ 
       //include the swift class 
       include_once 'swift/swift_required.php'; 
       //put info into an array to send to the function 
       $info = array(
        'username' => $username, 
        'email' => $email, 
        'key' => $key); 
       //send the email 
       if(send_email($info)){ 
        //email sent 
        $action['result'] = 'success'; 
        array_push($text,'Thanks for signing up. Please check your e-mail for confirmation.'); 
       }else{ 
        $action['result'] = 'error'; 
        array_push($text,'Could not send confirmation e-mail'); 
       } 
      }else{ 
       $action['result'] = 'error'; 
       array_push($text,'Confirm row was not added to the database. Reason: ' . mysql_error()); 
      } 
     }else{ 
      $action['result'] = 'error'; 
      array_push($text,'User could not be added to the database. Reason: ' . mysql_error()); 
     } 
    } 
    $action['text'] = $text; 
} 
?> 

我想我的禁制功能將有助於事情 - 得到了它的在線,但它似乎是有點用處或許這不僅有助於防止跨站腳本這是:

function cleanInput($input) { 
     $search = array(
      '@<script[^>]*?> 
.*?</script>@si', // Strip out javascript 
    '@<[\/\!]*?[^<>]*?>@si',   // Strip out HTML tags 
    '@<style[^>]*?>.*? 
    </style> 
@siU', // Strip style tags properly 
    '@<![\s\S]*?--[ \t\n\r]*>@'   // Strip multi-line comments 
    ); 
    $output = preg_replace($search, '', $input); 
    return $output; 
    } 
function sanitise($input) { 
    if (is_array($input)) { 
    foreach($input as $var=>$val) { 
    $output[$var] = sanitise($val); 
    } 
    } 
    else { 
    if (get_magic_quotes_gpc()) { 
    $input = stripslashes($input); 
    } 
    $input = cleanInput($input); 
    $output = $input; 
    } 
    return $output; 
} 

你會建議功能是沒用?

如果是的話,我將如何去保護的代碼原有的位?即:

$username = ($_POST['username']); 
    $password = ($_POST['password']); 
    $email = ($_POST['email']); 
+0

關於這個問題已經有一個非常大的話題,並且一個簡單的搜索會顯示它。 http://stackoverflow.com/questions/60174/how-to-prevent-sql-injection-in-php –

+0

確實如此,但我也在問關於粘貼的功能 - 我做了搜索。另外我對如何使用上面的post方法實現它有點困惑。因此請求新的線程。還請注意有關魔術引號和反斜槓的查詢,以及它們是否必要 –

+1

使用PDO或MySQLi切換到準備好的聲明。 – MrCode

回答

3

無論你做什麼,Read about injection here。正如你可以在這個網站上看到,準備的語句是要走的路,最好使用PDO:

$stmt = $pdo->prepare('SELECT foo from db.bar WHERE foobar = :something;'); 
$stmt->execute(array(':something' => $_POST['something'])); 

沒有必要依靠棄用功能,如魔術引號或者,其實,任何事情在mysql_*這件事的延期;因爲後者將被完全棄用,並最終會一起從語言中刪除(希望很快就會有一段時間)。

如果您(或其他人)想知道爲什麼我想PDO是首選:

  • 它支持多個驅動器(MySQL和MSSQL,PostrgreSQL,...)full list here
  • 其OO API與時間更加和諧,而mysqli_*也提供了程序化API。有些人認爲這是一個加號,主要是那些不熟悉面向對象的人,但遲早你必須學習。
  • 我個人認爲PDO使用更廣泛,而且由於PHP是一個開源產品,社區使用這個問題很重要:它會在更長的時間內得到支持,它會是(和更多的人)更好地測試,如果你被困住了,還有更多的同伴支持。
  • PDO模擬準備,你可以關閉它,但會減慢你的速度。另外,在模擬時,PDO會仔細查看您使用的佔位符。例如,如果一些古怪的驅動程序不支持指定的佔位符,您仍然可以使用它們,但PDO將用?替代它們,或者手冊頁將其替換爲「更適合的東西」。總而言之,PDO是相當聰明的:)
+0

只要向下選民可以告訴我,我不介意迴應票爲什麼?請,開導我... –

0

你列出連接到SQL注入:)

  • 的stripslashes都只是從魔術引號
  • 魔術引號恢復功能都不是一個錯誤的功能,從已刪除語言
  • mysql_real_escape_string(你使用它的方式) - 只是一個神奇的手動副本報價

作爲事實上,逃避(通過魔術引號和real_escape完成)只針對正常建立查詢需要一個真正的格式化的一小部分。一個人必須遵循整套規則,而不是單一的「逃避一切,你很好」。

然而,沒有什麼本質逃避錯誤,只要它是用來代替它,並不像魔杖保護您免受打針。例如,PDO在內部一直使用它。

請注意,「使用準備好的聲明」也不會被HTE魔杖,而是相同的口頭禪是「什麼都逃不過」 - 不足和不安全的爲好。

Some explanations I posted before

你會建議功能是沒用?

我建議,這個函數是相當有害的

Some explanations from the similar questiuon

這樣做的任何真正的好辦法嗎?

始終使用佔位符向查詢添加動態部分。這是安全的,可以非常方便地使用。請注意,準備好的聲明不是使用佔位符的唯一方式,顯然也不是最可靠的。另外,請記住,在應用程序代碼中使用原始API調用,無論是PDO,mysqli還是mysql,都同樣糟糕。必須使用抽象庫來處理他們的SQL,而不是原始的API函數。

另外,請記住,大多數傳播PDO的人,從來沒有使用過它的真正項目,或者至少有一些是「好處」。他們實際上只是在重複他們剛剛從別人聽到了同樣的文本;)

  • 說,「多數據庫支持」是不是經常使用的東西,當然是只改變DSN字符串它不是那麼容易的。切換數據庫是一項艱鉅的任務,而不同的API函數將成爲最小的問題。
  • 或者誰說「關閉仿真會減慢你的速度」只是從來沒有試過它在真實:)
  • 或者,問一個誰說「PDO是很聰明」創建一個簡單的查詢與IN子句填充一個數組;
+0

我認爲你指的是我在你的答案:我_have_嘗試關閉現實生活中的模擬,我一直在努力現實生活中的項目(但是,對於那些我使用了現有的附加抽象層,或者擴展了那個特定公關的項目) oject)。當我說_PDO非常聰明時,我只談論PDO如何處理您使用的佔位符與實際DB驅動程序支持的佔位符。當你說,使用原始API調用時,我不能與你爭論,不會使切換DB系統變得更容易... –

+0

_I用盡了字符_...我認爲PDO的主要優點支持多種驅動程序的是,即使驅動程序可能會更改,您編寫PHP代碼的方式也不會改變。如果您希望PDO使用帶有in-clause的準備好的語句:這並不難。我已經寫了一個方法來做到這一點,它只需要大約5行代碼。如果我遇到它,我很樂意發佈代碼。再說一次,你對此100%正確,你需要在那裏有一個額外的抽象層......對,就是這樣:鏈接+1,如果這些評論中有任何錯誤,請給我看看光:) –

+0

對不起,我已經看了一些你的答案......看起來好像你對我的回答很不喜歡,就像我一樣,建議準備好的陳述。我從來沒有這樣說過,準備好的陳述是最終的保護......但是當有人詢問逃生函數時,使用準備好的陳述是他們必須學習的第一件事。我只是將它們推向了這個方向,這取決於那些人員進一步調查職業球員和球員的情況。當然準備好的療法並不是一攬子療法,但它們是必須知道的,而國際海事組織是必須使用的...... –

3

使用準備好的語句,PDO或mysqli我個人更喜歡PDO,但兩者都會完成這項工作。