From f67994442a178545083343e43b9f3ddfac82fbde Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Wed, 18 Mar 2026 00:38:44 -0700 Subject: [PATCH] core: Reject oversized GET dns query parameter of DoH (#7926) * core: Reject oversized GET dns query parameter of DoH The DoH POST path limits request size using http.MaxBytesReader(..., 65536), but the GET path passes the dns query value directly to base64ToMsg() with no equivalent bound. This PR adds length check. Signed-off-by: Yong Tang * Fix Signed-off-by: Yong Tang --------- Signed-off-by: Yong Tang --- plugin/pkg/doh/doh.go | 8 +++++++- plugin/pkg/doh/doh_test.go | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/plugin/pkg/doh/doh.go b/plugin/pkg/doh/doh.go index e14c2ed28..f9f4e8df8 100644 --- a/plugin/pkg/doh/doh.go +++ b/plugin/pkg/doh/doh.go @@ -95,6 +95,9 @@ func requestToMsgPost(req *http.Request) (*dns.Msg, error) { return toMsg(req.Body) } +const maxDNSQuerySize = 65536 +const maxBase64Len = (maxDNSQuerySize*8 + 5) / 6 + // requestToMsgGet extract the dns message from the GET request. func requestToMsgGet(req *http.Request) (*dns.Msg, error) { values := req.URL.Query() @@ -105,11 +108,14 @@ func requestToMsgGet(req *http.Request) (*dns.Msg, error) { if len(b64) != 1 { return nil, fmt.Errorf("multiple 'dns' query values found") } + if len(b64[0]) > maxBase64Len { + return nil, fmt.Errorf("dns query too large") + } return base64ToMsg(b64[0]) } func toMsg(r io.ReadCloser) (*dns.Msg, error) { - buf, err := io.ReadAll(http.MaxBytesReader(nil, r, 65536)) + buf, err := io.ReadAll(http.MaxBytesReader(nil, r, maxDNSQuerySize)) if err != nil { return nil, err } diff --git a/plugin/pkg/doh/doh_test.go b/plugin/pkg/doh/doh_test.go index 047d0136d..2bdfd2d15 100644 --- a/plugin/pkg/doh/doh_test.go +++ b/plugin/pkg/doh/doh_test.go @@ -44,3 +44,26 @@ func TestDoH(t *testing.T) { }) } } + +func TestDoHGETRejectsOversizedDNSQuery(t *testing.T) { + // Exceeding max size 65536 + raw := make([]byte, 65536+1) + b64 := b64Enc.EncodeToString(raw) + + req, err := http.NewRequest( + http.MethodGet, + "https://example.org"+Path+"?dns="+b64, + nil, + ) + if err != nil { + t.Fatalf("failed to build request: %v", err) + } + + _, err = RequestToMsg(req) + if err == nil { + t.Fatalf("expected oversized GET dns query to be rejected") + } + if err.Error() != "dns query too large" { + t.Fatalf("expected %q, got %v", "dns query too large", err) + } +}