4.6. 目录穿越
4.6.1. 简介
目录穿越(也被称为目录遍历/directory traversal/path traversal)是通过使用 ../
等目录控制序列或者文件的绝对路径来访问存储在文件系统上的任意文件和目录,特别是应用程序源代码、配置文件、重要的系统文件等。
4.6.2. 攻击载荷
4.6.2.1. URL参数
../
..
..;/
4.6.2.2. Nginx Off by Slash
https://vuln.site.com/files../
4.6.2.3. UNC Bypass
\localhostc$windowswin.ini
4.6.3. 过滤绕过
- 单次替换
-
...//
- URL编码
- 16位Unicode编码
-
u002e
- 超长UTF-8编码
-
\%e0%40%ae
4.6.4. 防御
在进行文件操作相关的API前,应该对用户输入做过滤。较强的规则下可以使用白名单,仅允许纯字母或数字字符等。
若规则允许的字符较多,最好使用当前操作系统路径规范化函数规范化路径后,进行过滤,最后再进行相关调用。
4.6.5. 参考链接
- Directory traversal by portswigger
- Path Traversal by OWASP
- path normalization
- Breaking Parser Logic: Take Your Path Normalization Off and Pop 0days Out defcon
4.9. 文件包含
4.9.1. 基础
常见的文件包含漏洞的形式为 <?php include("inc/" . $_GET['file']); ?>
考虑常用的几种包含方式为
- 同目录包含
file=.htaccess
- 目录遍历
?file=../../../../../../../../../var/lib/locate.db
- 日志注入
?file=../../../../../../../../../var/log/apache/error.log
- 利用
/proc/self/environ
其中日志可以使用SSH日志或者Web日志等多种日志来源测试
4.9.2. 触发Sink
- PHP
-
- include
-
- 在包含过程中出错会报错,不影响执行后续语句
- include_once
-
- 仅包含一次
- require
-
- 在包含过程中出错,就会直接退出,不执行后续语句
- require_once
4.9.3. 绕过技巧
常见的应用在文件包含之前,可能会调用函数对其进行判断,一般有如下几种绕过方式
4.9.3.1. url编码绕过
如果WAF中是字符串匹配,可以使用url多次编码的方式可以绕过
4.9.3.2. 特殊字符绕过
- 某些情况下,读文件支持使用Shell通配符,如
?
*
等 - url中 使用
?
#
可能会影响include包含的结果 - 某些情况下,unicode编码不同但是字形相近的字符有同一个效果
4.9.3.3. %00截断
几乎是最常用的方法,条件是magic_quotes_gpc打开,而且php版本小于5.3.4。
4.9.3.4. 长度截断
Windows上的文件名长度和文件路径有关。具体关系为:从根目录计算,文件路径长度最长为259个bytes。
msdn定义 #define MAX_PATH 260
,其中第260个字符为字符串结尾的