前言

根据红日安全写的文章,学习PHP代码审计审计的第二节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完这个题目,会有一道CTF题目来进行巩固,外加一个实例来深入分析,想了解上一篇的内容,可以点击这里:PHP代码审计01之in_array()函数缺陷

下面我们开始分析。

漏洞分析

下面来看第一题,代码如下:

<?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 &raquo;</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 来验证。这个函数过滤其他的参数设置说明,如下:

  • FILTER_CALLBACK:调用用户自定义函数来过滤数据。
  • FILTER_SANITIZE_STRING:去除标签,去除或编码特殊字符。
  • FILTER_SANITIZE_STRIPPED:”string” 过滤器的别名。
  • FILTER_SANITIZE_ENCODED:URL-encode 字符串,去除或编码特殊字符。
  • FILTER_SANITIZE_SPECIAL_CHARS:HTML 转义字符 ‘”<>& 以及 ASCII 值小于 32 的字符。
  • FILTER_SANITIZE_EMAIL:删除所有字符,除了字母、数字以及 !#$%&’*+-/=?^_{|}~@.[]
  • FILTER_SANITIZE_URL:删除所有字符,除了字母、数字以及 $-_.+!*'(),{}|\^~[]<>#%”;/?&=
  • FILTER_SANITIZE_NUMBER_INT:删除所有字符,除了数字和 +-
  • FILTER_SANITIZE_NUMBER_FLOAT:删除所有字符,除了数字、+- 以及 .,eE。
  • FILTER_SANITIZE_MAGIC_QUOTES:应用 addslashes()。
  • FILTER_UNSAFE_RAW:不进行任何过滤,去除或编码特殊字符。
  • FILTER_VALIDATE_INT:在指定的范围以整数验证值。
  • FILTER_VALIDATE_BOOLEAN:如果是 “1”, “true”, “on” 以及 “yes”,则返回 true,如果是 “0”, “false”, “off”, “no” 以及 “”,则返回 false。否则返回 NULL。
  • FILTER_VALIDATE_FLOAT:以浮点数验证值。
  • FILTER_VALIDATE_REGEXP:根据 regexp,兼容 Perl 的正则表达式来验证值。
  • FILTER_VALIDATE_URL:把值作为 URL 来验证。
  • FILTER_VALIDATE_EMAIL:把值作为 e-mail 来验证。
  • FILTER_VALIDATE_IP:把值作为 IP 地址来验证。

通过对两个过滤器的了解,我们想想该如何绕过呢?,其实,这里可以通过JavaScript伪协议来绕过,为了更好的理解,这里写一小段简单的代码。

$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,这是换行符,所以执行了咱们的弹窗。

CTF练习

通过上面的分析,是不是对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函数拼接后就形成了三条命令

  • curl "javascript://123"
  • ls
  • "test.com"

    这就成功命令执行,第一条和第三条不会被执行,当第二条被执行后,就可以查看到当前目录,发现flag.php,然后用cat命令来查看文件,拿到flag,这里需要注意的是,如果直接使用cat是会包含空格的,这样无法绕过filter_var()函数的过滤,所以用<代替空格。最后的flag为:javascript://";cat<flag.php;"test.com

    如果是Windows机器,换一下语法就可以了,比如要查看目录:
//查看目录
javascript://";dir;"test.com
![](https://img2020.cnblogs.com/blog/1996712/202010/1996712-20201001112330129-253033111.png)
//查看文件
javascript://";type=flag.php;"test.com

实例分析

通过上面的题目和CTF练习,是不是感觉正到劲头了,下面咱们分析实例,是Anchor 0.9.2版本,在这个版本中,当用户访问一个不存在的url时,程序会调用404模板,而这个模板存在XSS漏洞。现在咱们来仔细分析。下面看代码:



现在我们打开themes\default\404.php文件,看第六行,标签中的current_url()函数,接下来我们搜索这个函数,发现它在anchor\functions\helpers.php文件中,并看到current_url是由Uri类的current方法实现的,如下图:



下面我们跟进Uri类,是在system\Uri.php文件中,如下图:



发现这里调用了static::detect()方法,( static:: 是在PHP5.3版本之后引入的延迟静态绑定写法)

detect()方法就在下方,具体代码如下图:



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()函数理解更深了呢?下一篇文章会对实例化任意对象漏洞进行学习和分析,一起努力吧!

PHP代码审计02之filter_var()函数缺陷的更多相关文章

  1. PHP代码审计01之in_array()函数缺陷

    前言 从今天起,结合红日安全写的文章,开始学习代码审计,题目均来自PHP SECURITY CALENDAR 2017,讲完这个题目,会再用一道有相同问题的CTF题来进行巩固.下面开始分析. 漏洞分析 ...

  2. [代码审计Day2] filter_var函数缺陷代码审计

    简介 // composer require "twig/twig" require 'vendor/autoload.php'; class Template { private ...

  3. PHP-Audit-Labs-Day2 - filter_var函数缺陷

    目录 分析 示例 payload 修复建议 Day02-CTF题解 参考链接 分析 先看源码 // composer require "twig/twig" require 've ...

  4. PHP代码审计04之strpos函数使用不当

    前言 根据红日安全写的文章,学习PHP代码审计的第四节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完题目会用一个实例来加深巩固,这是之前写的,有兴趣可以去看看: PHP代码 ...

  5. filter_var()函数

    我们使用 payload :?url=javascript://comment%250aalert(1) ,可以执行 alert 函数: 实际上,这里的 // 在JavaScript中表示单行注释,所 ...

  6. 代码审计学习01-in_array() 函数缺陷

    一.开始代码审计之旅 01 从今天起,学习代码审计了,这篇文章就叫代码审计01吧,题目来自 PHP SECURITY CALENDAR 2017 的第一题,结合 红日安全 写的文章,开始吧. 二.先看 ...

  7. PHP filter_var 函数用法

    先介绍下PHP Filter PHP手册地址:http://php.net/manual/zh/ref.filter.php PHP 过滤器用于对来自非安全来源的数据(比如用户输入)进行验证和过滤. ...

  8. 学习笔记:filter_var()函数

    PHP 过滤器用于对来自非安全来源的数据(比如用户输入)进行验证和过滤 filter_var() 函数通过指定的过滤器过滤变量. 如果成功,则返回已过滤的数据,如果失败,则返回 false. 语法 f ...

  9. 漏洞:阿里云盾phpMyAdmin <=4.8.1 后台checkPageValidity函数缺陷可导致GETSHELL

    阿里云盾提示phpMyAdmin <=4.8.1会出现漏洞有被SHELL风险,具体漏洞提醒: 标题 phpMyAdmin <=4.8.1 后台checkPageValidity函数缺陷可导 ...

随机推荐

  1. 从零开始的SpringBoot项目 ( 一 ) Spring、SpringMVC和SpringBoot

    要想开始一个SpringBoot项目 , 首先要知道SpringBoot是什么 , 可以做什么 , 再去研究怎么用 . 一.概念 1.Spring Spring是一个开源容器框架,可以接管web层,业 ...

  2. 原生 JavaScript30 练习 Day 1 (原生JS控制键盘模拟击鼓)

     代码如下   <!DOCTYPE html> <html lang="en"> <head>     <meta charset=&qu ...

  3. [C#.NET 拾遗补漏]08:强大的LINQ

    大家好,这是 [C#.NET 拾遗补漏] 系列的第 08 篇文章,今天讲 C# 强大的 LINQ 查询.LINQ 是我最喜欢的 C# 语言特性之一. LINQ 是 Language INtegrate ...

  4. Cortex-M4的快速memcpy,根据数据对齐情况自动优化,速度为普通memcpy的1.3到5.2倍

    代码:https://github.com/gamesun/memcpy_fast memcpy_fast与memcpy速度比较 测试方法 memcpy_fast(dest + a, src + b, ...

  5. go语言基础实例

    一:变量 1)变量声明 func main() { var v1 int var v2 int //一次声明多个变量 var ( v3 int v4 int ) //变量最开始会有一个零值 fmt.P ...

  6. 【Pod Terminating原因追踪系列之一】containerd中被漏掉的runc错误信息

    前一段时间发现有一些containerd集群出现了Pod卡在Terminating的问题,经过一系列的排查发现是containerd对底层异常处理的问题.最后虽然通过一个短小的PR修复了这个bug,但 ...

  7. Flutter —布局系统概述

    老孟导读:此篇文章非常详细的讲解了 Flutter 布局系统的工作原理. 翻译自:https://itnext.io/flutter-layout-system-overview-c70bbe9ba9 ...

  8. The Unique MST(最小生成树的唯一性判断)

    Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spann ...

  9. Codehorses T-shirts (map+遍历)

    Codehorses has just hosted the second Codehorses Cup. This year, the same as the previous one, organ ...

  10. Codeforces 1324F Maximum White Subtree DFS

    题意 给你无根一颗树,每个节点是黑色或白色.对于每一个节点,问包含该节点的权值最大的子树. 子树的权值等于子树中白点的个数减去黑点的个数. 注意,这里的子树指的是树的联通子图. 解题思路 这场就这题卡 ...