[Web] CloudService


In order to improve security, we moved authentication logic to cloud. Everything is performed inside the internal network. It’s unhackable!


Link to the challenge



For this challenge we’re given a URL and a source zip containing the source code of index.html (Attached below). Source code

When we visit the page we’re presented with a login form. Landing page

There’s nothing interesting in it so let’s take a look at the source code:

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
<?php
$message = 'Welcome! Please provide your credentials!';

if(isset($_REQUEST['login']) && isset($_REQUEST['password']))
{	
	/* Login attempt */
	if($_SERVER['SERVER_NAME'] == 'cloudservice' && $_SERVER['REMOTE_ADDR'] == '127.0.0.1')
	{
		/* Request from internal network */
		require("../internal_secrets.php");
		if($_REQUEST['login'] == $secret_login && $_REQUEST['password'] == $secret_password)
			exit('OK!');
		else
			exit('FAIL!');
		
	}
	else
	{
		/* Request from the Internet. Redirect to cloud service.*/
		$result = file_get_contents("http://cloudservice/?login={$_REQUEST['login']}&password={$_REQUEST['password']}");
		if($result === 'FAIL!')
		{
			$message = 'You have failed miserably.';
		}
		else
		{
			$message = require('flag.php');
		}
	}
}
?>
<!-- HTML PAGE SNIPPED -->


We can see that the page expects us to provide some credentials via the login form which it then processes in two different ways depending if the call was made from localhost or not.

If it wasn’t a local request, the app requests the page locally with our parameters and if it doesn’t detect FAIL! on the page, it prints out the flag.


Since our input isn’t sanitized, we don’t know the secrets and the parameters are placed directly in the URL, we can pass such parameters that will make the local request no longer proceed into the credential checking part of the application.

If we set username to “#” and password to “1” (random value) the request will look like this:

1
http://cloudservice/?login=#&password=1


The webserver will ignore the part of the request after the hash symbol which makes it print the normal page content instead of checking the credentials.

Since the default page content doesn’t contain FAIL! inside of it, the app will return the flag. request flag


Flag: CTF{l0st1ncL0u09}