原文地址:https://en.wikipedia.org/wiki/Directory_traversal_attack
一次目录遍历攻击(directory traversal attack)通常利用了“服务器安全认证缺失”或者“用户提供输入的文件处理操作”,使得服务器端文件操作接口执行了带有“遍历父文件目录”意图的恶意输入字符。
这种攻击的目的通常是利用服务器相关(存在安全漏洞的)应用服务,来恶意的获取服务器上本不可访问的文件访问权限。该攻击利用了程序自身安全的缺失(对于程序本身的意图而言是合法的),因此存在目录遍历缺陷的程序往往本身没有什么逻辑缺陷。
目录遍历攻击也被称为“…/攻击”、“目录爬寻”以及“回溯攻击”。甚至有些形式的目录遍历攻击是公认的标准化缺陷。
一个典型的易受攻击的PHP应用案例如下代码所示:
译者注:如果有读者看不懂php代码,可以看下面这段nodejs代码,与原文示例中的php代码效果完全一致:
var http=require("http");
var fs=require("fs");
var server=http.createServer(function(req,res){
var $template="red.php";
if(req.headers.cookie){
req.headers.cookie.split(";").forEach(function(index,i){
var map=index.split("=");
if(map[0]=="TEMPLATE"){
$template=map[1];
}
});
}
var stream=fs.createReadStream("/home/users/phpguru/templates/"+$template);
stream.pipe(res);
});
一个针对这个系统的目录遍历攻击即可像如下示例一样发送HTTP请求:
GET /vulnerable.php HTTP/1.0
Cookie: TEMPLATE=../../../../../../../../../etc/passwd
译者注:/etc/passwd是某些Unix系统的密码存储文件
进而服务器会发回如下响应:
HTTP/1.0 200 OK
Content-Type: text/html
Server: Apache
root:fi3sED95ibqR6:0:1:System Operator:/:/bin/ksh
daemon:*:1:1::/tmp:
phpguru:f8fk3j1OIf31.:182:100:Developer:/home/users/phpguru/:/bin/csh
正如上例所示,重复的“…/”字符跟在“/home/users/phpguru/templates/”后面,造成了服务器遍历到了跟目录,并最终访问了Unix密码文件“/etc/passwd”。
为了说明攻击者如何尝试获取服务器密码数据,我们在上例中使用了Unix的“/etc/passwd”公共文件来展示目录遍历攻击(directory traversal)。
不过值得庆幸的是,在较新版本的Unix系统中,“passwd”文件不再包含哈希密码。在新版Unix中,密码被存放在隐藏文件中,这样未授权的用户将无法再轻易查看。尽管如此,目录遍历攻击仍然是遍历服务器账号信息的有效手段,如今的许多账号服务器也确实仍存在类似的安全漏洞。
本小节我们列出了一些已知的目录遍历攻击字符串组合:
通用的类Unix系统的目录遍历攻击字符串形如“…/”。
对于微软的Windows操作系统以及DOS系统的目录结构,攻击者可以使用“…/”或者“…\”字符串。
在这种操作系统中,每个磁盘分区有一个独立的根目录(比如我们会把个人电脑分区成“C盘”、“D盘”等等),并且在所有磁盘分区之上没有更高级的根目录。这意味着Windows系统上的目录遍历攻击会被隔离在单个磁盘分区之内(C盘被攻击,D盘不受影响)。
目录遍历攻击是诸多微软的漏洞之一。
标准化缺陷
一些网络应用会通过查询危险的字符串,例如:
标准化缺陷
UTF-8编码被Bruce Scheneier和Jeffery Streifling标记为一种易受攻击的资源。
当微软向他们的Web服务增加Unicode支持时,一种新的编码方式——“…/”被引入,也正是这一举动最终引入了目录遍历攻击。
许多带百分号的编码方式,例如:
形如zip这样的归档文件格式也允许目录遍历攻击:就像回溯文件系统一样,在归档文件中的任何文件也会被重写。我们可以编写出查看归档文件内部文件路径的代码来。
一个用来防御目录遍历攻击的算法应该包含以下几点:
1.针对URI请求的服务功能不应该导致文件系统被操作。举例来说,在继续执行下一步操作之前,在用户代码中执行嗅探钩子。
2.当确实需要提供一个操作文件或目录的URI请求服务时,在访问文件时先生成完整的文件路径(如果相应参数存在的话),并且将路径内的所有的字符都标准化(举例来说,将%20转换成空格)。
3.程序应当设置一个“文档根节点”,以这个确信的、标准化的路径为基准,来确定一个最顶层的目录路径N。并且规定在该目录上层的所有目录或文件不可访问。
4.通过程序来检查客户端请求拼接解码后的目录路径字符串的头部是否和程序规定的“文档根节点”N的头部相同。
5.如果相同,则允许本次文件操作。
6.如果不同,返回一个错误,因为该请求需要访问的文件目录范围已经超出了Web程序服务的文件范围。
7.请注意对文件后缀名进行硬编码,并不能限定所有请求都操作硬编码后缀的文件,例如如下代码:
客户端只要使用形如“\0”(即NULL,表明字符串已经结束。类似的结束符还有很多,详见https://en.wikipedia.org/wiki/Null_character#Representation)的字符来结尾,就能使程序忽略$_GET[php specific]
后的所有内容。
熬夜不易,请作者喝杯酒!