Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Commit

Permalink
Merge branch 'security/remote-address' into develop
Browse files Browse the repository at this point in the history
Forward port zendframework/zendframework#5374 (`RemoteAddress` security fix)

Conflicts:
	README.md
  • Loading branch information
weierophinney committed Oct 31, 2013
156 parents 9fd964e + d222b5d + 4c82c64 + 593b71b + 8cc68f1 + 1642118 + 89a44d0 + 5c10b75 + db7d808 + 4ee93be + 9ecbeb2 + d240054 + 78d3205 + 8903b2d + 464835b + c59b54d + 14ad3a0 + f4ac37b + 0ec8036 + 8839d0e + 07564e2 + a65cb66 + ecb09fb + 6de3f68 + cb8f354 + d7ffaed + 1819a00 + e2ca906 + f897f74 + 0568c55 + d7f0623 + 8b4896f + 2f83acc + a44d7dd + 6bce797 + 6ad2b62 + 1e41fbd + a0078e6 + 9db875b + 2879406 + 9acc850 + eddeb7d + 5a77057 + 33c15ff + 9f13ebf + a2ad2a5 + c0ba21c + 94e82a8 + 459f1f9 + e0c8424 + 5ef6a39 + 58fd018 + 65e3b0b + d21655a + 1d20fd1 + fe81bc5 + 96fadae + 072c64d + d3c9780 + 9c15ae8 + 66a4342 + 85c9491 + 8ec8384 + 004366f + 55a086d + ac7c7af + f02a226 + 00c4ac3 + 3f52720 + 5508474 + 49ed2f6 + d562686 + 67b42b2 + bdb1dae + 9809630 + 7304e37 + 752a5af + 8181c8f + 53bdac2 + c2f9414 + f6341e9 + 57cde95 + c750616 + 293054e + 7432649 + 63f13f6 + 927c00d + 44e0d4b + bc03833 + 1fd7c61 + de0cb77 + 66e902f + 24354dc + 9f886a2 + 845333c + 96e9a1e + 52fbeb6 + 7f76d90 + fec4cec + 24efdcc + 219c9ad + 3025666 + 17d48b4 + 00f4506 + 0800032 + fc89677 + e89d79b + f329014 + a1bfde3 + 7dec05c + 734f9f2 + 2756031 + 408f714 + fd53447 + f1f6e0d + e193ac7 + dad06c3 + 03ab3c8 + d0b9eec + e47995d + 411b935 + ddc8029 + a6c1451 + e823524 + eb63995 + 2de2423 + a95575b + 03a862c + e195cc6 + f4ac757 + a53de82 + 42763a8 + 6b14b45 + 2c344a8 + ff8337b + 18b53cb + e669f19 + 592011d + 076244a + df3d273 + df0ceea + 52b821e + b5e6fa9 + be5e28e + d9404b8 + e77747f + c2783a1 + 777a056 + 40c699b + 78c73ae + b0a1695 + 03dc917 + 615fcf5 + 2558f0c + 67c0313 + 664fb1a commit fa17926
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 6 deletions.
18 changes: 12 additions & 6 deletions src/PhpEnvironment/RemoteAddress.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public function getIpAddress()
if ($ip) {
return $ip;
}

// direct IP address
if (isset($_SERVER['REMOTE_ADDR'])) {
return $_SERVER['REMOTE_ADDR'];
Expand All @@ -113,16 +113,18 @@ public function getIpAddress()
/**
* Attempt to get the IP address for a proxied client
*
* @see http://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded-10#section-5.2
* @return false|string
*/
protected function getIpAddressFromProxy()
{
if (!$this->useProxy) {
if (!$this->useProxy
|| !in_array($_SERVER['REMOTE_ADDR'], $this->trustedProxies)
) {
return false;
}

$header = $this->proxyHeader;

if (!isset($_SERVER[$header]) || empty($_SERVER[$header])) {
return false;
}
Expand All @@ -133,14 +135,18 @@ protected function getIpAddressFromProxy()
$ips = array_map('trim', $ips);
// remove trusted proxy IPs
$ips = array_diff($ips, $this->trustedProxies);

// Any left?
if (empty($ips)) {
return false;
}

// Return right-most
$ip = array_pop($ips);
// Since we've removed any known, trusted proxy servers, the right-most
// address represents the first IP we do not know about -- i.e., we do
// not know if it is a proxy server, or a client. As such, we treat it
// as the originating IP.
// @see http://en.wikipedia.org/wiki/X-Forwarded-For
$ip = array_pop($ips);
return $ip;
}

Expand Down
130 changes: 130 additions & 0 deletions test/PhpEnvironment/RemoteAddressTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace ZendTest\Http\PhpEnvironment;

use PHPUnit_Framework_TestCase as TestCase;
use Zend\Http\Headers;
use Zend\Http\Header\GenericHeader;
use Zend\Http\PhpEnvironment\RemoteAddress as RemoteAddr;

class RemoteAddressTest extends TestCase
{
/**
* Original environemnt
*
* @var array
*/
protected $originalEnvironment;

/**
* Save the original environment and set up a clean one.
*/
public function setUp()
{
$this->originalEnvironment = array(
'post' => $_POST,
'get' => $_GET,
'cookie' => $_COOKIE,
'server' => $_SERVER,
'env' => $_ENV,
'files' => $_FILES,
);

$_POST = array();
$_GET = array();
$_COOKIE = array();
$_SERVER = array();
$_ENV = array();
$_FILES = array();

$this->remoteAddress = new RemoteAddr();
}

/**
* Restore the original environment
*/
public function tearDown()
{
$_POST = $this->originalEnvironment['post'];
$_GET = $this->originalEnvironment['get'];
$_COOKIE = $this->originalEnvironment['cookie'];
$_SERVER = $this->originalEnvironment['server'];
$_ENV = $this->originalEnvironment['env'];
$_FILES = $this->originalEnvironment['files'];
}

public function testSetGetUseProxy()
{
$this->remoteAddress->setUseProxy(false);
$this->assertFalse($this->remoteAddress->getUseProxy());
}

public function testSetGetDefaultUseProxy()
{
$this->remoteAddress->setUseProxy();
$this->assertTrue($this->remoteAddress->getUseProxy());
}

public function testSetTrustedProxies()
{
$result = $this->remoteAddress->setTrustedProxies(array(
'192.168.0.10', '192.168.0.1'
));
$this->assertTrue($result instanceOf RemoteAddr);
}

public function testGetIpAddress()
{
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$this->assertEquals('127.0.0.1', $this->remoteAddress->getIpAddress());
}

public function testGetIpAddressFromProxy()
{
$this->remoteAddress->setUseProxy(true);
$this->remoteAddress->setTrustedProxies(array(
'192.168.0.10', '10.0.0.1'
));
$_SERVER['REMOTE_ADDR'] = '192.168.0.10';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '8.8.8.8, 10.0.0.1';
$this->assertEquals('8.8.8.8', $this->remoteAddress->getIpAddress());
}

public function testGetIpAddressFromProxyRemoteAddressNotTrusted()
{
$this->remoteAddress->setUseProxy(true);
$this->remoteAddress->setTrustedProxies(array(
'10.0.0.1'
));
// the REMOTE_ADDR is not in the trusted IPs, possible attack here
$_SERVER['REMOTE_ADDR'] = '1.1.1.1';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '8.8.8.8, 10.0.0.1';
$this->assertEquals('1.1.1.1', $this->remoteAddress->getIpAddress());
}

/**
* Test to prevent attack on the HTTP_X_FORWARDED_FOR header
* The client IP is always the first on the left
*
* @see http://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded-10#section-5.2
*/
public function testGetIpAddressFromProxyFakeData()
{
$this->remoteAddress->setUseProxy(true);
$this->remoteAddress->setTrustedProxies(array(
'192.168.0.10', '10.0.0.1', '10.0.0.2'
));
$_SERVER['REMOTE_ADDR'] = '192.168.0.10';
// 1.1.1.1 is the first IP address from the right not representing a known proxy server; as such, we
// must treat it as a client IP.
$_SERVER['HTTP_X_FORWARDED_FOR'] = '8.8.8.8, 10.0.0.2, 1.1.1.1, 10.0.0.1';
$this->assertEquals('1.1.1.1', $this->remoteAddress->getIpAddress());
}
}

0 comments on commit fa17926

Please sign in to comment.