Can a website make an HTTP request to "localhost"? How does it get around the cross-domain policy?

  • I found this website which talks about fixing a Redis vulnerability by exploiting that same vulnerability.

    The website in question has a "patch me" button, and if you have a password-less Redis server running on your machine, it will patch it.

    In other words, the website itself connects to the Redis Server in your computer and executes some commands.

    If you look into the website code you find, predictably, this:

        var text = "the code to run";
        var bad = "EVAL "  + JSON.stringify(text) + " 0\r\n";
        var x = new XMLHttpRequest();
        x.open("POST", "http://localhost:6379");
        x.send(bad);
    

    To my surprise, this works!

    I thought the Cross-Domain Policy would stop this from running, but it doesn't.

    Why does this work, and how can I now not be paranoid that every website I go into is reading the entire contents of my Redis server?

    It is because it's only writing but not reading? Still, any website in the world could empty my local Redis server / write to anything else listening to a port in my machine without authentication.

    Am I missing anything here?

    Do you mean Same-Origin Policy? That only applies to reading data from another origin, not sending it.

    BTW: if origin website is `https` this doesn't work anymore, as `http` AJAX to `localhost` is not allowed. (and `localhost` can't have a globally valid SSL certificate)

  • Was pointed out due to incorrect assumptions about the issue that this answer below is wrong. If I get a chance I will revisit, or just delete this answer. Sorry!

    To answer the question: Yes a website can make an HTTP request to localhost. It will not break cross domain policy, because the request will not cross domains. It will stay local. One way to avoid cross domain policies, is to get the target victim to make the HTTP request themselves. Thus the request never crosses domains.

    To help you understand the issue you described:

    The attack is not sending any data out, nor is it making a connection to anywhere other than the local Redis machine. It's not the website itself connecting to your Redis machine. It's you connecting to your Redis machine, executing client side code/scripts that you ran by clicking the link. Basically: You click link > Link downloaded and executes some code -> code generates an http request -> http request goes from your machine, to your machine.

    The vulnerability of the Redis server in this situation is Cross Site Request Forgery. The attacker leverages the victims (in this case, the owner of the server) authentication to execute the attack.

    The attacker doesn't have full control over the process. They rely on the owner of the Redis server to execute the code. Only the owner (or someone else local to the Redis server) has the visibility (and perhaps the permission and trust relationship) to access 127.0.0.1 (Localhost)

    All that the code can do is execute commands that the local user can execute, but it's not the attacker that executes them, it's the owner, and so no Cross Domain Policies are violated.

    The only people affected by links like that would be people running Redis servers. If you don't have one, the link won't do anything. Also, it will only run on the local Redis server. The attacker can't really choose where the exploit will happen.

    Look up Cross Site Request Forgery. https://en.wikipedia.org/wiki/Cross-site_request_forgery

    I understand this, but... a) Me clicking the link was optional, he could've run the AJAX request onload. b) Even without a vulnerability in Redis, he could've happily had run FLUSHALL, for example. c) *with* the vulnerability, he can probably escape sandboxes and do nasty stuff. Again, with a piece of JS that could run onload on any website... But that's not my point, the point is writing to local ports on my machine... Most developers have local Redis without passwords, and I'm sure they don't know browsing the web could clear their Redis DBs... I wonder how many other things like this I have

    There is a reason websites are not allowed to do stuff, like, for example, writing to your hard drive, or deleting files. It wouldn't be the website, it'd be you, running the code in the website, with your priviledges, so they could only access files you can access, but that doesn't quite mitigate it. In this case, "all they can do" is clean / write to my local Redis server. That sounds pretty bad on its own, but I wonder what other services I have running that you could write to and harm me in some way...

    I'm not sure what your question is then... You are correct, Cross Site Request Forgery could be a vulnerability in other services you run.

    There are things Redis could do that would ensure their server can't be cleaned or written to. Usually using nonces (random one time use numbers) that are required for each request/command to the server. The attacker won't be able to supply these from their script.

    This could also apply to an unsecured, local MySQL server, couldn't it? Couldn't someone write commands to MySQL using this same technique? (just using MySQL as an example)

    Yes, SQL injection could happen via Cross Site Request Forgery (CSRF), but it would require the MySQL server to be accessible via a web interface that can send commands to it. The attacker needs to find a way to get you to run a script that executes commands that you (the owner of the MySQL server) have access to. CSRF depends on a web application that has the ability to execute dangerous commands. If the web application can execute powerful MySQL commands, then that could be a problem.

    There are plenty of Web Applications with CSRF vulnerabilities such as: wordpress, drupal (known vulnerabilities get patched pretty quickly though)

    So if MySQL would require a web interface, why doesn't Redis need one?

    Oh, my bad. Web interface in terms of: The server is listening on certain ports, and responds to http requests, like get and post. It doesn't need to be graphical.

    Yeah, I got the non-graphical part. I just didn't know you could do HTTP requests to Redis, I thought it was plain text over TCP. Anyway, thanks for your answers!

    There are some wrong assumptions in this answer - have a look at my answer: https://security.stackexchange.com/a/232277/88501

    Indeed. This answer is completely wrong. The explanation grossly misunderstands the same origin policy and how this hotfix works.

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM