mirror of
https://github.com/misterunknown/ifm.git
synced 2025-08-09 17:46:31 +02:00
Security update: Prevent SSRF attacks by default.
This commit is contained in:
@@ -105,6 +105,7 @@
|
|||||||
"upload_overwrite_hint": "Die folgenden Dateien würden überschrieben:",
|
"upload_overwrite_hint": "Die folgenden Dateien würden überschrieben:",
|
||||||
"upload_remote": "Hochladen von außerhalb",
|
"upload_remote": "Hochladen von außerhalb",
|
||||||
"upload_remote_url": "Entfernte URL zum Hochladen",
|
"upload_remote_url": "Entfernte URL zum Hochladen",
|
||||||
|
"url_not_allowed": "Diese URL ist nicht erlaubt.",
|
||||||
"username": "Benutzername",
|
"username": "Benutzername",
|
||||||
"word_wrap": "Zeilenumbruch"
|
"word_wrap": "Zeilenumbruch"
|
||||||
}
|
}
|
||||||
|
@@ -107,6 +107,7 @@
|
|||||||
"upload_overwrite_hint": "The following files will be overwritten:",
|
"upload_overwrite_hint": "The following files will be overwritten:",
|
||||||
"upload_remote": "Remote Upload",
|
"upload_remote": "Remote Upload",
|
||||||
"upload_remote_url": "Remote Upload URL",
|
"upload_remote_url": "Remote Upload URL",
|
||||||
|
"url_not_allowed": "This URL is not allowed.",
|
||||||
"username": "Username",
|
"username": "Username",
|
||||||
"word_wrap": "Word Wrap"
|
"word_wrap": "Word Wrap"
|
||||||
}
|
}
|
||||||
|
57
src/main.php
57
src/main.php
@@ -47,6 +47,7 @@ class IFM {
|
|||||||
"extract" => 1,
|
"extract" => 1,
|
||||||
"upload" => 1,
|
"upload" => 1,
|
||||||
"remoteupload" => 1,
|
"remoteupload" => 1,
|
||||||
|
"remoteupload_disable_ssrf_check" => 0,
|
||||||
"rename" => 1,
|
"rename" => 1,
|
||||||
"zipnload" => 1,
|
"zipnload" => 1,
|
||||||
"createarchive" => 1,
|
"createarchive" => 1,
|
||||||
@@ -842,17 +843,19 @@ f00bar;
|
|||||||
if (!isset($d['method']) || !in_array($d['method'], ["curl", "file"]))
|
if (!isset($d['method']) || !in_array($d['method'], ["curl", "file"]))
|
||||||
throw new IFMException($this->l('invalid_params'));
|
throw new IFMException($this->l('invalid_params'));
|
||||||
|
|
||||||
|
if ($this->config['remoteupload_disable_ssrf_check'] != 1)
|
||||||
|
if (!$this->checkUrlSsrf($d['url']))
|
||||||
|
throw new IFMException($this->l('url_not_allowed'));
|
||||||
|
|
||||||
if ($d['method'] == "curl" && $this->checkCurl() == false)
|
if ($d['method'] == "curl" && $this->checkCurl() == false)
|
||||||
throw new IFMException($this->l('error')." cURL extention not installed.");
|
throw new IFMException($this->l('error')." cURL extention not installed.");
|
||||||
|
|
||||||
if ($d['method'] == "curl" && $this->checkCurl() == true) {
|
if ($d['method'] == "curl") {
|
||||||
$filename = (isset($d['filename']) && $d['filename'] != "") ? $d['filename'] : "curl_".uniqid();
|
$filename = (isset($d['filename']) && $d['filename'] != "") ? $d['filename'] : "curl_".uniqid();
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
if ($ch) {
|
if ($ch) {
|
||||||
if ($this->isFilenameValid($filename) == false)
|
if ($this->isFilenameValid($filename) == false)
|
||||||
throw new IFMException($this->l('invalid_filename'));
|
throw new IFMException($this->l('invalid_filename'));
|
||||||
elseif (filter_var($d['url'], FILTER_VALIDATE_URL) === false)
|
|
||||||
throw new IFMException($this->l('invalid_url'));
|
|
||||||
else {
|
else {
|
||||||
$fp = fopen($filename, "w");
|
$fp = fopen($filename, "w");
|
||||||
if ($fp) {
|
if ($fp) {
|
||||||
@@ -1297,6 +1300,54 @@ f00bar;
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function checks the URL for potential SSRF attacks. Allowed is only
|
||||||
|
* http/ftp and only global IP addresses. You can disable the SSRF check in
|
||||||
|
* the configuration.
|
||||||
|
*/
|
||||||
|
public function checkUrlSsrf($url) {
|
||||||
|
if (!filter_var($url, FILTER_VALIDATE_URL))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$parts = parse_url($url);
|
||||||
|
|
||||||
|
if (!$parts)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// no host is not acceptable
|
||||||
|
if (!isset($parts['host']))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// other protocols than http(s) or ftp are not allowed (curl assumes http per default)
|
||||||
|
if (isset($parts['scheme']) && !in_array(strtolower($parts['scheme']), ['http', 'https', 'ftp']))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// if the host is no IP, resolve the hostname
|
||||||
|
$ips = [];
|
||||||
|
if (filter_var($parts['host'], FILTER_VALIDATE_IP))
|
||||||
|
array_push($ips, $parts['host']);
|
||||||
|
else
|
||||||
|
$ips = array_merge($ips, array_map(fn($i) => $i['ip'] ?? $i['ipv6'], dns_get_record($parts['host'], DNS_A + DNS_AAAA)));
|
||||||
|
|
||||||
|
if (empty($ips))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check if any of the IPs is not global, if so then fail
|
||||||
|
foreach ($ips as $ip) {
|
||||||
|
if (version_compare(PHP_VERSION, '8.2.0') >= 0) {
|
||||||
|
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE + FILTER_FLAG_NO_RES_RANGE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private function fileDownload(array $options) {
|
private function fileDownload(array $options) {
|
||||||
if (!isset($options['name']) || trim($options['name']) == "")
|
if (!isset($options['name']) || trim($options['name']) == "")
|
||||||
$options['name'] = basename($options['file']);
|
$options['name'] = basename($options['file']);
|
||||||
|
Reference in New Issue
Block a user