238 comments

[ 2.2 ms ] story [ 294 ms ] thread
"How to steal some developer's local database"
Interesting attack. A far more feasible one is just to throw nmap around your next conferences WiFi network and try common postgres/mysql combinations. You'd be surprised how many developers have such services exposed, often with 'developer passwords' and production dumps loaded.
I think it'd be very common to "protect" these services by making them bound only to localhost. The fact that this attack bypasses that protection is pretty interesting.
It's also common to open these up so that team members can grab a copy of your database. I haven't done that, but I can think of a case in the past few months where a developer had done so.

Edit: Now that I think of it and especially with containerized dev environments and VMs, I'd bet it quite common. I'm sure I've opened up a DB or search container more than I needed to just because I couldn't get the damn things to talk. I still would have a firewall, but not everyone does.

Yeah, I'm pretty sure I've bound services to 0.0.0.0 just to avoid the trivial annoyance of checking an IP.
Of course, this can be done against anybody who hits a web page, instead of just against machines on your local network.

But yeah, binding services to 0.0.0.0 on your machine is a recipe for disaster too.

Usually you're behind either NAT or a firewall though.
So long as you have a DNS resolver which respects TTLs, you could be behind anything - they're dynamically changing DNS to point at your localhost. It's not the remote server making the connections, it's your web browser. At which point, it can be exfiltrated, thanks for the DNS tricks which get around CORS.
That doesn't make sense. A web browser is just a TCP connection after all. If the port isn't open on the server there's no way to connect to it.
Another good reason to develop w/in a virtualized server on your dev machine?
No.

If you are going to go to that much effort, better to just spend a little bit of time on security.

The gain by using VMs and provisioning sofware is not limited to security. There are a lot of good reasons to do that.
Correct. Like developing to a common deployment target, provisioning a development VM with the same toolchain you use to provision production VMs, isolating your VM from the system state of your development machine. I cannot imagine developing any other way.
I did this for a while, but it falls apart with constant care and feeding. I had a vagrant box that could be fully provisioned with Ansible, and checked everything in to the repo. I paid for Parallels because virtualbox is too slow to do any real work (unit tests take 2x or 3x longer to run for example).

I couldn't convince anyone else to use this stuff. They were happy to just run some homebrew commands every now and then.

I was away from the project for about six months. When I got back I thought "great, I'll just `vagrant up` and be back in business."

Parallels had upgraded itself to some version that wasn't compatible with vagrant. I was eventually able to find an old parallels installer and downgraded.

My laptop had a newer version of ansible, and it couldn't run the old ansible scripts. There was no easy fix to something that should be easy (ansible could no longer create postgres users when ansible was running through a non-root account. With vagrant you log in as the `vagrant` user and that user has sudo).

I deleted all that stuff, and now I do all my development locally. I do run my DB's in docker containers, but that's it. Now it is super easy to add any version of any database to any project. Just a few lines in docker-compose.yml. But my docker-compose.yml was written for an older version of docker-compose. I tried to upgrade it to the latest syntax and nothing worked. I reverted that and things are still running. It is only a matter of time before some docker update renders my db and redis useless.

At that point I'll just `brew install redis` and `brew install postgres` and be done with it. Everything will run, and run at native speeds. Yay!

I guess it depends on your use case but just about everyone I know uses Vagrant. It's true that you should never upgrade VirtualBox or Vagrant anywhere near a deadline, but I rarely have problems. I get similar performance from both VirtualBox and Parallels, both on network shares and execution. I'm on a 2014 MacBook Pro, Ubuntu guests, mostly doing PHP and Node.
That's interesting that you get the same performance on vbox and parallels. I tested vbox, vmware, and parallels on a macbook pro (2011 or 2012). vbox was an order of magnitude slower running our unit tests (and rails tests are slow enough as it is). Parallels was the fastest running the tests at close to native speed. Vmware was okay, but not great.
Did you use network shares or default shared filesystem?
I was using NFS - the default VirtualBox Shared Folders is slow as to be useless (which I guess is what you were going to say). But on NFS (which is recommended by Vagrant) I had no problems.
I think this is overstated. This only falls apart if you cannot get buy-in from your development team, and are not applying proper version management to your tool chain.

First, we use Ansible, not just for development, but for deployment. Because of this, if the time comes to upgrade Ansible, everybody upgrades, and any incompatible playbooks are immediately addressed.

Second, Parallels is a bad choice. They do not have a sufficient enterprise focus, and their product is updated too often. It's great for desktop virtualization, but not for much else.

We use VMWare Fusion, have no performance issues, and have never experienced the issue of hypervisor bit rot. On the one occasion when we upgraded VMWare, we also upgraded the corresponding Vagrant plugin, and everything worked fine.

At least we won't have to worry about any future VMware Fusion upgrades breaking anything, since there quite possibly won't be any future upgrades.
Yes! For instance stealing all your SSH keys and shell history, eg. by some node module down the dependency tree.
At least with what I do, it's not much effort at all. I have a bunch of Puppet recipes that spin up a Vagrant box and I'm done.
That much effort? It's just "vagrant up" for a lot of people.
I'd argue this is a good reason to browse from within a virtual machine :-)
and making sure the VM is not set up as bridged networking, I personally have a pfSense VM and route my computer and all my other VMs to it each on a separate virtual NIC with firewall rules etc.
How did you do this? I found pfSense pretty tricky to set up - it seemed like pfSense expected a dedicated WAN interface.
look at my profile for a link to my blog where I explain things in detail, it's not finished (I still have to write a post about how I configure i3 and how I start virtualbox more easily) but the pfSense stuff should be ready for public consumption
This is a non-issue for those of us who are using Vagrant or similar development VM technologies.
Not necessarily since it's not that uncommon to expose the ports from the VM. Not saying that's a good idea, but it happens fairly often.
The few guides I've seen on setting up virtual servers as devlopment environments have all recommended setting networks as bridged instead of NAT'ed.
That is the best approach, but a lot of people change it to NAT for testing purposes, like connecting to the VM from mobile devices, and other operating systems, etc..

I know there are ways to do that as well, but this is the easiest and so it's most often the way it's done.

Usually I access databases in my VMs by ssh tunneling. I have no databse server software on my computer. I thought most people work like that.
Most skilled developers probably. The rest can't figure out why the computer next to theirs can't connect to the test database and after googling a stackoverflow anwser have it listen on 0.0.0.0 forever.
Indeed. Turn off SELinux and disable the firewall too! And just leave the password for the MySQL root user blank since it's too much trouble keeping track of them.
I am guilty of this. The real question is will I ever change this habbit?

I see percentage of us here locking things down.

The rest, and the rest of the developers out there likely won't.

This needs to be fixed at the browser level I don't see it being solved any other way that would have the net benefit of having it fixed in the browser.

Simply pinning public and local and not allowing local rebinding should have most of the issues resolved.

Tunneling still binds a localhost port to your database, so it'd still be vulnerable to this attack even though it's running a container or VM.
No, it doesn't. If you are running Vagrant in a bridging config, it has it's own separate IP on the network. If you are running it as a private network, it has it's own IP on a private subnet isolated to the host machine. You have to explicitly do port forwarding to make it work as you describe.

EDIT: I'm not thinking straight. Please ignore me.

> You have to explicitly do port forwarding

> Tunneling

Yes, that is what GP was describing.

Sorry. You are correct, sir.
These exploits rely upon the ports being exposed on localhost. Even if you are not (as you should) using ssh tunneling to the VM, any exposed ports are on a separate IP address, not localhost. However, if one is forwarding ports to the host machine, that's obviously a problem.
These exploits rely upon the ports being exposed on a predictable IP. A lot of setups are going to give you very predictable IPs for the virtual machines.
Thanks to WebRTC, it's even easier - you can enumerate all local IP addresses and then you only have to scan one or two subnets.

Local VMs are definitely vulnerable to this as well.

Not if you actually work in the VM, and do not expose database ports to the host (why in hell would you do this anyway). No amount of ip scanning is going to open ports.
> why in hell would you do this anyway

Integration with IDEs.

> Integration with IDEs.

That's a fair point, but Rsync or shared folders should have you covered for this.

Actually I meant something like how Intellij has DB integration, so you could put in your host & port and connect to the DB to help you write queries etc.
(comment deleted)
If the user isn't using ssh tunneling into the vagrant vm, then this attack still works if the attacker uses the correct IP address instead of localhost.
Absolutely not a non-issue with all of the configuration options with vagrant. I'm honestly taken aback that you would consider this a nonissue with something like vagrant.

config.vm.network :forwarded_port, guest: 8080, host: 8080 config.vm.network "public_network", :bridge => 'en0: Wi-Fi (AirPort)'

You can intentionally configure anything to be insecure, and what you describe is one such example. Most devs are either bridging or using a private network (the latter in our case).
What I just described was a bridge that maps ports on the local machine to ports on the VM.
In a past life I had to write some DNS rebind attacks for some CPE testsuite software that is out there.

It was very easy to write some javascript that hangs out in the browser, gets the updated DNS host as the 192.168.0.1 address (sure sure, you can go crazy guessing other addresses) and then about 60% of everyone was on admin:admin or something as common; the first 12 or so bits of an ethernet address are the vendor identifier, which makes the process even easier to assume. Then you just start posting data to well-known web admin interfaces and update the router password.

I have no idea how well this works, three or four years later...

WOW. That's just... wow. You might even be to upload new firmware. And you could do all of that inside a hidden iframe with it's own domain, so the parent page DNS never needs to change.
I wonder there's a solution by requiring a PTR record pointing at each A record which should have Same Origin Policy applied.
This would break shared hosting, load balancers, or any other architecture without a unique IP address per hostname. I don't think this is feasible unless it's applied to IPv6 only due to IPv4 scarcity.
Fortunately most routers have a random default password now, rather than admin or changeme or whatever. At least that's what I've found; I guess it might be regional.
(comment deleted)
My takeaway from this is that binding to localhost doesn't give you as much security as you think.
I always kinda wondered when the other shoe was gonna drop on "why do databases even have passwords"...
I prefer key-based auth or local user based auth.
This problem doesn't just apply to localhost, although it's most straightfoward to exploit that way. You could also use this technique to scan the user's LAN or, in a more targeted attack, bypass IP address restrictions on specific servers.

Scripts from the public Internet shouldn't be able to access private or local networks as a matter of policy.

Similarly, in a high-security environment, scripts from a private network shouldn't be able to access the public Internet - to help prevent exfiltration of private data.

> Scripts from the public Internet shouldn't be able to access private or local networks as a matter of policy.

I agree, and it's encouraged some pretty stupid practices where it is used for things other than espionage or malicious intent.

Lenovo has a driver detection / update tool on their website, to run it you download a helper application that opens up a HTTP endpoint on localhost, then their website uses it to scan your system and (hopefully) shuts it down afterward. Why was this done in the first place, forcing users to download and run an executable (which has to be restarted each time you scan) that has no UI except for the web browser tab you already have open is dumb.

Recently Redis aliased POST and Host: to QUIT for this reason.
It seems to me that they should quit on reading any input that they can't parse. At best silently ignoring bad input leads to software not doing what it's supposed to do. At worst it leads to attacks like this.

I realize this is contrary to "be conservative in what you do, be liberal in what you accept from others", but I never thought that was a good way to write software.

That's at the very least a much harder change to roll out, since if things are broken after a new version of Redis comes out people will blame Redis for breaking things.
I'm not very familiar with Redis, so I might be missing something here.

But if the choice, after a Redis update, is between: a) my software breaking and, hopefully, an error message saying "redis failure parsing 'XYZ'" or b) my software /maybe/ continuing to function, while passing commands to Redis that it's ignoring

I would always pick (a), and I think most programmers would think likewise.

Let's say you're using a cache server as a best-effort cache, and you take advantage of its ability to store complicated data structures. Your client implementation has a small bug with one of them, and ~1% of the time it sends something to the server that's not to spec. Right now, the server returns an error for that specific request, but doesn't drop the connection and continues processing later requests on the connection. You know about the errors, but they're not worth fixing.

Now the cache server has a security update, so you apply it right away. But now when it gets your invalid command it not only returns an error but it drops the connection. Your client doesn't handle this well, and now your caching is fully broken and your server falls over from the load.

That's exactly my point of view on the matter.
Postel's law / the robustness principle is a good way to write robust software, like a TCP implementation or an HTML parser. Most software doesn't need to be robust, though, and failing fast probably leads to less security issues than trying to continue on.
So if you were in a terminal, e.g. redis-cli, and you do a typo, you get disconnected?
Redis could know that its being queried via a terminal and not do that
I always thought of it as "skip spaces and accept 1'234,00 if you wait for a number", not what redis does. Liberal != indifferent.
Which versions are safe?
Currently the feature is only committed in the "unstable" branch, but for the next 3.2 patch release it will be merged.
Looks like the best way to protect against this is filtering private IP addresses from DNS responses. Is there a reason why ISP DNS servers in general would ever need to serve out a private IP?
I know at least one large ISP that does exactly that, so I guess there's not much preventing everyone from doing it.
The only problem with that is all ISPs will have to configure their DNS systems to do so (not going to happen soon). The only reasonable fix would be applied at the browser level as they are updated reasonably often.

A better mitigation than that mentioned in the article is that browsers should ignore a DNS update if it goes from a public IP to a private IP range. DNS pinning as suggested would cause havoc with most wifi captive portals, especially for those not computer savvy or the badly configured/implemented captive portals.

I think you may be able to discover actual IP addresses with WebRTC. If the host is on IPv6 then it may well be a public adress. Hence it would be impossible to define "local" in this setup.
As far as I'm aware[0] there are private IPv6 addresses that should be treated the same as 169.254 and 10/172/192 in IPv4. It shouldn't matter what IP the host has, just what IP the address of the site you are communicating with goes from the public range to private range.

[0]: https://tools.ietf.org/html/rfc4291#section-2.5.6

> DNS pinning as suggested would cause havoc with most wifi captive portals

It will require extra page reloads. Everybody is used to reload pages for any random reason by now (and you can reload by javascript too). I don't think it would cause much havoc.

because some people set up services on internal/private networks, and split horizon DNS is a pain to set up.

I typically tell people if they can't connect to services on our VPN, to make sure they're using google's DNS servers because they don't protect against DNS rebinding "attacks."

One example:

www.dropboxlocalhost.com -> 127.0.0.1

I don't know if dropbox are still using that in their client though.

Out of curiosity, what data do you have in your development databases that this becomes such a grave concern? I mean I'm all for security and love to see how creative people can get but we are talking about dev environments and not some part of the infrastructure (automated test machines, production, etc).
I once requested sample data to work against while triaging/fixing a production issue and was given an unredacted copy of the production database. Lots of customer names/addresses/phone numbers/emails in there. I nuked it from orbit when I was done.
People work in development with copies of production databases all the time..

They absolutely should not, but I've seen it at companies I've worked at, at clients, and I'll admit I've done it at least a few times myself over the years.

If you had read the whole article, you would have the answer to your question. Es. It can get you to code execution if you poison python pickled data. Ecc..
I give you that; I stopped reading it just before he mentioned that point. Thanks for pointing it out, very creative vulnerability.
I actually thought the opposite. Surely the database is more valuable than the ability to execute code. Assuming its a copy of the production database.
You generally work with copies of production databases. Hell I have prod copies of a couple banks' databases on my machine at work which I'm pretty sure violates some data protection law somewhere, despite us being (I assume) legally bound to keep the data secret.

AFAIK we're only allowed to have them on our work machines and we encourage clients to sanitize them before handing them over but not many do.

I generally work with prod backups (it's not uncommon) because you get realistic performance and it makes debugging live bugs much easier.

I prefer to have an annonymization script but many companies are too cheap to allocate time for one.

I run my real databases on non-standard ports in docker and put honey pots on the standard ports. In those I fill it with dialog from love scenes in popular movies, it's not a ton of data but it's certainly interesting.
That's cute. Do you happen to have it on GitHub? Would love to see what comes through.
Can this be solved by configuring the local system (e.g. Debian?) to blacklist any DNS resolution that ends up being a private IP address? Is this is possible to configure at the firewall level?
How about local IPv6 addresses? I can easily see this being left out due to sheer complexity.
I'm guessing that even in a future in which we have 100% of IPv6 deployment, we would still run our loopback/LAN interfaces with IPv4 for simplicity...
It's too late. I have already run into issues on Linux distros with some daemons binding to 127.0.0.1, but localhost resolving to ::1.
There is only one local IPv6 address:

::1/128

Unlike IPv4 there is not an entire /8.

IPv6 still has the whole IPv4-mapped range at ::ffff:127.0.0.0/104
You can run a dnsmasq locally with "--stop-dns-rebind".

I have this enabled on my router.

Ubiquiti router owners (I know there are a few on HN) can enable this option like so:

  ssh <router>
  configure
  set service dns forwarding options stop-dns-rebind
  commit
  save
/var/log/dnsmasq.log should contain the resolution failures after that. e.g.:

  Sep  1 21:48:41 dnsmasq[26479]: possible DNS-rebind attack detected: www.dropboxlocalhost.com
I've become increasingly complacent and often allow NoScript to "temporarily allow all javascript on this page", but will stop doing it, having just tried the PoC. It found Redis (which runs in a container, but with the port exposed).

The PoC failed to work when using TorBrowser (with the security slider set to High) and letting NoScript temporarily allow.

With WebRTC local ip discovery [1] it can be easily extended to work against a whole local subnet. Looks very dangerous.

Probably best to attack this on the DNS rebind level. Encapsulating the browser network context somehow and firewalling this might help mitigating this attack too.

[1] https://www.browserleaks.com/webrtc

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

> 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.)

he means make them listen for 3.3.99.8 for example
3.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

Right, 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.

then 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?

It'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.

Is there a way to make root a requirement for binding to 0.0.0.0 though?
Selinux (semanage port) and iptables (SECMARK?) might help you there.
To 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')
(comment deleted)
I really appreciate this code example. I've been using 127.0.0.1 for all my local dev stuff, relying on ports. This is pretty awesome!
Nice use of __add__ operator over loading here
Hey, 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.

2^24 - 2 = not a lot, probably delays the attack for a few minutes
If 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.

I 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.
cbr 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.
Ahhh, 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.
I 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).

So then, presumably, even with this solution the attacker has birthday attack advantage for:

a) attacking multiple targets all using independent random IPs for their services

b) Users running multiple services, each on a separate random loopback IP

And if I'm correct there, then this would presumably extend to generic DNS rebinding attacks; the greater the number of IPs in a subnet, the greater the birthday attack advantage the attacker gains. (right?)

Your (a) is my example (2), where the dice are the IPs used by the multiple targets and the value 3 is the IP address you test for. It's still not a birthday attack, but it is helpful to the attacker, assuming the goal is "one compromise on any target, I don't care which". (In terms of the formula I gave as the solution to (2), if you make g guesses to attack t targets, your chance of success on at least one target is [1 - ([n-g]/n)^t].) In example (2) itself, there was 1 guess, 3, and 100 targets, the dice.

Your (b) is similar, but even more helpful to the attacker in that the loopback IPs are constrained not to overlap with each other, which makes searching for "any hit, I don't care which" easier.

It's a birthday attack if you generate a lot of values and hope for two of those values -- all of which you generated -- to be equal to each other. If you're generating values and hoping for one of those values to be equal to some externally-defined value, it's not a birthday attack, it's a guessing attack.

> If you set your DNS TTL to a relatively-low 1 minute (as in the POC), that's 31.9 years for an exhaustive search.

Right, but that assumes a new DNS record is created each time. An attacker might simply have records for the entire 127.0.0.0/8 range and would iterate over them.

It would still take a long time to make an exhaustive search, but it will be faster than waiting for a 1 minute TTL between each try.

I'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.

Yeah, 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. :-)
On 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.
On 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.

Recommendation 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.
The ifconfig man page just says the netmask must be "non-conflicting" if on the same subnet as the first network address for the interface (that'd be 127.0.0.1/8 for lo0). I'm presuming the narrower netmask qualifies as non-conflicting?
I had some fun with this as well a while ago. It's too bad that with IPv6 we'll only get one loopback address (i.e. ::1) and not again a whole loopback subnet.
IPv6 has a humongous private network range, though. fd00:/8 has 2^120 IP addresses. You could set up a Docker bridge with that range and run containers with random addresses. Correctly guessing one of 2^120 addresses would be nearly as difficult as cracking AES128.
If I'm binding to an IP why do I have to worry about DNS TTL?
Parent 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.
I 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.

Alternatively 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).
> 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.

> 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?

> 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

> 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.

They might mean instead that browsers can’t access domain sockets.

(comment deleted)
wait... there is also one/many(?) IPv6 loopback address ! I need to do something there too or not?
Are 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?
(comment deleted)
There's still a problem on multi-user machines.

The real solution is for tools to not assume local host connections are secure.

The DNS rebind seems weird, any sensible DNS forwarder should ignore local ip (127.0.01/8, 192.168.0.1, etc). This attack doesn't seem feasible if you can't hinack local adresses.
Oh no, my development database! What ever will I do if 10,000 entries of Lorem Ipsum get leaked!? In the wrong hands, all of my bunk data from trying to get a PUT right could be really dangerous.
you joke, but I have to constantly tell our devs "no, you can't have actual prod data to test your queries against"
Fine, as long as you can produce replacement data with the desired qualities.
it's called a test fixture.
Frequently data produced by hand (by developers writing the tests) or randomly generated (by something like quickcheck) does not have all the edge cases you would encounter in real data.

So there is some justification to having real data available - this is why in the finance space at least developer machines have relatively stringent restrictions placed on them compared to a lot of other organisations.

It must be a big test fixture to contain all the data of a production database.
Perhaps you don't have anything confidential on your development machine -- and hopefully you don't! -- but plenty of people do, unfortunately, use real data. :(
You have no idea how common it is to work with production db copies in the consulting world.
If the box doesn't beep any longer - how can I find where I stored my speaker-less server?
Question: could DNS rebinding be used to tap into 1Password inter-process communication? They use localhost websockets for IPC; it's authenticated through the request origin and then through verifying the PID is in fact the browser [1].

DNS rebinding could definitely get around the PID check, but could it spoof an origin to something like "safari-extension://com.agilebits.onepassword4-safari-2bua8c4s2c"?

[1] https://support.1password.com/mini-extension-security/

I don't see how this would work, seeing as the safari-extension protocol doesn't get the location to go to based on DNS.
Well first off, I honestly don't know if it's possible; if I knew, I'd just shoot an email off to 1password.

That being said, I don't think we're suggesting the same thing. I'm saying one could write a webpage that uses DNS rebinding to make requests on localhost, like OP. Then, the webpage, completely bypassing the browser's built-in extension system, makes a request to 1password over localhost (which they're already using for IPC).

The reason that DNS rebinding is relevant is twofold; first, you need the request to hijack existing IPC between the browser extension and the standalone desktop app, and two, because you need to have the request come from the browser's PID. That should all work.

The question here revolves around 1password's verification that the origin is coming from, for example, something similar to

> safari-extension://com.agilebits.onepassword4-safari-2bua8c4s2c

So then your webpage would also need to be able to spoof the origin of your localhost requests to look like they were coming from that origin. I don't know if that's possible or not, but if it is, it would imply that this technique could get you illegitimate access to 1password.

I love this class of attack. I wonder if you could use a similar technique to get German Trasmission users to download fine-inducing torrents, etc..
When you hear about someone jail breaking an iphone trough the browser, this is how. The fact that the browser works as a window to all tcp-sockets running on a device, it's the perfect way to exploit buffert overflows on a device that lacks a terminal.

Also remember this with all your IoT appliances running on your local network. Even if it has a local IP-address, as long as you have a computer with a browser on the same network, you might as well consider your devices being publicly accessible from the rest of the internet.

Remember, kids: a firewall is only one layer of your security. Make sure you always implement proper access control and guide users through changing the defaults.
(comment deleted)
what? I haven't heard of a single jailbreak that worked like that. You got some links?

edit: to people linking me safari CVEs (can't reply to you all) - these are memory corruptions. Not accessing ports on localhost.

jailbreakme took advantage of a Safari bug. All you needed to do was go to the website, hit a button and wait a few minutes.
That's a very different attack vector to the one in this post - buffer overflow vs legit service running on open ports unbeknownst to the user
I know one of the original iPhone and iPod Touch jailbreaks worked that way. I just went to a website and it automatically rooted and installed the homebrew app for me.
Since no one has provided you with a link, here's one such approach: http://www.redmondpie.com/how-to-jailbreak-ios-9.3.3-using-s...

I think one of the first sites to do it was this one: https://jailbreakme.qoid.us/

Your first link appears to require the installation of an app on the phone (after installing a dev certificate). The app, running arbitrary native code, performs the actual jailbreak (most likely using a chain of kernel exploits).

The devs seem to have gotten around the App Store by using an approach like TestFlight, which allows apps to be deployed for development and wider testing purposes without going through the App Store.

This write-up by CitizenLab [1] describes the Trident iOS exploit chain. Excerpt:

CVE-2016-4657 [2]: Visiting a maliciously crafted website may lead to arbitrary code execution

CVE-2016-4655 [3]: An application may be able to disclose kernel memory

CVE-2016-4656 [4]: An application may be able to execute arbitrary code with kernel privileges

[1] https://citizenlab.org/2016/08/million-dollar-dissident-ipho...

[2] http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2016-4657

[3] http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2016-4655

[4] http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2016-4656

None of these exploits have anything to do with accessing TCP services using a browser. The only exploit there having anything to do with Safari, CVE-2016-4657, is a WebKit memory corruption (per your [1]: "The stage1 employs a previously undocumented memory corruption vulnerability in WebKit to execute this code within the context of the Safari browser (CVE-2016-4657).").
You're right, of course. I realised my mistake after the delete link had disappeared. My bad!
No, iPhone jailbreaks usually just exploit bugs in WebKit to obtain code execution in the context of the Safari process. There generally aren't any system services running TCP locally on iOS - iOS has much more sophisticated IPC mechanisms for that.
Did you just make that up?