PHP特性之反射类ReflectionClass机制
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('/^+={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('/^+={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))等,降低攻击成功概率
来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除
页:
[1]