奇奇怪怪的问题

evalsystem的纠纷

问题

系统执行语句eval($cmd)

当输入$cmd=system(cat flag.php)无法执行 ,输入$cmd=system("cat flag.php")正常执行

系统执行语句system($cmd)

当输入$cmd=cat flag.php正常执行,输入$cmd="cat flag.php"无法执行

原因:

根本区别:eval() vs system()

eval():要求参数是合法的PHP代码字符串

system():要求参数是合法的Shell命令字符串

eval()

  • 执行的是 PHP 代码
  • PHP 解析逻辑
    1. catflag.php 会被 PHP 视为 常量(未定义则报错)。
    2. system(cat flag.php) 会被解析为 system('cat', 'flag.php'),导致参数数量错误。
    3. 输入 $cmd=system(cat flag.php) 失败原因
      • eval()会将字符串作为PHP代码执行。此时参数 cat flag.php 未用引号包裹,PHP会尝试将其解析为常量。
      • 若未定义名为 catflag.php 的常量,PHP会将其隐式转换为字符串(触发Notice级错误),但可能因错误配置导致执行中断。
      • 等效代码eval('system(cat flag.php)') → 语法不合法。
    4. 输入 $cmd=system("cat flag.php") 成功原因
      • 参数 "cat flag.php" 是合法的字符串,符合PHP语法。
      • 等效代码eval('system("cat flag.php")') → 直接执行系统命令。

system()

  • 执行的是 Shell 命令
  • Shell 解析逻辑
    1. 按空格分割命令和参数:cat 是命令,flag.php 是参数。
    2. 输入 $cmd=cat flag.php执行 /bin/cat flag.php,成功输出文件内容。
    3. 输入 $cmd=cat flag.php 成功原因
      • system()直接将字符串参数传递给系统Shell。
      • 等效命令sh -c "cat flag.php" → 正常执行cat命令。
    4. 输入 $cmd="cat flag.php" 失败原因
      • 参数 "cat flag.php" 被包裹在双引号中,Shell会尝试将其视为完整命令名(包含空格)。
      • 等效命令sh -c "\"cat flag.php\"" → 寻找名为 cat flag.php 的命令(不存在)。

没搞懂

算了,先记住吧。(好像又懂了,见下)

1
2
3
4
执行eval()如果要输入system(),system()的括号里面要加''或者"" 例如$cmd=system("cat flag.php")

执行system(),输入$cmd=cat flag.php即可

目前理解是eval()函数传入的命令要经过PHP解析(解析会将传入system()括号中命令的'' ""引号去除掉)之后再传递给shell,而system()直接传递给shell,所以不需要引号包裹括号里面的内容

结合场景的深度分析

场景一:eval($cmd)中的system()

  • 输入 system(cat flag.php)

    • eval()会将$cmd作为PHP代码解析。

    • 在PHP语法中,

      1
      system(cat flag.php)

      会被解析为:

      1
      system(constant('cat'), constant('flag.php'));
    • 若未定义常量catflag.php,PHP会将其视为未定义常量,并抛出一个Notice错误(但可能继续执行,将catflag.php当作字符串处理)。最终可能得到一个语法错误(如参数数量不匹配),导致执行失败。

  • 输入 system("cat flag.php")

    • 字符串"cat flag.php"在PHP中是合法参数。
    • 等效于直接调用系统命令cat flag.php,因此成功。

场景二:直接调用system($cmd)

  • 输入 cat flag.php
    • system()直接将cat flag.php传递给Shell。
    • Shell会按空格分割参数,执行cat命令并传入flag.php作为参数,因此成功。
  • 输入 "cat flag.php"
    • Shell会将整个字符串"cat flag.php"视为一个命令名(包含空格),尝试寻找名为cat flag.php的可执行文件(显然不存在),因此失败。

关键区别总结

场景 执行环境 输入要求 底层逻辑
eval($cmd) PHP解释器 必须是合法PHP代码 解析为PHP代码执行
system($cmd) 操作系统Shell 必须是合法Shell命令 将字符串原样传递给Shell解析

类比验证

假设在PHP中直接写以下代码:

1
2
3
4
5
6
7
// 场景一(eval环境)
eval('system(cat flag.php)'); // PHP语法错误,未定义常量
eval('system("cat flag.php")'); // 合法PHP代码,执行命令

// 场景二(system环境)
system('cat flag.php'); // 合法Shell命令
system('"cat flag.php"'); // 非法Shell命令(寻找名为`cat flag.php`的程序)