2013-05-03 36 views
-4

我被告知這段代碼非常容易受到SQL注入的影響。我如何改變它以變得安全?我知道使用準備好的語句是最好的,但我還沒有找到一種不會破壞它的方法。使用預準備語句?我完全不明白

<?php 

$con = new mysqli("localhost", "", "", ""); 
// Check connection 
if (mysqli_connect_errno()) { 
    echo "Failed to connect to MySQL: " . mysqli_connect_error(); 
} 

$existsQuery = "select count(*) as count from entry where emailaddress like '" . $_POST[emailaddress] . "'"; 
$existsResult = mysqli_query($con, $existsQuery); 

if ($existsResult->fetch_object()->count > 0) { 
    header('Location: index2.php?email=exists'); 
} else { 
    $sql = "INSERT INTO entry (firstname, lastname, emailaddress, favoritesong) VALUES ('$_POST[firstname]','$_POST[lastname]','$_POST[emailaddress]','$_POST[favoritesong]')"; 

    if (!mysqli_query($con, $sql)) { 
     die('Error: ' . mysqli_error($con)); 
    } 
    echo "1 record added"; 
} 

mysqli_close($con); 
?> 
+1

老實說,只需找到一份好的[PDO教程](http://j.mp/PoWehJ),然後讓它工作。然後返回並將您學到的知識應用於您的代碼。先理解它,然後再應用它。在同一時間嘗試兩種方法都很困難,而且可能是壓倒性的。 – 2013-05-03 12:44:40

+0

還有各種各樣的MySQLi教程(如[this](http://forum.codecall.net/topic/44392-php-5-mysqli-prepared-statements/)) – kero 2013-05-03 12:46:21

+0

永遠不會信任客戶端數據...多數民衆贊成在所有:) – 2013-05-03 12:48:00

回答

3

避免SQL注入的重要一點是,您不會使用字符串連接構建查詢。

因此,而不是建立這樣的查詢...

$sql = "select count(*) from entry where emailaddress like '" . $_POST[emailaddress] . "'"; 
$sth = $pdo->prepare($sql); 
$sth->execute(); 

...你會轉而使用綁定。通過綁定,佔位符將與電子郵件地址被替換,但數據庫知道如何報價以及如何逃脫的輸入...

$sql = 'select count(*) from entry where emailaddress like ?'; 
$sth = $pdo->prepare($sql); 
$sth->bindParam(1, $_POST[emailaddress], PDO::PARAM_STR); 
$sth->execute(); 

這個參數化查詢在PDO和SQLI工作。演示如何SQL注入工作,你可以看到​​,只需點擊下一個箭頭來填寫不良的用戶輸入。

還有一件事要考慮,綁定會給SQL注入一定的保護,但這不應該阻止您驗證用戶輸入。在你的例子中,這意味着,你檢查輸入是否真的是一個電子郵件地址,否則只是拒絕用戶輸入。

+0

這是更好的還是本質上相同的東西? ':'$ emailaddress = $ _POST ['emailaddress'];''$ stmt = $ db-> prepare('INSERT INTO entry(firstname,lastname,emailaddress, ');''$ stmt-> bindParam(':emailaddress',$ emailaddress,PDO :: PARAM_STR);' – AndB 2013-05-03 13:21:20

+0

@AndrewBrigance - 是的,使用命名參數與示例中的索引1相同,它更具可讀性。當然,你還需要綁定其他變量(名字,姓氏和參數)。 – martinstoeckli 2013-05-03 13:23:52

+0

太棒了,謝謝。 – AndB 2013-05-03 13:25:18

0

您需要轉義所有傳遞給SQL的變量,特別是所有$ _POST和$ _GET。

恕我直言,你可以使用PDO(例子引用:http://php.net/manual/en/pdo.quote.php)。

我希望有幫助。

+0

這是一個問題的答案,正如您所看到的,有一個指向PHP手冊的源代碼的鏈接。關於設計模式的討論在這裏是一個偏離主題。 – 2013-05-03 13:17:44