0x00 前言
之前看了SQL注入那么我们现在来看一下 Path traversal, 也叫做目录遍历,由于后端没有对路径进行很好的控制导致我们可以进行任意文件读取也就是 ../../../../../../etc/passwd
或者说是任意文件上传,我们可以将文件上传到任意目录下,所以我们来看一下
0x01 正文
Path traversal 02
首先我们来看一下要求
简单的翻译一下就是 我们要把文件上传到给出的目录的地址,但是这个地址不是一个普通的文件上传地址,所以我们要利用目录穿越将我们的文件传到上层目录下
首先先上传一下图片,发现文件被上传到了 /用户名/test
这个目录下
题目非常简单,我们在上传到时候发现test是目录名,我们只需要把test改成../test
这样就上传到上层目录下了
重点来看一下java源码
该功能的上传点是 /PathTraversal/profile-upload
,老样子我们直接进行全局搜索,找到我们的目标文件
发现目标代码主要是利用注解来获取上传表单的 uploadFile 和 fullName 参数中的内容
我们重新看一下我们burp中的请求包
发现uploadFile参数的数值是我们图片的内容
fullName的参数值是我们的文件名,也就是test,正是因为这里的fullName没有做好过滤才导致我们能将文件上传到上级文件夹中
查看代码发现执行了父类中的execute方法,我们跟过去
return super.execute(file, fullName);
来看我们父类的方法
首先会进行检测传入进来的参数 file和fullname是否为空,如果为空就返回报错
然后下面的这行代码规定了我们上传的目录
/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);
知道漏洞点在哪里了我们打断点来更加清晰的查看一下吧
这是我们正常的结果
文件被上传到了/test下
接下来我们来对fullname进行一个修改我们再来看看结果如何,将我们的fullname修改成 ../test
发现路径变成如下这样了,所以最终的上传路径就变成了
/User/xxxx/.webgoat-v8.1.0/PathTraversal/admin123/
Path traversal 03
根据题目意思发现这里做了修改,我们查看一下源码,发现修改后的源代码,将 ../
置空了
不过这样依旧很好绕过,我们只需要复写../
即可 ..././
查看断点处发现,我们借助过滤规则成功进行了绕过,进行了目录穿越
Path traversal 04
这次换了一个校验通过文件名来进行校验了
同样的文件名前面加 ../ 就可以绕过了
Path traversal 05
看题目的意思目录穿越还会存在在别的地方让我们来通过漏洞来找到jpg文件
我这里直接审计源码做了,点击show randowm cat picture的时候,发现请求了 /PathTraversal/random-picture
接口
直接在IDEA中进行全局搜索 ,找到如下文件
首先我们看到红框这里,后端代码会对我们传输过来的数值进行一个判断,如果里面包含 ..
或者 /
就直接回显不合理的字符串
尝试之后果然如此
但是这里有个缺陷,就是是直接获取了我们id的参数数值,众所周知后端在获取参数值之后会进行一次url解码,所以我们可以利用url编码对 ../
进行一个编码从而绕过检测机制
利用burp来发送请求
通过打断点,发现成功绕过
queryParams 获取到的参数为 %2e%2e%2f
id 获取到参数会进行一次url解码 ../
但是根据第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
如下图,如果发现没有发现目标文件,就会获取 catPicature 路径的父文件夹,并且列出所有的文件,在返回包中的body中返回,这也就解释了为什么 路径为什么是 /Users/xxxx/.webgoat-v8.1.0/PathTraversal/cat/../../.jpg
这样也能获取上上层文件的文件名
所以我们只需要找到path-traversal-secret.jpg位置在哪就可以了,简单尝试之后发现文件并不存在上个文件夹
那么就再向上一个目录 ,不出所料发现了我们要的jpg
直接获取即可,然后将username加密之后就是flag 提交就行了
0x02 修复建议
这么四个例子分析下来,其实造成漏洞最根本的原因就是没有对用户输入的地方进行严格的路径把控。
包括我们在漏洞挖掘的过程中 如果发现请求包中有如下请求
?file=/xxx/xxxx/xxx/xxx/1.jpg
这时候我们就需要重点留意一下,如果没有对路径进行严格的把控的话那么就很有可能存在目录穿越,任意文件读取等问题
所以我们在修复的时候 要对 路径严格过滤,将用户输入的路径限定在一个目录范围,同时做好对 ../
的过滤校验