SQLMap 是一个开源的渗透工具,它可以自动化检测和利用 SQL 注入缺陷以及接管数据库服务器的过程。他有一个强大的检测引擎,许多适合于终极渗透测试的小众特性和广泛的开关,从数据库指纹、从数据库获取数据到访问底层文件系统和通过带外连接在操作系统上执行命令。

SQLMap 介绍

我们在学习 SQLMap 的时候,可以根据官网的介绍来了解 SQLMap 的功能。

官网地址:https://sqlmap.org/

进入官网,我们可以看到这张图片,类似一个小针头的图标,可能为了表达我是 SQL 注入……

sqlmap is an open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of database servers. It comes with a powerful detection engine, many niche features for the ultimate penetration tester and a broad range of switches lasting from database fingerprinting, over data fetching from the database, to accessing the underlying file system and executing commands on the operating system via out-of-band connections.

根据官网的介绍,我们可以了解到 SQLMap,是一种开源渗透测试工具,它可以自动化检测和利用 SQL 注入缺陷以及接管数据库服务器的过程。他有一个强大的检测引擎,许多适合于终极渗透测试的小众特性和广泛的开关,从数据库指纹、从数据库获取数据到访问底层文件系统和通过带外连接在操作系统上执行命令

大家继续往下看官网,这里也介绍了 SQLMap 的特征,这里官网给出的特征一共有十点。大家如果英文不好的话,可以翻译一下。这些特征我们后面都会一一给大家讲解到,这里我就不做翻译了。

SQLMap 的安装

如果想使用 SQLMap 的话,需要安装 Python 环境,老版本的 SQLMap 是需要 Python2 的环境,现在则支持 Python3 了。

SQLMap 下载地址:

https://codeload.github.com/sqlmapproject/sqlmap/legacy.zip/master

下载完成后,解压目录即可,建议大家换一个目录名字,因为解压之后的目录名字比较长。

解压完成之后,我们可以测试一下,进入到 SQLMap 的目录,执行命令 python sqlmap.py –version,这个命令是查看 SQLMap 的版本。

$ python sqlmap.py --version1.5.8.6#dev# 这是最新的版本

如果看到上面的提示,说明 SQLMap 已经安装成功了。我们可以查看 SQLMap 的帮助文档:

python sqlmap.py--h 基本帮助信息python sqlmap.py--hh高级帮助信息

安装测试环境

有了 SQLMap 之后,我们还需要自己搭建一个靶场。这里我们用 SQLi-Labs,我们通过 GitHub 地址下载:

https://github.com/Audi-1/sqli-labs

SQLi-Labs 是一个专业的 SQL 注入练习平台。

这里我们还需要借助一个工具 PHPstudy。PHPstudy 可以快速帮我搭建 SQLi-Labs 所需要的环境。

PHPstudy 下载地址:

https://www.xp.cn/download.html

安装完 PHPstudy 之后,开启 MySQL 及 Apache 服务:

SQLi-Labsr 安装到 PHPstudy 目录的 WWW 中,到 sql-connections 目录下面找到 db-creds.inc,然后修改密码保存,到网页中访问,127.0.0.1/sqli,安装数据库:

这里我将下载的 SQLi-Labs 改了名字,改成了 sqli:

http://127.0.0.1/sqli/,点击安装数据库:

看到下面的页面,说明安装成功:

然后大家可以到数据库中查看 security,这个数据库到底有没有创建成功,如果看到这个数据库,说明数据已经创建成功。

至此我们的测试环境就已经搭建完成了。

SQL 注入介绍

我们直接通过具体的场景来给大家说明 SQL 注入,拿登录来说,我们一般会执行如下的 SQL 语句:

select * from users where username = '用户名' and pwd= '用户密码' 

用户名和密码是由用户输入的,假如我们用户名输入的是 ’ or 1=1 –,那数据库执行的就是:

select * from users where username = '' or 1=1 -- ' and pwd= '123';

如果这条 SQL 执行成功的话,那我就不需要密码就可以登录成功,这就是所谓的 SQL 注入。

具体来说,它是利用现有应用程序,将 SQL 命令注入到后台数据库引擎执行的能力,它可以通过在 Web 表单中输入 SQL 语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行 SQL 语句。

SQLMap 输出的级别

了解到什么是 SQL 注入,那我们在用 SQLMap 进行 SQL 注入的时候,SQLMap 会有一些输出的信息,由简单到复杂一共分为 7 个等级,分别从 0 到 6。

使用参数 -v ,来指定某个等级。默认 SQLMap 的级别为 1。

0:只显示 Python 的 tracebacks 信息、错误信息 [ERROR] 和关键信息 [CRITICAL]
1:同时显示普通信息 [INFO] 和警告信息 [WARNING]
2:同时显示调试信息 [DEBUG]
3:同时显示注入使用的攻击荷载
4:同时显示 HTTP 请求
5:同时显示 HTTP 响应头
6:同时显示 HTTP 响应体

SQLMap 获取目标

大家查看 SQLMap 的详细帮助文档,可以看到 SQLMap 有很多的功能。

我们来看第一个 Target,这是获取目标的功能。这里面有很多的参数,每个参数代表的功能都不一样。

SQLMap 连接数据库

python sqlmap.py -d "mysql://用户名:密码@地址:端口/数据库名字"--banner

查看目标系统信息:–banner

大家可以看到我们探测出 MySQL 数据的版本是 5.7.26。

SQLMap 指定目标 URL

SQLMap 直接对单一 URL 探测,参数使用 -u 或者 –url 参数。

我们可以探测自己搭建的测试环境。

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

探测的结果:

大家看到图中的 Type 是 SQL 注入的类型,我们后面会讲到。这里可以看到 SQLMap 使用了 4 种 SQL 注入的类型来进行测试。下面的 Payload 就是测试的语句。

不同类型的文件进行 SQL 探测

-x:为便于搜索引擎收录,许多网站专门为搜索引擎生成了 xml 格式的站点地图
-m:从多行文本格式文件读取多个目标,对多个目标进行探测
-r:可以将一个 HTTP 请求保存在文件中,然后使用参数 -r 加载该文件
-c:从配置文件 sqlmap.conf 中读取目标探测
xml 格式的站点地图不是特别常用,这几个文件类型,我们给大家说一些常用的。

-m 参数示例:

python sqlmap.py -m "url.txt" --bannerurl.txt 文件内容http://127.0.0.1/sqli/Less-1/" />

-c 参数示例:

SQLMap 的按照目录中有一个名为 sqlmap.conf 的文件,该文件是配置文件的模板将文件修改,添加探测目标,URL# Target URL.# Example: http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2url = http://127.0.0.1/sqli/Less-2/?id=2python sqlmap.py -c sqlmap.conf

SQLMap 设置请求参数

我们通过 python sqlmap.py -hh,查看到第二部分是请求参数,这里请求参数我们会给大家介绍一些比较常用的。SQLMap 运行时除了需要指定目标,有时还需要指定 HTTP 请求的一些细节。

HTTP 方法
一般来说,SQLMap 能自动判断出是使用 GET 方法还是 POST 方法,但在某些情况下需要的可能是 PUT 等很少见的方法,此时就需要用参数 --method 来指定方法。如:–method=put。

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

探测结果:

SQLMap 设置 POST 提交参数

我们通过 POST 请求的时候,一般会携带提交参数。这些参数会被用于 SQL 注入检测。如:

python sqlmap.py -u "http://127.0.0.1/sqli/Less-11/index.php" --data="uname=admin&passwd=admin&submit=Submit" --banner 

SQLMap 设置指定分隔符

在某些情况下,SQLMap 需要覆盖默认参数分隔符,默认是 & 才能正确地分割和单独处理每个参数,例如一些网站参数是以/作为分隔符的。

python sqlmap.py -u "http://127.0.0.1/sqli/Less-11/index.php" --data="uname=admin&passwd=admin&submit=Submit" --param-del="&" --banner

探测结果:

SQLMap 中用来设置 cookie 的参数
关于 cookie 的参数有四个:

–cookie:要测试的页面只有在登录状态下才能访问,登录状态用 cookie 识别。
–cookie-del:用于分割 cookie 值的字符。
–load-cookies:该参数用于从文件中载入 Netscape 或 wget 格式的 cookie。
–drop-set-cookie:若 HTTP 响应头中有“Set-Cookie”,SQLMap 会自动设置“Set-Cookie”设置的 cookie,并对这些 cookie 进行检测。若不想让 SQLMap 这么做,添加参数 –drop-set-cookie 即可,这样,SQLMap 会忽略“Set-Cookie”。

如果我们想用 SQLMap 来测试 cookie,我们还要搭建一个测试环境,就是 DVWA。

这是 DVWA 的 GitHub 地址:

https://github.com/digininja/DVWA

大家下载这个 ZIP 压缩包就可以了。下载到 PHPstudy 中的 WWW 目录下面。

DVWA 后台地址,先设置 DVWA Security,注入难度,选择 low

SQLMap 使用 cookie 过程:

  • 登录或浏览页面
  • 找到 cookie
  • 在 SQLMap 中使用 --cookie cookie 值

下面我们用 DVWA 来进行测试。

不带 cookie 注入:

python sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli/" />

探测结果:

带 cookie 注入:

python sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli/" />

DVWA 的 cookie 值:

由于这个探测时间比较久,我们只看最终的结果:

SQLMap 中用来设置 user-agent

user-agent:客户端运行的浏览器类型的详细信息。

我们可以通过 SQLMap 输出的等级来查看 SQLMap 的 UA:

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

-v 5 可以查看到 user-agent。

探测结果:

这个 UA 肯定在探测的时候,一眼就被识别出来了。我们可以指定 UA:

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

探测结果:

我们还可以设置一个随机的请求头,这些随机的请求在 SQLMap 目录下的 txt 文件夹中的 user-agents.txt:

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

每次的 UA 都不相同:

SQLMap 中用来设置代理

SQLMap 中设置代理是通过参数 --proxy。

设置 HTTP 代理服务器位置,格式:–proxy http(s)/ip[端口]。

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

这里的代理 IP,大家可以找一些免费的,或者去付费购买。

  • 设置 HTTP 代理服务器认证信息,参数:–proxy-cred user:pwd
  • 设置多条代理在文件中,参数:–proxy-file
python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" --proxy-file proxy.txt --bannerproxy.txt http://192.168.0.0:8080http://192.168.0.0:8080http://192.168.0.0:8080

这里由于我没有购买代理 IP,大家可以自行去测试。

SQLMap 中用来设置延迟

SQLMap 探测过程中会发送大量探测 Payload 到目标,如果默认情况过快的发包速度会导致目标预警。为了避免这样的情况发生,可以在探测设置 SQLMap 发包延迟。默认情况下,不设置延迟。

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" --delay 0.5 --banner

探测结果:

图片中大家可以看到明显的延迟。

SQLMap 中设置超时
在考虑超时 HTTP 请求之前,可以指定等待的秒数,默认是 30 秒:

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

在正常开启 PHPstudy 中的 Apache 服务的时候,可以探测到,如果关闭了 Apache 服务,大家可以发现探测是失败的。

SQLMap 中设置超时重试次数

如果请求超时了,我们可以让 SQLMap 再次去请求,通过参数 --retries 就可以。默认情况下是重试 3 次。

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

在正常情况下,请求成功是不会重试的,只有在请求失败的时候才会去重新请求。

SQLMap 避免错误请求

有时服务器检测到某个客户端错误请求过多会对其进行屏蔽,而 SQLMap 的测试往往会产生大量错误请求,为避免被屏蔽,可以时不时的产生几个正常请求以迷惑服务器。

参数:

–safe-url:隔一会就访问一下的安全 URL
–safe-post:访问安全 URL 时携带的 POST 数据
–safe-req:从文件中载入安全 HTTP 请求
–safe-freq:每次测试请求之后都会访问一下的安全 URL

SQLMap 性能优化

SQLMap 中可以设置连接为持久连接,HTTP 报文中设置 connection:keep-alive。

长连接避免重复建立连接的网络开销,但大量的长连接会严重占用服务器资源。

参数为 --keep-alive,该参数与 --proxy 矛盾。

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

–current-db,返回当前连接的数据库。

探测结果:

SQLMap 设置不接收 HTTP Body

SQLMap 中设置空连接,表示不接受 HTTP 当中的 Body。可以直接获得 HTTP 响应的大小而不用获得 HTTP 响应体,常用在盲注过程中,降低网络带宽消耗。

参数为:–null-connection

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

探测结果:

SQLMap 设置多线程

SQLMap 中设置同时发送多少个 HTTP 请求的多线程。

设置多线程参数:–thread 默认是 1 个多线程。

为了不影响目标站点服务器的性能,SQLMap 可以设置最大的线程数为 10 个:

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

探测结果,–dbs 是探测数据库的名字:

如果大家想同时设置这三个参数,可以通过 -o 参数。-o 参数相当于同时添加下面三个参数。

–keep-alive
–null-connection
–threads=3

SQLMap 自定义检测参数

在自定义检测参数这里,我们会给大家介绍两个参数分别是 --level和–risk。

SQLMap 设置探测等级
参数:–level

此参数用于指定检测级别,有 1~5 共 5 级。默认为 1,表示做最少的检测,相应的,5 级表示做最多的检测。

检测级别不仅会影响 payload 的使用,还会影响注入点的检测,GET 和 POST 参数是一直会被检测的,检测级别大于等于 2 时会检测 cookie 是否有注入,检测级别大于等于 3 时会检测 User-Agent 和 Referer 是否有注入。

用默认的级别去探测:

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

指定探测级别为 3:

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

由于探测的时间比较久,最后结果大家可以自行去测试:

SQLMap 设置风险等级

参数:–risk

此参数用于指定风险等级,有 1~3 共 3 级。默认风险等级为 1,此等级在大多数情况下对测试目标无害。风险等级 2 添加了基于时间的注入测试,等级 3 添加了 OR 测试。

若注入点是在 UPDATE 语句中,使用 OR 测试可能会修改整个表的数据,这显然不是攻击者想要看到的。因此用户需要能控制风险等级避开有潜在风险的 payload。

 python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

探测结果:

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

大家可以看到这次的探测结果很快,是因为有缓存的原因,SQLMap 会将探测的结果做一个保存,如果发现探测的地址一样,就会直接给你返回结果。

SQLMap 注入技术参数

这些参数用于对特定的 SQL 注入技术进行调整:

SQLMap 设置具体 SQL 注入技术

参数:–technique

此参数用于指定检测注入时所用技术。默认情况下 SQLMap 会使用自己支持的全部技术进行检测。此参数后跟表示检测技术的大写字母,其值为 B、E、U、S、T 或 Q,含义如下:

B:Boolean-based blind(布尔型注入)
E:Error-based(报错型注入)
U:Union query-based(可联合查询注入)
S:Stacked queries(可多语句查询注入)
T:Time-based blind(基于时间延迟注入)
Q:Inline queries(嵌套查询注入)
我们来给大家举个例子,基于布尔的盲注:

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

探测结果:

SQLMap 设置时间盲注延迟时间

参数:–time-sec

用此参数设置基于时间延迟注入中延时时长,默认为 5 秒。

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

探测结果:

如果大家不指定,默认的时间探测是 5 秒钟:

python sqlmap.py -u "http://127.0.0.1/sqli/Less-2/" />

SQLMap 设置 union 字段数

参数:–union-cols

在进行联合查询注入时,SQLMap 会自动检测列数,范围是 1 到 10。当 level 值较高时列数检测范围的上限会扩大到 50。

可以用此参数指定列数检测范围,如 --union-cols 12-18 就会让 SQLMap 的列数检测范围变成 12 到 18,当然这个范围也可以自己指定。

python sqlmap.py -u "http://127.0.0.1/sqli/Less-3/" />

探测结果,大家可以看到 union 的字段是 12~18 个:

SQLMap 设置 union 字符

参数:–union-char

默认情况下 SQLMap 进行联合查询注入时使用空字符(NULL)。但当 level 值较高时 SQLMap 会生成随机数用于联合查询注入。因为有时使用空字符注入会失败而使用随机数会成功。

使用此参数可以指定联合查询注入中使用的字符,如:–union-char 123。

默认情况下联合查询注入中使用的字符为空字符(NULL):

python sqlmap.py -u "http://127.0.0.1/sqli/Less-3/" />

探测结果:

SQLMap 设置 union 查询表

参数:–union-from

有些情况下在联合查询中必须指定一个有效和可访问的表名,否则联合查询会执行失败。

用此参数指定这个表名,如:–union-from=users。

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

SQLMap 检索 DBMS 信息

这些选项可用于枚举后端数据库信息:

检索 DBMS banner

获取后端数据库 banner 信息:

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/" />

检索 DBMS 当前用户

获取 DBMS 当前用户:

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=2"--current-user

检索 DBMS 当前数据库

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=2" --current-db

检索 DBMS 当前主机名

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=2" --hostname

枚举 DBMS 用户

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" --users

列举数据库名

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" --dbs

枚举数据库表

参数:–tables 列举数据库表明

参数:-D 数据库名字 指定具体数据库

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" --tables# 列出所有的数据库中的表python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" -D python-01 --tables # 列出 python-01 数据库中的表

枚举数据表列(字段)

参数:-- columns

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" --columns# 指定数据库 指定表明python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" -D security -T users --columns

枚举数据值

参数:–dump

1.获取到当前库名python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" --current-db2.获取该库的表明python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" --tables -D security3.获取该库中的某个表名中的列名python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" --columns -T users -D security4.获取该库中表中的列名中的某个字段的内容python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" --columns -T users -D security --dump username

检索数据表数量

如果用户只想知道表的条目数,则可以使用此参数。

参数:–count

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" --count -D python-01

设置条件获取信息

参数:–where

python sqlmap.py -u "http://127.0.0.1/sqli/Less-1/?id=1" -D security -T emails-C "id,email_id" --where="id>2" --dump

最后推荐大家一个网站:https://www.mozhe.cn/bug, 这个网站上有一些在线靶场给大家练习。