Loading HuntDB...

SSRF via filter bypass due to lax checking on IPs

Medium
N
Nextcloud
Submitted None
Reported by obitorasu

Vulnerability Details

Technical details and impact analysis

Server-Side Request Forgery (SSRF)
## Summary: Hello, I was reading up on the recent SSRF bug found on NextCloud which is originally a part of this [report](https://hackerone.com/reports/1608039) by @tomorrowisnew_ I went through the source code again which was highlighted in the report I mentioned and I noticed that filtering for some of the more advanced SSRF payloads were clearly missing. Alphanumeric payloads came to my mind when thinking about the same so I set up a local test environment with my friend @w1redch4d We primarily focused on the code around the IP checking namely `ThowIfLocalIp`: ```php public function ThrowIfLocalIp(string $ip) : void { $localRanges = [ '100.64.0.0/10', // See RFC 6598 '192.0.0.0/24', // See RFC 6890 ]; if ( (bool)filter_var($ip, FILTER_VALIDATE_IP) && ( !filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) || IpUtils::checkIp($ip, $localRanges) )) { $this->logger->warning("Host $ip was not connected to because it violates local access rules"); throw new LocalServerException('Host violates local access rules'); } // Also check for IPv6 IPv4 nesting, because that's not covered by filter_var if ((bool)filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) && substr_count($ip, '.') > 0) { $delimiter = strrpos($ip, ':'); // Get last colon $ipv4Address = substr($ip, $delimiter + 1); if ( !filter_var($ipv4Address, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) || IpUtils::checkIp($ip, $localRanges)) { $this->logger->warning("Host $ip was not connected to because it violates local access rules"); throw new LocalServerException('Host violates local access rules'); } } } ``` As seen above, the code is more than capable of rooting out most of the SSRF payloads including IPv4 and IPv6 as well as the recently pointed out payload involving the Alibaba metadata IP `100.100.100.200`. But as stated above, the filtration technique fails when met with some of the more advanced SSRF payloads like the alphanumeric ones. In our test environment, we edited the code and set up a dummy website to test different payloads. The workflow was simple, if the payload was an invalid attempt at an SSRF, the server will throw an exception but if all the filtrations were bypassed successfully, the server would echo Pass. ## Supporting Material/References: Our dummy code is as follows: ```php <?php require 'vendor/autoload.php'; use Symfony\Component\HttpFoundation\IpUtils; function ThrowIfLocalIp(string $ip) : void { $localRanges = [ '100.64.0.0/10', // See RFC 6598 '192.0.0.0/24', // See RFC 6890 ]; if ( (bool)filter_var($ip, FILTER_VALIDATE_IP) && ( !filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) || IpUtils::checkIp($ip, $localRanges) )) { throw new Exception('Host violates local access rules'); } // Also check for IPv6 IPv4 nesting, because that's not covered by filter_var if ((bool)filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) && substr_count($ip, '.') > 0) { $delimiter = strrpos($ip, ':'); // Get last colon $ipv4Address = substr($ip, $delimiter + 1); if ( !filter_var($ipv4Address, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) || IpUtils::checkIp($ip, $localRanges)) { throw new Exception('Host violates local access rules'); } } echo "Pass"; } ThrowIfLocalIp($_GET["ip"]) ?> ``` Here are some of the screenshots: **Server catches exception for Alibaba metadata IP and doesn't echo Pass** {F1934403} {F1934404} **Server catches normal payload for AWS Magic IP and doesn't echo Pass** {F1934407} {F1934406} **Server passes the Alphanumeric payload for AWS Magic IP and echoes Pass** {F1934411} {F1934412} **Server passes greenlighted IPs proof with `8.8.8.8` and `8.8.4.4` and echoes Pass** {F1934464} {F1934456} ## Impact Attackers can leverage enclosed alphanumeric payloads to bypass IP filters and gain SSRF. An example can be using `⑯⑨。②⑤④。⑯⑨。②⑤④` which would allow an attacker to read crucial metadata if the server is hosted on the AWS platform. The above payload will resolve to the magic IP of AWS namely `169.254.169.254` but bypasses all the filtering present in the code itself.

Report Details

Additional information and metadata

State

Closed

Substate

Resolved

Bounty

$250.00

Submitted

Weakness

Server-Side Request Forgery (SSRF)