Skip to content

Commit 074037a

Browse files
dschoGit for Windows Build Agent
authored andcommitted
http: disallow NTLM authentication by default
NTLM authentication is relatively weak. This is the case even with the default setting of modern Windows versions, where NTLMv1 and LanManager are disabled and only NTLMv2 is enabled: NTLMv2 hashes of even reasonably complex 8-character passwords can be broken in a matter of days, given enough compute resources. Even worse: On Windows, NTLM authentication uses Security Support Provider Interface ("SSPI"), which provides the credentials without requiring the user to type them in. Which means that an attacker could talk an unsuspecting user into cloning from a server that is under the attacker's control and extracts the user's NTLMv2 hash without their knowledge. For that reason, let's disallow NTLM authentication by default. NTLM authentication is quite simple to set up, though, and therefore there are still some on-prem Azure DevOps setups out there whose users and/or automation rely on this type of authentication. To give them an escape hatch, introduce the `http.<url>.allowNTLMAuth` config setting that can be set to `true` to opt back into using NTLM for a specific remote repository. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 14254d0 commit 074037a

3 files changed

Lines changed: 25 additions & 6 deletions

File tree

Documentation/config/http.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,11 @@ http.sslKeyType::
231231
See also libcurl `CURLOPT_SSLKEYTYPE`. Can be overridden by the
232232
`GIT_SSL_KEY_TYPE` environment variable.
233233

234+
http.allowNTLMAuth::
235+
Whether or not to allow NTLM authentication. While very convenient to set
236+
up, and therefore still used in many on-prem scenarios, NTLM is a weak
237+
authentication method and therefore deprecated. Defaults to "false".
238+
234239
http.schannelCheckRevoke::
235240
Used to enforce or disable certificate revocation checks in cURL
236241
when http.sslBackend is set to "schannel". Defaults to `true` if

http.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ enum http_follow_config http_follow_config = HTTP_FOLLOW_INITIAL;
131131

132132
static struct credential cert_auth = CREDENTIAL_INIT;
133133
static int ssl_cert_password_required;
134-
static unsigned long http_auth_methods = CURLAUTH_ANY;
134+
static unsigned long http_auth_any = CURLAUTH_ANY & ~CURLAUTH_NTLM;
135+
static unsigned long http_auth_methods;
135136
static int http_auth_methods_restricted;
136137
/* Modes for which empty_auth cannot actually help us. */
137138
static unsigned long empty_auth_useless =
@@ -430,6 +431,15 @@ static int http_options(const char *var, const char *value,
430431
return 0;
431432
}
432433

434+
if (!strcmp("http.allowntlmauth", var)) {
435+
if (git_config_bool(var, value)) {
436+
http_auth_any |= CURLAUTH_NTLM;
437+
} else {
438+
http_auth_any &= ~CURLAUTH_NTLM;
439+
}
440+
return 0;
441+
}
442+
433443
if (!strcmp("http.schannelcheckrevoke", var)) {
434444
http_schannel_check_revoke = git_config_bool(var, value);
435445
return 0;
@@ -726,11 +736,11 @@ static void init_curl_proxy_auth(CURL *result)
726736
if (i == ARRAY_SIZE(proxy_authmethods)) {
727737
warning("unsupported proxy authentication method %s: using anyauth",
728738
http_proxy_authmethod);
729-
curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
739+
curl_easy_setopt(result, CURLOPT_PROXYAUTH, http_auth_any);
730740
}
731741
}
732742
else
733-
curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
743+
curl_easy_setopt(result, CURLOPT_PROXYAUTH, http_auth_any);
734744
}
735745

736746
static int has_cert_password(void)
@@ -1077,7 +1087,7 @@ static CURL *get_curl_handle(void)
10771087
}
10781088

10791089
curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
1080-
curl_easy_setopt(result, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
1090+
curl_easy_setopt(result, CURLOPT_HTTPAUTH, http_auth_any);
10811091

10821092
#ifdef CURLGSSAPI_DELEGATION_FLAG
10831093
if (curl_deleg) {
@@ -1465,6 +1475,8 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
14651475
set_long_from_env(&http_max_retries, "GIT_HTTP_MAX_RETRIES");
14661476
set_long_from_env(&http_max_retry_time, "GIT_HTTP_MAX_RETRY_TIME");
14671477

1478+
http_auth_methods = http_auth_any;
1479+
14681480
curl_default = get_curl_handle();
14691481
}
14701482

t/t5563-simple-http-auth.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -804,8 +804,10 @@ test_expect_success NTLM 'access using NTLM auth' '
804804
EOF
805805
806806
test_config_global credential.helper test-helper &&
807-
GIT_TRACE_CURL=1 \
808-
git ls-remote "$HTTPD_URL/ntlm_auth/repo.git"
807+
test_must_fail env GIT_TRACE_CURL=1 git \
808+
ls-remote "$HTTPD_URL/ntlm_auth/repo.git" &&
809+
GIT_TRACE_CURL=1 git -c http.$HTTPD_URL.allowNTLMAuth=true \
810+
ls-remote "$HTTPD_URL/ntlm_auth/repo.git"
809811
'
810812

811813
test_done

0 commit comments

Comments
 (0)