0%

利用链分析

关于序列化与反序列化过程中使用的代理选择器以及代理这里就不再介绍了,代理(Surrogate)可以使得不能被序列化的类被序列化,具体的操作需要用户自行实现一个ISerializationSurrogate接口并实现其GetObjectData以及SetObjectData方法。

阅读全文 »

利用链分析

TextFormattingRunProperties实现了System.Runtime.Serialization.ISerializable接口,故其在序列化以及反序列化过程中会自动执行GetObjectData以及特定的构造方法internal TextFormattingRunProperties(SerializationInfo info, StreamingContext context)
img1
我们直接从反序列化时执行的特殊构造方法创建对象的过程开始。
在调用构造方法创建对象期间会调用GetObjectFromSerializationInfo方法从serializationInfo中获取属性值。

阅读全文 »

本文总结了一些常见的Java动态代理InvocationHandler在反序列化中的作用,这些InvocationHandler根据其功能的不同往往能达成奇妙的效果,本文对这些类进行了梳理总结,方便漏洞挖掘时能够快速有效地串联其各个Gadgets形成有效的利用链。

阅读全文 »

成员变量含义

变量名 默认值 含义
DEFAULT_INITIAL_CAPACITY 16 默认初始化容量
MAXIMUM_CAPACITY 1 << 30 最大容量
DEFAULT_LOAD_FACTOR 0.75 默认加载因子,当数组中元素数量超过总长度的0.75的时候会进行自动扩容
TREEIFY_THRESHOLD 8 当链表长度超过8的时候会将链表转换为红黑树
UNTREEIFY_THRESHOLD 6 当链表元素少于6的时候会将红黑树转换为链表
MIN_TREEIFY_CAPACITY 64 只有当数组长度大于64的时候才会执行链表的树化,因为链表树化会增加空间复杂度,如果只要某一个链表长度超过8就进行树化得到的查询时间优化与增加的空间消耗两相比较是得不偿失的
阅读全文 »

过滤器初始化

Struts2 的访问从配置的org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter过滤器开始。
过滤器在程序加载过程中首先被执行的是init方法

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
public void init(FilterConfig filterConfig) throws ServletException {
// 创建 InitOperations 对象 负责各个关键组件的初始化操作
InitOperations init = createInitOperations();
Dispatcher dispatcher = null;
try {
// 简单的包装了一下 filterConfig
FilterHostConfig config = new FilterHostConfig(filterConfig);
// 初始化日志记录器 不是重点
init.initLogging(config);
// 初始化dispatcher 重点
dispatcher = init.initDispatcher(config);
// 初始化静态类容加载器
init.initStaticContentLoader(config, dispatcher);

prepare = createPrepareOperations(dispatcher);
execute = createExecuteOperations(dispatcher);
// 设置将哪些path排除到strutsd的filter之外 这些请求将不会被struts处理 而交给之后的filter或者servlet处理
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
// 用户可以继承该过滤器 重写该方法 做一些额外的初始化操作
postInit(dispatcher, filterConfig);
} finally {
if (dispatcher != null) {
dispatcher.cleanUpAfterInit();
}
init.cleanup();
}
}
阅读全文 »

漏洞成因

crushftp.server.ServerSessionHTTP.handle_http_requests方法中对用户名有特殊处理。
当用户名中不包含~的时候 lookup_user_pass的值为true

1
2
3
4
5
6
boolean lookup_user_pass = true;
if (s3_username.indexOf("~") >= 0) {
user_pass = s3_username.substring(s3_username.indexOf("~") + 1);
user_name = s3_username.substring(0, s3_username.indexOf("~"));
lookup_user_pass = false;
}

后面在调用 login_user_pass 方法的时候传入的第一个参数就是lookup_user_pass

1
this.thisSession.login_user_pass(lookup_user_pass, false, user_name, user_pass))
阅读全文 »