-
-
Notifications
You must be signed in to change notification settings - Fork 29.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Security issue, unauthorized trusted access by spoofing x-forwarded-for header #14345
Comments
This used to work (last known working version 0.62)...but after upgrading recently and checking it in the latest dev version I can confirm that it is an issue |
The thing is that I didnt even hacked the headers and still no password is asked when connecting from external network |
@rofrantz if you are not spoofing the headers then I believe you are having a different issue. |
I use nginx as reverse proxy |
Do you have |
|
I made several tests in the past with different configurations, Here are the results: Test 1: use_x_forwarded_for: True Test2: Test3: I would avoid using the trusted networks configuration when exposing HA to the internet (specially when using reverse proxy) |
But it used to work and I had the same network setup :(((( |
Proposed solution: In https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/http/real_ip.py#L22 , change
to
A more complete solution would be to allow the user to specify, in the configuration, which index (from the end) in the X-Forwarded-For header to use. This will also allow cases where there are two or more reverse proxies inline. Such a use case requires deep understanding of reverse proxies. |
What's the difference between Test2 and Test3? The are booth the same as At the moment I don't see how replacing the client's source IP with the IP address of the last proxy in the chain would increase the security. The requests are coming from the proxy anyway. Usually the proxy is in the trustworthy network environment but not the client if we are talking about external access from the outside. At first glance it looks like it would get even worse. Also, the implication about using |
@fabaff Where is it documented properly? It looks like most people that use reverse proxy are not aware of this documentation, browsing some sample users configurations on the HA forums shows that this configuration is enabled and that they have no clue they are exposed to auth bypass. Here's an example: https://community.home-assistant.io/t/my-home-assistant-configuration-it-s-alive/52670/7 |
I can confirm this issue as well. The solution @ayavilevich suggested would work, but - as noted - will have some problems when multiple proxies are chained together (either by design or as part of an attack). As a workaround for the simplest setup with only one proxy, you can change your nginx config as below: |
Like here. To reproduce it with no proxy: http:
api_password: !secret http_password
trusted_networks:
- 192.168.100.0/24
use_x_forwarded_for: false $ curl http://192.168.0.1:8123/api/
401: Unauthorized http:
api_password: !secret http_password
trusted_networks:
- 192.168.100.0/24
use_x_forwarded_for: true $ curl http://192.168.0.1:8123/api/
401: Unauthorized
$ curl --header "X-Forwarded-For: 192.168.0.1" http://192.168.0.242:8123/api/
401: Unauthorized
$ curl --header "X-Forwarded-For: 192.168.100.1" http://192.168.0.1:8123/api/
{"message": "API running."} |
@fabaff I think you are missing the point, This is not documented properly, Properly is BIG BOLD RED WARNING MESSAGE explaining the DANGER of using trusted networks with reverse proxy and the risk. "Therefore in a reverse proxy scenario, this option should be used with extreme care." or " You should only enable this in a trustworthy network environment" for standard users is not clear what is "extreme care" ? what is a "trustworthy network environment" ? Not explaining the security risks PROPERLY to users in the age of "Cyber" is making them vulnerable targets. |
Feel free to improve the formatting or wording. But bigger warnings usually bring nothing because people tend to ignore them anyway. A "regular/standard" user will never setup a reverse proxy. It's too much work and just enabling port forwarding is easier. For the advance users we need to assume that they know what they are doing and understand the description of the configuration entries. Till now this was the case as there were no complains about that. |
There's also the people who tend to find some guide or howto on the internet and adapt it to their needs until it works. Those are the people who don't dive into the official docs and read every word written about the options they are enabling. |
Happy to explain further. LMK if I am understanding your terminology correctly: The current implementation takes an IP address from the header which it assumes is coming from a trusted proxy however due to a bug it is not a trusted IP address and can be spoofed. Therefore the current implementation allows for authentication bypass (under some conditions described above). If you agree to this base understanding then it is clear that fixing this will increase the security. I understand that there are warnings in the documentation, but the current situation prevents even a person who is an experienced network engineer from setting up a proper secure configuration. So no amount of knowledge or reading of the warnings will be an alternative to fixing this bug if a person wishes to use proper reverse proxy networking. I don't see how it would get worse. Please provide a use case so we can discuss. If needed I can provide use case for the current state and suggested solution. |
Wow, this is a nasty flaw. The current implementation of
It is extremely important that the I'll create a pull request with a potential implementation to resolve this issue, along with a PR to the docs explaining the change. |
I have submitted #15182 as a potential solution to this issue. @ayavilevich if you'd be able to review my approach (and possibly help test it) I'd greatly appreciate it! As a short-term alternative, I have also submitted home-assistant/home-assistant.io#5617 to help further prevent users from using this setting without understanding it. |
Some PRs were made to resolve this. Thanks to everybody who did. @colinodell People report unauthorized access which could be due to this vulnerability. I know it only affects a minority of the users, but it is critical nevertheless Test cases:Glosaryuse_x_forwarded_for - config, should we look at the header at all, false by default for most users Note case 1a - no use_x_forwarded_foruse_x_forwarded_for: false case 1b - no use_x_forwarded_for with spoof or proxyuse_x_forwarded_for: false case 2a - use_x_forwarded_for, normal case with proxyuse_x_forwarded_for: true case 2b - use_x_forwarded_for, spoof case, no proxyuse_x_forwarded_for: true case 3a - use_x_forwarded_for, spoof case, proxy that chains ipsuse_x_forwarded_for: true case 3b - use_x_forwarded_for, spoof case, proxy that replaces ipsuse_x_forwarded_for: true case 4a - use_x_forwarded_for, double proxy setupuse_x_forwarded_for: true case 4b - use_x_forwarded_for, double proxy setup, one trusteduse_x_forwarded_for: true |
Home Assistant release with the issue:
0.68.1 but probably older versions too
Last working Home Assistant release (if known):
N/A
Operating environment (Hass.io/Docker/Windows/etc.):
Hassbian but should be applicable to other deployment methods
Component/platform:
http
Description of problem:
There is a bug in HA that in certain conditions will allow a person to spoof a trusted source address and bypass password authentication.
Conditions:
Use case:
Attacker adds a spoofed x-forwarded-for header with an IP that is in the trusted list. HA grants access without asking for a password.
Cause:
https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/http/real_ip.py#L22
Uses the first IP in the header which can be spoofed.
Only the last IP in the header is guaranteed to be non-spoofed assuming a valid reverse proxy is in place.
https://en.wikipedia.org/wiki/X-Forwarded-For : Format :
“where the value is a comma+space separated list of IP addresses, the left-most being the original client, and each successive proxy that passed the request adding the IP address where it received the request from. In this example, the request passed through proxy1, proxy2, and then proxy3 (not shown in the header). proxy3 appears as remote address of the request.
Since it is easy to forge an X-Forwarded-For field the given information should be used with care. The last IP address is always the IP address that connects to the last proxy, which means it is the most reliable source of information. X-Forwarded-For data can be used in a forward or reverse proxy scenario.”
Problem-relevant
configuration.yaml
entries and (fill out even if it seems unimportant):Traceback (if applicable):
Additional information:
Work around: Disable trusted_network setting, remove reverse proxy or limit network access to authorized individuals only.
Problem first noticed first by https://community.home-assistant.io/u/NightRanger . Reference: https://community.home-assistant.io/t/trusted-networks-and-x-forwarded-for/20850
I would issue a PR but I don’t have the right environment to test this. Hopefully somebody who uses this setup can apply the fix and test it.
The text was updated successfully, but these errors were encountered: