欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

看我如何突破JFinal黑名单机制实现任意文件上传

来源:本站整理 作者:佚名 时间:2019-08-14 TAG: 我要投稿

JFinal是国产优秀的web框架,短小精悍强大,易于使用。近期团队内一名小伙伴(LuoKe)在安全测试的时候报了一个很玄学的任意文件上传,笔者本着知其然必知其所以然的态度去跟进了一下问题代码,发现问题系统在处理上传文件功能的时候使用了JFinal框架,于是去对该框架上传文件处的代码做了一下审计,发现了JFinal上传文件的黑名单机制的存在被绕过的风险。目前该漏洞已上报至厂商并修复,本文章意在和各位看官分享一下该漏洞的原理和发现过程。
 
关键函数
isSafeFile(UploadFile uploadFile)  //jfinal黑名单检测函数,负责对jsp与jspx类型文件进行过滤
readNextPart() //轮询处理从上传文件的时候前端传来的参数
 
漏洞发现
注:漏洞发现场景由我这边搭建的测试环境模拟,并非当时爆出漏洞的实际场景,如有疏漏,还请见谅。
某日下午,团队内的安全测试组的LuoKe同学分享了一个很有意思的任意文件上传大体情况如下
1、上传txt类型文件,提示上传成功。

2、上传jsp文件,显示上传失败

3、提交如下数据包,显示上传失败,但是给上传目录下,可以发现上传成功。

刚看到这种情况,还是比较懵,因为但是比对了一下3个数据包,立马可以明白一个问题,第三个数据包是不完整的,它的最末行缺少分割的boundary,为了验证这个想法,我试了一下如下形式的数据包,

果然是上传失败,那就说明一个道理,此次绕过黑名单一定是和程序报错有关系的。那接下来就是去跟进一下系统代码,确认一下我们的猜想。
漏洞分析
跟进代码的时候发现,系统中处理上传文件的代码是如下形式:
UploadFile file = getFile("file", "test");
看了一下lib,发现这个函数是JFinal框架处理上传文件的函数,那是不是代表这种利用方式是在JFinal框架中是具有通用性的,所以直接在本地搭了一个JFinal框架去看一下上传文件的代码。
首先去看一下黑名单处理函数
Upload/MultipartRequest.class  100-107
private boolean isSafeFile(UploadFile uploadFile) {
    String fileName = uploadFile.getFileName().trim().toLowerCase();
    if (!fileName.endsWith(".jsp") && !fileName.endsWith(".jspx")) {
        return true;
    } else {
        uploadFile.getFile().delete();
        return false;
    }
}
可以发现在处理后缀为jsp和jspx类型的文件的时候,会做一步删除操作“uploadFile.getFile().delete(); “,看到这一步的时候我就基本心如明镜了,在这个地方做了删除操作是不是就代表了,代码在处理上传文件的时候先是什么都不管的,上传完成后再对有问题的文件做删除。
那我们先去跟一下上传文件的代码
Servlet/MultipartRequest.class   84-108
while((part = parser.readNextPart()) != null) {
    String name = part.getName();
    if (name == null) {
        throw new IOException("Malformed input: parameter name missing (known Opera 7 bug)");
    }
    String fileName;
    if (part.isParam()) {
        ParamPart paramPart = (ParamPart)part;
        fileName = paramPart.getStringValue();
        existingValues = (Vector)this.parameters.get(name);
        if (existingValues == null) {
            existingValues = new Vector();
            this.parameters.put(name, existingValues);
        }
        existingValues.addElement(fileName);
    } else if (part.isFile()) {
        FilePart filePart = (FilePart)part;
        fileName = filePart.getFileName();
        if (fileName != null) {
            filePart.setRenamePolicy(policy);
            filePart.writeTo(dir);
            this.files.put(name, new UploadedFile(dir.toString(), filePart.getFileName(), fileName, filePart.getContentType()));

[1] [2]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载