More secured getURLContent method. Add PHPUnit on getURLContent
This commit is contained in:
parent
d750dc48a1
commit
80d13e711c
@ -147,7 +147,7 @@ if (GETPOST('target') == 'remote')
|
|||||||
$xmlarray = getURLContent($xmlremote);
|
$xmlarray = getURLContent($xmlremote);
|
||||||
|
|
||||||
// Return array('content'=>response,'curl_error_no'=>errno,'curl_error_msg'=>errmsg...)
|
// Return array('content'=>response,'curl_error_no'=>errno,'curl_error_msg'=>errmsg...)
|
||||||
if (!$xmlarray['curl_error_no'] && $xmlarray['http_code'] != '404')
|
if (!$xmlarray['curl_error_no'] && $xmlarray['http_code'] != '400' && $xmlarray['http_code'] != '404')
|
||||||
{
|
{
|
||||||
$xmlfile = $xmlarray['content'];
|
$xmlfile = $xmlarray['content'];
|
||||||
//print "xmlfilestart".$xmlfile."xmlfileend";
|
//print "xmlfilestart".$xmlfile."xmlfileend";
|
||||||
|
|||||||
@ -431,7 +431,6 @@ print '<br>';
|
|||||||
print '<strong>';
|
print '<strong>';
|
||||||
print $form->textwithpicto($langs->trans("CompressionOfResources"), $langs->trans("CompressionOfResourcesDesc"));
|
print $form->textwithpicto($langs->trans("CompressionOfResources"), $langs->trans("CompressionOfResourcesDesc"));
|
||||||
print '</strong>: ';
|
print '</strong>: ';
|
||||||
//$tmp=getURLContent(DOL_URL_ROOT.'/index.php','GET');var_dump($tmp);
|
|
||||||
print '<br>';
|
print '<br>';
|
||||||
// on PHP
|
// on PHP
|
||||||
print '<div id="httpcompphpok">'.img_picto('', 'tick.png').' '.$langs->trans("FilesOfTypeCompressed", 'php (.php)').'</div>';
|
print '<div id="httpcompphpok">'.img_picto('', 'tick.png').' '.$langs->trans("FilesOfTypeCompressed", 'php (.php)').'</div>';
|
||||||
|
|||||||
@ -54,7 +54,7 @@ $version = '0.0';
|
|||||||
|
|
||||||
if ($action == 'getlastversion')
|
if ($action == 'getlastversion')
|
||||||
{
|
{
|
||||||
$result = getURLContent('http://sourceforge.net/projects/dolibarr/rss');
|
$result = getURLContent('https://sourceforge.net/projects/dolibarr/rss');
|
||||||
//var_dump($result['content']);
|
//var_dump($result['content']);
|
||||||
$sfurl = simplexml_load_string($result['content']);
|
$sfurl = simplexml_load_string($result['content']);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1634,7 +1634,7 @@ class Setup extends DolibarrApi
|
|||||||
$xmlarray = getURLContent($xmlremote);
|
$xmlarray = getURLContent($xmlremote);
|
||||||
|
|
||||||
// Return array('content'=>response,'curl_error_no'=>errno,'curl_error_msg'=>errmsg...)
|
// Return array('content'=>response,'curl_error_no'=>errno,'curl_error_msg'=>errmsg...)
|
||||||
if (!$xmlarray['curl_error_no'] && $xmlarray['http_code'] != '404')
|
if (!$xmlarray['curl_error_no'] && $xmlarray['http_code'] != '400' && $xmlarray['http_code'] != '404')
|
||||||
{
|
{
|
||||||
$xmlfile = $xmlarray['content'];
|
$xmlfile = $xmlarray['content'];
|
||||||
//print "xmlfilestart".$xmlfile."endxmlfile";
|
//print "xmlfilestart".$xmlfile."endxmlfile";
|
||||||
|
|||||||
@ -18,11 +18,13 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \file htdocs/core/lib/geturl.lib.php
|
* \file htdocs/core/lib/geturl.lib.php
|
||||||
* \brief This file contains functions dedicated to get URL.
|
* \brief This file contains functions dedicated to get URLs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to get a content from an URL (use proxy if proxy defined)
|
* Function to get a content from an URL (use proxy if proxy defined).
|
||||||
|
* Support Dolibarr setup for timeout and proxy.
|
||||||
|
* Enhancement of CURL to add an anti SSRF protection.
|
||||||
*
|
*
|
||||||
* @param string $url URL to call.
|
* @param string $url URL to call.
|
||||||
* @param string $postorget 'POST', 'GET', 'HEAD', 'PUT', 'PUTALREADYFORMATED', 'POSTALREADYFORMATED', 'DELETE'
|
* @param string $postorget 'POST', 'GET', 'HEAD', 'PUT', 'PUTALREADYFORMATED', 'POSTALREADYFORMATED', 'DELETE'
|
||||||
@ -125,6 +127,7 @@ function getURLContent($url, $postorget = 'GET', $param = '', $followlocation =
|
|||||||
$newUrl = $url;
|
$newUrl = $url;
|
||||||
$maxRedirection = 5;
|
$maxRedirection = 5;
|
||||||
$info = array();
|
$info = array();
|
||||||
|
$response = '';
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -132,8 +135,43 @@ function getURLContent($url, $postorget = 'GET', $param = '', $followlocation =
|
|||||||
|
|
||||||
curl_setopt($ch, CURLOPT_URL, $newUrl);
|
curl_setopt($ch, CURLOPT_URL, $newUrl);
|
||||||
|
|
||||||
// TODO Test for $localurl on $newUrl
|
// Parse $newUrl
|
||||||
// Parse $newUrl, check server address, then set parsed value with CURLOPT_CONNECT_TO
|
$newUrlArray = parse_url($newUrl);
|
||||||
|
$hosttocheck = $newUrlArray['host'];
|
||||||
|
$hosttocheck = str_replace(array('[', ']'), '', $hosttocheck); // Remove brackets of IPv6
|
||||||
|
|
||||||
|
if (in_array($hosttocheck, array('localhost', 'localhost.domain'))) {
|
||||||
|
$iptocheck = '127.0.0.1';
|
||||||
|
} else {
|
||||||
|
// TODO Resolve $iptocheck to get an IP and set CURLOPT_CONNECT_TO to use this ip
|
||||||
|
$iptocheck = $hosttocheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filter_var($iptocheck, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) { // This is not an IP
|
||||||
|
$iptocheck = 0; //
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($iptocheck) {
|
||||||
|
if ($localurl == 0) { // Only external url allowed (dangerous, may allow to get malware)
|
||||||
|
if (!filter_var($iptocheck, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
|
||||||
|
$info['http_code'] = 400;
|
||||||
|
$info['content'] = 'Error bad hostname IP (private or reserved range). Must be an external URL.';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (in_array($iptocheck, array('100.100.100.200'))) {
|
||||||
|
$info['http_code'] = 400;
|
||||||
|
$info['content'] = 'Error bad hostname IP (Used by Alibaba metadata). Must be an external URL.';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($localurl == 1) { // Only local url allowed (dangerous, may allow to get metadata on server or make internal port scanning)
|
||||||
|
if (filter_var($iptocheck, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
|
||||||
|
$info['http_code'] = 400;
|
||||||
|
$info['content'] = 'Error bad hostname. Must be a local URL.';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Getting response from server
|
// Getting response from server
|
||||||
$response = curl_exec($ch);
|
$response = curl_exec($ch);
|
||||||
|
|||||||
@ -297,9 +297,9 @@ if (!empty($_SESSION['dol_loginmesg']))
|
|||||||
if (!empty($conf->global->MAIN_EASTER_EGG_COMMITSTRIP)) {
|
if (!empty($conf->global->MAIN_EASTER_EGG_COMMITSTRIP)) {
|
||||||
include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
|
include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
|
||||||
if (substr($langs->defaultlang, 0, 2) == 'fr') {
|
if (substr($langs->defaultlang, 0, 2) == 'fr') {
|
||||||
$resgetcommitstrip = getURLContent("http://www.commitstrip.com/fr/feed/");
|
$resgetcommitstrip = getURLContent("https://www.commitstrip.com/fr/feed/");
|
||||||
} else {
|
} else {
|
||||||
$resgetcommitstrip = getURLContent("http://www.commitstrip.com/en/feed/");
|
$resgetcommitstrip = getURLContent("https://www.commitstrip.com/en/feed/");
|
||||||
}
|
}
|
||||||
if ($resgetcommitstrip && $resgetcommitstrip['http_code'] == '200')
|
if ($resgetcommitstrip && $resgetcommitstrip['http_code'] == '200')
|
||||||
{
|
{
|
||||||
|
|||||||
@ -634,7 +634,7 @@ class MultiCurrency extends CommonObject
|
|||||||
|
|
||||||
dol_syslog("Call url endpoint ".$urlendpoint);
|
dol_syslog("Call url endpoint ".$urlendpoint);
|
||||||
|
|
||||||
// TODO Use getURLContent() function instead.
|
// FIXME Use getURLContent() function instead.
|
||||||
$ch = curl_init($urlendpoint);
|
$ch = curl_init($urlendpoint);
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
$response = curl_exec($ch);
|
$response = curl_exec($ch);
|
||||||
|
|||||||
@ -395,7 +395,7 @@ class SecurityTest extends PHPUnit\Framework\TestCase
|
|||||||
global $conf;
|
global $conf;
|
||||||
include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
|
include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
|
||||||
|
|
||||||
$url = 'ftp://aaaa';
|
$url = 'ftp://mydomain.com';
|
||||||
$tmp = getURLContent($url);
|
$tmp = getURLContent($url);
|
||||||
print __METHOD__." url=".$url."\n";
|
print __METHOD__." url=".$url."\n";
|
||||||
$this->assertGreaterThan(0, strpos($tmp['curl_error_msg'], 'not supported')); // Test error if return does not contains 'not supported'
|
$this->assertGreaterThan(0, strpos($tmp['curl_error_msg'], 'not supported')); // Test error if return does not contains 'not supported'
|
||||||
@ -408,9 +408,34 @@ class SecurityTest extends PHPUnit\Framework\TestCase
|
|||||||
$url = 'https://www.dolibarr.fr'; // This is a redirect 301 page
|
$url = 'https://www.dolibarr.fr'; // This is a redirect 301 page
|
||||||
$tmp = getURLContent($url); // We DO follow
|
$tmp = getURLContent($url); // We DO follow
|
||||||
print __METHOD__." url=".$url."\n";
|
print __METHOD__." url=".$url."\n";
|
||||||
//var_dump($tmp);
|
|
||||||
$this->assertEquals(200, $tmp['http_code'], 'GET url 301 with following -> 200'); // Test error if return does not contains 'not supported'
|
$this->assertEquals(200, $tmp['http_code'], 'GET url 301 with following -> 200'); // Test error if return does not contains 'not supported'
|
||||||
|
|
||||||
|
$url = 'http://localhost';
|
||||||
|
$tmp = getURLContent($url, 'GET', '', 0, array(), array('http', 'https'), 0); // Only external URL
|
||||||
|
print __METHOD__." url=".$url."\n";
|
||||||
|
$this->assertEquals(400, $tmp['http_code'], 'GET url to '.$url.' that resolves to a local URL'); // Test we receive an error because localtest.me is not an external URL
|
||||||
|
|
||||||
|
$url = 'http://127.0.0.1';
|
||||||
|
$tmp = getURLContent($url, 'GET', '', 0, array(), array('http', 'https'), 0); // Only external URL
|
||||||
|
print __METHOD__." url=".$url."\n";
|
||||||
|
$this->assertEquals(400, $tmp['http_code'], 'GET url to '.$url.' that is a local URL'); // Test we receive an error because localtest.me is not an external URL
|
||||||
|
|
||||||
|
$url = 'https://169.254.0.1';
|
||||||
|
$tmp = getURLContent($url, 'GET', '', 0, array(), array('http', 'https'), 0); // Only external URL
|
||||||
|
print __METHOD__." url=".$url."\n";
|
||||||
|
$this->assertEquals(400, $tmp['http_code'], 'GET url to '.$url.' that is a local URL'); // Test we receive an error because localtest.me is not an external URL
|
||||||
|
|
||||||
|
$url = 'http://[::1]';
|
||||||
|
$tmp = getURLContent($url, 'GET', '', 0, array(), array('http', 'https'), 0); // Only external URL
|
||||||
|
print __METHOD__." url=".$url."\n";
|
||||||
|
$this->assertEquals(400, $tmp['http_code'], 'GET url to '.$url.' that is a local URL'); // Test we receive an error because localtest.me is not an external URL
|
||||||
|
|
||||||
|
/*$url = 'localtest.me';
|
||||||
|
$tmp = getURLContent($url, 'GET', '', 0, array(), array('http', 'https'), 0); // Only external URL
|
||||||
|
print __METHOD__." url=".$url."\n";
|
||||||
|
$this->assertEquals(400, $tmp['http_code'], 'GET url to '.$url.' that resolves to a local URL'); // Test we receive an error because localtest.me is not an external URL
|
||||||
|
*/
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user