To Begin With
最近在准备 LANCTF,想把环境迁移到 PHP 7,却想到一些 payload 失效了。想着什么时候总结成一个笔记,恰巧在 FB 发现有人写了一篇博文,拜读后结合 CTF 环境整理了一下,总体来说,弃用了较多不安全的使用方式,但运行环境未过多限制时仍可使用。
测试环境
docker pull php:7.3.3-apache
docker pull php:7.0-apache
函数变化
preg_replace
preg_replace() 不再支持 /e 修饰符,官方曾提到
如果设置了这个被弃用的修饰符, preg_replace() 在进行了对替换字符串的 后向引用替换之后, 将替换后的字符串作为php 代码评估执行(eval 函数方式),并使用执行结果 作为实际参与替换的字符串。单引号、双引号、反斜线(\)和 NULL 字符在后向引用替换时会被用反斜线转义。
Version
Description
7.0.0
Support for the /e modifier has been removed. Use preg_replace_callback() instead.
5.5.0
The /e modifier is deprecated. Use preg_replace_callback() instead. See the PREG_REPLACE_EVAL documentation for additional information about security risks.
但在 php 7.0 时,移除了(removed)该修饰符,不能再使用此方式的后门。
create_function
create_function 被废弃 php7.2
Warning
This function has been DEPRECATED as of PHP 7.2.0. Relying on this function is highly discouraged.
但目前还是弃用状态,在简单环境下仍可以使用该函数,但在未来的版本中会被移除。后面出现的相似情况不再赘述。
mysql_*
需要使用 mysqli 或者 pdo
unserialize
unserialize 第二个参数( optional )添加了白名单。可以通过unserialize的过滤参数来设定是否过滤指定的类返回__PHP_Incomplete_Class_Name类的对象,__PHP_Incomplete_Class_Name是一个没有方法的类。具体的参数为allowed_classes,其指向需要过滤的类,默认是true,既可以对所有类都可以完全反序列化。
$data = unserialize($serializedObj1 , ["allowed_classes" => true]);
$data2 = unserialize($serializedObj2 , ["allowed_classes" => ["MyClass1", "MyClass2"]]);
assert
第一个参数为 string 断言的情况被废弃。
Warning: Cannot call assert() with string argument dynamically (after 7.0)[6]
Version
Description
7.2.0
Usage of a string as the assertion became deprecated. It now emits an E_DEPRECATED notice when both assert.active and zend.assertions are set to 1.
7.0.0
assert() is now a language construct and not a function. assertion can now be an expression. The second parameter is now interpreted either as an exception (if a Throwable object is given), or as the description supported from PHP 5.4.8 onwards.
目前尚可使用。
parse_str
Warning
Using this function without the result parameter is highly DISCOURAGED and DEPRECATED as of PHP 7.2.
Dynamically setting variables in function's scope suffers from exactly same problems as register_globals.
Read section on security of Using Register Globals explaining why it is dangerous.
没有第二个参数的使用方式被弃用,将来第二个参数会是必选。
Version
Description
7.2.0
Usage of parse_str() without a second parameter now emits an E_DEPRECATED notice.
session_start
BabyPHPPlease input your name:
highlight_file(__FILE__);
ob_start();
error_reporting(0);
ini_set('open_basedir', '/var/www/html:/tmp');
$file = 'function.php';
$func = isset($_GET['function'])?$_GET['function']:'filters';
call_user_func($func,$_GET);
include($file);
session_start();
$_SESSION['name'] = $_POST['name'];
if($_SESSION['name']=='admin'){
header('location:admin.php');
}
?>
dl
dl 函数由 enable_dl 影响。
This directive is really only useful in the Apache module version of PHP. You can turn dynamic loading of PHP extensions with dl() on and off per virtual server or per directory.
Version
Description
7.0.0
dl() is disabled in PHP-FPM.
5.3.9
dl() is enabled in PHP-FPM, albeit discouraged.
5.3.0
dl() is now disabled in some SAPIs due to stability issues. The only SAPIs that allow dl() are CLI and Embed. Use the Extension Loading Directives instead.
杂项
十六进制字符串
如:'0x0e12345' 不再是弱类型
移除了 ASP 和 script PHP 标签
即、不再支持,只能使用<?php ?>、= ?>。
此外 ?>需要看是否开启短标签。
无引号字符串
PHP 7.2 废弃
不带引号的字符串是不存在的全局常量,转化成他们自身的字符串。 在以前,该行为会产生 E_NOTICE,但现在会产生 E_WARNING。在下一个 PHP 主版本中,将抛出 Error 异常。
花括号偏移访问
PHP 7.4 废弃。Array and string offset access using curly braces
The array and string offset access syntax using curly braces is deprecated. Use $var[$idx] instead of $var{$idx}.
allow_url_include ini directive
PHP 7.4 废弃
Enabling it will generate a deprecation notice at startup.
FFI
PHP 7.4 添加
FFI is a new extension, which provides a simple way to call native functions, access native variables, and create/access data structures defined in C libraries.
OPcache preload
PHP 7.4 添加