parse_url() keeps the brackets around an IPv6 literal, so "[::1]" or "[::ffff:127.0.0.1]" never matched an address and isPrivateURL() let the request through. A host that does not resolve was allowed for the same reason, while cURL still connects to forms like "0x7f000001" or "127.0.0.1." on its own. Strip the brackets and the trailing dot, check IP literals directly, check every resolved address, and treat a host without any address as private. IPv4-mapped IPv6 addresses are checked through their IPv4 part, since FILTER_FLAG_NO_RES_RANGE does not classify them the same way on every PHP version. Fixes #5858 Fixes #5871
124 lines
4.5 KiB
PHP
124 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace KanboardTests\units\Core\Http;
|
|
|
|
use KanboardTests\units\Base;
|
|
use Kanboard\Core\Http\Client;
|
|
|
|
class ClientTest extends Base
|
|
{
|
|
public function testGetCanDisableRedirects()
|
|
{
|
|
$client = $this
|
|
->getMockBuilder('\Kanboard\Core\Http\Client')
|
|
->setConstructorArgs(array($this->container))
|
|
->onlyMethods(array('doRequest'))
|
|
->getMock();
|
|
|
|
$client
|
|
->expects($this->once())
|
|
->method('doRequest')
|
|
->with('GET', 'https://example.org', '', array('X-Test: 1'), true, false)
|
|
->willReturn('response-body');
|
|
|
|
$this->assertSame(
|
|
'response-body',
|
|
$client->get('https://example.org', array('X-Test: 1'), true, false)
|
|
);
|
|
}
|
|
|
|
public function testIsPrivateIpAddressWithPrivateIPv4()
|
|
{
|
|
$client = new Client($this->container);
|
|
|
|
$this->assertTrue($client->isPrivateIpAddress('10.0.0.1'));
|
|
$this->assertTrue($client->isPrivateIpAddress('172.16.5.10'));
|
|
$this->assertTrue($client->isPrivateIpAddress('192.168.1.20'));
|
|
$this->assertTrue($client->isPrivateIpAddress('127.0.0.1'));
|
|
}
|
|
|
|
public function testIsPrivateIpAddressWithPrivateIPv6()
|
|
{
|
|
$client = new Client($this->container);
|
|
|
|
$this->assertTrue($client->isPrivateIpAddress('::1'));
|
|
$this->assertTrue($client->isPrivateIpAddress('fd12:3456:789a:1::1'));
|
|
}
|
|
|
|
public function testIsPrivateIpAddressWithIPv4MappedIPv6()
|
|
{
|
|
$client = new Client($this->container);
|
|
|
|
$this->assertTrue($client->isPrivateIpAddress('::ffff:127.0.0.1'));
|
|
$this->assertTrue($client->isPrivateIpAddress('::ffff:7f00:1'));
|
|
$this->assertTrue($client->isPrivateIpAddress('::ffff:169.254.169.254'));
|
|
$this->assertTrue($client->isPrivateIpAddress('::ffff:10.0.0.1'));
|
|
$this->assertFalse($client->isPrivateIpAddress('::ffff:8.8.8.8'));
|
|
}
|
|
|
|
public function testIsPrivateIpAddressWithPublicAndInvalidValues()
|
|
{
|
|
$client = new Client($this->container);
|
|
|
|
$this->assertFalse($client->isPrivateIpAddress('8.8.8.8'));
|
|
$this->assertFalse($client->isPrivateIpAddress('2607:f8b0:4005:805::200e'));
|
|
$this->assertFalse($client->isPrivateIpAddress('not-an-ip'));
|
|
$this->assertFalse($client->isPrivateIpAddress(''));
|
|
}
|
|
|
|
public function testIsPrivateUrlWithPrivateHostnames()
|
|
{
|
|
$client = new Client($this->container);
|
|
|
|
$this->assertTrue($client->isPrivateURL('http://localhost'));
|
|
$this->assertTrue($client->isPrivateURL('http://127.0.0.1/path'));
|
|
$this->assertTrue($client->isPrivateURL('http://10.0.0.15/api'));
|
|
}
|
|
|
|
public function testIsPrivateUrlWithBracketedIPv6Literals()
|
|
{
|
|
$client = new Client($this->container);
|
|
|
|
$this->assertTrue($client->isPrivateURL('http://[::1]/'));
|
|
$this->assertTrue($client->isPrivateURL('http://[::ffff:127.0.0.1]:9099/'));
|
|
$this->assertTrue($client->isPrivateURL('http://[0:0:0:0:0:ffff:127.0.0.1]/'));
|
|
$this->assertTrue($client->isPrivateURL('http://[::ffff:169.254.169.254]/'));
|
|
$this->assertTrue($client->isPrivateURL('http://[fd00::1]/'));
|
|
$this->assertFalse($client->isPrivateURL('http://[2607:f8b0:4005:805::200e]/'));
|
|
}
|
|
|
|
public function testIsPrivateUrlWithOtherIPv4Notations()
|
|
{
|
|
$client = new Client($this->container);
|
|
|
|
$this->assertTrue($client->isPrivateURL('http://2130706433:9000/'));
|
|
$this->assertTrue($client->isPrivateURL('http://0x7f000001/'));
|
|
$this->assertTrue($client->isPrivateURL('http://0177.0.0.1/'));
|
|
$this->assertTrue($client->isPrivateURL('http://2852039166/'));
|
|
$this->assertTrue($client->isPrivateURL('http://127.0.0.1./'));
|
|
}
|
|
|
|
public function testIsPrivateUrlWithUnresolvableHost()
|
|
{
|
|
$client = new Client($this->container);
|
|
|
|
$this->assertTrue($client->isPrivateURL('http://kanboard.invalid/'));
|
|
}
|
|
|
|
public function testIsPrivateUrlWithPublicAddresses()
|
|
{
|
|
$client = new Client($this->container);
|
|
|
|
$this->assertFalse($client->isPrivateURL('http://8.8.8.8/data'));
|
|
$this->assertFalse($client->isPrivateURL('https://ipv6.google.com/test'));
|
|
}
|
|
|
|
public function testIsPrivateUrlWithUnsupportedScheme()
|
|
{
|
|
$client = new Client($this->container);
|
|
|
|
$this->assertFalse($client->isPrivateURL('ftp://127.0.0.1'));
|
|
$this->assertFalse($client->isPrivateURL('mailto:test@example.com'));
|
|
}
|
|
}
|