6 ms·
These have a fairly simple fix that you can implement yourself as a developer. Don't let your services listen on (AKA bind to) 0.0.0.0 or 127.0.0.1. The entire
by andrewstuart2 10y ago
These have a fairly simple fix that you can implement yourself as a developer. Don't let your services listen on (AKA bind to) 0.0.0.0 or 127.0.0.1.
The entire 127.0.0.0/8 block is dedicated to the loopback interface [1]. That's 2^24 - 2 unique IP addresses you can choose at random. This basically eliminates the feasibility of the DNS rebinding component, as it would take prohibitively long to find the actual loopback address that your services have bound to.
It's important to note that this is much more effective than not using the default port. It's much faster to iterate all 2^16 ports on the same IP address than it is to wait for DNS TTL to expire so you can rebind to another IP address.
As a bonus, you don't have to worry about port collisions when nobody's allowed to listen on 0.0.0.0. Everybody can use 8080 if they want.
[1] https://tools.ietf.org/html/rfc5735#section-3 https://tools.ietf.org/html/rfc5735#section-3
- an_ko 10y ago> Don't let your services listen on (AKA bind to) 0.0.0.0 or 127.0.0.1. How do I do that? Iptables? (Sorry if this is a dumb question.)
- baby 10y agohe means make them listen for 3.3.99.8 for example
- thewhitetulip 10y ago3.0.0.0/8 isn't loopback. Or did I miss something? I thought he said use 127.3.99.7 or something of that sort to avoid using the default localhost
- andrewstuart2 10y agoRight, and furthermore an address in 3.0.0.0/8 isn't likely to be added on any of your interfaces, so attempting to bind/listen on that will just fail. Even if you add it yourself, there's a tiny chance you might start redirecting some traffic you care about (say, facebook) to a local interface where facebook services are definitely not running. :-P Fortunately, the whole 127.0.0.0/8 block is automatically added to the loopback interface (edit: on Linux at least), so you can bind away to your heart's content.
- thewhitetulip 10y agothen how can you run the webapp if you aren't binding it to localhost? How will your PC know how to resolve 3.0.0.0/8?
- thewhitetulip 10y agono, it depends which language you use, but each allows you to 'listen' on an ip address and a port. The point is that the most commonly used IP is 127.0.0.1 but we can as well use 127.120.99.12 because the entire subnet is the loopback address. https://github.com/thewhitetulip/web-dev-golang-anti-textbook/blob/master/manuscript/2.0implementationBasics.md#basic-web-application https://github.com/thewhitetulip/web-dev-golang-anti-textboo... For an example in Go.
- andrewstuart2 10y agoIt's part of configuring whatever services you're running (or an option in your tcp/ip library if you're programming your own), and will depend on the service. For memcached for example, you can change the listen address with `-l <addr>`. Usually you just have to find the configuration documentation and ctrl-f search for "address," "bind address," "listen address," "IP address," etc. Or scan the page for something networking related. It's pretty much always a command line flag or config file parameter. If you're running with docker, it's even more standard. When you expose a port, just use `-p 127.12.12.3:11211:11211` (with your chosen IP address, of course), and docker will set up the forwarding for you, only for that address.
- JonnieCache 10y agoIs there a way to make root a requirement for binding to 0.0.0.0 though?
- TimPrice 10y agoSelinux (semanage port) and iptables (SECMARK?) might help you there.
- d0mine 10y agoTo choose an ip address from 127.0.0.0/8 subnet randomly in Python 3: >>> import ipaddress >>> import random >>> ipaddress.IPv4Address('127.0.0.1') + random.randrange(2**24 - 2) IPv4Address('127.23.181.175')
- wcarron27 10y agoHey, I know I'm a bit late to the party. But I'm looking to protect my company's redis instance from these attacks and your approach looks very promising. Things is, I don't know what to do now that I've written a similar script. Where should I use this code? In the redis.conf file? Bear in mind, I'm a front end developer, so this is absolutely not my forte. Thanks for the help.
- deleted 10y ago[deleted]
- baby 10y ago2^24 - 2 = not a lot, probably delays the attack for a few minutes
- andrewstuart2 10y agoIf you set your DNS TTL to a relatively-low 1 minute (as in the POC), that's 31.9 years for an exhaustive search. The birthday paradox means that you're probably going to spend a lot less time than that, but it's certainly going to buy me a lot longer than 1 minute that I get if I'm using 127.0.0.1. The chances I stay on any random website longer than 15 minutes are pretty slim, and you've got really poor odds of finding the right IP in that time.
- cbr 10y agoI don't see how the birthday paradox applies. If you pick a random IP under 127.0.0.0/8, then on average a website searching will take 1/2 of time required to check every IP sequentially.
- thaumasiotes 10y agocbr is correct; the birthday paradox refers to trying to find two random values that are equal to each other, with no other constraint on their value (so (3,3) and (78,78) are both valid solutions). What we have here is trying to find one value that is constrained (if 3 is a solution, 78 can't be). Assuming you enumerate IP addresses in random order, the expectation will be 16 years to find the one you want.
- andrewstuart2 10y agoAhhh, thank you for explaining that distinction much better than Wikipedia (maybe you ought to add this tidbit :-) ). I'd been assuming it applied to any probability of collision in a fixed space.
- thaumasiotes 10y agoI guess I'll elaborate by distinguishing these types of problem: 1. I roll 1 die. What are the odds of getting a 3? (Assuming the die is evenly distributed 1-n, and n >= 3, the answer is 1/n ) 2. I roll 100 dice. What are the odds of getting, among those dice, at least one result of 3? ( 1 - [(n-1)/n]^100 ) 3. I roll 2 dice. What are the odds of those dice matching each other? ( 1/n ) 4. I roll 100 dice. What are the odds of there being, among those 100 dice, any 2 dice that rolled the same result? The birthday paradox provides the answer to problems of type (4).
- jlgaddis 10y agoI'll point out for the benefit of others that not all operating systems treat 127.0.0.0/8 as belonging to the loopback interface. Linux does, so this will probably work for the majority of users here, but, I believe, it will not work for FreeBSD, for example (I'm on an iPad and don't have an SSH client at the moment so I can't verify). In those cases, however, you can add "aliases" to the loopback interface, with specific IP addresses in the 127/8 subnet, and then use them.
- andrewstuart2 10y agoYeah, good point. I fired up my Windows VM and confirmed that I can listen on a randomly-chosen 127.* address as well, so that should mean most people don't need that extra step. :-)
- JonathonW 10y agoOn OSX (and, I suspect, vanilla FreeBSD), this looks like (replacing 127.1.2.3 with the address you want to use; 0xff000000 must stay the same, since netmasks of all addresses on an interface must not confict if they're on the same subnet): sudo ifconfig lo0 alias 127.1.2.3 0xff000000 And then, when you're done: sudo ifconfig lo0 -alias 127.1.2.3 to tear it back down.
- inferiorhuman 10y agoOn FreeBSD at least you can assign whatever address you want to a loopback interface. I'm currently using aliases on a loopback device (lo1 in this case) for host <-> jail communication. The jails get 172.16.0.0/16. You can manage this trivially in rc.conf and then restart the netif and route services.
- X-Istence 10y agoRecommendation for aliases on an interface is to use 255.255.255.255 as the netmask on FreeBSD. For example to add extra interfaces to lo0 on FreeBSD you may use: ipv4_addrs_lo0="127.0.0.2-5/8" in rc.conf And now those addresses are automatically assigned to lo0, the netmask will be set to 255.255.255.255 automatically for all but the first in that range (.2). Since 127.0.0.1 is unconditionally assigned to lo0, you could also use: ipv4_addrs_lo0="127.0.0.2-5/32" This is what I do on FreeBSD.
- wdr1 10y agoIf I'm binding to an IP why do I have to worry about DNS TTL?
- mynameisvlad 10y agoParent comment is referring to the PoC created here. The PoC creator would have to wait for TTL to expire each time for all of 127.0.0.1/8 as opposed to just having to wait for one TTL to expire to set it to just 127.0.0.1.
- semi 10y agoI don't think that is true, though maybe I'm misunderstanding. The DNS rebinding is a workaround so that you can read the reply of a message. Enumerating a list of services that are running is something you could do as a precursor to using the dns rebinding attack to attack it. I am not familiar with javascript networking enough to say what kind of rate limiting you would incur, but in theory at least you should be able to probe many IPs at once.
- dividuum 10y agoAlternatively just use unix domain sockets. That way only locally running programs can access your service. Random ports sounds like security through obscurity (which might work from time to time).
- bahjoite 10y ago> That way only locally running programs can access your service A web browser is a locally running program. You mean, of course, that access to the socket can be limited to programs running under a user account sufficiently privileged to read and/or write to the socket file. Can all services be made to communicate only through domain sockets? I agree that choosing randomly from the available loopback addresses and/or ports isn't providing any real security; it surely wouldn't take the web browser very long to make a connection to every port in the 127/8 address range.
- dividuum 10y ago> A web browser is a locally running program That is of course correct. I should have worded it a bit more technical, I guess :-) Support of unix domain sockets depends on the program, so not all support that, but Redis and memcache do. At least for those you can prevent the browser from connecting to them using TCP. I guess another option would be to just limit what ports a browser can access. Some ports a blocked by default, but I feel like a whitelist instead of a blacklist makes more sense and I'm fairly certain that most of my daily browser usage would still work if only 80, 443 and maybe 8080 would be whitelisted. Is there a way to archive this (in chrome/Firefox) without reverting to some outside sandbox?
- bahjoite 10y ago> limit what ports a browser can access After briefly looking into this:- - there doesn't seem to be a way to configure firefox with a whitelist of ports it may connect to - AppArmor doesn't appear to yet be capable of constraining network access at the level of IP address or port number - The good news is that it should be possible to use linux network namespaces along with iptables - I've not attempted it
- deleted 10y ago[deleted]
- therealmarv 10y agowait... there is also one/many(?) IPv6 loopback address ! I need to do something there too or not?
- underwater 10y agoAre you sure this actually makes a difference? Can't you detect errors when searching the IP space using the POST method, or try and resolve multiple IPs simultaneously through the DNS reminding trick?
- deleted 10y ago[deleted]
- jjnoakes 10y agoThere's still a problem on multi-user machines. The real solution is for tools to not assume local host connections are secure.