Server-Side Request Forgery (SSRF) in frenchbread/private-ip
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
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.
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
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)
Thanks for explanation and links. I'll work on a patch for this issue then.