Skip to content

cntlm example

Alistair Michael edited this page Sep 6, 2023 · 1 revision

cntlm is an authentication proxy for Microsoft NTLM.

It is still reasonably widely-used, but has not been updated since 2013 https://sourceforge.net/projects/cntlm/.

Debian package popularity

The http_parse_basic method in http.c contains multiple errors we could detect through bounds checking and information flow through binary analysis.

/*
 * Parse headers for BASIC auth credentials
 *
 * Return 1 = creds parsed OK, 0 = no creds, -1 = invalid creds
 */
int http_parse_basic(hlist_t headers, const char *header, struct auth_s *tcreds) {
	char *tmp = NULL, *pos = NULL, *buf = NULL, *dom = NULL;
	int i;

	if (!hlist_subcmp(headers, header, "basic"))
		return 0;
        
	tmp = hlist_get(headers, header);
	buf = new(strlen(tmp) + 1);                       // buf = "domain\\userid:password"
	i = 5;
	while (i < strlen(tmp) && tmp[++i] == ' ');
	from_base64(buf, tmp+i);
	pos = strchr(buf, ':');

	if (pos == NULL) {
		memset(buf, 0, strlen(buf));		/* clean password memory */  // optimised out
		free(buf);
		return -1;
	} else {
		*pos = 0;                                          // strlen(buf) == strlen(user)
		dom = strchr(buf, '\\');
		if (dom == NULL) {
			auth_strcpy(tcreds, user, buf);
		} else {
			*dom = 0;                                  // strlen(buf) == strlen(domain)
			auth_strcpy(tcreds, domain, buf);
			auth_strcpy(tcreds, user, dom+1);
		}

		if (tcreds->hashntlm2) {
			tmp = ntlm2_hash_password(tcreds->user, tcreds->domain, pos+1);
			auth_memcpy(tcreds, passntlm2, tmp, 16);
			free(tmp);
		}

		if (tcreds->hashnt) {
			tmp = ntlm_hash_nt_password(pos+1);
			auth_memcpy(tcreds, passnt, tmp, 21);
			free(tmp);
		}

		if (tcreds->hashlm) {
			tmp = ntlm_hash_lm_password(pos+1);
			auth_memcpy(tcreds, passlm, tmp, 21);
			free(tmp);
		}

		memset(buf, 0, strlen(buf));      // optimised out         
		free(buf);
	}

	return 1;
}
Clone this wiki locally