Skip to content

Commit

Permalink
packetbeat/protos/http: don't panic when host is empty
Browse files Browse the repository at this point in the history
Previously, extractHostHeader would panic if the host part of header was
empty. Avoid this by using standard library functions to do splits and
clean up IPv6 addresses.

Add tests to confirm old behaviour and test to cover panic case.
  • Loading branch information
efd6 committed Sep 5, 2023
1 parent ffae391 commit 6325774
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ https://github.com/elastic/beats/compare/v8.8.1\...main[Check the HEAD diff]

*Packetbeat*

- Fix panic in HTTP protocol parsing when host header has empty host part. {issue}36497[36497] {issue}36518[36518]

*Winlogbeat*

Expand Down
20 changes: 10 additions & 10 deletions packetbeat/protos/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -735,20 +735,20 @@ func parseCookieValue(raw string) string {
}

func extractHostHeader(header string) (host string, port int) {
if len(header) == 0 || net.ParseIP(header) != nil {
if header == "" || net.ParseIP(header) != nil {
return header, port
}
// Split :port trailer
if pos := strings.LastIndexByte(header, ':'); pos != -1 {
if num, err := strconv.Atoi(header[pos+1:]); err == nil && num > 0 && num < 65536 {
header, port = header[:pos], num
}
host, ps, err := net.SplitHostPort(header)
if err != nil {
return header, port
}
// Remove square bracket boxing of IPv6 address.
if last := len(header) - 1; header[0] == '[' && header[last] == ']' && net.ParseIP(header[1:last]) != nil {
header = header[1:last]
host = strings.TrimPrefix(host, "[")
host = strings.TrimSuffix(host, "]")
pi, err := strconv.ParseInt(ps, 10, 16)
if err != nil || pi == 0 {
return header, port
}
return header, port
return host, int(pi)
}

func (http *httpPlugin) hideHeaders(m *message) {
Expand Down
25 changes: 25 additions & 0 deletions packetbeat/protos/http/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1901,6 +1901,31 @@ func TestHttpParser_Extension(t *testing.T) {
}
}

func TestExtractHostHeader(t *testing.T) {
tests := []struct {
header string
wantHost string
wantPort int
}{
{header: "", wantHost: "", wantPort: 0},
{header: "localhost:0", wantHost: "localhost:0", wantPort: 0},
{header: "localhost:9001", wantHost: "localhost", wantPort: 9001},
{header: "localhost:9000000", wantHost: "localhost:9000000", wantPort: 0},
{header: "127.0.0.1:9001", wantHost: "127.0.0.1", wantPort: 9001},
{header: "[::]:9001", wantHost: "::", wantPort: 9001},
{header: ":9001", wantHost: "", wantPort: 9001},
}
for _, test := range tests {
host, port := extractHostHeader(test.header)
if host != test.wantHost {
t.Errorf("unexpected host for %q: got:%q want:%q", test.header, host, test.wantHost)
}
if port != test.wantPort {
t.Errorf("unexpected port for %q: got:%d want:%d", test.header, port, test.wantPort)
}
}
}

func benchmarkHTTPMessage(b *testing.B, data []byte) {
http := httpModForTests(nil)
parser := newParser(&http.parserConfig)
Expand Down

0 comments on commit 6325774

Please sign in to comment.