根据红日安全写的文章,学习PHP代码审计审计的第二节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完这个题目,会有一道CTF题目来进行巩固,外加一个实例来深刻分析,想了解上一篇的内容,能够点击这里:PHP代码审计01之in_array()函数缺陷
下面咱们开始分析。javascript
下面来看第一题,代码以下:php
<?php require 'vendor/autoload.php'; class Template{ private $twig; public function __construct() { //这里是第一次过滤 $indexTemplate = 'img'.'src="https://loremflickr.com/320/240">'. '<a href="{{link|escape}}">Next slide »</a>'; $loader = new Twig\Loader\ArrayLoader([ 'index.html'=>$indexTemplate ]); $this->twig = new Twig\Environment($loader); } public function getNexSlideUrl(){ $nexSlide = $_GET['nexSlide']; //这里是第二次过滤 return filter_var($nexSlide,FILTER_VALIDATE_URL); } public function render(){ echo $this->twig->render( 'index.html', ['link'=>$this->getNexSlideUrl()] ); } } (new Template())->render(); ?>
这一关用的是PHP的一个模板引擎Twig,考察的是XSS漏洞,也就是跨站脚本攻击。虽然程序使用了escape和filter_var()两个过滤方法,可是。仍是能够被绕过的。下面咱们看第一处过滤,在上面代码的第10行,使用Twig模板引擎定义的escape过滤器来过滤link。而escape过滤器默认状况下,它使用HTML转义策略,也就是escape将PHP本机htmlspecialchars函数用于HTML转义策略,如今咱们看一下PHP手册,htmlspecialchars函数是如何定义的。
其实就是把一些预约义字符转换成HTML实体。具体看下表:
下面咱们来看第二处过滤,是在上面代码第20行,是用filter_var()来进行过滤,下面咱们来看看PHP手册对这个函数的定义:
具体参数设置以下表:
上面代码是用了FILTER_VALIDATE_URL,把值做为 URL 来验证。这个函数过滤其余的参数设置说明,以下:html
经过对两个过滤器的了解,咱们想一想该如何绕过呢?,其实,这里能够经过JavaScript伪协议来绕过,为了更好的理解,这里写一小段简单的代码。java
$url = filter_var($_GET['url'],FILTER_VALIDATE_URL); var_dump($url); $url = htmlspecialchars($url); var_dump($url); echo "<a href='$url'>测试一下</a>";
下面咱们构造payload,用JavaScript伪协议来绕过,payload为:javascript://test%250aalert(1)
,而后执行以下图:
其实上面payload中,//后面的内容全是注释的内容,那为何仍是会被执行呢?由于在上面的payload用了%0a,%进行了编码,成了%25,这是换行符,因此执行了我们的弹窗。web
经过上面的分析,是否是对filter_var()函数有了必定的了解呢,让我们用一道CTF的题目来巩固一下吧。这道题也是由于filter_var被绕过,致使命令执行。看下面代码。正则表达式
<?php $url = $_GET['url']; //检查是不是合法的URL if (isset($url)&&filter_var($url,FILTER_VALIDATE_URL)) { $site_info = parse_url($url); //正则判断 if (preg_match('/test.com$/', $site_info['host'])) { exec('curl "' . $site_info['host'] . '"', $result); echo "<center><h1>You have curl {$site_info['host']} successfully!</h1></center> <center><textarea rows ='20' cols='90'>"; echo implode(' ', $result); } else { die("<center><h1>Error: Host not allowed</h1></center>"); } } else{ echo "<center><h1>Just curl test.com.com!</h1></center><br> <center><h3>For example:?url=http://test.com.com</h3></center>"; } ?>
如今分析上面的代码,GET接收url参数,而后用filter_var检查是否为合法的URL,接着走到下面的代码,正则判断结尾必须还有test.com。
而后用了exec函数,看到它咱们嘴就有了笑容,由于只要咱们绕过上面两处检查,咱们就能够随心所欲,命令执行了。而上面咱们分析了,可使用伪协议来绕过filter_var的检查,至于正则判断,只要咱们结尾包含test.com,就绕过了正则检查。
如今咱们设置payload:javascript://123";ls;"test.com
伪协议绕过了filter_var检查。结尾绕过了正则判断,当与exec函数拼接后就造成了三条命令数组
javascript://";cat<flag.php;"test.com
//查看目录 javascript://";dir;"test.com //查看文件 javascript://";type=flag.php;"test.com
经过上面的题目和CTF练习,是否是感受正到劲头了,下面我们分析实例,是Anchor 0.9.2版本,在这个版本中,当用户访问一个不存在的url时,程序会调用404模板,而这个模板存在XSS漏洞。如今我们来仔细分析。下面看代码:
如今咱们打开themes\default\404.php文件
看第六行,接下来咱们搜索这个函数,发现它在anchor\functions\helpers.php文件中,并看到current_url是由Uri类的current方法实现的,以下图:安全
下面咱们跟进Uri类,是在system\Uri.php文件中,以下图:curl
发现这里调用了static::detect()方法,( static:: 是在PHP5.3版本以后引入的延迟静态绑定写法)
detect()方法就在下方,具体代码以下图:ide
detect()方法会获取$_SERVER数组中的REQUEST_URI, PATH_INFO, ORIG_PATH_INFO键值,若是存在其中一个键,而且符合filter_var($uri, FILTER_SANITIZE_URL)和parse_url($uri, PHP_URL_PATH)则直接将$uri传入format()方法中。如今咱们跟进这个方法。就在下边,如图:
发现程序过滤了三次,看截图130行到136行。可是没有对XSS进行过滤。下面咱们来构造payload。
如今咱们构造payload:localhost/anchor/index.php/<script>alert("XSS")</script>
如今结合上面的讲解来分析,当咱们访问这个不存在的url时,程序会调用404模板页面,而后调用current_url()函数来获取当前文件名,也就是我们构造的<script>alert("XSS")</script>
,嵌入了进去,找成XSS攻击。效果以下图:
经过上面的分析,是否是对filter_var()函数理解更深了呢?下一篇文章会对实例化任意对象漏洞进行学习和分析,一块儿努力吧!