Web 应用渗透测试 01 - 命令注入(Code Injection)之 create_function

news/2024/11/17 9:27:44/

背景

这篇文章将讨论 PHP Web 应用中 create_function 的命令注入。命令注入,究其根源,都是未对用户提供的输入做合理过滤造成的。当然,编程语言本身内置的危险方法的使用,是命令注入频发的另一原因。

各种变成语言的危险方法有所不同,对于 PHP 而言,我们可以再这里找到一系列的 PHP 危险方法。在使用这些方法的时候,一定要考虑其安全隐患。

在这些众多的危险方法中,最臭名昭著的,当是 eval() 莫属。这个方法可以直接调用,也可以通过其他的 PHP 内置方法间接调用。

今天,我们看一下 PHP 4 时代就存在的 create_function 内置方法,是如何走向命令注入的。

环境参数

create_function 存在于 PHP 4 >= 4.0.1, PHP 5, PHP 7 版本中。

该方法已经在 PHP 7.2.0 中废弃,并在 PHP 8.0.0 中移除。

在这里插入图片描述

create_function 方法

这里,我们看一下该方法的基本作用,它的应用,最后看一下源码,找出命令注入的成因。

方法介绍

根据官方文档,create_function 方法,顾名思义,就是可以将自定义的代码字符串,解析成可执行代码,并且可以指定任意个方法参数。

我们到 Online PHP Playground 来通过实例看一下这个方法的使用。

我们选择 PHP 7.0.33。

在这里插入图片描述

定义一个方法,两数相加。

<?php
$func = create_function('$a, $b', 'return "$a + $b = " . $a + $b;');
echo $func(1, 2);
?>

将这个方法赋值给 $func,就可以调用该方法做加法运算。

在这里插入图片描述

如果选择高 PHP 版本,如 7.4.32,该自定义方法还是可以执行,只是会报警告,因为该方法已经废弃。

在这里插入图片描述

实际应用

create_function 方法通常会被用于对数组的自定义排序,会和另一个 usort 方法 一起使用。例如对从数据库中取出的数据,根据某个属性,做自定义的排序。

用以下代码举例,创建一个 User 类,创建一个包含4个 User 对象的数组,自定义使用 username 属性排序。

<?phpclass User {public $username;public $passwd;function __construct($username, $passwd) {$this->username = $username;$this->passwd = $passwd;}
}$users = array(new User('able', 'best'),new User('zigzag', 'empty'),new User('boy', 'coolest'),new User('luke', 'force')
);$order = 'username';// 自定义使用 User 对象的 username 属性作为排序的依据
usort($users, create_function('$a, $b', 'return strcmp($a->' . $order . ', $b->' . $order . ');'));print_r($users);?>

结果如下:

在这里插入图片描述

$order 改为使用 passwd 属性排序。

结果如下:

在这里插入图片描述

这就是该方法的实际应用场景。

create_function 源码及 CVE-2008-4096

CVE-2008-4096phpAdmin 2.11.9.1 远程代码执行的漏洞。成因就是利用 sort_by 参数,将命令注入到 create_function 方法。

现在我们看一下 create_function 方法的源码。

找到 PHP 在 Github 的仓库,选择 5.2 分支(CVE-2008-4096 的 PHP 版本是 5.2.6)。

搜索 create_function,在 1449 行找到了方法定义。

在这里插入图片描述

比较关心用户输入在哪里被使用。所以看到 1470 行,两个 %s 的时候,就找到了目标。可以看到源码中到处都是 eval,应该就是使用 eval 执行我们的代码字符串。

1464 行到 1469 行定义了整个代码字符串的边界。

在这里插入图片描述
方法名在 1446 行被定义成 __lambda_func,然后加上参数的长度,加上两个方法参数的括号 (),加上两个代码体的括号 {},最后加上代码长度。

其实就是拼接了一个方法,如:

function __lambda_func(){}

然后在 **1470 ** 行,zend_spprintf 会把整个代码拷贝到 eval_code 变量中。最后,会在 1473 行调用自定义的方法。

在这里插入图片描述

因此,如果用户输入没有做合理的过滤,就会造成恶意的命令注入。

命令注入实践

在 Online PHP Playground 中,尝试注入 uname -a

看到如下警告,因为安全原因,Online PHP Playground 禁用了如 system 的调用。

在这里插入图片描述

有警告,说明其实命令注入是成功的。

转到虚拟机上尝试。

在虚拟机上安装了 PHP 7.0.33。

在这里插入图片描述

使用同样的测试代码。

<?phpclass User {public $username;public $passwd;function __construct($username, $passwd) {$this->username = $username;$this->passwd = $passwd;}
}$users = array(new User('able', 'best'),new User('zigzag', 'empty'),new User('boy', 'coolest'),new User('luke', 'force')
);$order = 'username';usort($users, create_function('$a, $b', 'return strcmp($a->' . $order . ', $b->' . $order . ');'));print_r($users);?>

在这里插入图片描述
运行。

可以看到命令注入成功。

在这里插入图片描述

总结

综上,create_function 命令注入的条件只需要两个:

  1. 4.0.1 <= PHP 版本 < 8.0.0;
  2. 用户输入没有做过滤或者过滤不完全;

参考链接

  • https://cxsecurity.com/issue/WLB-2008090063
  • https://bugs.php.net/bug.php?id=48231
  • https://www.exploit-db.com/exploits/32417
  • https://www.php.net/manual/en/function.create-function.php
  • https://www.geeksforgeeks.org/php-create_function-function/
  • https://www.w3schools.com/php/php_oop_constructor.asp
  • https://www.geeksforgeeks.org/php-usort-function/
  • https://github.com/php/php-src/blob/PHP-5.0/Zend/zend_builtin_functions.c
  • https://opensource.apple.com/source/apache_mod_php/apache_mod_php-110/php/Zend/zend_builtin_functions.c.auto.html

http://www.ppmy.cn/news/22304.html

相关文章

数据库面试题

数据库面试什么是事务?以及事务的ACID?请描述数据库的隔离级别视图和数据表的区别是什么?SQL优化:什么是索引?以及索引的应用?什么是事务?以及事务的ACID? 事务:事务是指严密逻辑的操作&#xff0c;要么都成功&#xff0c;要么都失败。 通俗一点说:一件事中有很多个环…

html+css网页练习一

文章目录一、活动页面1、要求2、效果图3、index.html4、style.css二、改革进展与成效管理平台页面1、要求2、效果图3、index.html4、normalize.css三、头部静态html1、要求2、效果图3、header.html4、header.css四、课程表1、要求2、效果图3、table.html4、table.css素材在我的…

DGIOT开源物联网-移动云部署

感谢来自苏州的用户支持为了节省开发者和实施工程师的时间&#xff0c;降低部署难度&#xff0c;本文提供了一套基于linux系统的一键式部署方式&#xff0c;以便快速交付&#xff0c;提升学习和商用部署的效率。安装部署1.服务器移动云地址云服务器购买时选择如下操作系统&…

pyqt5主窗口按键弹出子窗口

目标&#xff1a;主窗口保持&#xff0c;通过按键弹出子窗口 步骤一&#xff1a;pyqt5创建主窗口&#xff0c;并设置按键 from PyQt5.QtWidgets import * import sys# 主窗口 class Main(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("主窗口…

基于linux5.15.5的IMX 参考手册 --- 6

基于linux5.15.5的IMX 参考手册 — 6 4.4 FEC (Fast Ethernet Controller) 4.4.1介绍 快速以太网控制器(FEC)驱动程序执行全套IEEE 802.3/以太网CSMA/CD媒体访问控制和通道接口功能。 FEC需要外部接口适配器和收发器功能来完成与以太网媒体的接口。10 Mbps、100 Mbps和1000 Mb…

超声波测距LCD1602显示

超声波测距模块&#xff1a;1、采用IO口TRIG触发测距&#xff0c;给至少10us的高电平信号&#xff1b;2、模块自动发送8个40khz的方波&#xff0c;自动检测是否有信号返回&#xff1b;3、有信号返回&#xff0c;通过IO口ECHO输出一个高电平&#xff0c;高电平持续的时间就是超声…

《枢纽》- 在起伏的浪潮中,一个人怎么认知环境?

01关于作者施展&#xff0c;外交学院世界政治研究中心主任&#xff0c;青年学者&#xff0c;工科出身的北京大学史学博士&#xff0c;"得到"App大师课《中国史纲50讲》主讲人。主要研究西方政治思想史、西方文明史等领域。02关于本书《枢纽》这个书名形容的是今天中国…

2023最新版多线程面试题(四)(持续更新中)

41、在java 中 wait和 sleep 方法的不同? 最大的不同是在等待时 wait 会释放锁&#xff0c;而 sleep一直持有锁。Wait 通常被用于线程间交互&#xff0c;sleep 通常被用于暂停执行。 直接了解的深入一点吧: 在 Java 中线程的状态一共被分成 6种: 初始态: NEW 创建一个 Th…