Skip to content

Commit e806304

Browse files
committedJun 6, 2016
MAGETWO-52867: [APPSEC-1446] Sensitive server information disclosure upon specific URL requests
1 parent 2eaa8b5 commit e806304

File tree

7 files changed

+85
-64
lines changed

7 files changed

+85
-64
lines changed
 

‎.htaccess

+5-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@
206206

207207
###########################################
208208
## Deny access to root files to hide sensitive application information
209-
RedirectMatch 404 /\.git
209+
RedirectMatch 403 /\.git
210210

211211
<Files composer.json>
212212
order allow,deny
@@ -281,6 +281,10 @@
281281
deny from all
282282
</Files>
283283

284+
# For 404s and 403s that aren't handled by the application, show plain 404 response
285+
ErrorDocument 404 /pub/errors/404.php
286+
ErrorDocument 403 /pub/errors/404.php
287+
284288
################################
285289
## If running in cluster environment, uncomment this
286290
## http://developer.yahoo.com/performance/rules.html#etags

‎lib/internal/Magento/Framework/App/Bootstrap.php

+10-8
Original file line numberDiff line numberDiff line change
@@ -404,15 +404,17 @@ public function getErrorCode()
404404
*/
405405
public function isDeveloperMode()
406406
{
407-
if (isset($this->server[State::PARAM_MODE]) && $this->server[State::PARAM_MODE] == State::MODE_DEVELOPER) {
408-
return true;
409-
}
410-
/** @var \Magento\Framework\App\DeploymentConfig $deploymentConfig */
411-
$deploymentConfig = $this->getObjectManager()->get('Magento\Framework\App\DeploymentConfig');
412-
if ($deploymentConfig->get(State::PARAM_MODE) == State::MODE_DEVELOPER) {
413-
return true;
407+
$mode = 'default';
408+
if (isset($this->server[State::PARAM_MODE])) {
409+
$mode = $this->server[State::PARAM_MODE];
410+
} else {
411+
$deploymentConfig = $this->getObjectManager()->get(DeploymentConfig::class);
412+
if (($configMode = $deploymentConfig->get(State::PARAM_MODE)) !== null) {
413+
$mode = $configMode;
414+
}
414415
}
415-
return false;
416+
417+
return $mode == State::MODE_DEVELOPER;
416418
}
417419

418420
/**

‎lib/internal/Magento/Framework/App/StaticResource.php

+32-27
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
*/
66
namespace Magento\Framework\App;
77

8+
use Magento\Framework\App\Filesystem\DirectoryList;
89
use Magento\Framework\ObjectManager\ConfigLoaderInterface;
10+
use Magento\Framework\Filesystem;
911

1012
/**
1113
* Entry point for retrieving static resources like JS, CSS, images by requested public path
@@ -14,46 +16,33 @@
1416
*/
1517
class StaticResource implements \Magento\Framework\AppInterface
1618
{
17-
/**
18-
* @var State
19-
*/
19+
/** @var State */
2020
private $state;
2121

22-
/**
23-
* @var \Magento\Framework\App\Response\FileInterface
24-
*/
22+
/** @var \Magento\Framework\App\Response\FileInterface */
2523
private $response;
2624

27-
/**
28-
* @var Request\Http
29-
*/
25+
/** @var Request\Http */
3026
private $request;
3127

32-
/**
33-
* @var View\Asset\Publisher
34-
*/
28+
/** @var View\Asset\Publisher */
3529
private $publisher;
3630

37-
/**
38-
* @var \Magento\Framework\View\Asset\Repository
39-
*/
31+
/** @var \Magento\Framework\View\Asset\Repository */
4032
private $assetRepo;
4133

42-
/**
43-
* @var \Magento\Framework\Module\ModuleList
44-
*/
34+
/** @var \Magento\Framework\Module\ModuleList */
4535
private $moduleList;
4636

47-
/**
48-
* @var \Magento\Framework\ObjectManagerInterface
49-
*/
37+
/** @var \Magento\Framework\ObjectManagerInterface */
5038
private $objectManager;
5139

52-
/**
53-
* @var ConfigLoaderInterface
54-
*/
40+
/** @var ConfigLoaderInterface */
5541
private $configLoader;
5642

43+
/** @var Filesystem */
44+
private $filesystem;
45+
5746
/**
5847
* @param State $state
5948
* @param Response\FileInterface $response
@@ -116,12 +105,14 @@ public function launch()
116105
*/
117106
public function catchException(Bootstrap $bootstrap, \Exception $exception)
118107
{
119-
$this->response->setHttpResponseCode(404);
120-
$this->response->setHeader('Content-Type', 'text/plain');
121108
if ($bootstrap->isDeveloperMode()) {
109+
$this->response->setHttpResponseCode(404);
110+
$this->response->setHeader('Content-Type', 'text/plain');
122111
$this->response->setBody($exception->getMessage() . "\n" . $exception->getTraceAsString());
112+
$this->response->sendResponse();
113+
} else {
114+
require $this->getFilesystem()->getDirectoryRead(DirectoryList::PUB)->getAbsolutePath('errors/404.php');
123115
}
124-
$this->response->sendResponse();
125116
return true;
126117
}
127118

@@ -156,4 +147,18 @@ protected function parsePath($path)
156147
$result['file'] = $parts[5];
157148
return $result;
158149
}
150+
151+
/**
152+
* Lazyload filesystem driver
153+
*
154+
* @deprecated
155+
* @return Filesystem
156+
*/
157+
private function getFilesystem()
158+
{
159+
if (!$this->filesystem) {
160+
$this->filesystem = $this->objectManager->get(Filesystem::class);
161+
}
162+
return $this->filesystem;
163+
}
159164
}

‎lib/internal/Magento/Framework/App/Test/Unit/BootstrapTest.php

+24-15
Original file line numberDiff line numberDiff line change
@@ -162,26 +162,35 @@ public function testGetObjectManager()
162162
$this->assertSame($this->objectManager, $bootstrap->getObjectManager());
163163
}
164164

165-
public function testIsDeveloperMode()
165+
/**
166+
* @param $modeFromEnvironment
167+
* @param $modeFromDeployment
168+
* @param $isDeveloper
169+
*
170+
* @dataProvider testIsDeveloperModeDataProvider
171+
*/
172+
public function testIsDeveloperMode($modeFromEnvironment, $modeFromDeployment, $isDeveloper)
166173
{
167-
$bootstrap = self::createBootstrap();
168-
$this->assertFalse($bootstrap->isDeveloperMode());
169-
$testParams = [State::PARAM_MODE => State::MODE_DEVELOPER];
174+
$testParams = [];
175+
if ($modeFromEnvironment) {
176+
$testParams[State::PARAM_MODE] = $modeFromEnvironment;
177+
}
178+
if ($modeFromDeployment) {
179+
$this->deploymentConfig->method('get')->willReturn($modeFromDeployment);
180+
}
170181
$bootstrap = self::createBootstrap($testParams);
171-
$this->assertTrue($bootstrap->isDeveloperMode());
172-
$this->deploymentConfig->expects($this->any())->method('get')->willReturn(State::MODE_DEVELOPER);
173-
$bootstrap = self::createBootstrap();
174-
$this->assertTrue($bootstrap->isDeveloperMode());
182+
$this->assertEquals($isDeveloper, $bootstrap->isDeveloperMode());
175183
}
176184

177-
public function testIsDeveloperModeСontradictoryValues()
185+
public function testIsDeveloperModeDataProvider()
178186
{
179-
$this->deploymentConfig->expects($this->any())->method('get')->willReturn(State::MODE_PRODUCTION);
180-
$bootstrap = self::createBootstrap();
181-
$this->assertFalse($bootstrap->isDeveloperMode());
182-
$testParams = [State::PARAM_MODE => State::MODE_DEVELOPER];
183-
$bootstrap = self::createBootstrap($testParams);
184-
$this->assertTrue($bootstrap->isDeveloperMode());
187+
return [
188+
[null, null, false],
189+
[State::MODE_DEVELOPER, State::MODE_PRODUCTION, true],
190+
[State::MODE_PRODUCTION, State::MODE_DEVELOPER, false],
191+
[null, State::MODE_DEVELOPER, true],
192+
[null, State::MODE_PRODUCTION, false]
193+
];
185194
}
186195

187196
public function testRunNoErrors()

‎lib/internal/Magento/Framework/App/Test/Unit/StaticResourceTest.php

+9-10
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
namespace Magento\Framework\App\Test\Unit;
1010

11+
use Magento\Framework\App\Bootstrap;
12+
use Magento\Framework\Filesystem;
13+
1114
class StaticResourceTest extends \PHPUnit_Framework_TestCase
1215
{
1316
/**
@@ -188,17 +191,13 @@ public function testLaunchWrongPath()
188191
$this->object->launch();
189192
}
190193

191-
public function testCatchException()
194+
public function testCatchExceptionDeveloperMode()
192195
{
193-
$bootstrap = $this->getMock('Magento\Framework\App\Bootstrap', [], [], '', false);
194-
$bootstrap->expects($this->at(0))->method('isDeveloperMode')->willReturn(false);
195-
$bootstrap->expects($this->at(1))->method('isDeveloperMode')->willReturn(true);
196-
$exception = new \Exception('message');
197-
$this->response->expects($this->exactly(2))->method('setHttpResponseCode')->with(404);
198-
$this->response->expects($this->exactly(2))->method('setHeader')->with('Content-Type', 'text/plain');
199-
$this->response->expects($this->exactly(2))->method('sendResponse');
200-
$this->response->expects($this->once())->method('setBody')->with($this->stringStartsWith('message'));
201-
$this->assertTrue($this->object->catchException($bootstrap, $exception));
196+
$bootstrap = $this->getMockBuilder(Bootstrap::class)->disableOriginalConstructor()->getMock();
197+
$bootstrap->expects($this->once())->method('isDeveloperMode')->willReturn(true);
198+
$exception = new \Exception('Error: nothing works');
199+
$this->response->expects($this->once())->method('setHttpResponseCode')->with(404);
200+
$this->response->expects($this->once())->method('sendResponse');
202201
$this->assertTrue($this->object->catchException($bootstrap, $exception));
203202
}
204203
}

‎nginx.conf.sample

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ root $MAGE_ROOT/pub;
2626
index index.php;
2727
autoindex off;
2828
charset UTF-8;
29+
error_page 404 403 = /errors/404.php;
2930
#add_header "X-UA-Compatible" "IE=Edge";
3031

3132
location ~* ^/setup($|/) {
@@ -185,6 +186,7 @@ gzip_types
185186
image/svg+xml;
186187
gzip_vary on;
187188

188-
location ~ \.php$ {
189+
# Banned locations (only reached if the earlier PHP entry point regexes don't match)
190+
location ~* (\.php$|\.htaccess$|\.git) {
189191
deny all;
190192
}

‎pub/get.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@
4545
// Serve file if it's materialized
4646
if ($mediaDirectory) {
4747
if (!$isAllowed($relativePath, $allowedResources)) {
48-
header('HTTP/1.0 404 Not Found');
48+
require_once 'errors/404.php';
4949
exit;
5050
}
5151
$mediaAbsPath = $mediaDirectory . '/' . $relativePath;
5252
if (is_readable($mediaAbsPath)) {
5353
if (is_dir($mediaAbsPath)) {
54-
header('HTTP/1.0 404 Not Found');
54+
require_once 'errors/404.php';
5555
exit;
5656
}
5757
$transfer = new \Magento\Framework\File\Transfer\Adapter\Http(

0 commit comments

Comments
 (0)
Please sign in to comment.