SQLセキュリティ対策
SQLによるデータベースアクセスの実装に不備があると、SQLインジェクションという脆弱性が生じます。
SQLインジェクション概要
Webアプリケーションに対する攻撃手法の1つで、SQLを使って不正にデータベースを操作することを目的としています。
その攻撃によって以下のような影響を受ける可能性があります。
・データベース内のすべての情報が外部から盗まれる。
・データベースの内容が書き換えられる
・認証を回避される(IDとPASSなしにログインされる)
・データベースサーバー上のファイルを読み出し、書き込み、プログラムの実行などが行われる。
このように非常に影響が大きな脆弱性ですので、細心の注意を払う必要があります。
対策としては、静的プレースホルダを利用してSQLを呼び出すことです。
対策
プレースホルダによりSQL文を組み立てていきます。
プレースホルダには、静的プレースホルダと動的プレースホルダの2種類があります。
それぞれ説明します。
静的プレースホルダ
静的プレースホルダは、値のバインドをデータベース側で行います。プレースホルダがついたままのSQL文がそのままデータベースに送られ、その後バインド値がデータベースに送られ値を当てはめSQLが実行されます。
プレースホルダの状態でSQL文がコンパイルされるため、後からSQL文が変更されることはありません。
動的プレースホルダ
動的プレースホルダは、アプリ側で値をバインドしてからデータベースに送る方式です。処理系にバグがなければSQLインジェクションは発生しません。
静的、動的どちらを使ってもインジェクションは解消されますが、原理的にインジェクション可能性がないという点で静的プレースホルダの方が優れています。
可能であれば静的プレースホルダを使うべきです。
デフォルトの設定は動的プレースホルダになっているので、静的プレースホルダを使用する設定に変えます。
変え方は、Mysqlに接続するときに下記の文を追加します。
1 2 | //静的プレースホルダ使用する方法 PDO::ATTR_EMULATE_PREPARES => false |
プレースホルダを利用した例
1 | select * from book where book_name = ? order by book_id |
例の「?」がプレースホルダで可変のパラメータ部分に埋め込んでおくものです。
以下サンプルです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <?php try { // MySQLサーバへ接続 $dbh = new PDO("mysql:host=localhost; dbname=pdotest", "root", "password", array( PDO::MYSQL_ATTR_READ_DEFAULT_FILE => '/etc/mysql/my.cnf', PDO::MYSQL_ATTR_READ_DEFAULT_GROUP => 'cliant', //静的プレースホルダ使用 PDO::ATTR_EMULATE_PREPARES => false )); } catch(PDOException $e){ var_dump($e->getMessage()); } $sql = "select * from book where book_name = ? order by book_id "; $stmt = $dbh->prepare($sql); //プレースホルダ部分に値をバインド $stmt -> bindValue(1, $book_name, PDO::PARAM_STR); //実行 $stmt -> execute(); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); //切断 $dbh = null; ?> |
このように書くことで、静的プレースホルダを使用しSQLインジェクションを防ぐことができます。
Author Profile
スターフィールド編集部
SHARE