PHP魔术方法

发布时间:2023-05-20

一、PHP魔术方法漏洞利用

利用魔术方法漏洞可以非常方便地实现代码注入,因此,需要在应用程序中小心使用这些方法。下面是一些需要避免的魔术方法:

  • __sleep()__wakeup() 可以用来反序列化攻击;
  • __call()__callStatic()__get() 可能会导致代码注入;
  • __toString() 可以用来插入恶意代码到输出结果中。
class User {
    public $username;
    public function __toString() { 
        return $this->username; // 存在代码注入漏洞
    }
}
$user = new User();
$user->username = "John' OR 1=1; -- ";
echo "SELECT * FROM users WHERE username='" . $user . "'"; // 输出 SELECT * FROM users WHERE username='John' OR 1=1; -- '

上面这段代码在直接使用 $username 时存在注入漏洞,攻击者可以通过输入 "John' OR 1=1; --" 来执行恶意的 SQL 语句。

二、PHP魔术方法有什么用

PHP魔术方法是在类中自动调用的方法,它们是一种灵活强大的工具,可以帮助我们轻易地实现很多常见的编程任务。例如:

  • __construct() 方法可以在对象创建时初始化属性;
  • __destruct() 方法可以在对象销毁时执行清理工作;
  • __get()__set() 方法可以动态设置和获取属性值;
  • __toString() 方法可以在对象使用 echoprint 输出时返回特定的字符串表示形式。
class User {
    private $name;
    private $age;
    public function __construct($name, $age) {
        $this->name = $name;
        $this->age = $age;
    }
    public function __get($property) {
        if (property_exists($this, $property)) {
            return $this->$property;
        }
    }
    public function __toString() {
        return $this->name . ' is ' . $this->age . ' years old.';
    }
}
$user = new User('John', 30);
echo $user; // 输出 "John is 30 years old."
echo $user->name; // 输出 "John"

上面这段代码中的 __construct() 方法用于初始化对象的属性,__get() 方法则可动态设置和获取属性值,而 __toString() 方法则可以在对象使用 echoprint 输出时返回特定的字符串表示形式。

三、PHP魔术方法有哪些

下面是 PHP 中常用的魔术方法:

  • __construct()
  • __destruct()
  • __call()
  • __callStatic()
  • __get()
  • __set()
  • __isset()
  • __unset()
  • __sleep()
  • __wakeup()
  • __toString()
  • __invoke()
  • __set_state()
  • __clone()
  • __debugInfo()

四、PHP魔术方法的作用

PHP魔术方法的作用在上面部分已经进行了简单介绍,这里再详细说明一下:

  • __construct():类的构造函数,用于初始化类的属性。
  • __destruct():析构函数,用于在对象被销毁前执行一些清理工作。
  • __call():在对象中调用一个不可访问的方法时被调用。
  • __callStatic():在静态上下文中调用一个不可访问的方法时被调用。
  • __get():在读取不存在或不可访问的属性值时被调用。
  • __set():在设置不存在或不可访问的属性值时被调用。
  • __isset():在对不存在或不可访问的属性调用 isset() 函数时被调用。
  • __unset():在对不存在或不可访问的属性调用 unset() 函数时被调用。
  • __sleep():在对象序列化之前被调用。
  • __wakeup():在对象反序列化之后被调用。
  • __toString():在使用 echoprint 输出一个对象时被调用。
  • __invoke():在把对象当函数调用时被调用。
  • __set_state():用于在 var_export() 导出类的实例时被调用。
  • __clone():在克隆对象时被调用。
  • __debugInfo():在使用 var_dump() 导出对象时被调用。

五、PHP魔术方法与魔术常量

PHP 还定义了一些特殊的常量,称为魔术常量。这些常量的命名格式与魔术方法相同,以两个下划线开头和结尾。魔术常量是根据它们所处的上下文动态改变值的。 例如,__LINE__ 常量返回源代码中的当前行号,而 __FILE__ 常量返回包含当前文件的文件名。

echo "This is line " . __LINE__ . " of file " . __FILE__;
// 输出 "This is line 2 of file /path/to/script.php"

还有一些其他的魔术常量:

  • __FUNCTION__:返回当前函数的名称
  • __CLASS__:返回当前类的名称
  • __TRAIT__:在一个 trait 中使用返回 trait 的名称
  • __METHOD__:返回当前方法的名称
  • __DIR__:返回当前脚本所在的目录
  • __NAMESPACE__:返回当前命名空间的名称

六、PHP魔术方法自动载入文件

当使用一个未定义的类时,PHP 会自动调用 __autoload() 函数,尝试从 include_path 中载入该文件。

function __autoload($class_name) {
    include $class_name . '.php';
}
$obj = new MyClass1();

上面的代码中,当尝试创建一个名为 MyClass1 的对象时,如果该类没有定义,则会调用 __autoload() 函数,该函数会自动包含 MyClass1.php 文件。

七、PHP魔术方法有几个

PHP 魔术方法共有 15 个,具体定义和功能如前所述。其中一个 __call() 方法和 __callStatic() 方法是在使用不存在的或不可访问的方法时自动调用的,其余的方法都是在对象创建、访问属性、控制对象序列化等过程中自动调用的。

八、PHP魔术方法是不是特有的

PHP 魔术方法并不是 PHP 特有的,其他一些编程语言如 Python、Ruby 和 Java 等都有类似的概念。例如,在 Python 中,__init__() 方法用于初始化对象,__str__() 方法用于返回对象的字符串表示形式。

九、PHP魔术变量

PHP 还包括一些特殊的变量,称为魔术变量。这些变量是在不同的上下文中被自动赋值的。 例如,$this 变量在对象的方法中自动赋值为当前对象,$GLOBALS 变量总是包含全局作用域中的变量,并可以在函数内部直接访问。

class MyClass {
    public function myMethod() {
        echo $this->myVariable; // 输出 "Hello, World!"
    }
}
$obj = new MyClass();
$obj->myVariable = "Hello, World!";
$obj->myMethod();

在上面的代码中,$this 变量在对象的方法 myMethod() 中自动赋值为当前对象,因此可以访问该对象的属性 myVariable

十、魔术方法 Python

和 PHP 一样,Python 也有类似的魔术方法,可以在对象被创建、操作、销毁的不同阶段自动调用。例如,__init__() 方法用于初始化对象,在对象创建时自动调用;__str__() 方法用于返回对象的字符串表示形式,在对象被转化为字符串时自动调用。

class MyList(list):
    def __init__(self, *args):
        super(MyList, self).__init__(*args)
        self.sum = sum(self)
    def __str__(self):
        return "{} (sum: {})".format(super(MyList, self).__str__(), self.sum)
a = MyList([1, 2, 3, 4, 5])
print(a) # 输出 "[1, 2, 3, 4, 5] (sum: 15)"

上面的代码是 Python 中的一个例子,其中 MyList 类继承了原生的 list 类,并增加了一个计算 sum 的功能。在类中定义了 __init__()__str__() 两个魔术方法。 魔术方法对于 Python 和 PHP 等编程语言而言,是一个极大的方便,简化了编程过程,使编程变得更加灵活高效。