サイバー 大 学 IT 総 合 学 部 専 門 基 礎 科 目 科 目 名 データベース 入 門 SQLインジェクション 対 策 ( 学 習 資 料 ) 上 出 哲 広
学 習 目 標 SQLインジェクションについて 理 解 する SQLインジェクションの 実 験 をする SQLインジェクション 対 策 について 理 解 する インターネットに 公 開 する 際 の 対 策 について 理 解 する
参 考 文 献 西 沢 夢 路 基 礎 からのMySQL [ 改 定 版 ] SoftBank Creative 2012
SQLインジェクションとは
SQLインジェクションとは 不 正 にSQL 文 を 注 入 (injection)させる 攻 撃 Webアプリケーションの 作 者 が 想 定 していない SQL 文 を 実 行 させることで データベースシステ ムを 不 正 に 操 作 する 攻 撃 手 法 アプリケーションの 入 力 テキストボックスに 不 正 なコマンドを 入 力 することによって 実 現 される アプリケーションが 入 力 値 を 適 切 にエスケープし ないままSQL 中 に 展 開 することで 発 生
SQLインジェクションの 例 例 1: 複 数 のSQL 文 を 注 入 することによるデー タの 破 壊 や 改 竄 例 2:ストアドプロシージャを 実 行 することによる 情 報 の 漏 洩 や 改 竄 例 3(ブラインドSQLインジェクション): SELECTの 条 件 式 にデータベース 内 の 情 報 を 確 認 するようなサブクエリを 含 ませ その 抽 出 の 成 否 によって 本 来 参 照 することのできないデ ータベース 内 の 情 報 (テーブル 名 など)を 知 る
SQLインジェクションの 具 体 例 (1) 指 定 したレコード 番 号 のレコードを 削 除 する 機 能 をもつアプリを 仮 定 する 削 除 するレコー ドの 番 号 をテキストボックスに 入 力 すると 対 応 するレコードが 削 除 される テキストボックスにレコー ド 番 号 を 入 力
SQLインジェクションの 具 体 例 (2) テキストボックスに 入 力 された 番 号 を 送 信 すると PHPスクリプトは 以 下 のSQL 文 を 発 行 する: DELETE FROM tbk WHERE bang=$b1_d $b1_d の 部 分 に 数 値 が 入 力 されることが 想 定 されている 一 方 この 部 分 に 6 or 1=1 が 入 力 された 場 合 1=1 はいつも 真 なので テーブ ルtbkのすべてのレコードが 削 除 されてしまう この 例 については 後 ほど 実 験 で 確 認 する
SQLインジェクション 対 策 (1) 意 図 したデータ( 例 えば 数 値 ) 以 外 を 入 力 させ ないようにする 意 図 したデータ 以 外 のデータが 送 信 された 場 合 正 規 表 現 やPHPのpreg_match 関 数 など を 使 用 してDELETEコマンドを 含 むクエリを 実 行 させないようにする 具 体 例 を 後 程 説 明 する
SQLインジェクション 対 策 (2) 入 力 されたタグなどの 特 殊 文 字 を 別 の 文 字 列 に 変 換 し 意 図 しないタグを 実 行 させないように する このような 処 理 をエスケープ 処 理 という PHPのhtmlspecialchars 関 数 を 使 用 すると 以 下 のような 変 換 を 実 現 できる: < < > > & & amp; " ' 具 体 例 を 後 程 説 明 する
サニタイジングとエスケープ 処 理 サニタイジング(sanitizing, 無 害 化 ): 入 力 デー タを 無 害 化 すること サニタイジングの 手 法 の 一 つとして エスケープ 処 理 がある エスケープ 処 理 : 入 力 データ 中 に 含 まれる 不 エスケープ 処 理 : 入 力 データ 中 に 含 まれる 不 正 の 原 因 となるような 記 号 特 殊 文 字 を 適 切 な 文 字 列 に 置 換 すること 例 : 入 力 データに & や < などのメタキャラクターが 存 在 した 場 合 以 下 のような 変 換 を 行 う: & & < <
SQLインジェクションの 実 験
実 験 に 使 用 するアプリの 概 要 データベースに 接 続 して 以 下 の 処 理 を 行 う 簡 易 掲 示 板 :(1) レコードを 表 示 (2) レコードを 挿 入 ( 氏 名 とメッセージを 書 き 込 む) (3) レコード を 削 除 (4) レコードを 検 索 この 掲 示 板 アプリは 学 習 資 料 簡 易 掲 示 板 アプ リの 作 成 で 紹 介 したものと 同 じ 機 能 をもつ ここ では 上 記 資 料 で 作 成 した4つのphpソースコー ドを 統 合 したソースコード(kantan2_syori.php) を 使 用 する テーブルは 上 記 資 料 で 作 成 したものと 同 じもの (データベースdb1のテーブルtbk)を 使 用 する
実 験 で 使 用 するテーブルの 作 成 (1) データベース db1 に アプリで 操 作 するため のテーブル tbk を 作 成 する tbk を 構 成 するカラムは 番 号 氏 名 メッ セージ 用 とする それぞれ bang nama mess というカラム 名 を 付 ける カラム bang は メッセージの 連 続 番 号 を 表 示 するために 使 用 する 連 続 番 号 表 示 機 能 を 付 ける 主 キーを 設 定 する
実 験 で 使 用 するテーブルの 作 成 (2) コマンドプロンプトでMySQLを 起 動 して 以 下 のコマンドを 実 行 する CREATE TABLE tbk (bang INT AUTO_INCREMENT PRIMARY KEY, nama VARCHAR(100), mess VARCHAR(100)); 以 下 を 実 行 してtbkの 状 態 を 確 かめる: DESC tbk;
実 験 に 使 用 するソースコード kantan2.html: 簡 易 掲 示 板 のトップページ kantan2_syori.txt: レコードを 表 示 挿 入 削 除 検 索 する 機 能 を 記 述 してあるPHPスクリ プトのソースコード
kantan2.htmlの 説 明 簡 易 掲 示 板 のトップページを 表 示 する 表 示 挿 入 削 除 検 索 の 機 能 を 持 つ 表 示 挿 入 削 除 検 索 の 機 能 を 持 つ PHPスクリプト kantan2_shyori.php を 呼 び 出 すwebページ
kantan2_syori.txtの 説 明 レコードを 表 示 挿 入 削 除 検 索 するPHPス クリプトのソースコード 以 下 のパスワード 部 分 を 自 分 の 使 用 してい るMySQLのパスワードに 書 き 換 える 必 要 が ある 以 下 はパスワードが kamide の 場 合 : $s=mysql_connect( localhost, root, kamide ) or die( 失 敗 しました ); このパスワード 部 分 を 書 き 換 えた 後 拡 張 子 を txt から php に 書 き 換 える
Kantan2_syori.txt この 部 分 に 自 分 のMySQLパスワードを 記 述
実 行 例 (1) kantan2.html と kantan2_syori.php を 以 下 のフォルダに 格 納 する: C: xampp htdocs ブラウザのアドレスバーに 以 下 を 入 力 する: http://localhost/kantan2.html 簡 易 掲 示 板 が 表 示 される 掲 示 板 のテキストボックスに 名 前 とメッセージ を 入 力 して 送 信 をクリックする 実 行 結 果 が 表 示 される
実 行 例 (2) http://localhost/kantan2.htmlを 入 力 名 前 とメッセージを 入 力 して 送 信 をクリック
実 行 例 (3) 入 力 結 果 が 表 示 される
実 行 例 (4) 削 除 ボックスに 6 or 1=1 を 入 力 送 信 をク リックする テキストボックスに 入 力 された 番 号 を 送 信 する とPHPスクリプトはSQL 文 DELETE FROM tbk WHERE bang=$b1_d を 発 行 する $b1_d の 部 分 に 6 or 1=1 が 入 力 された 場 合 1=1 はいつも 真 なので テーブルtbkのす べてのレコードが 削 除 されてしまう
実 行 例 (5) 削 除 ボックスに 6 or 1=1 を 入 力 送 信 を 実 行
実 行 例 (6) 実 行 結 果 先 程 まであったデータベースの 内 容 (コメント6 番 -11 番 )がすべて 消 えてしまった テキストボックスに 入 力 された 番 号 を 送 信 するとPHPスクリプトは SQL 文 DELETE FROM tbk WHERE bang=$b1_d を 発 行 する $b1_d の 部 分 に 6 or 1=1 が 入 力 された 場 合 1=1 はいつも 真 なので テーブルtbkのすべてのレコードが 削 除 されてしまう
SQLインジェクション 対 策
いろいろな 対 策 SQLインジェクション 対 策 として 以 下 の 方 法 がある: (1) 正 規 表 現 とpreg_match 関 数 を 使 用 して 数 値 以 外 のデータを 排 除 する (2) htmlspecialchars 関 数 を 使 用 してエスケ ープ 処 理 を 施 す 以 下 これらについて 順 に 説 明 する
正 規 表 現 とは 文 字 列 のパターンを 記 述 する 方 法 preg_match 関 数 と 組 み 合 わせて 使 用 すること により あるパターンの 文 字 列 を 入 力 から 排 除 する 仕 組 みを 記 述 できる 正 規 表 現 では 例 えば[ ] 内 の 文 字 がどこかに 含 まれていることを 表 すことができる 例 : [0-9]: ど こかに 数 字 が 含 まれていることを 表 す 後 述
正 規 表 現 の 例 (1) [7]: どこかに7が 含 まれていることを 表 す [0-9]: どこかに 数 値 が 含 まれていることを 表 す [a-z]: どこかに 小 文 字 のアルファベットが 含 まれ ていることを 表 す [A-Za-z]: どこかに 大 文 字 か 小 文 字 のアルファベ ットが 含 まれていることを 表 す [A-Z][0-9]: どこかに 最 初 が 大 文 字 のアルファ ベット で 次 が 数 字 という 連 続 した 文 字 のパタ ーンが 含 まれていることを 表 す
正 規 表 現 の 例 (2) [^0-9]: 0から9の 文 字 以 外 が 含 まれている( 数 字 以 外 が 含 まれている)ことを 表 す [^A]: A 以 外 が 含 まれていることを 表 す [^A-Z]: 大 文 字 のアルファベット 以 外 が 含 まれて いることを 表 す [^0-9a-zA-Z]: 数 字 とアルファベット 以 外 が 含 ま れていることを 表 す
正 規 表 現 の 例 (3) ^の 次 の 文 字 で 始 まっていることを 表 す 例 : ^h: hで 始 まっている $の 前 の 文 字 で 終 わっていることを 表 す 例 : E$: Eで 終 わっている { }の 前 の 文 字 が{ } 内 の 回 数 だけ 連 続 している ことを 表 す 例 : 7{3}: どこかに7が3 個 以 上 連 続 して 含 まれ ている
preg_match 関 数 正 規 表 現 を 使 ってあいまい 検 索 を 行 うための 関 数 あいまい 検 索 : だいたいこんな 感 じの 文 字 を 探 しなさい というような 対 象 範 囲 を 広 めに 取 った 検 索 preg_match 関 数 の 書 式 : preg_mach(/ 正 規 表 現 /, 調 査 する 文 字 列 )
preg_match 関 数 の 記 述 例 - の 形 式 の 郵 便 番 号 が 入 力 されていることをチェックするPHPスクリプト: <?php?> $m=``107-0052``; if(preg_mach(``/^[0-9]{3}-[0-9]{4}$/``,$m)){ print ``OK``; }else{ print ``Error``; }
実 験 例 のPHPスクリプトの 改 良 例 実 験 で 使 用 したスクリプトの mysql_query("delete FROM tbk WHERE bang=$b1_d"); の 部 分 を 正 規 表 現 とpreg_mach 関 数 を 使 用 して 以 下 のように 書 き 換 える: if(preg_match("/[^0-9]/",$b1_d)){ print "<FONT COLOR='red'> 数 字 以 外 は 入 力 するなボケ!</FONT><BR>"; }else{ mysql_query("delete FROM tbk WHERE bang=$b1_d"); }
htmlspecialchars 関 数 タグなどの 特 殊 文 字 を 別 の 文 字 列 に 変 換 す る 関 数 エスケープ 処 理 に 使 用 する htmlspecialchars 関 数 の 書 式 : htmlspecialchars( 文 字 列 ) htmlspecialchars 関 数 による 変 換 例 : 変 換 前 < 変 換 後 < 変 換 前 > 変 換 後 > 変 換 前 & 変 換 後 & 変 換 前 `` 変 換 後 " 変 換 前 ` 変 換 後 '
エスケープ 処 理 の 実 験 使 用 するソースコード(エスケープ 処 理 なし): okuri.html: ボックスに 文 字 列 を 入 力 して 送 信 uke.php: 送 信 された 文 字 列 を 受 け 取 り 表 示 使 用 するソースコード(エスケープ 処 理 あり): 上 記 のソースコードを 改 良 したもの okuri_anzen.html uke._anzen.php: htmlspecialchars 関 数 を 使 用
エスケープ 処 理 なしの 場 合 uke.php の 内 容 (エスケープ 処 理 なし): <?php print $_POST["a"];?> okuri.html と uke.php を 以 下 のフォルダに 格 納 する: C: xampp htdocs ブラウザのアドレスバーに 以 下 を 入 力 する: http://localhost/okuri.html
エスケープ 処 理 なしの 実 行 例 (1) アドレスバーに http://localhost/okuri.html を 入 力 ボックスに タグ 付 き 文 字 列 <BODY bgcolor=black> を 入 力 送 信 を 押 す
エスケープ 処 理 なしの 実 行 例 (2) タグ 付 き 文 字 列 <BODY bgcolor=black> が 実 行 されてしまった その 結 果 表 示 がブラックアウトした
エスケープ 処 理 後 の 場 合 uke.php の 内 容 (エスケープ 処 理 あり): <?php htmlspecialchars($_post["a"]);?> okuri_anzen.html と uke_anzen.php を 以 下 のフォルダに 格 納 する: C: xampp htdocs ブラウザのアドレスバーに 以 下 を 入 力 する: http://localhost/okuri_anzen.html
エスケープ 処 理 後 の 実 行 例 (1) アドレスバーに http://localhost/okuri_anzen.html を 入 力 ボックスに タグ 付 き 文 字 列 <BODY bgcolor=black> を 入 力 送 信 を 押 す
エスケープ 処 理 後 の 実 行 例 (2) 入 力 文 字 列 がそのまま 表 示 された タグ 付 き 文 字 列 <BODY bgcolor=black> は 実 行 されない そのため 表 示 がブラックアウトすることはない
インターネットに 公 開 する 際 の 対 策
インターネットに 公 開 する 際 の 対 策 重 要 な 情 報 は 非 公 開 のフォルダに 外 部 ファ イルとして 格 納 する そしてそれら 外 部 ファイ ルは 別 の 場 所 ( 公 開 フォルダ)から 読 み 込 む ようにする 外 部 ファイルを 読 み 込 むためのPHP 関 数 とし て 以 下 のものがある: require_once include_once
require_once 関 数 この 関 数 でファイルを 読 み 込 んだ 場 合 ファイ ルを 一 度 だけ 読 み 込 み 読 み 込 めない 場 合 は 処 理 を 中 止 する require_once 関 数 の 書 式 : require_once( 読 み 込 みファイル 名 )
include_once 関 数 この 関 数 でファイルを 読 み 込 んだ 場 合 ファイ ルを 一 度 だけ 読 み 込 み 読 み 込 めない 場 合 も 処 理 を 続 行 する include_once 関 数 の 書 式 : include_once( 読 み 込 みファイル 名 )
require_once 関 数 の 使 用 例 重 要 な 情 報 ( 例 えば サーバ 名 ユーザ 名 パ スワード データベース 名 )を 記 述 したファイル を 作 成 する このファイルを 非 公 開 のフォルダ に 格 納 する 非 公 開 フォルダは 例 えば 公 開 されるフォルダ の 上 位 のどこかの 場 所 が 推 測 されにくい 安 全 なフォルダにする この 非 公 開 フォルダ 中 の 当 該 ファイルを 公 開 フォルダ 中 のPHPスクリプトからrequire_once 関 数 を 使 用 して 読 み 込 む
まとめ SQLインジェクション: 入 力 ボックスに 不 正 な SQL 文 や 文 字 列 を 注 入 データベースが 破 壊 さ れる 可 能 性 がある SQLインジェクション 対 策 : エスケープ 処 理 を 施 す(htmlspecialchars 関 数 を 使 用 ) タグを 無 効 化 する(preg_match 関 数 を 使 用 ) インターネット 公 開 対 策 : 重 要 ファイルは 非 公 開 フォルダに 格 納 してrequire_once 関 数 などを 使 用 してアクセスする
データベース 入 門 SQLインジェクション 対 策 ( 学 習 資 料 ) 終 わり