Skip to content

Commit c3a9a20

Browse files
committed
Merge pull request #88 from HonzaCZ/master
RequestFactory: Fixed possible remoteAddr spoofing (issue #87)
2 parents dca62fe + cae5d68 commit c3a9a20

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

src/Http/RequestFactory.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,20 @@ public function createHttpRequest()
203203
}
204204

205205
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
206-
$remoteAddr = trim(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0]);
206+
$xForwardedForWithoutProxies = array_filter(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']), function ($ip) {
207+
return !array_filter($this->proxies, function ($proxy) use ($ip) {
208+
return Helpers::ipMatch(trim($ip), $proxy);
209+
});
210+
});
211+
$remoteAddr = trim(end($xForwardedForWithoutProxies));
212+
$xForwardedForRealIpKey = key($xForwardedForWithoutProxies);
207213
}
208214

209-
if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
210-
$remoteHost = trim(explode(',', $_SERVER['HTTP_X_FORWARDED_HOST'])[0]);
215+
if (isset($xForwardedForRealIpKey) && !empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
216+
$xForwardedHost = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']);
217+
if (isset($xForwardedHost[$xForwardedForRealIpKey])) {
218+
$remoteHost = trim($xForwardedHost[$xForwardedForRealIpKey]);
219+
}
211220
}
212221
}
213222

tests/Http/RequestFactory.proxy.phpt

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ test(function () {
1515
$_SERVER = [
1616
'REMOTE_ADDR' => '127.0.0.3',
1717
'REMOTE_HOST' => 'localhost',
18-
'HTTP_X_FORWARDED_FOR' => '23.75.345.200, 10.0.0.1',
19-
'HTTP_X_FORWARDED_HOST' => 'otherhost, anotherhost',
18+
'HTTP_X_FORWARDED_FOR' => '23.75.45.200',
19+
'HTTP_X_FORWARDED_HOST' => 'otherhost',
2020
];
2121

2222
$factory = new RequestFactory;
@@ -25,6 +25,24 @@ test(function () {
2525
Assert::same('localhost', $factory->createHttpRequest()->getRemoteHost());
2626

2727
$factory->setProxy('127.0.0.1/8');
28-
Assert::same('23.75.345.200', $factory->createHttpRequest()->getRemoteAddress());
28+
Assert::same('23.75.45.200', $factory->createHttpRequest()->getRemoteAddress());
2929
Assert::same('otherhost', $factory->createHttpRequest()->getRemoteHost());
3030
});
31+
32+
test(function () {
33+
$_SERVER = [
34+
'REMOTE_ADDR' => '10.0.0.2', //proxy2
35+
'REMOTE_HOST' => 'proxy2',
36+
'HTTP_X_FORWARDED_FOR' => '123.123.123.123, 172.16.0.1, 10.0.0.1',
37+
'HTTP_X_FORWARDED_HOST' => 'fake, real, proxy1',
38+
];
39+
40+
$factory = new RequestFactory;
41+
$factory->setProxy('10.0.0.0/24');
42+
Assert::same('172.16.0.1', $factory->createHttpRequest()->getRemoteAddress());
43+
Assert::same('real', $factory->createHttpRequest()->getRemoteHost());
44+
45+
$factory->setProxy(['10.0.0.1', '10.0.0.2']);
46+
Assert::same('172.16.0.1', $factory->createHttpRequest()->getRemoteAddress());
47+
Assert::same('real', $factory->createHttpRequest()->getRemoteHost());
48+
});

0 commit comments

Comments
 (0)