tomcat temp 大量 upload 文件_原创 | 浅谈URI中的任意文件下载

4227d4bb465f6f5c85f1a0bd85502c35.gif点击上方蓝字 关注我吧引言2375df37847f8da25d0fd1aff45c8c4a.png


文件下载是比较常见的业务。常见的接口格式为/download?fileName=xxx.png,整个过程若没过滤目录穿越符号…/或者未对下载的路径进行处理限制。当传入的filename参数为../../etc/passwd即可穿越路径达到任意文件下载的效果。

有些接口在尝试获取某一文件时,路径是/file/test.jpg,通过解析URI中的内容来得到对应的文件名test.jpg,然后完成相关的下载操作。此时如果尝试访问/file/../../test.jpg,相关的中间件或者开发框架在解析路由时会做相关的处理。那么此时是否可以进行目录穿越的实际利用呢?

以下是实际项目中遇到的URI中任意文件下载实例:

URI中任意文件下载实例

2375df37847f8da25d0fd1aff45c8c4a.png

自定义Servlet

相关业务为用户上传文件的下载,主要通过Servlet进行交互,以下是相关的实现。

servlet的具体映射:

<servlet-mapping>      <servlet-name>UserfilesDownloadServletservlet-name>      <url-pattern>/userfiles/*url-pattern>servlet-mapping>

下载业务具体实现如下:

public class UserfilesDownloadServlet extends HttpServlet {  private static final long serialVersionUID = 1L;  private Logger logger = LoggerFactory.getLogger(getClass());  public void fileOutputStream(HttpServletRequest req, HttpServletResponse resp)       throws ServletException, IOException {    String filepath = req.getRequestURI();    int index = filepath.indexOf(Global.USERFILES_BASE_URL);    if(index >= 0) {      filepath = filepath.substring(index + Global.USERFILES_BASE_URL.length());    }    try {      filepath = UriUtils.decode(filepath, "UTF-8");    } catch (UnsupportedEncodingException e1) {      logger.error(String.format("解释文件路径失败,URL地址为%s", filepath), e1);    }    File file = new File(Global.getUserfilesBaseDir() + Global.USERFILES_BASE_URL + filepath);    try {      FileCopyUtils.copy(new FileInputStream(file), resp.getOutputStream());      resp.setHeader("Content-Type", "application/octet-stream");      return;    } catch (FileNotFoundException e) {      req.setAttribute("exception", new FileNotFoundException("请求的文件不存在"));      req.getRequestDispatcher("/WEB-INF/views/error/404.jsp").forward(req, resp);    }  }......}

这里使用了springframework的FileCopyUtils.copy()

方法,具体实现如下,主要是对File对象进行相应的处理,

将读取的文件内容复制到response内容中:

public static int copy(File in, File out) throws IOException {        Assert.notNull(in, "No input File specified");        Assert.notNull(out, "No output File specified");        return copy((InputStream)(new BufferedInputStream(new FileInputStream(in))), (OutputStream)(new BufferedOutputStream(new FileOutputStream(out))));    }
最后通过设置response header返回文件内容,具体效
果如下:

2fd07dfa74d8f951f4f60c127453c22e.png

其中下载的文件名filepath是通过
req.getRequestURI()来获取的。
该方法是不会对URI中的../或者;等特殊字符进行规范化
处理的。同时在获取到对应的filepath后直接进行路径
拼接然后进行文件读取,整个过程未限定下载的文件目录
范围,也并未过滤..//等敏感关键字,存在任意文件下
载风险。但是这里场景比较特殊,相关参数的获取是在URI中获取的,能否深入利用还有待商榷。
当前项目的upload目录位置如下:

f13cb7160677e977e17332a5bff2f975.png

这里尝试访问../WEB-INF/web.xml(回到upload上级

目录WebContent),成功完成目录穿越读取到对应的

web.xml配置信息:

09063609bde47a681a4fb7d46a128aec.png

中间件在进行解析时,会对URI中的../进行相关处理从

而得到相关的servlet,tomcat解析时已经对../进行

处理了处理,上面的访问方式其实跟直接访问

/userfiles/WEB-INF/web.xml是一样的:

27797ff7854559e51b7de8b3e0d2cefd.png

若此时如果想读取/etc/passwd,就需要写入更多的目
录穿越符../,此时tomcat处理完../后已经不在/userfiles/*这个servlet映射范围内了,那么此时
会抛出相关的异常,并不能进一步获取更多的敏感信息。
尝试扩大漏洞的危害,读取更多的敏感文件。首先要让
tomcat不处理../../
filepath = UriUtils.decode(filepath, "UTF-8");
尝试进行编码请求,发现触发400 Invalid URI错误,因为tomcat会对URI路径信息进行解码并进行检测,当遇到斜杠的URL(即%2F)时,出于安全的考虑会返回400状态码:
else if (metaChar == '%')      {        char res = (char)Integer.parseInt(str          .substring(strPos + 1, strPos + 3), 16);        if ((noSlash) && (res == '/')) {          throw new IllegalArgumentException(sm.getString("uDecoder.noSlash"));        }        dec.append(res);        strPos += 3;      }    }    return dec.toString();

a2ac30ff232b87e780a02ce31fb77bf2.png

在URL中有一个保留字符分号;,主要作为参数分隔符进行使用,有时候是请求中传递的参数太多了,所以使用分号;将参数对(key=value)连接起来作为一个请求参数进行传递。

tomcat在对;进行处理时,同样的也会对;进行截断并当成参数处理,在URI编码的基础上加上;再次访问,经过一系列处理获取到的路径为/upload/;/../../../../../../../../etc/passwd,此时返回的是404状态码,应该是在进行文件读取的时候找不到名为;的目录,触发了FileNotFoundException异常:

try {      FileCopyUtils.copy(new FileInputStream(file), resp.getOutputStream());      resp.setHeader("Content-Type", "application/octet-stream");      return;    } catch (FileNotFoundException e) {      req.setAttribute("exception", new FileNotFoundException("请求的文件不存在"));      req.getRequestDispatcher("/WEB-INF/views/error/404.jsp").forward(req, resp);    }

e6767cdf5f4cde293685cc2bd13dae6b.png

刚好结合网站的其他业务可以进行目录创建,在upload下创建名为;的目录名,此时访问/userfiles/upload/;%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc%2fpasswd即可获取到相关的敏感文件:

2a0085bec2dcab0a4f9f6784a5a2b06b.png

@PathVariable注解

@PathVariable注解是spring3.0的一个新功能,可以接收请求路径中占位符的值并将URL中占位符参数{xxx} 绑定到控制器处理方法的入参中。该功能在SpringMVC向REST 、目标挺进发展过程中具有十分重要的意义。例如下面的例子:
  • 获取id = 1的订单信息
@RequestMapping("/Order/{id}")public String getOrderDetails(@PathVariable("id") Integer id){   //......}

除此之外,@PathVariable同样可以用于实现文件的下载,例如下面的例子:

@RequestMapping("/file/get/{filename:.+}")  public ResponseEntity<byte[]> download(HttpServletRequest request,      @PathVariable(value = "filename") String fileName) throws IOException {    String uploadRoot = "/var/work/download";    File file = new File(uploadRoot + URLDecoder.decode(File.separator + fileName, "UTF-8"));    byte[] body = null;    InputStream is = new FileInputStream(file);    body = new byte[is.available()];    is.read(body);    HttpHeaders headers = new HttpHeaders();    headers.add("Content-Disposition", "attchement;filename=" + file.getName());    HttpStatus statusCode = HttpStatus.OK;    ResponseEntity<byte[]> entity = new ResponseEntity<>(body, headers, statusCode);    return entity;  }
具体效果如下,例如这里尝试获取上传的test.png图片:

8c94b924a5238e5fc709f7d60af1b703.png

这里将URL中占位符参数filename跟初始路径/var/work/download进行拼接,然后下载对应的文件。这里对应的文件名用户可控,未限定下载的文件目录范围,同时并未过滤..//等敏感关键字,存在任意文件下载风险。


但是这里参数的位置在URI中,能否利用还需要进一步探究。
正常来说,直接使用../../../尝试目录穿越即可下载/etc/passwd等敏感文件,实际上中间件在进行解析时,会对URI中的../行相关处理从而得到相关的servlet,以tomcat为例,实际上解析时已经对../进行处理了,占位符参数filename并不能获取到../来进行目录穿越。这里因为处理后URI为/file/etc/passwd没找到对应的映射,所以返回了404状态码:

b40cf4de7b94ddf70c81a860d84fe090.png

同样的,尝试对/进行URL编码,tomcat源码会对URI路径信息进行解码并进行检测,当遇到斜杠的URL(即%2F)时,出于安全的考虑会返回400状态码(抛出Invalid URI: noSlash异常):


tomcat源码中相关处理流程如下:
else if (metaChar == '%')      {        char res = (char)Integer.parseInt(str          .substring(strPos + 1, strPos + 3), 16);        if ((noSlash) && (res == '/')) {          throw new IllegalArgumentException(sm.getString("uDecoder.noSlash"));        }        dec.append(res);        strPos += 3;      }    }    return dec.toString();

e0962cc4236c3f23e984053a3368c926.png

这里可以使用双重URL编码绕过中间件的处理,对/进行URL双重编码后返回404状态码,说明已经绕过noSlash异常了:

8916eaa92abcb6eeb832c4f6b4c6a164.png

中间件后就是Spring的处理过程,查看Spring的解析过程,主要通过getPathWithinServletMapping方法获取路由:

public String getPathWithinServletMapping(HttpServletRequest request) {        String pathWithinApp = this.getPathWithinApplication(request);        String servletPath = this.getServletPath(request);        String sanitizedPathWithinApp = this.getSanitizedPath(pathWithinApp);
getPathWithinApplication方法中会使用 getRequestUri 来获取对应路由:
public String getRequestUri(HttpServletRequest request) {        String uri =(String)request.getAttribute("javax.servlet.include.request_uri");        if (uri == null) {            uri = request.getRequestURI();        }        return this.decodeAndCleanUriString(request, uri);    }

随即在decodeAndCleanUriString对URI进行格式化处理,首先对分号进行处理,然后进行URI解码,最后进行返回:

private String decodeAndCleanUriString(HttpServletRequest request, String uri){        uri = this.removeSemicolonContent(uri);        uri = this.decodeRequestString(request, uri);        uri = this.getSanitizedPath(uri);        return uri;}
也就是说,Spring本身会对URI进行一次解码处理
例如/file/get/..%252fetc/passwd
经过tomcat+spring处理后会变成
/file/get%2fetc/passwd

再回到案例代码,这里应该是考虑到了中文传输的问题,在前端用js对URL进行编码后再发送请求,这时候开发可能忽略了Spring自身的一次解码操作,在对应的接口再次进行了一次解码:
File file = new File(uploadRoot + URLDecoder.decode(File.separator + fileName, "UTF-8"));
那么也就是说使用双重URL编码的方式处理../进行请求,即可在Spring以及接口自身的URLDecode获得漏洞利用需要的../../,从而成功进行目录穿越读取到/etc/passwd内容:

6a8092db1d4b86b3b9bd02976266c846.png

拓展延伸

因为涉及到URI部分的解析,参与的有中间件、spring、人工的解码等一系列处理。那么如果在上面案例的基础上集成shiro框架。那相关的利用poc又是如何呢?
案例一的;可能需要编码成%3b。这里就有点CVE-2020-13933的味道了,但是高版本shiro对编码的;进行了处理,怎么继续利用还是值得思考的。4227d4bb465f6f5c85f1a0bd85502c35.gif4227d4bb465f6f5c85f1a0bd85502c35.giff0605a61c1890c173a801dfeaec36c4b.png526afb006094505b0afd056855e20af3.gif点分享831f911c6f70ea76355ca9f765b397c8.gif点收藏e4ba1b841918c6145c72bee2912a88a5.gif点点赞9c371caca6c0637ce3eca5ed04ceadd3.gif点在看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/244670.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql编写函数 求1 n 偶数之和,编写求1 2 3 - n的函数.在main函数中调用该函数

输入两个正整数m,n,编写求阶乘的函数,计算m!/(n!*(m-n)!). C语言函数解答,谢谢.#includelongfactorial(intm,intn){longsum1,sum11;inti;if(m-n>n){for(im;i>m-n;i--)sum*i;for编写函数fun求1!2!3! …… n!的和,在main函中由键盘输入n值,并输出运算结果#includeintfun(in…

python range在for循环里的用法_PyThon range()函数中for循环用法

最初range和xrange都生成可以用for循环迭代的数字&#xff0c;然而在python2和3里实现方式并不完全一致&#xff0c;下面着重讲讲python3的range()函数for循环用法。1、函数语法range(start, stop, [step])2、参数说明start: 可选参数&#xff0c;计数从 start 开始。默认是从 …

matlab实现图像放大两倍,matlab图像处理基础知识0(双线性插值matlab实现--调整水平和垂直放大倍数)...

需求说明&#xff1a;图像处理FPGA实现前期算法准备当前算法&#xff1a;已通过matlab验证成功function scaler_bilinear()%-----------------------------0:配置输入输出--------------------------------m2; %放大或缩小的高度n2; %放大或缩小的宽度Iimread(F:ookDigital ima…

win10虚拟内存怎么设置最好_淘宝直通车时间段怎么设置?哪个时间段开最好?...

大家好&#xff0c;我是西瓜电商培训的子木。淘宝直通车一直都是商家们最受关注的一款推广工具&#xff0c;开过直通车的商家应该都知道在开直通车的时候是可以通过自己设定时间和金额的&#xff0c;所以很多商家可能会根据每天店铺的流量时间段来分析开车投入&#xff0c;商家…

php小于neq qe,PHP模板判断语句eq相等 ne、neq不相等, gt大于, lt小于

eq相等 ne、neq不相等&#xff0c; gt大于&#xff0c; lt小于 gte、ge大于等于 lte、le 小于等于 not非 mod求模 is [not] div by是否能被某数整除 is [not] even是否为偶数 is [not] even by $b即($a / $b) % 2 0 is [not] odd是否为奇 is not odd by $…

笔记本屏幕出现横条纹_笔记本支架+拓展坞+立式无线充:给你的桌面一个简单的品质升级...

一、写在前面如果每个女孩都想拥有一个自己的衣帽间的话&#xff0c;每个喜欢科技的男孩&#xff0c;都想拥有一个属于自己的书房或者说游戏间&#xff0c;而这其中书桌是陪伴我们最多的地方&#xff0c;怎么打造一个舒适好用的桌面&#xff0c;让桌面简单而有品质呢&#xff0…

excel 公式 单引号 concat_从Excel的数据类型说Python

转自&#xff1a;可乐的数据分析之路写在前面这节内容是python基础知识中的数据类型和运算符&#xff0c;可以回顾一下前两篇文章来复习一下&#xff1a;利用Excel学习Python&#xff1a;变量利用Excel学习Python&#xff1a;准备篇本来想分开写的&#xff0c;但发现好像分不开…

matlab slider不可移动,GUI界面能运行,但是_slider不能用,不能控制波长

下面是GUI的程序&#xff0c;在c的地方设置的是可见光的波长&#xff0c;但是lamda_slider不能进行控制&#xff0c;默认波长600e-9&#xff0c;运行后只有c [0 0 0;1 0 0]求解function varargout untitled(varargin)%UNTITLED M-file for untitled.fig% UNTITLED, by i…

xx是一个类型 这在给定的上下文_BERT, ELMo, amp; GPT-2: 这些上下文相关的表示到底有多上下文化?...

作者&#xff1a;Kawin Ethayarajh编译&#xff1a;ronghuaiyang &#xff08;AI公园&#xff09;具有上下文信息的词表示到底有多大程度的上下文化&#xff1f;这里给出了定量的分析。将上下文信息放到词嵌入中 — 就像BERT&#xff0c;ELMo和GPT-2 — 已经证明了是NLP的一个分…

不是有效的win32应用程序_杀毒软件有坑!三分之二的安卓杀毒软件的“主业”并不是杀毒...

更多全球网络安全资讯尽在E安全官网www.easyaq.com小编来报&#xff1a;奥地利杀毒测试机构AV-Comparatives研究发现&#xff0c;大约三分之二的安卓杀毒软件并没有合格的杀毒功能&#xff0c;它们都是披着羊皮的狼&#xff01;据外媒报道&#xff0c;奥地利杀毒测试机构AV-Com…

java字符串除法函数,java – 函数式编程:如何处理函数式编程中的异常或它的等价物...

以下显示了如何在Haskell中完成它.基于类型siginure divide :: Int – > Int – >无论[Char] Int,您都可以看到函数除法将返回Left字符串或Right Int.要么是代数数据结构,还有更多,你可以自己编写.divide :: Int -> Int -> Either [Char] Intdivide dividend divis…

phpfpm内存越来越高_硬件集成度越来越高 未来DIY玩法方向已定?

【PConline 杂谈】前一阵子&#xff0c;英特尔发布了他们家的黑科技处理器&#xff0c;代号为Lakefield。能称得上黑科技那肯定是有点东西的&#xff0c;这款处理器采用了3D封装工艺&#xff0c;将内存颗粒也封装进处理器里面。这样的话处理器、内存和显卡这些大件都集成在一块…

苹果6可以分屏吗_榨苹果汁可以加蜂蜜水吗?蜂蜜苹果汁的作用

榨苹果汁可以加蜂蜜水吗?蜂蜜苹果汁的功效鲜榨果汁是很多人都喜欢的饮品&#xff0c;现在生活水平都比较好了&#xff0c;大家也可以在家中自己榨果汁喝&#xff0c;苹果汁是很多人的第一选择&#xff0c;那榨苹果汁可以加蜂蜜水吗?榨苹果汁可以加蜂蜜水&#xff0c;苹果营养…

mysql5.5索引,MySQL--5索引选择原则

大家好我是安小生&#xff0c;这篇文章讲述索引的选择原则。1.explain分析语句。explain&#xff1a;通常是用于sql语句性能分析。举个栗子&#xff1a;explain select * from user where name "张三"我们来看一下explain 查询出来的字段都是什么&#xff1f;id:sel…

winform 鼠标 静止时间_赢得电竞的奥秘,你需要一块好鼠标垫

如今&#xff0c;电竞游戏成为很多PC用户喜爱的娱乐“运动”&#xff0c;这使得相关PC电竞外设流行起来&#xff0c;耳机、音箱、鼠标、鼠标垫都成为电竞用户追求的产品。然而对于职业选手、电竞玩家而言&#xff0c;除了一款性能出色的鼠标外&#xff0c;搭配一款合适的鼠标垫…

IAR在写结构体时不提示_智能物流装车系统的结构优化与改进

文&#xff5c;滇西应用技术大学管理学院鄢良国、姚敏、孙荷琴、杨晓滇西应用技术大学基础实验实训中心朱丹智能物流装车系统主要用于烟草生产基地和物流配送中心之间往返运输的自动化装车业务中。本文针对智能物流装车系统会损坏外层箱体的现象&#xff0c;对结构进行了具体分…

python模块管理工具,Python的包管理工具

Python的包管理工具python包管理工具python包管理工具简介distribute是setuptools的取代&#xff0c;pip是easy_install的取代。Distribute是对标准库disutils模块的增强&#xff0c;我们知道disutils主要是用来更加容易的打包和分发包&#xff0c;特别是对其他的包有依赖的包。…

循环机换变速箱油教程_水箱内全是油, 变速箱内全是水!看师傅怎么修...

点击↑汽修案例关注置顶&#xff0c;获得正时大全识别添加汽配大师微信车主到店说变速箱顿挫太厉害了&#xff0c;像这种行驶8万多公里的车&#xff0c;变速箱油是主要检查对象&#xff0c;先放掉变速箱油&#xff0c;结果放出的油已经看不出油原来的样子&#xff0c;水和油的混…

RequestBody获取前端数据_360视频云Web前端HEVC播放器实践剖析

360视频云前端团队围绕HEVC前端播放及解密实现了一套基于WebAssembly、WebWorker的通用模块化Web播放器&#xff0c;在LiveVideoStackCon2019深圳的演讲中360奇舞团Web前端技术经理胡尊杰对其架构设计、核心原理&#xff0c;具体痛点问题的解决方式进行了详细剖析。文 / 胡尊杰…

oracle 11g函数包缓存,Oracle11新特性——PLSQL函数缓存结果(一)

Oracle11g新增的SQL缓存结果集的功能前面已经介绍过了。同时Oracle对PL/SQL的函数也进行了相应的增加。允许函数缓存返回结果。先看一个简单的例子&#xff1a;SQL> CREATE TABLE T AS SELECT * FROM DBA_SOURCE;表已创建。SQL> CREATE OR REPLACE FUNCTION F_NO_RESULT_…