From 30d359083fee84642cce7dccaf8bf9ec54fbd669 Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Sat, 11 Jul 2020 07:30:55 -0700 Subject: [PATCH] bin/git-http-backend-verify: scrutinize /info/refs query string According to RFC 3986 section 2.3 "Unreserved Characters", characters in the unreserved range (i.e matches [A-Za-z0-9._~-]) should not be percent encoded by producers and when found percent encoded, should be decoded back to the corresponding unreserved character. Although Git's `git-http-backend` *does* decode any percent-encoded characters it finds in either the name and/or value of parameters in the query string, the much simpler `git-http-backend-verify` script does not. Furthermore, the only accepted and understood query strings (and then only when the URL ends with "/info/refs") are: 1) service=git-upload-pack 2) service=git-receive-pack Each of these potential query string values consists only of "unreserved" characters and therefore should never contain any percent-encoded characters. Although `git-http-backend` does tolerate additional parameters in the query string (that are ignored) and `git-http-backend-verify` also tolerates extra, ignored parameters in the query string, none are currently defined. Therefore, reject any query strings provided for "GET" or "HEAD" and a path ending in "/info/refs" that contain a "%" character. Sending either of the accepted "service" parameters using any percent-encoded characters could only be a request from a bad actor and would be interpreted as a non-smart request by the `git-http-backend-verify` script (unless the server software properly normalizes the incoming URL before processing it). By explicitly rejecting such query strings for GET/HEAD requests (those with a path ending in /info/refs and a query string containing a "%" character), the client's incorrect behavior gets flagged immediately rather than attempting to process the request as a non-smart request which could precipitate difficult to diagnose problems. It's worth noting that one particularly well-known and very popular Git repository hosting provider accepts exactly only "service=git-upload-pack" or "service=git-receive-pack" as the query string for ".../info/refs" requests and rejects anything else including any percent encodings and or extra parameters. Signed-off-by: Kyle J. McKay --- bin/git-http-backend-verify | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/bin/git-http-backend-verify b/bin/git-http-backend-verify index ba19dd3..cb0523d 100755 --- a/bin/git-http-backend-verify +++ b/bin/git-http-backend-verify @@ -90,6 +90,14 @@ internalerr() exit 0 } +badrequest() +{ + errorhdrs 400 "Bad Request" + [ $# -gt 0 ] || set -- "Bad Request" + msglines "$@" + exit 0 +} + methodnotallowed() { errorhdrs 405 "Method Not Allowed" "Allow: GET,HEAD,POST" @@ -198,6 +206,13 @@ if [ "$REQUEST_METHOD" = "GET" ] || [ "$REQUEST_METHOD" = "HEAD" ]; then *"/info/refs") proj="${pathcheck%/info/refs}" case "&$QUERY_STRING&" in + *"%"*) + # we reject any requests with url-encoded characters + # in the QUERY_STRING as a precaution since they should + # never be required for either supported request type + badrequest "invalid query string" + exit 1 + ;; *"&service=git-receive-pack&"*) smart=1 needsauthcheck=1 -- 2.11.4.GIT