aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2016-08-03 10:36:47 +0200
committerArthurHoaro <arthur@hoa.ro>2016-08-03 10:36:47 +0200
commit50d179183810a7b719bc10da2b9c4a95fd9dddee (patch)
treee669db360950025b4b6534075e940f532b0f00f3
parentc7a42ab1d9b21bf53cd30bc57b57789716c8711b (diff)
downloadShaarli-50d179183810a7b719bc10da2b9c4a95fd9dddee.tar.gz
Shaarli-50d179183810a7b719bc10da2b9c4a95fd9dddee.tar.zst
Shaarli-50d179183810a7b719bc10da2b9c4a95fd9dddee.zip
Add trusted IPs in config and try to ban forwarded IP on failed login
* Add a new settings (which needs to be manually set): `security.trusted_proxies` * On login failure, if the `REMOTE_ADDR` is in the trusted proxies, try to retrieve the forwarded IP in headers. * If found, the client address is added in ipbans, else we do nothing. Fixes #409
-rw-r--r--application/HttpUtils.php26
-rw-r--r--index.php11
-rw-r--r--tests/HttpUtils/GetIpAdressFromProxyTest.php58
3 files changed, 94 insertions, 1 deletions
diff --git a/application/HttpUtils.php b/application/HttpUtils.php
index 2e0792f9..354d261c 100644
--- a/application/HttpUtils.php
+++ b/application/HttpUtils.php
@@ -215,3 +215,29 @@ function page_url($server)
215 } 215 }
216 return index_url($server); 216 return index_url($server);
217} 217}
218
219/**
220 * Retrieve the initial IP forwarded by the reverse proxy.
221 *
222 * Inspired from: https://github.com/zendframework/zend-http/blob/master/src/PhpEnvironment/RemoteAddress.php
223 *
224 * @param array $server $_SERVER array which contains HTTP headers.
225 * @param array $trustedIps List of trusted IP from the configuration.
226 *
227 * @return string|bool The forwarded IP, or false if none could be extracted.
228 */
229function getIpAddressFromProxy($server, $trustedIps)
230{
231 $forwardedIpHeader = 'HTTP_X_FORWARDED_FOR';
232 if (empty($server[$forwardedIpHeader])) {
233 return false;
234 }
235
236 $ips = preg_split('/\s*,\s*/', $server[$forwardedIpHeader]);
237 $ips = array_diff($ips, $trustedIps);
238 if (empty($ips)) {
239 return false;
240 }
241
242 return array_pop($ips);
243}
diff --git a/index.php b/index.php
index 55b12adc..ab51fa23 100644
--- a/index.php
+++ b/index.php
@@ -318,8 +318,17 @@ include $conf->get('resource.ban_file', 'data/ipbans.php');
318function ban_loginFailed($conf) 318function ban_loginFailed($conf)
319{ 319{
320 $ip = $_SERVER['REMOTE_ADDR']; 320 $ip = $_SERVER['REMOTE_ADDR'];
321 $trusted = $conf->get('security.trusted_proxies', array());
322 if (in_array($ip, $trusted)) {
323 $ip = getIpAddressFromProxy($_SERVER, $trusted);
324 if (!$ip) {
325 return;
326 }
327 }
321 $gb = $GLOBALS['IPBANS']; 328 $gb = $GLOBALS['IPBANS'];
322 if (!isset($gb['FAILURES'][$ip])) $gb['FAILURES'][$ip]=0; 329 if (! isset($gb['FAILURES'][$ip])) {
330 $gb['FAILURES'][$ip]=0;
331 }
323 $gb['FAILURES'][$ip]++; 332 $gb['FAILURES'][$ip]++;
324 if ($gb['FAILURES'][$ip] > ($conf->get('security.ban_after') - 1)) 333 if ($gb['FAILURES'][$ip] > ($conf->get('security.ban_after') - 1))
325 { 334 {
diff --git a/tests/HttpUtils/GetIpAdressFromProxyTest.php b/tests/HttpUtils/GetIpAdressFromProxyTest.php
new file mode 100644
index 00000000..6a74a45a
--- /dev/null
+++ b/tests/HttpUtils/GetIpAdressFromProxyTest.php
@@ -0,0 +1,58 @@
1<?php
2
3require_once 'application/HttpUtils.php';
4
5/**
6 * Unitary tests for getIpAddressFromProxy()
7 */
8class GetIpAdressFromProxyTest extends PHPUnit_Framework_TestCase {
9
10 /**
11 * Test without proxy
12 */
13 public function testWithoutProxy()
14 {
15 $this->assertFalse(getIpAddressFromProxy(array(), array()));
16 }
17
18 /**
19 * Test with a single IP in proxy header.
20 */
21 public function testWithOneForwardedIp()
22 {
23 $ip = '1.1.1.1';
24 $server = array('HTTP_X_FORWARDED_FOR' => $ip);
25 $this->assertEquals($ip, getIpAddressFromProxy($server, array()));
26 }
27
28 /**
29 * Test with a multiple IPs in proxy header.
30 */
31 public function testWithMultipleForwardedIp()
32 {
33 $ip = '1.1.1.1';
34 $ip2 = '2.2.2.2';
35
36 $server = array('HTTP_X_FORWARDED_FOR' => $ip .','. $ip2);
37 $this->assertEquals($ip2, getIpAddressFromProxy($server, array()));
38
39 $server = array('HTTP_X_FORWARDED_FOR' => $ip .' , '. $ip2);
40 $this->assertEquals($ip2, getIpAddressFromProxy($server, array()));
41 }
42
43 /**
44 * Test with a trusted IP address.
45 */
46 public function testWithTrustedIp()
47 {
48 $ip = '1.1.1.1';
49 $ip2 = '2.2.2.2';
50
51 $server = array('HTTP_X_FORWARDED_FOR' => $ip);
52 $this->assertFalse(getIpAddressFromProxy($server, array($ip)));
53
54 $server = array('HTTP_X_FORWARDED_FOR' => $ip .','. $ip2);
55 $this->assertEquals($ip2, getIpAddressFromProxy($server, array($ip)));
56 $this->assertFalse(getIpAddressFromProxy($server, array($ip, $ip2)));
57 }
58}