


























I recently disclosed several vulnerabilities (CVE) that exposed critical SSRF bypasses in popular npm packages. What can you learn from the mistakes those maintainers made? what are some weak code patterns that introduce an SSRF? Let’s dive in.
What’s SSRF? In short, A server-side request forgery (SSRF) vulnerability happens when the Node.js application makes unintended server requests from the Node.js backend to other servers (internal or external), based on user-controlled input. Attackers can then exploit this behavior to trick the vulnerable Node.js application into fetching all kinds of server resources and potentially accessing unauthorized actions which don’t need authentication (think about internal servers, sidecars, etc).
Denylists are often frowned upon in the security domain because they are too brittle and can be easily bypassed or made obsolete with new attack vectors (and trust that an adversarial will not stop looking for them).
Let’s see some use-cases that denylists fail miserably with protecting against SSRF attacks:
The IP address 127.0.0.1 is often used as a localhost address. Technically speaking, the entire IP address range comprising of the address space between 127.0.0.1 to 127.255.255.255 is reserved for the loopback (the localhost) address.
As such, it might seem like a good idea to check if the hostname simply begins with a ‘127’ character set such as the following code snippet:
if (hostname.startsWith('127')) {
return 'Private';
}
However, what if a hostname starts with the number ‘127’? For example, users are free to buy domain names such as 127-my-local-domain.com. In this case, the above code snippet would incorrectly classify the domain provided by the user as a private IP address / hostname.
A common localhost reserved address space is 172.16.0.0. Details matter though. While we see a lot of IP addresses starting with the string 172.16. the actual address space is not a limited to that of all the addresses within the /16 address space. Meaning, the “last” address in that space ends at 172.16.255.255 ? Not really.
The actual address space for loopback IP address spaces is limited to the scope of the following subnet definition: 172.16.0.0/21 which yields addresses starting from 172.16.0.0 and all the way up to 172.31.255.255. This makes it a bit more tricky to check for an IP address within the range as it involves a little bit more string parsing and manipulation if you want to keep things simple and not use binary conversions and other mathematical ways to approach the problem.
224.0.0.0/4 and ff00::/8) which allows for this:'http://239.255.255.250:1900' // Common SSDP discovery address
console.log(ip.isPublic("0x7f.1"));
127.1, 127.0.1, 127.00.0x1, 127.0.0x0.1
01200034567
012.1.2.3
fe80::0001, 000:0:0000::01, 000:0:0000:0:000:0:00:001
::fFFf:127.0.0.1
So, ultimately, do not allow redirects in HTTP requests.
For example, you approve some-domain.com which resolves to public IP but the GET request ends up with a redirect to a local IP address that isn’t checked because only the initial domain was checked. Solve this by disallowing redirects follow or by including SSRF at each socket connection made by the HTTP layer.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。