浮尘 发表于 2015-9-17 17:05:52

PfSense XSS漏洞分析

0×00 导言

PfSense是一款基于FreeBSD操作系统的开源网络防火墙软件,已经被世界各地的公司广泛用来保护其基础设施。

在去年的时候,我们在PfSense中发现了一些安全漏洞(FreeBuf曾报道过),并提交给了PfSense的安全团队,到目前为止,时间已经过去一年有余,这段时间足以让使用PfSense的公司和个人通过打补丁升级到了最新的版本。因此,我们打算将这些漏洞公之于众,以便于安全研究人员互通有无,共享信息。

在本文中,我们将向大家介绍在pfSense中发现的CVE-2014-4687漏洞,该漏洞只存在于2.1.3及以下的版本中,此后的版本已经修复了该漏洞。

0×01 Schedules接口中的存储型XSS

如果我们点击Schedules,就会看到如下所示的Web接口。
http://image.3001.net/images/20150917/14424470976692.png!small
图1 Schedules页面

打开这个页面之后,我们就可以通过按+按钮来添加时间表了。在这个过程中,我们可以把starttime0这个POST参数的值改为0:00'><script>alert(1);</script><,如下图在高亮部分所示。
http://image.3001.net/images/20150917/14424471125379.png!small
图2 发送给服务器的恶意JavaScript请求

之后,输入的这段JavaScript代码会被原封不动地写入到响应中,并且没有对特殊字符进行任何的封装处理。这个响应的内容如下图所示。
http://image.3001.net/images/20150917/14424471359667.png!small
图3 响应中的恶意JavaScript代码

一旦这个请求被显示于一个Web浏览器中,那么它就会变成一个XSS漏洞,因为其中的JavaScript代码会被浏览器所执行,具体如下图所示。
http://image.3001.net/images/20150917/14424471483143.png!small
图4 JavaScript代码被浏览器执行

由于这个漏洞可在用户的Web浏览器中执行任意的JavaScript代码,所以,它能够用来窃取用户的会话cookie。

0×02 Rss.widget.php文件中的存储型XSS漏洞

在PHP脚本widgets/widgets/rss.widget.php中,有一个存储型XSS漏洞,更确切地说,这个漏洞位于名为rssfeed的POST参数中。与这个漏洞相关的代码如下所示,其中高亮显示的部分为漏洞所在的代码。
<?php
if($POST) {
$config = str_replace(n, ,, $POST);
$config = str_replace(n, ,,
POST);
$config = $POST;
$config = $POST;
writeconfig(Saved RSS Widget feed via Dashboard);
Header(Location: /);
}
if($config)
$textareatxt = strreplace(,, n, $config);
else
$textareatxt = "";
?>
<textarea name="rssfeed" class="formfld unknown" id="rssfeed"
ols="40" rows="3">
<?=$textareatxt;?>
</textarea>
下面所示的这个请求,会被名为rssfeed的POST参数中的恶意JavaScript代码发送给对应的Web服务器。
http://image.3001.net/images/20150917/14424471757203.png!small
图5 POST参数rssfeed中的恶意JavaScript代码

之后,返回的响应中,会包含如下所示的代码,并且其中的特殊字符没有经过适当的安全处理。

http://image.3001.net/images/20150917/14424471878525.png!small

图6 之前发送的恶意JavaScript代码被直接放入返回的Web页面中

下面展示的POST参数中也存在安全漏洞,并且它们都是位于同一个脚本中:
-   rssmaxitems
-   rsswidgetheight
-   rsswidgettextlength
-   rsswidgettextlength
攻击者可以将恶意JavaScript代码发送给Web应用,并且该应用也会把这些代码存储到页面中返回给其他用户。

0×03 Services_status.widget.php脚本中的反射型XSS

我们发现,widgets/widgets/services_status.widget.php脚本也没有对用户提供的数据进行恰当地封装处理。例如,对于下面所示的代码,我们可以直接将POST变量servicestatusfilter赋值为 $config',因为该脚本并没有对用户输入进行任何的“消毒”处理。之后,我们可以利用HTML代码来显示这个变量的值。
<?php
if(isset($_POST['servicestatusfilter'])) {
$config['widgets']['servicestatusfilter'] =_POST['servicestatusfilter'];
write_config("Saved Service Status Filter via Dashboard");
header("Location: ../../index.php");
}
?>
<input type="text" size="30" name="servicestatusfilter"
lass="formfld unknown" id="servicestatusfilter" value="<?=config['widgets']['servicestatusfilter'] ?>" />
下面的请求中,含有一个POST参数servicestatusfilter,其值为"/><script>alert(1);</script><"。
http://image.3001.net/images/20150917/14424472139870.png!small
图7 POST参数servicestatusfilter中的恶意JavaScript代码

通过观察下图可以发现,响应中的值跟之前的值一模一样。
http://image.3001.net/images/20150917/14424472264041.png!small
图8 POST参数rssfeed中的恶意JavaScript代码

需要注意的是,这里的JavaScript代码并不会在Web浏览器中执行,因为这里还提供了一个Location头部,因此,JavaScript代码在执行之前就被重定向了。虽然如此,这仍然是一个安全漏洞,同样需要进行修补。因为攻击者能够利用它在用户的浏览器中执行任意的JavaScript代码。

0×04 Log.widget.php脚本中HTTP头部Referer中的XSS漏洞

在widgets/widgets/log.widget.php脚本中也存在一个XSS漏洞,相应的代码如下图所示。其中,HTTP头部Referer被读入变量$filename中,而这个变量随后会被放入响应页面中,但是并没有对特殊字符进行相应的编码处理。
$filename = $_SERVER['HTTP_REFERER'];
if(headers_sent($file, $line)){
echo '<script type="text/javascript">';
echo '//<![CDATA[';
echo 'window.location.href="'.$filename.'";';
echo '//]]>';
echo '</script>';
echo '<noscript>';
echo '<meta http-equiv="refresh" content="0;url='.$filename.'" />';
echo '</noscript>';
}
如果我们利用HTTP头部Referer发送一个字符串<script>,那么,我们就会收到如下所示的响应,表明遇到了一个问题,原因是HTTP头部Referer中的字符串与系统设置的不相符。
http://image.3001.net/images/20150917/14424472529882.png!small
图9 利用HTTP头部referer发送<script>时的响应

之所以出现这种情况,是因为Pfsense实现了HTTP_REFERER重定向检测,并且默认设置会阻止这种行为,要想改变这个设置,可以通过System – Advanced – Admin settings进行修改,如下图所示。
http://image.3001.net/images/20150917/14424472667760.png!small
图10 与HTTP头部referer有关的pfsense设置

我们需要禁用强制检查HTTP_REFERER,并保存相应的设置。这样,我们就可以利用HTTP的Referer头来发送字符串"/></noscript><script>alert(1);</script><noscript><"了,具体如下图所示。
http://image.3001.net/images/20150917/14424472784997.png!small
图11 在HTTP的Referer头部中含有恶意JavaScipt代码的请求

在下面的响应中,存储在HTTP头部Referer中的这个值,向用户呈现了两次。
http://image.3001.net/images/20150917/14424472926502.png!small
图12 恶意JavaScript代码被放入返回的Web页面中

由于我们对<noscript>及其他HTML元素进行了相应的转义处理,所以,这些注入的JavaScript就能够在用户的浏览器中执行了,如下图所示。
http://image.3001.net/images/20150917/14424473051170.png!small
图13 执行恶意JavaScript代码

由于Pfsense的默认设置会启用HTTP_REFERER的强制检查功能,因此,这个漏洞是比较难以利用的,不过,这个漏洞的确是存在的,所以必须进行相应的安全处理。除此之外,这个响应中含有的其他一些POST参数也没有经过适当的消毒处理,这使得被攻击的可能性更大了。这些存在安全缺陷的POST参数包括:
-   filterlogentries
-   actpass
-   actblock
-   actreject
-   filterlogentriesinterfaces
此外,攻击者还能向HTTP的Referer头中注入JavaScript代码,并使其在用户的浏览器中被执行。

0×05 Exec.php脚本中的JavaScript注入漏洞
我们知道,The Diagnostics :Execute command 功能允许攻击者向服务器上载文件,具体如下所示。
http://image.3001.net/images/20150917/14424473239406.png!small
图14 文件上载功能

为了使用户能够访问这一功能,必须赋予他访问Diagnostics :Command的相应权限,具体如下图所示。
http://image.3001.net/images/20150917/1442447335118.png!small
图15 所需的权限

当上传文件的时候,攻击者有机会向参数txtRecallBuffer中注入任意的JavaScript代码。如下图所示,本例在参数txtRecallBuffer注入了一个字符串,即"bbb'); var arrRecalBuffer = new Array('aaa",见图中高亮显示部分。
http://image.3001.net/images/20150917/14424473471294.png!small
图16 发送给服务器的恶意输入数据

上面的请求所导致的响应如下所示,这说明注入任意JavaScript代码是可行的。
http://image.3001.net/images/20150917/14424473604852.png!small
图17 前面发送的输入数据被直接放入JavaScript代码块中

需要注意的是,我们无法利用这个漏洞,因为整个JavaScript代码块都位于注释中,即被<!—->注释掉了。通常来说,我们是可以设法让这些代码逃出注释符的魔咒的,比如先注入符号>,然后在其后加入任意代码即可。但是就本例来说,我们是不能这样做的,因为<和>这两个特殊字符都会被正确地编码的。
此外,JavaScript代码还可以注入到Web页面中,这样的话,攻击者就可以在用户的浏览器中执行任意JavaScript代码了。

0×06小结

本文详细介绍了我们在PfSense中发现的一些XSS漏洞,希望对读者朋友们有所帮助。
页: [1]
查看完整版本: PfSense XSS漏洞分析