SQLインジェクション対策

※動作テストは自己責任で必ず自分の環境で確認すること。

SQLインジェクションとは

データベースと連動したWebサイトで、データベースへの問合せや操作を行うプログラムにパラメータとしてSQL文の断片を与えることにより、データベースを改竄したり不正に情報を入手する攻撃。
また、そのような攻撃を許してしまうプログラムの脆弱性のこと。
多くのWebアプリケーションではデータベースの操作にSQLという言語を利用しており、ユーザーがフォームから送信した検索後などのパラメータを受け取り、これをSQL文に埋め込んでデータベースへの問合せや操作を行う。
このとき、SQLの断片として解釈出来る文字列をパラメータに含めることで、本来アクセス出来ない情報を表示させたりすることができてしまう場合がある。
このような攻撃手法をSQLインジェクションという。
SQLインジェクションはパラメータをSQL文に埋め込む際にきちんとチェックが行われていない為に起こる。
パラメータ中にSQL構文やSQL文で特殊な意味を持つ文字が含まれていないか調べ含まれていた場合はこれを削除したり別の文字列に変換(エスケープ)するといった処理を組み込む必要がある。

データベースへの問合せ部分を乗っ取り、パスワードを盗んだり、データを改竄する攻撃

■攻撃先

SQL文構成部
クエリ発行関数mysql_query()mysqli_query()pg_query()sqlite_query()

■被害

あらゆるデータベース操作を行われる(PsotgreSQL、SQLiteの場合)
パスワードを盗まれる(SELECT文)
サイト内の内容を改竄される(INSERT/UPDATE文)
INTO OUTFILE等のファイルに書き出し系コマンドを利用してのPHP任意コード実行

CASE 1

<?php
$result = mysql_query('SELECT name FROM bbs WHERE id='.$_GET['id'], $conn);
while($data = mysql_fetch_array($result))
{
  print_r($data);
}
?>
http://【被害サイト】/?id=1 UNION SELECT pass FROM bbs WHERE id=1
などでアクセスするとパスワードが表示される。

対策方法

<?php
// クエリ文生成時にエスケープ
$result = mysql_query('SELECT name FROM bbs WHERE id='.addslashes($_GET['id']), $conn);
?>
addslashes()mysql_real_escape_string()pg_escape_string()等を利用する。
addslashes()のメリットは処理が速い、データベースコネクションの有無に影響されない、逆変換が容易、magic_quotes_gpc設定との相性が良い等。

Case 2

<?php
$order_sql = addslashes($_GET['order']);
mysql_query('SELECT name FROM bbs ORDER BY '.$order_sql, $conn);
?>
上記のコードに対して、リクエスト変数に「;」が含まれると、それ以降のあらゆるSQLが発行可能となる。

対策方法

<?php
// ホワイトリスト法
$order_sql = in_array($_GET['order'], array('name ASC', 'postdate DESC')) ? $_GET['order'] : 'postdate DESC';
mysql_query('SELECT name FROM bbs ORDER BY '.$order_sql, $conn);
?>
引用符で囲まれていない要素にリクエスが混ざる場合はホワイトリスト法でチェックする。
上記の例では、カラム名やSQL予約後をGET変数から受け取っているが、本来SQL文の構成要素は配列として内部に持っておき、その配列のキーをGET変数で受け渡しする。

PHPサイバーテロの技法―攻撃と防御の実際

新品価格
¥1,890から
(2013/10/3 19:55時点)

Comments are closed.