雷石|对用友NC“任意文件读取”漏洞的分析
2024-1-19 12:48:24 Author: 雷石安全实验室(查看原文) 阅读量:80 收藏

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

⽤友NC-word.docx任意⽂件读取?你确定吗?

     起始时看到漏洞⽂章,所有公众号都在发该接⼝的存在任意⽂件读取,但清⼀⾊给出的poc都是读取web.xml


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

漏洞复现

     ⾸先看⽹上给的POC:

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

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


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


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

漏洞分析:

     从代码下⼿,发现了⼤问题。

     关键代码如下:

packagenc.uap.lfw.file.action;  importjava.io.IOException; importjavax.servlet.RequestDispatcher; importjavax.servlet.ServletException; importjavax.servlet.ServletRequest; importjavax.servlet.ServletResponse; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importorg.apache.commons.lang.StringUtils;  public class DocServlet extends HttpServlet {  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throwsServletException, 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) throwsServletException, 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)”漏洞是通过EequestDispatcher转发或包含时Shiro中的身份验证绕过⽽产⽣的漏洞上⾯看了反⾯例⼦,再来看⼀个正经的⽂件读取漏洞。

⽤友U8C-PrintTemplateFileServlet⽂件读取-删除

     这⾥先贴下代码吧。

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

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

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

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

复现漏洞

 POC

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

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


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


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


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


结语

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

本文作者:xueqi

雷石安全实验室

商务咨询:

0571-87031601

商务邮箱:

[email protected]


文章来源: http://mp.weixin.qq.com/s?__biz=MzI5MDE0MjQ1NQ==&mid=2247525935&idx=1&sn=d4a2b2dd8fe84cec8ddeb4c46cb56d44&chksm=ed4bbbae1a7d2dc044710992b02197f1f56ff0659c0b5208200f0988121c9259da028d8074aa&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh