JAVA代码审计04: WEBGOAT 目录遍历

0x00 前言

之前看了SQL注入那么我们现在来看一下 Path traversal, 也叫做目录遍历,由于后端没有对路径进行很好的控制导致我们可以进行任意文件读取也就是 ../../../../../../etc/passwd 或者说是任意文件上传,我们可以将文件上传到任意目录下,所以我们来看一下

0x01 正文

Path traversal 02

首先我们来看一下要求

简单的翻译一下就是 我们要把文件上传到给出的目录的地址,但是这个地址不是一个普通的文件上传地址,所以我们要利用目录穿越将我们的文件传到上层目录下

image-20201108134728998

首先先上传一下图片,发现文件被上传到了 /用户名/test这个目录下

image-20201108135430529

题目非常简单,我们在上传到时候发现test是目录名,我们只需要把test改成../test 这样就上传到上层目录下了

image-20201108134923746

重点来看一下java源码

该功能的上传点是 /PathTraversal/profile-upload,老样子我们直接进行全局搜索,找到我们的目标文件

发现目标代码主要是利用注解来获取上传表单的 uploadFile 和 fullName 参数中的内容

image-20201108135136918

我们重新看一下我们burp中的请求包

发现uploadFile参数的数值是我们图片的内容

image-20201108135300335

fullName的参数值是我们的文件名,也就是test,正是因为这里的fullName没有做好过滤才导致我们能将文件上传到上级文件夹中

image-20201108135337897

查看代码发现执行了父类中的execute方法,我们跟过去

return super.execute(file, fullName);

来看我们父类的方法

首先会进行检测传入进来的参数 file和fullname是否为空,如果为空就返回报错

image-20201108135853729

然后下面的这行代码规定了我们上传的目录

/PathTraversal/用户名

var uploadDirectory = new File(this.webGoatHomeDirectory, "/PathTraversal/" + webSession.getUserName());

继续往下看我们的代码,发现会在上面定义的目录下新创建一个文件夹,主要是以fullname的名字来命名,就是这里也就是 45行没有对fullname传进来的参数进行一个过滤才导致目录穿越

uploadDirectory.mkdirs();
// 创建一个文件夹 文件夹名字为fullname,这里应该对fullname进行一个过滤
var uploadedFile = new File(uploadDirectory, fullName);
// 直接进行文件夹的创建
uploadedFile.createNewFile();
FileCopyUtils.copy(file.getBytes(), uploadedFile);

知道漏洞点在哪里了我们打断点来更加清晰的查看一下吧

这是我们正常的结果

image-20201108140526026

文件被上传到了/test下

image-20201108140617765

接下来我们来对fullname进行一个修改我们再来看看结果如何,将我们的fullname修改成 ../test

image-20201108140805919

发现路径变成如下这样了,所以最终的上传路径就变成了

/User/xxxx/.webgoat-v8.1.0/PathTraversal/admin123/

image-20201108140859632

Path traversal 03

根据题目意思发现这里做了修改,我们查看一下源码,发现修改后的源代码,将 ../ 置空了

image-20201108143838248

不过这样依旧很好绕过,我们只需要复写../ 即可 ..././

image-20201108143928167

查看断点处发现,我们借助过滤规则成功进行了绕过,进行了目录穿越

image-20201108144015449

Path traversal 04

这次换了一个校验通过文件名来进行校验了

同样的文件名前面加 ../ 就可以绕过了

image-20201108145042514

image-20201108144531303

Path traversal 05

看题目的意思目录穿越还会存在在别的地方让我们来通过漏洞来找到jpg文件

image-20201108161307271

我这里直接审计源码做了,点击show randowm cat picture的时候,发现请求了 /PathTraversal/random-picture接口

直接在IDEA中进行全局搜索 ,找到如下文件

首先我们看到红框这里,后端代码会对我们传输过来的数值进行一个判断,如果里面包含 .. 或者 / 就直接回显不合理的字符串

image-20201108161615703

尝试之后果然如此

image-20201108161801287

但是这里有个缺陷,就是是直接获取了我们id的参数数值,众所周知后端在获取参数值之后会进行一次url解码,所以我们可以利用url编码对 ../进行一个编码从而绕过检测机制

利用burp来发送请求

通过打断点,发现成功绕过

queryParams 获取到的参数为 %2e%2e%2f

id 获取到参数会进行一次url解码 ../

image-20201108162206231

但是根据第83行,我们的文件后会加一个 .jpg

也就是说我们输入url编码后的 ../ 绕过校验的之后,后端收到的路径是这样的

../../.jpg

但是这样的路径为什么最后会列出上上层目录的文件名呢?我们来自己看一下是怎么走的

首先会判断我们id的参数值里面 是否存在 path-traversal-secret.jpg

然后来到下面一个判断,判断我们的catPicature是否存在,这时候我们的catPicture为

/Users/xxxx/.webgoat-v8.1.0/PathTraversal/cat/../../.jpg 是存在的

然后就会来到return语句,我们来看我们红框框出来的地方,会通过base64编码我们的路径为catPictcure的图片内容,放在返回包中的body中作为内容,但是此时我们的路径是不存在图片的,所以该语句执行失败,来到下面的一个return

image-20201108164222536

如下图,如果发现没有发现目标文件,就会获取 catPicature 路径的父文件夹,并且列出所有的文件,在返回包中的body中返回,这也就解释了为什么 路径为什么是 /Users/xxxx/.webgoat-v8.1.0/PathTraversal/cat/../../.jpg 这样也能获取上上层文件的文件名

image-20201108164651559

所以我们只需要找到path-traversal-secret.jpg位置在哪就可以了,简单尝试之后发现文件并不存在上个文件夹

image-20201108162531337

那么就再向上一个目录 ,不出所料发现了我们要的jpg

image-20201108162646879

直接获取即可,然后将username加密之后就是flag 提交就行了

image-20201108162712169

0x02 修复建议

这么四个例子分析下来,其实造成漏洞最根本的原因就是没有对用户输入的地方进行严格的路径把控。

包括我们在漏洞挖掘的过程中 如果发现请求包中有如下请求

?file=/xxx/xxxx/xxx/xxx/1.jpg

这时候我们就需要重点留意一下,如果没有对路径进行严格的把控的话那么就很有可能存在目录穿越,任意文件读取等问题

所以我们在修复的时候 要对 路径严格过滤,将用户输入的路径限定在一个目录范围,同时做好对 ../ 的过滤校验

点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像