Java代码审计之目录穿越(任意文件下载/读取)
一、目录穿越漏洞
1、什么是目录穿越
所谓的目录穿越指利用操作系统中的文件系统对目录的表示。在文件系统路径中,".."表示上一级目录,当你使用"../"时,你正在引用当前目录的上一级目录。如果你使用"../../",你实际上在两次".."的基础上,再次引用上一级目录,从而返回到上两级目录。
例子:假设你目前所在目录为:C:\Windows\System32\drivers\etc
- 使用"../" 一次返回上一级目录,即:C:\Windows\System32\drivers
- 使用"../../" 一次返回上一级目录,即:C:\Windows\System32
这是因为在文件系统路径中,每个".."都表示回到上一级目录。所以多个连续的".."会连续返回到更高级别的目录。然而在漏洞利用中Windows和Linux系统会有区别,后续漏洞利用中会提到。
2、目录穿越漏洞成因
目录穿越漏洞,也叫做目录遍历/路径遍历漏洞。常发生于文件上传,文件下载,文件下载等处。由于后端直接接收前端传过来的文件名或路径,没有对其进行检测与过滤,导致攻击者利用../的方式进行目录穿越,达到任意文件读取/下载,任意文件删除,或将任意文件上传到指定目录等。
3、目录穿越漏洞的利用
Windows中目录穿越漏洞由于操作系统可能导致只能在设定好的盘符下进行穿越,不能越过其他盘符读取,如:读取日志文件,后端代码F:/wwwroot/logs + "前端传递的文件名"。此时通过../进行目录穿越只能在F盘下进行读取,不能读取F盘以外的任何文件,如:C:\windows\win.ini。而Linux中却不受到这种限制,只要有足够的权限可以读任意目录下的文件。
一般目录穿越导致的主要为任意文件读取,一般都是读取配置文件,因为配置文件中保存着大量敏感信息,如:各种数据库连接地址与账号密码
4、案例代码演示
环境:
jdk 1.8(1.8.0_211)
Maven 3.9.1
IDEA 2022.3.3
创建spring项目
使用IDEA新建一个项目,如下图所示,按需配置。这里记得选择2.x的版本
演示代码如下:
参考自:https://github.com/j3ers3/Hello-Java-Sec/blob/master/src/main/java/com/best/hello/controller/Traversal.java
代码就是正常的文件读取操作,如果不理解学习一下java I/O
// 任意文件读取/下载 @ApiOperation(value = "任意文件读取/下载") @GetMapping("readBuffer") public String readbuffer(String filename,HttpServletResponse response) throws IOException { try (InputStream inputStream = new BufferedInputStream(Files.newInputStream(Paths.get(filename)))){ response.setHeader("Content-Disposition", "attachment; filename=" + filename); response.setContentLength((int) Files.size(Paths.get(filename))); response.setContentType("application/octet-stream"); // 使用 Apache Commons IO 库的工具方法将输入流中的数据拷贝到输出流中 IOUtils.copy(inputStream, response.getOutputStream()); return "文件下载成功:" + filename; }catch (IOException e){ return "文件下载失败:" + filename; } }
任意文件读取:
任意路径遍历:
5、绕过方式
5.1、url编码绕过
单次url编码,../编码后..%2f,%2e%2e%2f。
5.2、双/多重url编码
进行双重url编码,多了个25
. = %252e / = %252f \ = %255c
5.3、Unicode的URL编码
. = %u002e / = %u2215 \ = %u2216
5.4、UTF-8的Unicode编码
. = %c0%2e, %e0%40%ae, %c0ae / = %c0%af, %e0%80%af, %c0%2f \ = %c0%5c, %c0%80%5c
5.5、超长UTF-8编码
. = %c0%2e, %e0%40%ae, %c0ae / = %c0%af, %e0%80%af, %c0%2f \ = %c0%5c, %c0%80%5c
5.6、空字节截断
也就是大家熟知的00截断,用于判断后缀名,使用空字节URL编码绕过(出现几率非常小)
../../../../../passwd%00.jpg
6、漏洞修复
通过前面原理介绍,目录穿越是由于文件系统的特性所导致的,通过../进行目录的跨越。修复只需要检测字符".."与"/"即可,在对应语言中加入检测即可,以java为例:写一个工具类检测即可
public class Security { // 目录穿越检验 public static boolean checkTraversal(String content){ return content.contains("..") || content.contains("/"); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~