Server-Side Request Forgery (SSRF) in frenchbread/private-ip

Valid

Reported on

Jun 12th 2021


✍️ Description

private-ip is an npm module that is used to check if the IP address is private or not for preventing SSRF attacks. It has nearly 11k+ weekly downloads on npmjs. However, I discovered that an attacker may simply get around this check by constructing a malicious IP.

🕵️‍♂️ Proof of Concept

Payloads:
127.000.000.1
2130706433
127.1
127.0.1

These payloads resolve to private IP and the application returns true for each case that I have tested and here are the test cases on runkit

💥 Impact

Bypass SSRF in any webapp where private-ip npm module is used.

Occurrences

x3rz modified the report
a year ago
x3rz modified the report
a year ago
Damir Mustafin
a year ago

Maintainer


Hi! Thank you for reporting this.

I've run a little test with given payloads, and can not confirm the issue. Also, on runkit, package resolves those payloads to 'false'.

I assume, that you might expect 127.000.000.1 to be a private ip address, and technically, it's possible to allow leading zeros, but community-wise, an npm package called is-ip does not treat these kind of addresses as IP addresses at all. This topic can be discussed on GitHub or somewhere else to get an idea of how this kind of addresses should be treated.

The other payloads does not follow ipv4 address schema, and for that reason, ideally, we could resolve it to 'undefined'.

Please let me know what do you think, and did I understand the issue correctly.

x3rz
a year ago

Researcher


Hello thank you for response, Yes it gives 'false' because they are resolved to private IP as the main objective of the package is telling that the IP is private or not. As you said about 127.000.000.1 so basically this resolves to localhost which is private IP and also for the other payloads especially like decimal encoded of localhost value i.e 2130706433 gives false but if you visit this from your browser you will see that this also resolves to localhost but for the hex-encoded payload for localhost package works just fine 0x7f000001 gives "true" for this one. And Yes you can resolve it to undefined and stop the further execution as similar to 'false' but as these all payloads resolve to localhost which could cause ssrf For more refrences you can check This one which contains all the payloads that resolves to private IP addresses https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery#file This one is just for reference that a blocklist could be implemented which could handel this issue pretty easily https://github.com/y-mehta/ssrf-req-filter/blob/master/test/blockUrls.txt This one shows the possible bypasses and the logic behind them https://vickieli.medium.com/bypassing-ssrf-protection-e111ae70727b

x3rz
a year ago

Researcher


I have added one more case for the hex encoded payload so that it can be easily identified which implies that 127.0.0.1 = Dec(2130706433) = Hex(0x7f000001)

Damir Mustafin
a year ago

Maintainer


Thanks for explanation and links. I'll work on a patch for this issue then.

Damir Mustafin validated this vulnerability a year ago
x3rz has been awarded the disclosure bounty
The fix bounty is now up for grabs
Damir Mustafin
a year ago

Maintainer


I've created a PR with patch for an issue.

Damir Mustafin confirmed that a fix has been merged on 055759 a year ago
Damir Mustafin has been awarded the fix bounty
to join this conversation