Bug 280705 - 0.0.0.0/32 is equivalent to 127.0.0.1/32, which may be considered a security flaw
Summary: 0.0.0.0/32 is equivalent to 127.0.0.1/32, which may be considered a security ...
Status: Open
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Many People
Assignee: freebsd-net (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-08-09 14:27 UTC by Eirik Oeverby
Modified: 2024-09-03 14:56 UTC (History)
9 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Eirik Oeverby 2024-08-09 14:27:04 UTC
Looking at
https://github.com/freebsd/freebsd-src/blob/872164f559d2637f8de30fcd9da46d9b43d24328/sys/netinet/in_pcb.c#L1312-L1331
and confirming by testing, any listening port, no matter which interface it is on, will also accept connections on 0.0.0.0/32.

This has recently gained attention in the form of a "browser bug", where network sandboxing can be evaded (and remotely-loaded javascript can talk to any service running on the host).

The original code is from BSD4.3, and (guessing here) might be there because someone didn't want to wait for the tape with the localhost interface code - or was simply too lazy to type 127.0.0.1? :)
Comment 1 John Baldwin freebsd_committer freebsd_triage 2024-08-09 19:45:05 UTC
The change appears to have originated in BSD here: 
https://github.com/csrg/csrg/commit/86fd50f180107b5998a451da64dd08668499e9f9

The context of these changes is that at the time, the broadcast address appeared to be all zeroes, and this series of commits was creating separate INADDR_ANY and INADDR_BROADCAST.  Curiously, INADDR_ANY was previously blocked by the old code in in_pcbconnect:

https://github.com/csrg/csrg/commit/86fd50f180107b5998a451da64dd08668499e9f9#diff-947bd731f5c96a4641a584beac83dfcab5bac246a65cdba49fcf041bbb0ad5aeL111-R121

It does seem to be intentional, and the comment documenting it was added a month later in commit 125629be4b7de3a379dee96a625a272271c0bb87.  Given that it was an error before makes me wonder if this might have been intended as some sort of compatibility hack?

One of the other commits in this series is https://github.com/csrg/csrg/commit/b7aed1f9e438540acd1a66e07dd809fe8af34021 which added some similar logic in icmp_reflect().  That logic was later cleaned up a few months later in commit 36dd422b2b80fd43eb60c920c2494858cded07b8 to not depend on INADDR_ANY, and I believe that commit 02eb20c4604d7dad81aaa8cf7a96ef9f712f410d effectively blocked ICMP replies back to 0.0.0.0.

macOS Sonoma seems to also still support this behavior.

I do think just removing the block of code in question is sensible.
Comment 2 Eirik Oeverby 2024-08-09 22:00:09 UTC
Some rudimentary testing - on my own retro hardware and on copy.sh/v86/ - it seems that many OSes with IP stacks of BSD origin share this trait. Notable exceptions are OpenBSD and Windows 2000, but macOS, NetBSD, Haiku and others all do this. Even OS/2, at least versions 2.11 and 3.0 (both 16 and 32-bit TCP/IP stacks).

I can't think of a good reason to keep this now, but I'll leave that decision to people with more experience with obscure use cases. Perhaps hide it behind a compile-time option, default off?
Comment 3 paul vixie 2024-08-09 22:09:35 UTC
It certainly was intentional and I think documented. The first libresolv depended upon an uninitialized resaddr being the local host.
Comment 4 paul vixie 2024-08-09 22:09:56 UTC
It certainly was intentional and I think documented. The first libresolv depended upon an uninitialized resaddr being the local host.
Comment 5 Eirik Oeverby 2024-08-09 23:05:34 UTC
(In reply to paul vixie from comment #4)
I don't think that's a concern any longer, is it?
The reason I'm even reporting this as a bug (and not simply leaving it to browser vendors to fix since that's how this surfaced now) is how it completely blindsides anyone who might come across it, and I would not be surprised if a plethora of new attack vectors - having nothing to do with browsers - crop up in the near future. 

I don't have a firm understanding of how bad it might be, but it might be worth a security advisory. Then again, I might be seeing ghosts in broad daylight.

(Well, a ghost it is, I guess..)
Comment 6 paul vixie 2024-08-09 23:23:34 UTC
It has always been the case that if you bind to inaddr_any your socket will be available on all host interface addresses, and if you connect or sendto inaddr_any you'll reach some socket bound to some host interface address. In that sense yes this will be a breaking change. However, it's "good trouble" and we should follow openbsd's lead on the matter.
Comment 7 Mark Johnston freebsd_committer freebsd_triage 2024-08-09 23:49:35 UTC
It seems to me that the logical first step is to introduce a sysctl to control this behaviour.  Using that, we can see what breaks.

I posted a straw proposal here: https://reviews.freebsd.org/D46259
Comment 8 Eirik Oeverby 2024-08-10 11:05:16 UTC
(In reply to paul vixie from comment #6)
But this happens also if you do not; bind *only* to localhost, and it works. Bind *only* to some other interface, and it works.
Comment 9 Jamie Landeg-Jones 2024-08-10 14:20:08 UTC
(In reply to Eirik Oeverby from comment #8)

I tried this on 14.0-stable from March, and from my testing, it appears this does happen if you bind to 127.0.0.1, but not any other IP (even 127.0.0.2 aliased on lo0 didn't exhibit the behaviour)

IE bind to 127.0.0.1 allows connections to 0.0.0.0, but binding to anything else doesn't.

Still, I wouldn't have expected the bind to 127.0.0.1 to accept 0.0.0.0
Comment 10 Eirik Oeverby 2024-08-12 16:45:02 UTC
(In reply to Jamie Landeg-Jones from comment #9)
Apparently, I may have misread my own tests. I cannot reproduce other than with 127.0.0.1/0.0.0.0 now. Not sure what I was doing.

However, the original statement in the subject stands.
Comment 11 Jamie Landeg-Jones 2024-08-13 00:29:42 UTC
(In reply to Eirik Oeverby from comment #10)

> However, the original statement in the subject stands.

Yep, I agreed with you in my last sentence!
Comment 12 Gleb Smirnoff freebsd_committer freebsd_triage 2024-08-14 23:11:03 UTC
I also support idea of removing this whole block of code,
including the case for INADDR_BROADCAST as well.
Comment 13 commit-hook freebsd_committer freebsd_triage 2024-08-20 21:35:36 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=417b35a97b7669eb0bf417b43e97cccbedbce6f9

commit 417b35a97b7669eb0bf417b43e97cccbedbce6f9
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-08-20 21:31:57 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-08-20 21:31:57 +0000

    netinet: Add a sysctl to allow disabling connections to INADDR_ANY

    See the discussion in Bugzilla PR 280705 for context.

    PR:             280705
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D46259

 sys/netinet/in_pcb.c   |  8 +++++++-
 sys/netinet6/in6_pcb.c | 12 +++++++++++-
 2 files changed, 18 insertions(+), 2 deletions(-)
Comment 14 commit-hook freebsd_committer freebsd_triage 2024-09-03 14:56:06 UTC
A commit in branch stable/14 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=8ae58e0edbfb4c56125fb6d7468ebfea638847b9

commit 8ae58e0edbfb4c56125fb6d7468ebfea638847b9
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-08-20 21:31:57 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-09-03 14:54:42 +0000

    netinet: Add a sysctl to allow disabling connections to INADDR_ANY

    See the discussion in Bugzilla PR 280705 for context.

    PR:             280705
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D46259

    (cherry picked from commit 417b35a97b7669eb0bf417b43e97cccbedbce6f9)

 sys/netinet/in_pcb.c   |  8 +++++++-
 sys/netinet6/in6_pcb.c | 12 +++++++++++-
 2 files changed, 18 insertions(+), 2 deletions(-)