XXE+序列化和代码审计危险函数总结

XXE+序列化和代码审计危险函数总结

1、代码执行危险函数

1.1eval() 函数

eval() 函数可以执行传递给它的字符串作为 PHP 代码。如果不谨慎处理用户输入,可能导致恶意代码执行。

常见的一句话木马就是由这个构成

 eval($_REQUEST[6]);?>

1.2 exec()函数

exec() 是 PHP 中用于执行外部命令的函数之一。它允许你执行系统命令,并返回最后一行输出。这个函数的用法如下:

string exec ( string $command [, array &$output [, int &$return_var ]] 
  • $command 是要执行的命令。
  • $output 是一个可选的数组参数,用于存储命令的输出结果。
  • $return_var 是一个可选的整型参数,用于存储命令执行的返回值。

1.3 shell_exec()函数

shell_exec() 是 PHP 中执行 shell 命令的函数之一。它会执行系统命令,并返回命令的输出作为字符串,类似于使用命令行执行命令并捕获输出。

使用示例:

string|null shell_exec ( string $cmd )

1.4 system()

system() 是 PHP 中用于执行外部命令的函数之一。它允许你执行系统命令,并将输出直接打印到输出流或者作为字符串返回。

使用示例:

string|null system ( string $command [, int &$return_var ] )

system() 是 PHP 中用于执行外部命令的函数之一。它允许你执行系统命令,并将输出直接打印到输出流或者作为字符串返回。

phpCopy code
string|null system ( string $command [, int &$return_var ] )
  • $command 是要执行的命令。

  • $return_var 是一个可选的整型参数,用于存储命令执行的返回值。

1.5array_map()函数

array_map()函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。 回调函数接受的参数数目应该和传递给array_map()函数的数组数目一致。

$cmd=$_GET['cmd'];
$array[0]=$cmd;
$new_array=array_map("assert",$array);      //等价于 ==>  assert($cmd);

1.6assert()函数

与eval类似,字符串被 assert() 当做 PHP 代码来执行

和eval的区别在于,eval一次性可以执行多条语句,但是assert()一次性只能执行一条(函数)。

如果传参为多条语句,assert只能执行第一条

1.7 create_function()函数

create_function主要用来创建匿名函数,create_function()函数会在内部执行 eval()

如果没有严格对参数传递进行过滤,攻击者可以构造特殊字符串传递给create_function()执行任意命令

使用示例:

$myfunc = create_function('$name','echo "hello".$name;');
相当于:
function myfunc($name) {
  echo "hello".$name;
}

攻击示例:

$id = $_GET['id'];
$code = 'return $a."_"'.$id.';';
// 动态创建函数
$func = create_function('$a', $code);
// 调用
$func(1);
payload: ?id=;}phpinfo();/*

1.8 call_user_func()函数

调用回调函数,并把一个数组参数作为回调函数的参数

使用示例:

$func=$_GET['func'];
$cmd=$_GET['cmd'];
$array=array($cmd);
call_user_func_array($func,$array);

1.9unlink() 和文件删除相关函数

unlink() 是 PHP 中用于删除文件的函数。它接受一个文件路径作为参数,并尝试删除指定的文件。

  • $filename 是要删除的文件路径。
  • $context 是可选的上下文参数,通常在使用流上下文时使用。

unlink() 可以被用来删除文件,但是如果不谨慎使用,可能导致安全风险,特别是当文件路径来自用户提供的数据时。

1.10preg_replace() 函数

语法:

mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )

搜索 subject 中匹配 pattern 的部分, 以 replacement 进行替换。

参数说明:

  • $pattern: 要搜索的模式,可以是字符串或一个字符串数组。
  • $replacement: 用于替换的字符串或字符串数组。
  • $subject: 要搜索替换的目标字符串或字符串数组。
  • $limit: 可选,对于每个模式用于每个 subject 字符串的最大可替换次数。 默认是-1(无限制)。
  • $count: 可选,为替换执行的次数。

返回值:

如果 subject 是一个数组, preg_replace() 返回一个数组, 其他情况下返回一个字符串。

如果匹配被查找到,替换后的 subject 被返回,其他情况下返回没有改变的 subject。

如果发生错误,返回 NULL。

危险点:

  • preg_replace()函数原本是执行一个正则表达式的搜索和替换
    • 但因为存在危险的**/e**修饰符,使 preg_replace() 将 replacement 参数当作 PHP 代码
 
  @preg_replace("/abc/e",$_REQUEST[6],"abcd");
?>
  • 首先 p a t t e r n ,一定要能在 pattern,一定要能在 pattern,一定要能在subject中匹配到

  • 其次要加上/e修饰符replacement 才能被当作代码来执行


$pattern=$_GET[1];
$subject=$_GET[2];

@preg_replace($pattern,$_REQUEST[6],$subject);
http://192.168.13.1/rce/shell.php?1=/abc/e&2=abcd&6=phpinfo();

代码审计重点判断参数是否可控

  • 判断$pattern的**/e**能不能被我们传进去

拓展:

  • 变量:$name
  • 函数:function name($name){}

但是/e参数要注意PHP的版本。

img

  • php版本7以上:无法使用
  • php5.5-php7,可以使用但是会告警
  • php5.5以下,可以直接使用

2、序列化危险函数

2.1serialize()函数

用于将变量序列化为一个字符串

使用 serialize() 函数非常简单,只需将要序列化的变量作为参数传递给函数即可。这个函数可以序列化包括但不限于整数、浮点数、字符串、数组和对象等 PHP 数据类型。

用法:

$data = ['apple', 'banana', 'orange']; // 要序列化的数组

$serialized_data = serialize($data); // 序列化数组

// 输出序列化后的字符串
echo $serialized_data;

下面是 serialize() 函数的基本用法示例:

2.2unserialize()函数

执行相反的操作,将序列化的字符串转换回原始的 PHP 值。

要恢复序列化后的字符串为原始的 PHP 变量,可以使用 unserialize() 函数:

$original_data = unserialize($serialized_data); // 还原序列化后的字符串为原始数据

// 输出还原后的数组
print_r($original_data);

以上两个都是序列化漏洞的起点

2.3__construct()函数

构造函数,在对象被创建时自动调用,用于初始化对象。

class Person {
    public $name;

    // 构造函数
    public function __construct($name) {
        $this->name = $name;
        echo "A new person {$this->name} has been created.
"
; } } // 实例化对象时自动调用构造函数 $person = new Person("Alice");

2.4 __destruct函数

析构函数,在对象被销毁时自动调用,通常用于释放资源或执行清理操作。

class MyClass {
    public function __construct() {
        echo "Object initialized.
"
; } public function doSomething() { echo "Doing something...
"
; } public function __destruct() { echo "Object destroyed. Cleaning up...
"
; } } // 创建对象 $obj = new MyClass(); // 执行一些操作 $obj->doSomething(); // 当对象超出作用域或显式销毁对象时,__destruct() 方法会被自动调用 unset($obj); // 或者 $obj = null;

2.5__get()__set()

分别用于在获取和设置不可访问属性时调用。__get() 在读取不可访问属性时被调用,__set() 在给不可访问属性赋值时被调用。

class MyClass {
    private $data = [];

    public function __get($name) {
        echo "Trying to access undefined property: $name
"
; if (array_key_exists($name, $this->data)) { return $this->data[$name]; } else { return null; } } public function __set($name, $value) { echo "Trying to set undefined property: $name to $value
"
; $this->data[$name] = $value; } } $obj = new MyClass(); // 尝试访问不存在的属性 echo $obj->undefinedProperty; // 触发 __get() 方法 // 尝试设置不存在的属性 $obj->anotherUndefinedProperty = "Value"; // 触发 __set() 方法

2.6__isset()__unset()

分别在对不可访问属性使用 isset()unset() 时调用。__isset() 用于检查不可访问属性是否已设置,__unset() 用于释放不可访问属性。

class MyClass {
    private $data = [];

    public function __isset($name) {
        echo "Is '$name' set?
"
; return isset($this->data[$name]); } public function __unset($name) { echo "Unsetting '$name'
"
; unset($this->data[$name]); } } $obj = new MyClass(); // 检测未定义的属性是否设置 isset($obj->undefinedProperty); // 触发 __isset() 方法 // 取消设置未定义的属性 unset($obj->anotherUndefinedProperty); // 触发 __unset() 方法

2.7__call()__callStatic()

分别在调用不可访问方法或静态方法时调用。__call() 用于处理不可访问方法的调用,__callStatic() 用于处理不可访问的静态方法的调用。

class MyClass {
    public function __call($name, $arguments) {
        echo "Calling method '$name' with arguments: " . implode(', ', $arguments) . "
"
; } public static function __callStatic($name, $arguments) { echo "Calling static method '$name' with arguments: " . implode(', ', $arguments) . "
"
; } } $obj = new MyClass(); // 调用不存在的方法 $obj->undefinedMethod('arg1', 'arg2'); // 触发 __call() 方法 // 调用不存在的静态方法 MyClass::undefinedStaticMethod('arg1', 'arg2'); // 触发 __callStatic() 方法

2.8 __toString函数

当对象被当作字符串进行输出时自动调用,用于返回对象的字符串表示。

class MyClass {
    public function __toString() {
        return "This is a string representation of MyClass.";
    }
}

$obj = new MyClass();

echo $obj; // 输出:This is a string representation of MyClass.

2.9__clone()

当对象被克隆时自动调用,用于执行对象的克隆操作。

class MyClass {
    public $value;

    public function __construct($value) {
        $this->value = $value;
    }

    public function __clone() {
        echo "Object cloned.
"
; } } $obj1 = new MyClass(10); $obj2 = clone $obj1; // 克隆对象时触发 __clone() 方法 echo $obj2->value; // 输出:10

你可能感兴趣的:(笔记,经验分享,网络安全)