PHP7和PHP5在安全上的区别
字数 1622 2025-08-18 11:38:08

PHP7与PHP5安全特性对比分析

前言

PHP7相比PHP5在安全性方面做出了多项重要改进,这些改动直接影响了许多传统Web渗透技术和后门利用方式。本文详细分析PHP7与PHP5在安全方面的主要区别,帮助开发者和安全研究人员了解这些变化。

函数修改

1. preg_replace()不再支持/e修饰符

PHP5情况

preg_replace("/.*/e", $_GET["h"], "");

/e修饰符允许将替换后的字符串作为PHP代码执行(eval方式)。

PHP7变化

  • 完全移除了/e修饰符支持
  • 替代方案:使用preg_replace_callback()

PHP7替代实现

preg_replace_callback("/.*/", function ($a){ @eval($a[0]); }, $_GET["h"]);

2. create_function()被废弃

PHP5后门示例

$func = create_function('', $_POST['cmd']);
$func();

PHP7影响

  • 该函数内部使用eval实现,移除后少了一种后门创建方式
  • 可使用匿名函数直接替代

3. mysql_*系列函数移除

变化内容

  • 移除了mysql_connect()mysql_query()等传统MySQL函数
  • 官方推荐使用mysqli或PDO_MySQL

安全影响

  • 推动开发者使用参数化查询,减少SQL注入风险
  • 但需注意:预编译查询的正确使用才是关键

4. unserialize()增加白名单参数

新函数签名

unserialize($serializedObj, ["allowed_classes" => true|false|array]);

选项说明

  • true:允许所有类(默认,向后兼容)
  • false:将所有对象转换为__PHP_Incomplete_Class对象
  • 数组:类名白名单

安全影响

  • 提供了防御不安全反序列化的机制
  • 但目前仍是可选参数,不是强制要求

5. assert()默认不再执行代码

PHP5情况

assert('eval($_POST[cmd])'); // 可执行代码

PHP7变化

  • assert()现在仅用于断言检查,不再执行代码
  • 导致大量基于assert()的Webshell失效

影响范围

  • 中国菜刀等工具使用的assert()函数失效
  • 通常需要修改为eval()才能正常工作

语法修改

1. foreach不再改变内部数组指针

PHP5行为

$a = array('1','2','3');
foreach ($a as $k=>&$n){ echo ""; }
foreach ($a as $k=>$n){ echo ""; } // 会影响数组值

PHP7变化

  • 通过值遍历时操作数组副本,不影响原数组
  • 注:仅影响PHP7.0.0版本,后续版本恢复原行为

2. 8进制字符容错率降低

PHP5行为

octdec('012999999999999') == octdec('012'); // true

无效8进制数字被静默截断

PHP7变化

  • 无效8进制数字会触发解析错误
  • 注:仅影响PHP7.0.0版本,后续版本恢复原行为

3. 十六进制字符串不再被认为是数字

PHP5行为

var_dump("0x123" == "291"); // true
var_dump(is_numeric("0x123")); // true

PHP7变化

  • 严格区分十六进制字符串和数字
  • 此修改是永久性的,未在后续版本恢复

安全影响

  • 影响某些CTF解题技巧
  • 减少类型混淆漏洞利用可能性

4. 移除了ASP和script PHP标签

移除的标签形式

<% %> 
<script language="php"> </script>

保留的标签

<?php ?>

其他安全相关修改

1. 超大浮点数类型转换

PHP5行为

  • 超大浮点数转整数时静默截断

PHP7行为

  • 会报错,防止不可预期的截断行为

2. 执行函数对NULL增加保护

涉及函数

  • exec(), system(), passthru()
  • 对NULL输入增加了安全处理

3. parse_str()必须使用第二个参数

PHP5行为

parse_str("a=1&b=2"); // 变量$a和$b被创建

PHP7要求

parse_str("a=1&b=2", $output); // 必须提供输出变量

安全影响

  • 防止意外污染当前符号表
  • 减少变量注入风险

4. 杂项修改

  • list()不再能解开字符串变量
  • $HTTP_RAW_POST_DATA被移除
  • __autoload()方法被废弃
  • 统一了不同平台下的整型长度
  • session_start()可接受配置数组覆盖php.ini设置

总结

PHP7的这些安全改进总体上提高了语言的安全性,使得许多传统的Web攻击技术失效。主要影响包括:

  1. Webshell技术需要更新,许多传统后门函数被移除或限制
  2. 数据类型处理更加严格,减少类型混淆漏洞
  3. 推动更安全的编程实践,如参数化查询
  4. 提供了更多安全控制选项,如反序列化白名单

开发者应当了解这些变化,及时更新代码;安全研究人员也需要调整测试方法,适应PHP7的新特性。

PHP7与PHP5安全特性对比分析 前言 PHP7相比PHP5在安全性方面做出了多项重要改进,这些改动直接影响了许多传统Web渗透技术和后门利用方式。本文详细分析PHP7与PHP5在安全方面的主要区别,帮助开发者和安全研究人员了解这些变化。 函数修改 1. preg_ replace()不再支持/e修饰符 PHP5情况 : /e修饰符允许将替换后的字符串作为PHP代码执行(eval方式)。 PHP7变化 : 完全移除了/e修饰符支持 替代方案:使用 preg_replace_callback() PHP7替代实现 : 2. create_ function()被废弃 PHP5后门示例 : PHP7影响 : 该函数内部使用eval实现,移除后少了一种后门创建方式 可使用匿名函数直接替代 3. mysql_* 系列函数移除 变化内容 : 移除了 mysql_connect() 、 mysql_query() 等传统MySQL函数 官方推荐使用mysqli或PDO_ MySQL 安全影响 : 推动开发者使用参数化查询,减少SQL注入风险 但需注意:预编译查询的正确使用才是关键 4. unserialize()增加白名单参数 新函数签名 : 选项说明 : true :允许所有类(默认,向后兼容) false :将所有对象转换为 __PHP_Incomplete_Class 对象 数组:类名白名单 安全影响 : 提供了防御不安全反序列化的机制 但目前仍是可选参数,不是强制要求 5. assert()默认不再执行代码 PHP5情况 : PHP7变化 : assert()现在仅用于断言检查,不再执行代码 导致大量基于assert()的Webshell失效 影响范围 : 中国菜刀等工具使用的assert()函数失效 通常需要修改为eval()才能正常工作 语法修改 1. foreach不再改变内部数组指针 PHP5行为 : PHP7变化 : 通过值遍历时操作数组副本,不影响原数组 注:仅影响PHP7.0.0版本,后续版本恢复原行为 2. 8进制字符容错率降低 PHP5行为 : 无效8进制数字被静默截断 PHP7变化 : 无效8进制数字会触发解析错误 注:仅影响PHP7.0.0版本,后续版本恢复原行为 3. 十六进制字符串不再被认为是数字 PHP5行为 : PHP7变化 : 严格区分十六进制字符串和数字 此修改是永久性的,未在后续版本恢复 安全影响 : 影响某些CTF解题技巧 减少类型混淆漏洞利用可能性 4. 移除了ASP和script PHP标签 移除的标签形式 : 保留的标签 : 其他安全相关修改 1. 超大浮点数类型转换 PHP5行为 : 超大浮点数转整数时静默截断 PHP7行为 : 会报错,防止不可预期的截断行为 2. 执行函数对NULL增加保护 涉及函数 : exec() , system() , passthru() 对NULL输入增加了安全处理 3. parse_ str()必须使用第二个参数 PHP5行为 : PHP7要求 : 安全影响 : 防止意外污染当前符号表 减少变量注入风险 4. 杂项修改 list() 不再能解开字符串变量 $HTTP_RAW_POST_DATA 被移除 __autoload() 方法被废弃 统一了不同平台下的整型长度 session_start() 可接受配置数组覆盖php.ini设置 总结 PHP7的这些安全改进总体上提高了语言的安全性,使得许多传统的Web攻击技术失效。主要影响包括: Webshell技术需要更新,许多传统后门函数被移除或限制 数据类型处理更加严格,减少类型混淆漏洞 推动更安全的编程实践,如参数化查询 提供了更多安全控制选项,如反序列化白名单 开发者应当了解这些变化,及时更新代码;安全研究人员也需要调整测试方法,适应PHP7的新特性。