最近在看PHP SECURITY CALENDAR 2017的题目,这是第二题
Can you spot the vulnerability?
// composer require "twig/twig"
require 'vendor/autoload.php';
class Template {
private $twig;
public function __construct() {
$indexTemplate = '' .
'Next slide »';
// Default twig setup, simulate loading
// index.html file from disk
$loader = new Twig\Loader\ArrayLoader([
'index.html' => $indexTemplate
]);
$this->twig = new Twig\Environment($loader);
}
public function getNexSlideUrl() {
$nextSlide = $_GET['nextSlide'];
return filter_var($nextSlide, FILTER_VALIDATE_URL);
}
public function render() {
echo $this->twig->render(
'index.html',
['link' => $this->getNexSlideUrl()]
);
}
}
(new Template())->render();
这里考察的是XSS漏洞。对于XSS漏洞,大部分出现的地方在输出环节,如 echo $var; $var可控且无过滤,或者过滤不严格,导致了XSS漏洞的产生。
而在这里,XSS的出现是因为标签内的code过滤不严格,导致可利用javascript伪协议绕过。
代码不长,首先来通读下整段代码。 这是一个Template的类的定义,类的内部定义了三个函数函数,分别为construct()、getNexSlideUrl()以及render()。
construct()主要实现了模板载入,getNexSlideUrl()主要实现了URL过滤识别,render()则主要是实现了传入URL的功能。函数的功能并不复杂,关键点在于两个过滤函数:
对于twig的escape过滤器,可以见官网的说明:
escape uses the PHP native htmlspecialchars function for the HTML escaping strategy.
其实也就是将htmlspecialchars包装到了escape的过滤器中,换了个使用方式,真正起作用的,还是htmlspecialchars函数
htmlspecialchars(string,flags,character-set,double_encode)
我们都知道htmlspeciachars的主要作用就是将特殊字符转换为 HTML 实体,这一方法不但可以在一定程度上防止SQL,也可以在一定程度上防止XSS。
但是有些xss并不需要特殊字符。 再来看看filter_var():
filter_var(variable, filter, options)
filter_var($nextSlide, FILTER_VALIDATE_URL);
将获取的nextSlide值传入filter_var()函数中,然后判断其是否符合URL的相关规则。 这里的URL的判断就很有意思,有很多绕过判断的方式,有兴趣的朋友可以自行谷歌。 但是这里考虑到htmlspecicalchars,因此对于单双引号以及尖括号的payload都不考虑。
官方给的解答是:
?nextSlide=javascript://comment%250aalert(1)
NextSlide传入的值为
javascript://comment%250aalert(1)
如果将这个值echo出来,结合标签,就会产生xss,具体流程如下: 首先传入到标签内:
Next slide »
//为注释符,%25为百分号,%与0a组成为换行符
最终单独生成一行为alert(1),成功执行了alert函数
// index.php
You have curl {$site_info['host']} successfully!