freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

对用友NC“任意文件读取”漏洞的分析
2024-01-29 11:43:57

前言:
最近看到⼀些漏洞资讯越来越离谱,⼀些错误的信息竟可以互相转发却⽆⼈察觉,今天就分析⼀下漏洞。

⽤友NC-word.docx任意⽂件读取?你确定吗?
起始时看到漏洞⽂章,所有公众号都在发该接⼝的存在任意⽂件读取,但清⼀⾊给出的poc都是读取web.xml
image

看到漏洞正好有环境当然要复现下,但复现过程中发现了不对劲,对其展开了⼀番研究。

漏洞复现

⾸先看⽹上给的POC:

http://127.0.0.1/portal/docctr/open/word.docx?disp=/WEB-INF/web.xml

看起来似乎没有没问题,试了⼀下确实"读"到了⽂件,但试了不能穿越⽬录。
image

那么再试试该其他⽂件。先查看下该⽬录下有什么⽂件。
image

试⼀下index.jsp,显示了html代码,jsp解析了,这样⽂件"读取"有点奇怪啊~

image

漏洞分析

从代码下⼿,发现了⼤问题。
关键代码如下:

package
nc.uap.lfw.file.action
; 
 
import
java.io.
IOException; 
import
javax.servlet.
RequestDispatcher; 
import
javax.servlet.
ServletException; 
import
javax.servlet.
ServletRequest; 
import
javax.servlet.
ServletResponse; 
import
javax.servlet.http.
HttpServlet; 
import
javax.servlet.http.
HttpServletRequest; 
import
javax.servlet.http.
HttpServletResponse; 
import
org.apache.commons.lang.
StringUtils; 
 
public class DocServlet extends HttpServlet { 
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws
ServletException, IOException { 
 String url = req.getParameter("disp"); 
 if (StringUtils.isEmpty(url)) //判断url是否为空
 return; 
 if (url.toLowerCase().startsWith("/portal")) //字符转⼩写,并字符串检查开头
 url = url.substring(7); //第7个字符开始提取⼦字符串
 if (StringUtils.isEmpty(url)) 
 return; 
 if (url.toLowerCase().startsWith("/docctr/open/office")) 
 return; 
 byte[] byte1 = url.getBytes("ISO-8859-1"); 
 url = new String(byte1, "UTF-8"); 
 RequestDispatcher dispatcher =
req.getSession().getServletContext().getRequestDispatcher(url); 
 dispatcher.forward((ServletRequest)req, (ServletResponse)resp); 
 } 
 
 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws
ServletException, IOException { 
 doGet(req, resp); 
 } 
}

⾸先⼤概看⼀眼代码,并没有⽤于⽂件操作或IO流的包和函数。

阅读如上代码,从接收参数disp后,先是⼏次判读是否为空和字符串开头,条件为真直接结束,否则往下执⾏。

⽽关键代码是

req.getSession().getServletContext().getRequestDispatcher(url);

getRequestDispatcher()是请求转发,前后⻚⾯共享⼀个request ; 这个是在服务端运⾏的,对浏览器来说是透明的.很明显这绝不是⼀个⽂件读取的漏洞,⽽是请求转发造成的漏洞,访问⼀个URL会将请求转发到另⼀个URL,访问jsp⽂件能够解析执⾏也证明了这点。

但请求转发造成的漏洞也不能够称呼"重定向漏洞",请求重定向(redirect):客户端发送⼀个请求,服务器返响应,响应⾥⾯记录客户端需再次发起请求的地址,此时客户端会再次请求发送给这个新的地址。重定向是客户端的⾏为,客户端需要访问两次服务器,发送的是两次请求且是不同的Request请求和Response响应,请求过程数据不共享。在第⼆次请求时浏览器url地址会变化。

请求转发(forward):指的是浏览器向服务器发送⼀个请求,服务器会帮客户端将请求转发到⽬标地址,再将响应结果返回给客户端,重定向是服务器实现的,客户端不关⼼服务器如何⼯作,只接受响应,在交互过程中使⽤同⼀个Request请求对象和Response响应对象,数据都是共享的,浏览器URL地址不会发⽣变化。

那为什么能访问WEB-INF⽬录下配置⽂件呢?

正常情况访问查阅资料了解到:WEB-INF⽬录,应⽤服务器把它指为禁访⽬录,在浏览器中⽆法访问,但是可以让servlet进⾏访问。

从以上可以判断,漏洞原理是通过请求转发绕过了对web-inf⽬录的访问限制,应该称为绕过,⽽绝⾮⽂件读取。相似的漏洞如 Apache Shiro身份验证绕过(CVE-2022-40664)漏洞,是通过RequestDispatcher转发或包含时Shiro中的身份验证绕过⽽产⽣的漏洞。

上⾯看了反⾯例⼦,再来看⼀个正经的⽂件读取漏洞。

⽤友U8C-PrintTemplateFileServlet⽂件读取-删除
这⾥先贴下代码吧。

image

从代码引⽤的包就可看到引⽤了⽂件流的包。

⾸先是接收参数filePath,然后定义realPath变量,并拼接组合,然后读取⽂件。

在46⾄62⾏,是读取⽂件流并返回给浏览器的实现过程。但在64⾏的判断中会删除服务器中的⽂件。

由于会删除⽂件,建议在测试环境复现。

复现漏洞:
POC:

http://172.16.1.200:8088/servlet/~uapweb/nc.lfw.billtemplate.servlet.PrintTemplateFileS
ervlet?filePath=2222.txt

访问不存在⽂件会报错,并泄漏绝对路径。
image

⾸先在服务器该⽬录放置⼀个测试⽂件flag.txt,并再次访问该⽂件。
image

读取该⽂件,成功返回⽂件内容

image

此时服务器⽬录下⽂件已被删除
image

结语:

不知何时圈⼦从浮躁到现在的抽象,SQL注⼊不叫“注入”叫“任意文件上传”(通过sql注⼊写webshell)或叫“RCE”(写webshell再调⽤命令执⾏函数)、权限绕过不叫“绕过”叫任意⽂件读取 ,漏洞评级也有了“核弹级”。

# 漏洞 # 漏洞分析
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录