PHP特性之反射类ReflectionClass机制
目录
- PHP特性之反射类ReflectionClass机制
- 引例
- 详细阐述
- 反射机制的核心作用
- ReflectionClass 的基本使用流程
- 常用方法与应用场景
- 反射机制进一步的利用
- 防御措施
引例
最近在刷polarD&N靶场的时候,做到了一道关于ReflectionClass机制
原题是这样的- <?php
- class FlagReader {
- private $logfile = "/tmp/log.txt";
- protected $content = "<?php system(\$_GET['cmd']); ?>";
- public function __toString() {
- if (file_exists('/flag')) {
- return file_get_contents('/flag');
- } else {
- return "Flag file not found!";
- }
- }
- }
- class DataValidator {
- public static function check($input) {
- $filtered = preg_replace('/[^\w]/', '', $input);
- return strlen($filtered) > 10 ? true : false;
- }
- public function __invoke($data) {
- return self::check($data);
- }
- }
- class FakeDanger {
- private $buffer;
-
- public function __construct($data) {
- $this->buffer = base64_encode($data);
- }
- public function __wakeup() {
- if (rand(0, 100) > 50) {
- $this->buffer = str_rot13($this->buffer);
- }
- }
- }
- class VulnerableClass {
- public $logger;
- private $debugMode = false;
- public function __destruct() {
- if ($this->debugMode) {
- echo $this->logger;
- } else {
- $this->cleanup();
- }
- }
- private function cleanup() {
- if ($this->logger instanceof DataValidator) {
- $this->logger = null;
- }
- }
- }
- function sanitize_input($data) {
- $data = trim($data);
- return htmlspecialchars($data, ENT_QUOTES);
- }
- if(isset($_GET['data'])) {
- $raw = base64_decode($_GET['data']);
- if (preg_match('/^[a-zA-Z0-9\/+]+={0,2}$/', $_GET['data'])) {
- unserialize($raw);
- }
- } else {
- highlight_file(__FILE__);
- }
- ?>
复制代码 将上述内容作为 xml 参数传入(即 ?xml=上述XML内容),PHP 解析后会将 /etc/passwd 文件内容替换到 <?php
class FlagReader {
private $logfile = "/tmp/log.txt";
protected $content = "<?php system(\$_GET['cmd']); ?>";
public function __toString() {
if (file_exists('/flag')) {
return file_get_contents('/flag');
} else {
return "Flag file not found!";
}
}
}
class DataValidator {
public static function check($input) {
$filtered = preg_replace('/[^\w]/', '', $input);
return strlen($filtered) > 10 ? true : false;
}
public function __invoke($data) {
return self::check($data);
}
}
class FakeDanger {
private $buffer;
public function __construct($data) {
$this->buffer = base64_encode($data);
}
public function __wakeup() {
if (rand(0, 100) > 50) {
$this->buffer = str_rot13($this->buffer);
}
}
}
class VulnerableClass {
public $logger;
private $debugMode = false;
public function __destruct() {
if ($this->debugMode) {
echo $this->logger;
} else {
$this->cleanup();
}
}
private function cleanup() {
if ($this->logger instanceof DataValidator) {
$this->logger = null;
}
}
}
function sanitize_input($data) {
$data = trim($data);
return htmlspecialchars($data, ENT_QUOTES);
}
if(isset($_GET['data'])) {
$raw = base64_decode($_GET['data']);
if (preg_match('/^[a-zA-Z0-9\/+]+={0,2}$/', $_GET['data'])) {
unserialize($raw);
}
} else {
highlight_file(__FILE__);
}
?> 位置,导致敏感文件被读取并可能通过后续逻辑泄露。
3.绕过访问控制执行私有危险方法
若类中存在私有方法包含危险操作(如执行系统命令),攻击者可通过反射的setAccessible(true)突破限制并调用:- class FlagReader {
- private $logfile = "/tmp/log.txt";
- protected $content = "<?php system(\$_GET['cmd']); ?>";
- public function __toString() {
- if (file_exists('/flag')) {
- return file_get_contents('/flag');
- } else {
- return "Flag file not found!";
- }
- }
- }
复制代码 通过?cmd=whoami即可触发命令执行
防御措施
- 严格过滤输入:对反射操作中使用的类名、方法名、参数进行白名单校验,禁止用户输入直接作为反射参数。
- class VulnerableClass {
- public $logger;
- private $debugMode = false;
- public function __destruct() {
- if ($this->debugMode) {
- echo $this->logger;
- } else {
- $this->cleanup();
- }
- }
- private function cleanup() {
- if ($this->logger instanceof DataValidator) {
- $this->logger = null;
- }
- }
- }
复制代码 - 避免动态调用危险函数:禁止通过反射调用exec、system、shell_exec等命令执行函数,以及eval、assert等代码执行函数。
- 谨慎使用setAccessible:除非必要,否则不使用setAccessible(true)绕过访问控制,尤其避免对包含敏感操作的私有方法使用。
- 限制反射范围:在框架或库中,反射应仅用于已知的、可信的类和方法,避免对用户可控的未知类进行反射操作。
- 开启 PHP 安全配置:禁用危险函数(disable_functions)、限制 XML 外部实体(libxml_disable_entity_loader(true))等,降低攻击成功概率
来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除 |