PHP Database Security(データベースのセキュリティ)
すなわちSQLインジェクションのための防御策である。
■SQLインジェクションの実例
以下のログインフォームで考える。
<form method="post" action="login.php"> Name: <input type="text" name="name" /> Password: <input type="password" name="password" /> <input type="submit" /> </form>
以下のコードで存在するユーザかどうか、DBに問い合わせて検証する。
<?php
$password = md5($_POST['password']);
$sql = "SELECT * FROM `user` WHERE `name` = '{$_POST['name']}' AND `password` = '{$password}'";
?>
一見、何の問題も無いようだが、Nameに「1′ OR 1 = 1 –」とすると以下のSQL文を実行することになる。
SELECT * FROM `user` WHERE `name` = '1' OR 1 = 1 --' AND `password` = 'password_str'
「–」以降は改行コードまで全てコメントとみなされ、条件「`name` = ’1′」は殆ど成立しないが、条件「1 = 1」が常に成立し、全てのユーザデータが返ることになる。従って、アルゴリズムにもよるが、ログインが常にできてしまう。
対策1
以下のように、プリペアドステートメントを用いる。
<?php
try {
$dsn = 'mysql:host=localhost;dbname=db';
$dbh = new PDO($dsn, DB_USER, DB_PASS);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
}
catch(PDOException $e){
//code
}
$password = md5($_POST['password']);
$sql = "SELECT * FROM `user` WHERE `name` = ? AND `password` = ?";
$stmt = $dbh->prepare($sql);
$stmt->execute(array(
$_POST['name'],
$pasword
));
$result = $stmt->fetchAll();
?>
対策2
以下のように、エスケープ処理を忘れずに行う。
$dbh = mysql_connect(DB_HOST, DB_USER, DB_PASS);
mysql_select_db(DB_NAME, $dbh);
$password = md5($_POST['password']);
$name = mysql_real_escape_string($_POST['name']);
$sql = "SELECT * FROM `user` WHERE `name` = '{$name}' AND `password` = '{$password}'";
但し、ログインフォームなので大概において英数字のユーザ名なのでフィルタリングすることをお勧めする。
TrackBack URL :
Comments (0)
コメントはまだありません»
コメントはまだありません。
この投稿へのコメントの RSS フィード。TrackBack URL
コメントする