Skip to content
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

kv/memberlist: fix incorrect TCP transport host parsing #396

Merged
merged 8 commits into from
Oct 12, 2023

Conversation

kevinburkesegment
Copy link
Contributor

@kevinburkesegment kevinburkesegment commented Oct 9, 2023

Previously, if you passed "localhost" as the bind address for a TCPTransport, we would attempt to parse this as an IP address, fail, and then begin listening on 0.0.0.0.

This is a security issue since 0.0.0.0 binds to all interfaces, including public ones, while "localhost" is a shortcut for an IP address that is typically is only accessible from the local machine, not the wider Internet. A user who intended to bind only to the loopback interface might inadvertently expose a server to the public Internet.

Fix this by returning an error if you attempt to pass a BindAddr to TCPTransport that is not actually an IP address. Also, fix the tests to resolve "localhost" to an IP address before proceeding - typically, but not always, this is 127.0.0.1, which is why we try to parse the loopback address instead of hardcoding it.

I can confirm that on a Mac, with this patch applied I no longer get dialog boxes warning me that the tests are attempting to listen on 0.0.0.0.

Updates #381.

kv/memberlist/tcp_transport.go Show resolved Hide resolved
for {
select {
case <-start:
start = nil

// let's join the first member
if portToConnect > 0 {
_, err := kv.kv.JoinMembers([]string{fmt.Sprintf("127.0.0.1:%d", portToConnect)})
_, err := kv.kv.JoinMembers([]string{localhostIP.String() + fmt.Sprintf(":%d", portToConnect)})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likely going to be a conflict between this and the "join host port" PR, I will resolve once that is merged.

Copy link
Contributor

@charleskorn charleskorn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for spotting and fixing this @kevinburkesegment!

kv/memberlist/memberlist_client_test.go Outdated Show resolved Hide resolved
kv/memberlist/tcp_transport.go Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
Previously, if you passed "localhost" as the bind address for a
TCPTransport, we would attempt to parse this as an IP address,
fail, and then begin listening on 0.0.0.0.

This is a security issue since 0.0.0.0 binds to all interfaces,
including public ones, while "localhost" is a shortcut for an IP
address that is typically is only accessible from the local machine,
not the wider Internet.

Fix this by returning an error if you attempt to pass a BindAddr to
TCPTransport that is not actually an IP address. Also, fix the tests
to resolve "localhost" to an IP address before proceeding - typically,
but not always, this is 127.0.0.1, which is why we try to parse the
loopback address instead of hardcoding it.

I can confirm that on a Mac, with this patch applied I no longer get
dialog boxes warning me that the tests are attempting to listen on
0.0.0.0.

Updates grafana#381.
kevinburkesegment and others added 3 commits October 9, 2023 23:33
Co-authored-by: Charles Korn <charleskorn@users.noreply.github.com>
Comment on lines 102 to 108
if err == nil {
t.Fatal("expected non-nil err, got nil")
}
want := `could not parse bind addr "localhost" as IP address`
if err.Error() != want {
t.Fatalf("NewTCPTransport with non-IP address BindAddr: got %v, want %v", err, want)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use the require package in other tests to make assertions like these.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

kv/memberlist/memberlist_client_test.go Outdated Show resolved Hide resolved
Comment on lines 102 to 103
require.Error(t, err)
require.Equal(t, err.Error(), `could not parse bind addr "localhost" as IP address`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to simplify this even further:

Suggested change
require.Error(t, err)
require.Equal(t, err.Error(), `could not parse bind addr "localhost" as IP address`)
require.EqualError(t, err, `could not parse bind addr "localhost" as IP address`)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@charleskorn charleskorn merged commit 3b80e3b into grafana:main Oct 12, 2023
2 checks passed
@charleskorn
Copy link
Contributor

Thanks @kevinburkesegment!

ying-jeanne pushed a commit that referenced this pull request Nov 2, 2023
* kv/memberlist: fix incorrect TCP transport host parsing

Previously, if you passed "localhost" as the bind address for a
TCPTransport, we would attempt to parse this as an IP address,
fail, and then begin listening on 0.0.0.0.

This is a security issue since 0.0.0.0 binds to all interfaces,
including public ones, while "localhost" is a shortcut for an IP
address that is typically is only accessible from the local machine,
not the wider Internet.

Fix this by returning an error if you attempt to pass a BindAddr to
TCPTransport that is not actually an IP address. Also, fix the tests
to resolve "localhost" to an IP address before proceeding - typically,
but not always, this is 127.0.0.1, which is why we try to parse the
loopback address instead of hardcoding it.

I can confirm that on a Mac, with this patch applied I no longer get
dialog boxes warning me that the tests are attempting to listen on
0.0.0.0.

Updates #381.

* kv/memberlist: add test for IP address rejection

* Update CHANGELOG.md

Co-authored-by: Charles Korn <charleskorn@users.noreply.github.com>

* fix more tests

* rework sync.Once usage

* use require instead of manual tests

* require.EqualError

* require.Error no longer necessary

---------

Co-authored-by: Charles Korn <charleskorn@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants