mirror of
https://github.com/mattermost/mattermost.git
synced 2026-05-28 04:35:04 -04:00
server/utils: verify trusted ip headers are valid ip addresses (#23140)
Co-authored-by: Ibrahim Serdar Acikgoz <ibrahim@ibrahims-mac.local>
This commit is contained in:
parent
96b537167c
commit
b2e0aa7088
2 changed files with 127 additions and 97 deletions
|
|
@ -107,16 +107,15 @@ func GetIPAddress(r *http.Request, trustedProxyIPHeader []string) string {
|
|||
}
|
||||
}
|
||||
|
||||
if address != "" {
|
||||
if address != "" && net.ParseIP(address) != nil {
|
||||
return address
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if address == "" {
|
||||
address, _, _ = net.SplitHostPort(r.RemoteAddr)
|
||||
}
|
||||
host, _, _ := net.SplitHostPort(r.RemoteAddr)
|
||||
|
||||
return address
|
||||
return host
|
||||
}
|
||||
|
||||
func GetHostnameFromSiteURL(siteURL string) string {
|
||||
|
|
|
|||
|
|
@ -50,119 +50,150 @@ func TestStringSliceDiff(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetIPAddress(t *testing.T) {
|
||||
// Test with a single IP in the X-Forwarded-For
|
||||
httpRequest1 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.0.0.1"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
t.Run("Single IP in the X-Forwarded-For", func(t *testing.T) {
|
||||
httpRequest1 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.0.0.1"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.0.0.1", GetIPAddress(&httpRequest1, []string{"X-Forwarded-For"}))
|
||||
assert.Equal(t, "10.0.0.1", GetIPAddress(&httpRequest1, []string{"X-Forwarded-For"}))
|
||||
})
|
||||
|
||||
// Test with multiple IPs in the X-Forwarded-For
|
||||
httpRequest2 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.0.0.1, 10.0.0.2, 10.0.0.3"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
t.Run("Multiple IPs in the X-Forwarded-For", func(t *testing.T) {
|
||||
httpRequest2 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.0.0.1, 10.0.0.2, 10.0.0.3"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.0.0.1", GetIPAddress(&httpRequest2, []string{"X-Forwarded-For"}))
|
||||
assert.Equal(t, "10.0.0.1", GetIPAddress(&httpRequest2, []string{"X-Forwarded-For"}))
|
||||
})
|
||||
|
||||
// Test with an empty X-Forwarded-For
|
||||
httpRequest3 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{""},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
t.Run("Empty X-Forwarded-For", func(t *testing.T) {
|
||||
httpRequest3 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{""},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.1.0.1", GetIPAddress(&httpRequest3, []string{"X-Forwarded-For", "X-Real-Ip"}))
|
||||
assert.Equal(t, "10.1.0.1", GetIPAddress(&httpRequest3, []string{"X-Forwarded-For", "X-Real-Ip"}))
|
||||
})
|
||||
|
||||
// Test without an X-Forwarded-For
|
||||
httpRequest4 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
t.Run("Without an X-Forwarded-For", func(t *testing.T) {
|
||||
httpRequest4 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.1.0.1", GetIPAddress(&httpRequest4, []string{"X-Forwarded-For", "X-Real-Ip"}))
|
||||
assert.Equal(t, "10.1.0.1", GetIPAddress(&httpRequest4, []string{"X-Forwarded-For", "X-Real-Ip"}))
|
||||
})
|
||||
|
||||
// Test without any headers
|
||||
httpRequest5 := http.Request{
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
t.Run("Without any headers", func(t *testing.T) {
|
||||
httpRequest5 := http.Request{
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.2.0.1", GetIPAddress(&httpRequest5, []string{"X-Forwarded-For", "X-Real-Ip"}))
|
||||
assert.Equal(t, "10.2.0.1", GetIPAddress(&httpRequest5, []string{"X-Forwarded-For", "X-Real-Ip"}))
|
||||
})
|
||||
|
||||
// Test with both headers, but both untrusted
|
||||
httpRequest6 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
t.Run("Two headers, but both untrusted", func(t *testing.T) {
|
||||
httpRequest6 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.2.0.1", GetIPAddress(&httpRequest6, nil))
|
||||
assert.Equal(t, "10.2.0.1", GetIPAddress(&httpRequest6, nil))
|
||||
})
|
||||
|
||||
// Test with both headers, but only X-Real-Ip trusted
|
||||
httpRequest7 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
t.Run("Two headers, but only X-Real-Ip trusted", func(t *testing.T) {
|
||||
httpRequest7 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.1.0.1", GetIPAddress(&httpRequest7, []string{"X-Real-Ip"}))
|
||||
assert.Equal(t, "10.1.0.1", GetIPAddress(&httpRequest7, []string{"X-Real-Ip"}))
|
||||
})
|
||||
|
||||
// Test with X-Forwarded-For, comma separated, untrusted
|
||||
httpRequest8 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1, 10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
t.Run("X-Forwarded-For, comma separated, untrusted", func(t *testing.T) {
|
||||
httpRequest8 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1, 10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.2.0.1", GetIPAddress(&httpRequest8, nil))
|
||||
assert.Equal(t, "10.2.0.1", GetIPAddress(&httpRequest8, nil))
|
||||
})
|
||||
|
||||
// Test with X-Forwarded-For, comma separated, untrusted
|
||||
httpRequest9 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1, 10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
t.Run("X-Forwarded-For, comma separated, untrusted", func(t *testing.T) {
|
||||
httpRequest9 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1, 10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.3.0.1", GetIPAddress(&httpRequest9, []string{"X-Forwarded-For"}))
|
||||
assert.Equal(t, "10.3.0.1", GetIPAddress(&httpRequest9, []string{"X-Forwarded-For"}))
|
||||
})
|
||||
|
||||
// Test with both headers, both allowed, first one in trusted used
|
||||
httpRequest10 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
t.Run("Two headers, both allowed, first one in trusted used", func(t *testing.T) {
|
||||
httpRequest10 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.3.0.1"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.1.0.1", GetIPAddress(&httpRequest10, []string{"X-Real-Ip", "X-Forwarded-For"}))
|
||||
assert.Equal(t, "10.1.0.1", GetIPAddress(&httpRequest10, []string{"X-Real-Ip", "X-Forwarded-For"}))
|
||||
})
|
||||
|
||||
// Test with multiple IPs in the X-Forwarded-For with no spaces
|
||||
httpRequest11 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.0.0.1,10.0.0.2,10.0.0.3"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
t.Run("Multiple IPs in the X-Forwarded-For with no spaces", func(t *testing.T) {
|
||||
httpRequest11 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"10.0.0.1,10.0.0.2,10.0.0.3"},
|
||||
"X-Real-Ip": []string{"10.1.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.0.0.1", GetIPAddress(&httpRequest11, []string{"X-Forwarded-For"}))
|
||||
assert.Equal(t, "10.0.0.1", GetIPAddress(&httpRequest11, []string{"X-Forwarded-For"}))
|
||||
})
|
||||
|
||||
t.Run("Make sure that the parsed value from headers only accept IP Addresses", func(t *testing.T) {
|
||||
httpRequest12 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"127.0.0.1"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "127.0.0.1", GetIPAddress(&httpRequest12, []string{"X-Forwarded-For"}))
|
||||
|
||||
httpRequest13 := http.Request{
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": []string{"localhost"},
|
||||
},
|
||||
RemoteAddr: "10.2.0.1:12345",
|
||||
}
|
||||
|
||||
assert.Equal(t, "10.2.0.1", GetIPAddress(&httpRequest13, []string{"X-Forwarded-For"}))
|
||||
})
|
||||
}
|
||||
|
||||
func TestRemoveStringFromSlice(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue