6、绕过 Web 应用程序保护
在理想情况下,目标端不会部署任何保护措施,因此不会阻止自动利用。否则,在针对此类目标运行任何类型的自动化工具时,我们可能会遇到问题。尽管如此,SQLMap 中加入了很多机制,可以帮助我们成功绕过这种保护。
Anti-CSRF 令牌绕过
防止使用自动化工具的第一道防线之一是将 Anti-CSRF(即跨站点请求伪造)令牌合并到所有 HTTP 请求中,尤其是那些因 Web 表单填写而生成的请求。
用最基本的术语来说,这种情况下的每个 HTTP 请求都应该有一个(有效的)令牌值,只有当用户实际访问和使用该页面时才可用。虽然最初的想法是防止出现带有恶意链接的情况,在这种情况下,仅打开这些链接会对不知情的登录用户产生不良后果(例如,打开管理员页面并添加具有预定义凭据的新用户),但此安全功能也无意中强化了针对(不需要的)自动化的应用程序。
然而,SQLMap 有一些选项可以帮助绕过反 CSRF 保护。即,最重要的选项是 --csrf-token
。通过指定令牌参数名称(它应该已经在提供的请求数据中可用),SQLMap 将自动尝试解析目标响应内容并搜索新的令牌值,以便它可以在下一个请求中使用它们。
此外,即使在用户未通过 --csrf-token
明确指定令牌名称的情况下,如果提供的参数之一包含任何常见的中缀(即 csrf
、xsrf
、token
),系统也会提示用户是否在进一步的请求中更新它:
$ sqlmap -u "http://www.example.com/" --data="id=1&csrf-token=WfF1szMUHhiokx9AHFply5L2xAOfjRkE" --csrf-token="csrf-token"
___
__H__
___ ___[,]_____ ___ ___ {1.4.9}
|_ -| . ['] | .'| . |
|___|_ [)]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[*] starting @ 22:18:01 /2020-09-18/
POST parameter 'csrf-token' appears to hold anti-CSRF token. Do you want sqlmap to automatically update it in further requests? [y/N] y
Unique(唯一) Value Bypass
在某些情况下,Web 应用程序可能只需要在预定义参数内提供唯一值。这种机制类似于上面描述的Anti-CSRF 技术,只是不需要解析网页内容。因此,通过简单地确保每个请求都有一个预定义参数的唯一值,Web 应用程序可以轻松防止 CSRF 尝试,同时避免一些自动化工具。为此,应使用选项 --randomize
,指向包含在发送前应随机化的值的参数名称:
$ sqlmap -u "http://www.example.com/?id=1&rp=29125" --randomize=rp --batch -v 5 | grep URI
URI: http://www.example.com:80/?id=1&rp=99954
URI: http://www.example.com:80/?id=1&rp=87216
URI: http://www.example.com:80/?id=9030&rp=36456
URI: http://www.example.com:80/?id=1.%2C%29%29%27.%28%28%2C%22&rp=16689
URI: http://www.example.com:80/?id=1%27xaFUVK%3C%27%22%3EHKtQrg&rp=40049
URI: http://www.example.com:80/?id=1%29%20AND%209368%3D6381%20AND%20%287422%3D7422&rp=95185
计算参数 Bypass
另一种类似的机制是 Web 应用程序期望根据某些其他参数值计算出适当的参数值。大多数情况下,一个参数值必须包含另一个参数的消息摘要(例如 h=MD5(id)
)。要绕过这个,应该使用选项 --eval
,在将请求发送到目标之前评估有效的 Python 代码:
$ sqlmap -u "http://www.example.com/?id=1&h=c4ca4238a0b923820dcc509a6f75849b" --eval="import hashlib; h=hashlib.md5(id).hexdigest()" --batch -v 5 | grep URI
URI: http://www.example.com:80/?id=1&h=c4ca4238a0b923820dcc509a6f75849b
URI: http://www.example.com:80/?id=1&h=c4ca4238a0b923820dcc509a6f75849b
URI: http://www.example.com:80/?id=9061&h=4d7e0d72898ae7ea3593eb5ebf20c744
URI: http://www.example.com:80/?id=1%2C.%2C%27%22.%2C%28.%29&h=620460a56536e2d32fb2f4842ad5a08d
URI: http://www.example.com:80/?id=1%27MyipGP%3C%27%22%3EibjjSu&h=db7c815825b14d67aaa32da09b8b2d42
URI: http://www.example.com:80/?id=1%29%20AND%209978%socks4://177.39.187.70:33283ssocks4://177.39.187.70:332833D1232%20AND%20%284955%3D4955&h=02312acd4ebe69e2528382dfff7fc5cc
IP地址隐藏
如果我们想隐藏我们的 IP 地址,或者如果某个 Web 应用程序具有将我们当前 IP 地址列入黑名单的保护机制,我们可以尝试使用代理或匿名网络 Tor。可以使用选项 --proxy
设置代理(例如 --proxy="socks4://177.39.187.70:33283"
),我们应该在其中添加一个工作代理。
除此之外,如果我们有一个代理列表,我们可以使用选项 --proxy-file
将它们提供给 SQLMap。这样,SQLMap 将按顺序遍历列表,如果出现任何问题(例如,将 IP 地址列入黑名单),它只会从列表中的当前跳到下一个。另一种选择是使用 Tor 网络提供易于使用的匿名化,我们的 IP 可以出现在大量 Tor 出口节点列表中的任何地方。当在本地机器上正确安装时,本地端口 9050 或 9150 应该有一个 SOCKS4
代理服务。通过使用开关 --tor
,SQLMap 将自动尝试找到本地端口并适当地使用它。
如果我们想确保 Tor 被正确使用,以防止不必要的行为,我们可以使用开关 --check-tor
。在这种情况下,SQLMap 将连接到 https://check.torproject.org/
并检查预期结果的响应(即,Congratulations
出现在里面)。
WAF Bypass
每当我们运行 SQLMap 时,作为初始测试的一部分,SQLMap 会使用不存在的参数名称(例如?pfov=...
)发送一个预定义的恶意负载,以测试是否存在 WAF(Web 应用程序防火墙)。在用户和目标之间有任何保护的情况下,与原始响应相比会有实质性的变化。例如,如果实施了最流行的 WAF 解决方案之一 (ModSecurity),则在此类请求之后应该有 406 - Not Acceptable
响应。
在检测到阳性的情况下,为了识别实际的保护机制,SQLMap 使用第三方库 identYwaf,其中包含 80 种不同的 WAF 解决方案的签名。如果我们想完全跳过这个启发式测试(即产生更少的噪音),我们可以使用开关 --skip-waf
。
用户代理黑名单绕过
如果在运行 SQLMap 时出现直接问题(例如,从一开始就出现 HTTP 错误代码 5XX),我们首先应该想到的事情之一是 SQLMap 使用的默认用户代理(例如 User-agent: sqlmap/ 1.4.9(http://sqlmap.org)
)。
使用开关 --random-agent
绕过这一点很简单,它使用从浏览器使用的大量值中随机选择的值更改默认用户代理。
注意:如果在运行期间检测到某种形式的保护,我们可以预料目标会出现问题,甚至其他安全机制也会出现问题。主要原因是此类防护措施的不断发展和新改进,留给攻击者的机动空间越来越小。
Tamper Scripts
最后,在 SQLMap 中实现的绕过 WAF/IPS 解决方案的最流行机制之一是所谓的“Tamper”脚本。Tamper 脚本是一种特殊的 (Python) 脚本,用于在发送到目标之前修改请求,在大多数情况下绕过某些保护。
例如,最流行的 Tamper 脚本之一是将所有出现的大于运算符 (>
) 替换为 NOT BETWEEN AND #
,将等于运算符 (=
) 替换为 BETWEEN # AND #
。这样,许多原始保护机制(主要集中在防止 XSS 攻击)很容易被绕过,至少对于 SQLi 而言是这样。
Tamper 脚本可以在 --tamper
选项(例如 --tamper=between,randomcase
)中一个接一个地链接起来,它们根据预定义的优先级运行。预定义优先级以防止任何不需要的行为,因为某些脚本通过修改其 SQL 语法(例如 ifnull2ifisnull)来修改有效负载。相反,一些 Tamper 脚本不关心内部内容(例如 appendnullbyte)。
Tamper 脚本可以修改请求的任何部分,但大多数会更改负载内容。最著名的篡改脚本如下:
Tamper-Script | Description |
---|---|
0eunion |
用 e0UNION 替换 UNION 的实例 |
base64encode |
Base64 编码给定负载中的所有字符 |
between |
将大于运算符 (> ) 替换为 NOT BETWEEN AND # ,将等于运算符 (= ) 替换为 BETWEEN # AND # |
commalesslimit |
用 LIMIT N OFFSET M 对应物替换 (MySQL) LIMIT M, N 实例 |
equaltolike |
将所有出现的运算符等于 (= ) 替换为 LIKE 对应项 |
halfversionedmorekeywords |
在每个关键字前添加 (MySQL) 版本注释 |
modsecurityversioned |
包含带有 (MySQL) 版本注释的完整查询 |
modsecurityzeroversioned |
包含带有 (MySQL) 零版本注释的完整查询 |
percentage |
在每个字符前添加百分号 (% )(例如 SELECT -> %S%E%L%E%C%T) |
plus2concat |
用 (MsSQL) 函数 CONCAT() 对应项替换加号运算符 (+ ) |
randomcase |
用随机大小写值替换每个关键字字符(例如 SELECT -> SEleCt) |
space2comment |
将空格字符 ( ) 替换为注释 `/ |
space2dash |
将空格字符 ( ) 替换为破折号注释 (-- ),后跟随机字符串和新行 (\n ) |
space2hash |
将空格字符 ( ) 的 (MySQL) 实例替换为井号字符 (#),后跟随机字符串和换行符 (\n ) |
space2mssqlblank |
用一组有效的备用字符中的随机空白字符替换 (MsSQL) 空格字符 ( ) 的实例 |
symboliclogical |
将 AND 和 OR 逻辑运算符替换为其符号对应项(&& 和 || ) |
versionedkeywords |
用 (MySQL) 版本注释将每个非函数关键字括起来 |
versionedmorekeywords |
用 (MySQL) 版本注释括起每个关键字 |
要获得已实施的篡改脚本的完整列表以及上面的描述,可以使用开关 --list-tampers
。我们还可以为任何自定义类型的攻击开发自定义篡改脚本,例如二阶 SQLi。
其他 Bypasses
在其他保护 Bypass 机制中,还有两个值得一提。第一个是 Chunked
传输编码,使用开关 --chunked
打开,它将 POST 请求的主体拆分为所谓的“chunks(块)”。列入黑名单的 SQL 关键字在块之间拆分,这样包含它们的请求可以在不被注意的情况下通过。
其他绕过机制是 HTTP 参数污染 (HPP,HTTP parameter pollution
),其中有效负载以与 --chunked
在不同的相同参数命名值之间的类似方式拆分(例如 ?id=1&id=UNION&id=SELECT&id=username,password&id=FROM&id =users...
),如果支持它(例如 ASP
),则由目标平台连接。