2012-03-04 34 views
1

previous question I had postedに応答して、データベースをSQLインジェクションに開放しているという応答がありました。何のSQLインジェクションが発生しない可能性があることを確認するために「[-ZA-Z0-9]// ^」私は、サーバー側の検証チェックを行うことができますということでしたが、それは十分であるSQLインジェクションを防止するために必要なステップは何ですか?

<?php 


     $firstname = stripslashes(strip_tags($_POST['firstname'])); 

     $lastname = stripslashes(strip_tags($_POST['lastname'])); 
     $email = stripslashes(strip_tags($_POST['email'])); 
     $title = stripslashes(strip_tags($_POST['title'])); 
     $organization = stripslashes(strip_tags($_POST['organization'])); 


    $pdbHost = "localhost"; 
    $pdbUserName = "******"; 
    $pdbPassword = "******"; 
    $pdbName  = "db1080824_emails"; 



    // Connect to mySQL 
    $conlink = mysql_connect($pdbHost, $pdbUserName, $pdbPassword); 
    if(!$conlink) {die('Unable to connect to '.$pdbHost);} 
    if (!mysql_select_db($pdbName, $conlink)){die('Cannot find database '.$pdbName);} 

    //SQL query 

     $SQL2="INSERT INTO `db1080824_emails`.`emails` (`record_id` ,`firstname`,`lastname`,`email`,`title`,`organization`)VALUES (NULL , '".$firstname."', '".$lastname."', '".$email."', '".$title."', '".$organization."')"; 

     mysql_query($SQL2); 
    // Connect to Closing the connection 
    mysql_close($conlink); 
?> 

提案:コードを以下に示します。データのサニタイズを確実にするために従うべきベストプラクティスがありますか?

+0

http://en.wikipedia.org/wiki/SQL_injection - どのように行うの上よりHOを読みますwを "元に戻す" – Joseph

+1

準備されたステートメントのみを使用します。期間。 – knittl

+3

最初のステップ:** mysql_query **の使用を中止し、PDOやmysqliのような最新のAPIを使用します。両方とも、準備されたステートメントをサポートしています。これは、適切に使用されると、SQLインジェクションを防止するための手段になります。 – cHao

答えて

3

準備文を使用してください。真剣に。これを行う簡単な方法は、PHPのデータベースラッパーPDOを使用することです。

$firstname = $_POST['firstname']; 
$lastname = …; 
… 

$db = new PDO('mysql:host=hostname;dbname=dbname', 'username', 'password'); 
$stmt = $db->prepare('INSERT INTO `db1080824_emails`.`emails` (`firstname`,`lastname`,`email`,`title`,`organization`) 
    VALUES (:firstname, :lastname, :email, :title, :organization)'); 
$stmt->execute(array(
    ':firstname' => $firstname, 
    ':lastname' => $lastname, 
    ':email' => $email, 
    ':title' => $title, 
    ':organization' => $organization)); 
1

SQLインジェクションを防止するためにmysql_real_escape_string()を使用してください。この機能だけで十分です。

また、@knittlが述べたように、prepared statementを使うことは、それを防ぐための非常に良い方法です。しかし、通常のmysql_ * libaryはそれをサポートしていません。そんなことをするには、PDOやMySQLiというライブラリが必要です。 PDOやMySQLiに切り替えることをお勧めします。これは、より高いPHPバージョンではmysql_ * libaryが非推奨になるためです。あなたのコードを改善するための

他のいくつかのヒント:

  • die()を使用しないでください。あなたが間違いを犯すなら、あなたは死なないでしょう。エラーを素早く処理し、必要な場所に配置する方がよいでしょう。
  • mysql_close()は必要ありません。 PHPは実行終了時にすべての接続を閉じます。
  • クエリでエラー処理が使用され、クエリでfalseが返された場合は問題が発生します。クエリで何かが行われた場合は、mysql_affected_rows()またはmysql_num_rowsもチェックしてください。

私はこの回答のコメントに答えるため。文字列の場合は、mysql_real_escape_ 文字列を使用する必要があります。あなたがmysql_real_escape_string()を使用している場合は、クエリで文字列を囲む引用符(')を入れていることを確認してください:

$query = "SELECT foo FROM bar WHERE name = '".mysql_real_escape_string($_POST['name'])."'"; 

あなたがintergersまたは任意の他の番号を使用する場合はtypecastingなくエスケープ関数を使用する必要があります。

$query = "SELECT foo FROM bar WHERE id = ".(int) $_POST['id']; 
+0

mysql_real_escape_stringを使用することができますが、あなたが何をしているのかが分かっている場合に限ります。つまり、引用符で囲まれた値(ただしその値はすべて)に対してのみ使用し、クライアント側(PHP)およびサーバー/接続側(mysql)に適切なエンコーディングを設定します。ちょっとしたことを見逃して、もう一度やり直すことができます。 – knittl

+0

この機能は注入を防ぐものではありません。 Go figure –

+0

コメントありがとう、私はいくつかの情報で私の答えを更新しました。 @ Col.Shrapnelなぜこの機能はSQLインジェクションを防ぐためではないのですか? php.netから: 'この関数がデータをエスケープするために使われない場合、クエリはSQLインジェクション攻撃に対して脆弱です。 ' –

0

I PDOを使用してきた、私はこれは注入から保護することを信じている:

$db_user = "****"; 
$db_pass= "****"; 
$dsn = "mysql:dbname=yourdatabasename; host=localhost"; 
$dbh = new PDO($dsn, $db_user, $db_pass); 

$sql = 'INSERT INTO 
     emails(firstname, lastname, email, title, organization) 
     VALUES(:firstname,:lastname,:email,:title,:organization)'; 
$data = array(':firstname'=>$firstname, 
       ':lastname'=>$lastname, 
       ':email'=>$email, 
       ':title'=>$title, 
       ':organization'=>$organization); 

$sth = $dbh->prepare($sql); 
$sth->execute($data); 
+0

私は明らかにタイプが遅すぎます! – TerryProbert

関連する問題