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 添加