Closed Bug 1763632 Opened 3 months ago Closed 2 months ago

connection reuse may route traffic to malicious servers

Categories

(Core :: Networking: HTTP, defect)

Firefox 98
defect

Tracking

()

RESOLVED INVALID

People

(Reporter: bjoern, Unassigned, NeedInfo)

References

()

Details

Attachments

(2 files)

Attached image ipv6-reuse-firefox.png

User Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:98.0) Gecko/20100101 Firefox/98.0

Steps to reproduce:

In this announcement https://lists.samba.org/archive/samba/2022-April/240285.html the Samba team linked a test site which revealed a bug with HTTP/2 connection reusing in Firefox. The site initially showed that IPv6 would be supported even though IPv6 was not available. The test site was extended then to show also the problem that Firefox has.

Actual results:

If you have a IPv4-only internet connection, then only a sad smiley should be shown. With current Firefox however, two sad smileys are displayed. The second smiley comes from a host that had only a IPv6 address, it's the same IPv6 address though that the host of the first sad smiley has, which has an IPv4 and IPv6 address assigned and where the IPv6 address is the same. So Firefox was sending the request for the IPv6-only host to the IPv4 address of the other host that has IPv4 and IPv6 addresses.

Expected results:

This is obviously a security issue.

Imagine this case: I'm a bad guy. I want to route your sensitive http traffic to my server. Your sensitive http traffic would go to a IPv6-only server usually. You don't have IPv6 now and I make you connect to my malicious site hacker.com, for which I put my own IPv4 and your sensitive site's IPv6 address in DNS. You will then send your sensitive site requests to my hacker.com server's IPv4 address.

I hope that no one wants to argue that this is not a problem because the TLS certificate of the server is then supposed to be non-matching. This should not the the only and final safety net here.

The Chrome engine does not expose the server request to the IPv4 server. Firefox should definitely also not do that.

(In reply to bjoern from comment #0)

With current Firefox however, two sad smileys are displayed. The second smiley comes from a host that had only a IPv6 address, it's the same IPv6 address though that the host of the first sad smiley has, which has an IPv4 and IPv6 address assigned and where the IPv6 address is the same. So Firefox was sending the request for the IPv6-only host to the IPv4 address of the other host that has IPv4 and IPv6 addresses.

I can't reproduce this - on an ipv4-only connection, only 1 sad smiley shows up, on both nightly and 99.0 (released earlier this week).

Can you reproduce on a clean profile? Can you provide an http log so as to share more details about what is happening, and/or more details about the specifics of how to reproduce this? (see https://firefox-source-docs.mozilla.org/networking/http/logging.html for docs on this)

(Edit: test site link so other triage folks don't have to search for it: https://ipv6-test.samba.org )

Flags: needinfo?(bjoern)
Group: core-security → network-core-security

FWIW, looks like the testcase reproduces with cloudflare / DoH, but not with my normal DNS provider. I'm not on the networking team but I expect an http log may still be helpful.

attached the requested log from a clean profile only with DoH enabled. I see the same without DoH enabled here though.

Attachment #9271344 - Attachment mime type: application/octet-stream → text/plain
Flags: needinfo?(bjoern)

I hope that no one wants to argue that this is not a problem because the TLS certificate of the server is then supposed to be non-matching. This should not the the only and final safety net here.

Right, I want to argue that Firefox will only coalesce connections when server's TLS certificate are matched, so I think this is not a security issue.

Another thing that triggers this issue is that we always resolve both A and AAAA address when using DoH. I think this is intended and we don't want to change this behavior.

Dragana, what do you think?

Flags: needinfo?(dd.mozilla)

as mentioned in comment 3, this is the same here with DoH disabled. I definetely consider "just" a connection attemp to a different server, as described in comment 0 (which is de facto a traffic rerouting to a malicious site) as a serious security issue.

I want to argue that Firefox will only coalesce connections when server's TLS certificate are matched, so I think this is not a security issue.

How does that work with "Virtual Hosting"? It's quite common to see certificates with a zillion names of unrelated entities presented by the server, and you are connect to the correct content by going through the whole handshake dance. "Having the same certificate" may mean they are hosted by the same entity, but that does not mean they are same-origin!

Status: UNCONFIRMED → NEW
Ever confirmed: true

Maybe I'm over-worried, but this sounds like a same-origin violation, although much easier to construct on purpose with cooperative domains (as in this case) than malicious in a real Virtual Hosting (mutually-mistrusting domain) situation, where usually all the hosts would be equally available (or not) over IPv4 and IPv6

Flags: needinfo?(kershaw)

(In reply to Daniel Veditz [:dveditz] from comment #7)

Maybe I'm over-worried, but this sounds like a same-origin violation, although much easier to construct on purpose with cooperative domains (as in this case) than malicious in a real Virtual Hosting (mutually-mistrusting domain) situation, where usually all the hosts would be equally available (or not) over IPv4 and IPv6

I think we do check the origin here, but I am not so familiar with that PSM code and not completely sure if that check could violate same-origin policy.

Dana, could you comment on this? Thanks.

Flags: needinfo?(kershaw) → needinfo?(dkeeler)

I think the same origin policy is orthogonal here. The origins are still distinct with respect to JS, the DOM, etc.. Unless I'm misunderstanding the situation, the question seems to be if it's valid to re-use a connection for a different domain than the one originally connected to. As far as I know, the answer is yes, as long as all of the same security checks that Firefox would make when making a new connection pass. To put it another way, if when connecting to a.com, a server presents a certificate that is valid for a.com and b.com, it would be valid to connect to that server when making a new connection to b.com. Consequently, it should be valid to re-use that connection to connect to b.com.

Flags: needinfo?(dkeeler)

Dana got it. This is something permitted by the specifications, though I believe that Firefox is unique in that it does not perform a DNS lookup for names that it has an open connection to (I don't know this code, but it could also be that it looks for a set intersection between the IP addresses it found for the host for which it made the connection and the IP addresses it found for the new host name; that would produce this effect also). This isn't completely non-contentious in that there are sites that don't like this aspect of what Firefox does, but it is not presently in violation of the specification.

This isn't a same-origin violation in that the origin assigned to the images is correct insofar as they each have a unique origin (the page doesn't use the crossorigin attribute on the image loads). I confirmed this with document.querySelector(".buggy-v6only-via-v4").crossOrigin = 'anonymous', which produces a CORS warning. So :dveditz, your caution - while sensible - isn't necessary; this isn't a SOP issue.

This really boils down to the site making an invalid assumption about how connections are managed, so this bug is invalid. (I can't clear the security flag, but I can remove the keywords.)

(I'll leave n-i for Dragana here, but to answer Kershaw's question about DoH, I agree that fetching both A and AAAA is a good idea, even if we can't use them presently. That might change.)

Status: NEW → RESOLVED
Closed: 2 months ago
Resolution: --- → INVALID

Violating the basic rules of the IP layer (sending packages to a different IP than the actual hostname points to) because a HTTP/2 document may be interpreted like this is fine to do looks like a really bad idea. Also assuming that trusting two servers in one site is secure and just distrusting two servers in different sites lokks like a dangerous assumption. Thinking security is not what this is. I'm slightly shocked reading the comments on this issue.

Group: network-core-security

Regarding

Right, I want to argue that Firefox will only coalesce connections when server's TLS certificate are matched, so I think this is not a security issue.

and

Dana got it. This is something permitted by the specifications, though I believe that Firefox is unique in that it does not perform a DNS lookup for names that it has an open connection to

I haven't tested it, but according to the bug description, Firefox might use an IP address for a server which is not provided in the DNS lookup. This violates the HTTP/2 specification, as far as I understand it. From section 9.1.1. Connection Reuse:

A connection can be reused as long as the origin server is authoritative (Section 10.1). For TCP connections without TLS, this depends on the host having resolved to the same IP address. For "https" resources, connection reuse additionally depends on having a certificate that is valid for the host in the URI.

Well, in this case, the host does not resolve to the IP address of the server. If you resolve the statement “as long as the origin server is authoritative”, you end up in the HTTP scheme specification of RFC7230. RFC7230 explicitly states “All of the requirements listed above for the "http" scheme are also requirements for the "https" scheme”, and “Note that the "https" URI scheme depends on both TLS and TCP for establishing authority.” You cannot tell me that sending an unencrypted HTTP request to the wrong server would be valid according to the HTTP specification, since this would be the consequence of your argumentation.

I'm seeing the same IP addresses on the different domains for this site:

ipv6-without-ipv4.samba.org. 0 IN AAAA 2a01:4f8:192:486::2:3

ipv6-test.samba.org. 0 IN AAAA 2a01:4f8:192:486::2:3

www.v6.samba.org. 0 IN CNAME www.samba.org.
www.samba.org. 0 IN CNAME hr2-3.samba.org.
hr2-3.samba.org. 0 IN AAAA 2a01:4f8:192:486::2:3

Maybe it is this one that you are having a problem with:

ipv6-only.samba.org. 0 IN AAAA 2a01:4f8:192:486::2:6663

I'm seeing the same IP addresses on the different domains for this site

The bug description states that the IPv6 addresses are the same. The problem is that Firefox sends requests for the IPv6-only host to the IPv4 address, i.e. to an address which is not valid for that domain.

I have also reproduced the issue with Firefox 100.0.2 while using a shared IPv4 address, instead of a shared IPv6 address. You can try it yourself at https://testvm1763632.johanness.dev/, but I may shut down the service in a few days or weeks. In my case, I have two domains which share one IPv4 address but have two different IPv6 addresses.

domain1: address0 (IPv4), address1 (IPv6)
domain2: address0 (IPv4), address2 (IPv6)

Lets assume I have a working IPv6 connection. If I send requests to domain1 and domain2 in that order, the second request – i.e. the request for domain2 – will be sent to address1. This violates the HTTP specification because address1 is not a valid endpoint for domain2.

For reference, here is the nginx configuration I have used in my setup:

server {
        listen [2a03:b0c0:3:d0::10f2:b00a]:443 ssl http2 ipv6only=on;
        server_name _;

        root /var/www/html;
        index test1.html;
        location / {
                try_files $uri $uri/ =404;
        }

        ssl_certificate /etc/letsencrypt/live/testvm1763632.johanness.dev/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/testvm1763632.johanness.dev/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
        listen [2a03:b0c0:3:d0::10f2:b00b]:443 ssl http2 ipv6only=on;
        server_name _;

        root /var/www/html;
        index test2.html;
        location / {
                try_files $uri $uri/ =404;
        }

        ssl_certificate /etc/letsencrypt/live/testvm1763632.johanness.dev/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/testvm1763632.johanness.dev/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
You need to log in before you can comment on or make changes to this bug.