1 /*
2 **   VNC Password Checking Medusa Module
3 **
4 **   ------------------------------------------------------------------------
5 **    Copyright (C) 2011 Joe Mondloch
6 **    JoMo-Kun / jmk@foofus.net
7 **
8 **    This program is free software; you can redistribute it and/or modify
9 **    it under the terms of the GNU General Public License version 2,
10 **    as published by the Free Software Foundation
11 **
12 **    This program is distributed in the hope that it will be useful,
13 **    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 **    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 **    GNU General Public License for more details.
16 **
17 **    http://www.gnu.org/licenses/gpl.txt
18 **
19 **    This program is released under the GPL with the additional exemption
20 **    that compiling, linking, and/or using OpenSSL is allowed.
21 **
22 **   ------------------------------------------------------------------------
23 **
24 **   Based on code from:
25 **      VNCrack [FX/Phenolite]
26 **      RealVNC (VNC Server 4 -- FREE)
27 **      UltraVNC 1.0.9.6.1
28 **
29 **   Supports: password-less VNC, password-only VNC and UltraVNC MS-Logon
30 */
31 
32 #include <sys/types.h>
33 #include <libgen.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include "module.h"
38 #include "d3des.h"
39 
40 #define MODULE_NAME    "vnc.mod"
41 #define MODULE_AUTHOR  "JoMo-Kun <jmk@foofus.net>"
42 #define MODULE_SUMMARY_USAGE  "Brute force module for VNC sessions"
43 #define MODULE_VERSION    "2.1"
44 #define MODULE_VERSION_SVN "$Id: vnc.c 9217 2015-05-07 18:07:03Z jmk $"
45 #define MODULE_SUMMARY_FORMAT  "%s : version %s"
46 #define MODULE_SUMMARY_FORMAT_WARN  "%s : version %s (%s)"
47 #define OPENSSL_WARNING "No usable OPENSSL. Module disabled."
48 
49 #ifdef HAVE_LIBSSL
50 
51 #include <openssl/dh.h>
52 
53 #define PORT_VNC 5900
54 #define CHALLENGE_SIZE 16
55 
56 #define SESSION_SUCCESS 1
57 #define SESSION_FAILURE 2
58 #define SESSION_SUCCESS_NO_AUTH 3
59 #define SESSION_MAX_AUTH_REALVNC 4
60 #define SESSION_MAX_AUTH_ULTRAVNC 5
61 
62 #define AUTH_VNC 1
63 #define AUTH_UVNC_MSLOGIN 2
64 
65 typedef struct __VNC_DATA {
66   int nMaxAuthSleep;
67   int nAuthType;
68   unsigned char* szChallenge;
69   char* szDomain;
70 } _VNC_DATA;
71 
72 // Tells us whether we are to continue processing or not
73 enum MODULE_STATE
74 {
75   MSTATE_NEW,
76   MSTATE_RUNNING,
77   MSTATE_EXITING,
78   MSTATE_COMPLETE
79 };
80 
81 // Forward declarations
82 int tryLogin(int hSocket, sLogin** login, _VNC_DATA* _psSessionData, char* szLogin, char* szPassword);
83 int initModule(sLogin* login, _VNC_DATA *_psSessionData);
84 int vncSessionSetup(int hSocket, _VNC_DATA *_psSessionData);
85 
86 // Tell medusa how many parameters this module allows
getParamNumber()87 int getParamNumber()
88 {
89   return 0;    // we don't need no stinking parameters
90 }
91 
92 // Displays information about the module and how it must be used
summaryUsage(char ** ppszSummary)93 void summaryUsage(char **ppszSummary)
94 {
95   // Memory for ppszSummary will be allocated here - caller is responsible for freeing it
96   int  iLength = 0;
97 
98   if (*ppszSummary == NULL)
99   {
100     iLength = strlen(MODULE_SUMMARY_USAGE) + strlen(MODULE_VERSION) + strlen(MODULE_SUMMARY_FORMAT) + 1;
101     *ppszSummary = (char*)malloc(iLength);
102     memset(*ppszSummary, 0, iLength);
103     snprintf(*ppszSummary, iLength, MODULE_SUMMARY_FORMAT, MODULE_SUMMARY_USAGE, MODULE_VERSION);
104   }
105   else
106   {
107     writeError(ERR_ERROR, "%s reports an error in summaryUsage() : ppszSummary must be NULL when called", MODULE_NAME);
108   }
109 }
110 
111 /* Display module usage information */
showUsage()112 void showUsage()
113 {
114   writeVerbose(VB_NONE, "%s (%s) %s :: %s\n", MODULE_NAME, MODULE_VERSION, MODULE_AUTHOR, MODULE_SUMMARY_USAGE);
115   writeVerbose(VB_NONE, "Available module options:");
116   writeVerbose(VB_NONE, "  MAXSLEEP:?");
117   writeVerbose(VB_NONE, "    Sets the maximum allowed sleep time when the VNC RealVNC anti-brute force delay");
118   writeVerbose(VB_NONE, "    is encountered. This value is in seconds and, if left unset, defaults to 60.");
119   writeVerbose(VB_NONE, "  DOMAIN:?");
120   writeVerbose(VB_NONE, "    Sets the domain value when authenticating against UltraVNC's MS-Logon feature.");
121   writeVerbose(VB_NONE, "");
122   writeVerbose(VB_NONE, "Some versions of VNC have built-in anti-brute force functionality. RealVNC, for example,");
123   writeVerbose(VB_NONE, "allows 5 failed attempts and then enforces a 10 second delay. For each subsequent");
124   writeVerbose(VB_NONE, "attempt that delay is doubled. UltraVNC appears to allow 6 invalid attempts and then forces");
125   writeVerbose(VB_NONE, "a 10 second delay between each following attempt. This module attempts to identify these");
126   writeVerbose(VB_NONE, "situations and react appropriately by invoking sleep(). The user can set a sleep limit when");
127   writeVerbose(VB_NONE, "brute forcing RealVNC using the MAXSLEEP parameter. Once this value has been reached, the");
128   writeVerbose(VB_NONE, "module will exit.");
129   writeVerbose(VB_NONE, "");
130   writeVerbose(VB_NONE, "It should be noted that this module currently supports password-less and password-only VNC");
131   writeVerbose(VB_NONE, "servers. In addition, it supports UltraVNC's MS-Logon feature that can be used to provide");
132   writeVerbose(VB_NONE, "pass-through authentication against local and domain Windows accounts. In the case of basic");
133   writeVerbose(VB_NONE, "password-only VNC, provide any arbitrary username value.");
134   writeVerbose(VB_NONE, "");
135   writeVerbose(VB_NONE, "Usage example: \"-M vnc -m MAXSLEEP:120 -m DOMAIN:FOOFUSDOM\"");
136 }
137 
138 // The "main" of the medusa module world - this is what gets called to actually do the work
go(sLogin * logins,int argc,char * argv[])139 int go(sLogin* logins, int argc, char *argv[])
140 {
141   int i;
142   char *strtok_ptr, *pOpt, *pOptTmp;
143   _VNC_DATA *psSessionData;
144   psSessionData = malloc(sizeof(_VNC_DATA));
145   memset(psSessionData, 0, sizeof(_VNC_DATA));
146   psSessionData->nMaxAuthSleep = 60;
147 
148   if ((argc < 0) || (argc > 2))
149   {
150     writeError(ERR_ERROR, "%s: Incorrect number of parameters passed to module (%d). Use \"-q\" option to display module usage.", MODULE_NAME, argc);
151     return FAILURE;
152   }
153   else
154   {
155     writeError(ERR_DEBUG_MODULE, "OMG teh %s module has been called!!", MODULE_NAME);
156 
157     for (i=0; i<argc; i++) {
158       pOptTmp = malloc( strlen(argv[i]) + 1);
159       memset(pOptTmp, 0, strlen(argv[i]) + 1);
160       strncpy(pOptTmp, argv[i], strlen(argv[i]));
161       writeError(ERR_DEBUG_MODULE, "Processing complete option: %s", pOptTmp);
162       pOpt = strtok_r(pOptTmp, ":", &strtok_ptr);
163       writeError(ERR_DEBUG_MODULE, "Processing option: %s", pOpt);
164 
165       if (strcmp(pOpt, "MAXSLEEP") == 0)
166       {
167         pOpt = strtok_r(NULL, "\0", &strtok_ptr);
168         writeError(ERR_DEBUG_MODULE, "Processing option parameter: %s", pOpt);
169 
170         if ( pOpt )
171           psSessionData->nMaxAuthSleep = atoi(pOpt);
172         else
173           writeError(ERR_WARNING, "Method MAXSLEEP requires value to be set.");
174       }
175       else if (strcmp(pOpt, "DOMAIN") == 0)
176       {
177         pOpt = strtok_r(NULL, "\0", &strtok_ptr);
178         writeError(ERR_DEBUG_MODULE, "Processing option parameter: %s", pOpt);
179 
180         if ( pOpt )
181         {
182           psSessionData->szDomain = malloc(strlen(pOpt) + 1);
183           memset(psSessionData->szDomain, 0, strlen(pOpt) + 1);
184           strncpy((char *) psSessionData->szDomain, pOpt, strlen(pOpt));
185         }
186         else
187           writeError(ERR_WARNING, "Method DOMAIN requires value to be set.");
188       }
189       else
190          writeError(ERR_WARNING, "Invalid method: %s.", pOpt);
191 
192       free(pOptTmp);
193     }
194 
195     initModule(logins, psSessionData);
196   }
197 
198   FREE(psSessionData);
199   return SUCCESS;
200 }
201 
initModule(sLogin * psLogin,_VNC_DATA * _psSessionData)202 int initModule(sLogin* psLogin, _VNC_DATA *_psSessionData)
203 {
204   int hSocket = -1;
205   enum MODULE_STATE nState = MSTATE_NEW;
206   int iRet;
207   sConnectParams params;
208   int nAngrySleep = 10;
209   int bAuthAllowed = FALSE;
210   sCredentialSet *psCredSet = NULL;
211 
212   psCredSet = malloc( sizeof(sCredentialSet) );
213   memset(psCredSet, 0, sizeof(sCredentialSet));
214 
215   if (getNextCredSet(psLogin, psCredSet) == FAILURE)
216   {
217     writeError(ERR_ERROR, "[%s] Error retrieving next credential set to test.", MODULE_NAME);
218     nState = MSTATE_COMPLETE;
219   }
220   else if (psCredSet->psUser)
221   {
222     writeError(ERR_DEBUG_MODULE, "[%s] module started for host: %s user: %s", MODULE_NAME, psLogin->psServer->pHostIP, psCredSet->psUser->pUser);
223   }
224   else
225   {
226     writeError(ERR_DEBUG_MODULE, "[%s] module started for host: %s - no more available users to test.", MODULE_NAME);
227     nState = MSTATE_COMPLETE;
228   }
229 
230   memset(&params, 0, sizeof(sConnectParams));
231   if (psLogin->psServer->psAudit->iPortOverride > 0)
232     params.nPort = psLogin->psServer->psAudit->iPortOverride;
233   else
234     params.nPort = PORT_VNC;
235   initConnectionParams(psLogin, &params);
236 
237   while (nState != MSTATE_COMPLETE)
238   {
239     switch (nState)
240     {
241       case MSTATE_NEW:
242         while (!bAuthAllowed)
243         {
244           if (hSocket > 0)
245             medusaDisconnect(hSocket);
246 
247           hSocket = medusaConnect(&params);
248 
249           if (hSocket < 0)
250           {
251             writeError(ERR_NOTICE, "%s: failed to connect, port %d was not open on %s", MODULE_NAME, params.nPort, psLogin->psServer->pHostIP);
252             psLogin->iResult = LOGIN_RESULT_UNKNOWN;
253             return FAILURE;
254           }
255 
256           writeError(ERR_DEBUG_MODULE, "Connected");
257 
258           iRet = vncSessionSetup(hSocket, _psSessionData);
259           switch( iRet )
260           {
261             case SESSION_SUCCESS:
262               writeError(ERR_DEBUG_MODULE, "VNC Session Initialized.");
263               bAuthAllowed = TRUE;
264               nState = MSTATE_RUNNING;
265               break;
266             case SESSION_SUCCESS_NO_AUTH:
267               writeError(ERR_DEBUG_MODULE, "VNC Server Does Not Require Authentication.");
268               psLogin->iResult = LOGIN_RESULT_SUCCESS;
269               setPassResult(psLogin, "[NO AUTH REQUIRED]");
270               bAuthAllowed = TRUE;
271               nState = MSTATE_EXITING;
272               break;
273             case SESSION_MAX_AUTH_REALVNC:
274               writeError(ERR_ALERT, "[%s] Host %s reported too many security failures. Sleeping %d seconds before next attempt.", MODULE_NAME, psLogin->psServer->pHostIP, nAngrySleep);
275               if (nAngrySleep > _psSessionData->nMaxAuthSleep)
276               {
277                 writeError(ERR_ERROR, "[%s] Host %s exceeded maximum allowed sleep. Terminating connection.", MODULE_NAME, psLogin->psServer->pHostIP);
278                 psLogin->iResult = LOGIN_RESULT_UNKNOWN;
279                 bAuthAllowed = TRUE;
280                 nState = MSTATE_EXITING;
281               }
282               else
283               {
284                 sleep(nAngrySleep + 1);
285                 nAngrySleep = 2 * nAngrySleep;
286               }
287               break;
288             case SESSION_MAX_AUTH_ULTRAVNC:
289               writeError(ERR_ALERT, "[%s] Host %s has rejected the connection. Sleeping 10 seconds before next attempt.", MODULE_NAME, psLogin->psServer->pHostIP);
290               if (nAngrySleep > _psSessionData->nMaxAuthSleep)
291               {
292                 writeError(ERR_ERROR, "[%s] Host %s exceeded maximum allowed sleep. Terminating connection.", MODULE_NAME, psLogin->psServer->pHostIP);
293                 psLogin->iResult = LOGIN_RESULT_UNKNOWN;
294                 bAuthAllowed = TRUE;
295                 nState = MSTATE_EXITING;
296               }
297               else
298               {
299                 sleep(10 + 1);
300                 nAngrySleep = nAngrySleep + 10;
301               }
302               break;
303             default:
304               writeError(ERR_DEBUG_MODULE, "VNC Session Setup Failed.");
305               psLogin->iResult = LOGIN_RESULT_UNKNOWN;
306               bAuthAllowed = TRUE;
307               nState = MSTATE_EXITING;
308               break;
309           }
310         }
311 
312         bAuthAllowed = FALSE;
313         break;
314       case MSTATE_RUNNING:
315         nState = tryLogin(hSocket, &psLogin, _psSessionData, psCredSet->psUser->pUser, psCredSet->pPass);
316 
317         if (psLogin->iResult != LOGIN_RESULT_UNKNOWN)
318         {
319           if (getNextCredSet(psLogin, psCredSet) == FAILURE)
320           {
321             writeError(ERR_ERROR, "[%s] Error retrieving next credential set to test.", MODULE_NAME);
322             nState = MSTATE_EXITING;
323           }
324           else
325           {
326             if (psCredSet->iStatus == CREDENTIAL_DONE)
327             {
328               writeError(ERR_DEBUG_MODULE, "[%s] No more available credential sets to test.", MODULE_NAME);
329               nState = MSTATE_EXITING;
330             }
331             else if (psCredSet->iStatus == CREDENTIAL_NEW_USER)
332             {
333               writeError(ERR_DEBUG_MODULE, "[%s] Starting testing for new user: %s.", MODULE_NAME, psCredSet->psUser->pUser);
334               nState = MSTATE_NEW;
335             }
336             else
337               writeError(ERR_DEBUG_MODULE, "[%s] Next credential set - user: %s password: %s", MODULE_NAME, psCredSet->psUser->pUser, psCredSet->pPass);
338           }
339         }
340         break;
341       case MSTATE_EXITING:
342         if (hSocket > 0)
343           medusaDisconnect(hSocket);
344         hSocket = -1;
345         nState = MSTATE_COMPLETE;
346         break;
347       default:
348         writeError(ERR_CRITICAL, "Unknown %s module state %d", MODULE_NAME, nState);
349         if (hSocket > 0)
350           medusaDisconnect(hSocket);
351         hSocket = -1;
352         psLogin->iResult = LOGIN_RESULT_UNKNOWN;
353         return FAILURE;
354     }
355   }
356 
357   FREE(psCredSet);
358   return SUCCESS;
359 }
360 
361 /* VNC Specific Functions */
362 
363 /*
364 ** Encrypt CHALLENGE_SIZE bytes in memory using a password.
365 ** Ripped from vncauth.c
366 */
vncEncryptBytes(unsigned char * bytes,char * passwd)367 void vncEncryptBytes(unsigned char *bytes, char *passwd)
368 {
369   unsigned char key[8];
370   unsigned int i;
371 
372   /* key is simply password padded with nulls */
373   for (i = 0; i < 8; i++) {
374     if (i < strlen(passwd)) {
375       key[i] = passwd[i];
376     } else {
377       key[i] = 0;
378     }
379   }
380   deskey(key, EN0);
381   for (i = 0; i < CHALLENGE_SIZE; i += 8) {
382     des(bytes + i, bytes + i);
383   }
384 }
385 
vncEncryptPasswdMs(unsigned char * encryptedPasswd,char * passwd)386 void vncEncryptPasswdMs( unsigned char *encryptedPasswd, char *passwd )
387 {
388   unsigned char key[8];
389   unsigned int i;
390 
391   /* pad password with nulls */
392   for (i = 0; i < 32; i++) {
393     if (i < strlen(passwd)) {
394       encryptedPasswd[i] = passwd[i];
395     } else {
396       encryptedPasswd[i] = 0;
397     }
398   }
399 
400   /* Do encryption in-place - this way we overwrite our copy of the plaintext
401      password */
402   deskey(key, EN0);
403   des(encryptedPasswd, encryptedPasswd);
404 }
405 
406 /* [UltraVNC/rfb/dh.cpp] */
bytesToInt64(const unsigned char * const bytes)407 uint64_t bytesToInt64(const unsigned char* const bytes) {
408   uint64_t result = 0;
409   int i;
410 
411   for (i = 0; i < 8; i++) {
412     result <<= 8;
413     result += bytes[i];
414   }
415   return result;
416 }
417 
int64ToBytes(const uint64_t integer,char * const bytes)418 int int64ToBytes(const uint64_t integer, char* const bytes) {
419   int i;
420   for (i = 0; i < 8; i++) {
421     bytes[i] = (unsigned char) (integer >> (8 * (7 - i)));
422   }
423   return SUCCESS;
424 }
425 
426 /* [UltraVNC/vncviewer/vncauth.c] */
vncEncryptBytes2(unsigned char * where,const int length,unsigned char * key)427 void vncEncryptBytes2(unsigned char *where, const int length, unsigned char *key) {
428   int i, j;
429   deskey(key, EN0);
430   for (i = 0; i< 8; i++)
431     where[i] ^= key[i];
432   des(where, where);
433   for (i = 8; i < length; i += 8) {
434     for (j = 0; j < 8; j++)
435       where[i + j] ^= where[i + j - 8];
436     des(where + i, where + i);
437   }
438 }
439 
440 
vncSessionSetup(int hSocket,_VNC_DATA * _psSessionData)441 int vncSessionSetup(int hSocket, _VNC_DATA* _psSessionData)
442 {
443   unsigned char ProtocolVersion[13];
444   int iServerProtocolVersion;
445   unsigned char* bufReceive;
446   int nReceiveBufferSize = 0;
447   int i = 0;
448   int nSecurityTypes = 0;
449   unsigned char* szSecurityTypes = NULL;
450 
451   memset(ProtocolVersion, 0, 13);
452 
453   /* --- VNC Protocol Handshake --- */
454 
455   /* Retrieve server VNC protocol version */
456   nReceiveBufferSize = 0;
457   bufReceive = medusaReceiveRaw(hSocket, &nReceiveBufferSize);
458   if (bufReceive == NULL)
459     return SESSION_FAILURE;
460 
461   writeError(ERR_DEBUG_MODULE, "VNC Server Protocol Version: %s", bufReceive);
462 
463   /* The following message is triggered by 5 failed authentication attempts, at which
464   ** point a 10 second lockout is applied before the next attempt is permitted.  Each
465   ** subsequent failed attempt causes the timeout to be doubled.
466   **
467   **   RealVNC: Too many security failures
468   **   WinVNC (<=3.3.3r2): Too many authentication failures
469   */
470   if ((strncmp((char *)bufReceive + 20, "Too many security failures", 26) == 0) || (strncmp((char *)bufReceive + 20, "Too many authentication failures", 32) == 0))
471   {
472     writeError(ERR_DEBUG_MODULE, "[%s] Host reported too many security failures.", MODULE_NAME);
473     return SESSION_MAX_AUTH_REALVNC;
474   }
475   /* 3.3, 3.7 and 3.8 are the only published protocol versions (RFB Protocol v3.8 11/26/2010) */
476   else if (strncmp((char *)bufReceive, "RFB 003.003", 11) == 0)
477   {
478     memcpy(ProtocolVersion, "RFB 003.003\n", 12);
479     iServerProtocolVersion = 3;
480   }
481   else if (strncmp((char *)bufReceive, "RFB 003.007", 11) == 0)
482   {
483     memcpy(ProtocolVersion, "RFB 003.007\n", 12);
484     iServerProtocolVersion = 7;
485   }
486   else if (strncmp((char *)bufReceive, "RFB 003.008", 11) == 0)
487   {
488     memcpy(ProtocolVersion, "RFB 003.008\n", 12);
489     iServerProtocolVersion = 8;
490   }
491   /* RealVNC - VNC Server Enterprise Edition E4.6.3 (r66752) */
492   else if (strncmp((char *)bufReceive, "RFB 004.001", 11) == 0)
493   {
494     memcpy(ProtocolVersion, "RFB 004.001\n", 12);
495     iServerProtocolVersion = 8;
496   }
497   else
498   {
499     writeError(ERR_DEBUG_MODULE, "[%s] Unknown session setup response: %s. Setting client response to version 3.3.", MODULE_NAME, bufReceive);
500     memcpy(ProtocolVersion, "RFB 003.003\n", 12);
501     iServerProtocolVersion = 3;
502   }
503 
504   /* Send client VNC protocol version */
505   writeError(ERR_DEBUG_MODULE, "VNC Client Protocol Version: %s", ProtocolVersion);
506   if (medusaSend(hSocket, ProtocolVersion, 12, 0) < 0)
507   {
508     writeError(ERR_ERROR, "%s failed: medusaSend was not successful", MODULE_NAME);
509   }
510 
511   /* Some VNC servers seem to get upset if we go too fast. Sleeping 1/2 second seems to help. */
512   usleep(0.5 * 1000000);
513 
514   /* --- VNC Security Type Handshake --- */
515 
516   /* Retrieve VNC protocol authentication scheme response */
517   nReceiveBufferSize = 0;
518   bufReceive = medusaReceiveRaw(hSocket, &nReceiveBufferSize);
519 
520   if ((bufReceive == NULL) || (nReceiveBufferSize == 0))
521   {
522     writeError(ERR_ERROR, "No security type response received from server.");
523     return SESSION_FAILURE;
524   }
525   /* RFB Protocol 3.3 - Security Type
526   **
527   ** Server: U32 [security type]
528   **
529   ** if the security types is 0, response is followed by:
530   ** Server: U32 [reason-length]
531   **         U8 array [reason for connection failure]
532   */
533   else if (iServerProtocolVersion == 3)
534   {
535     writeErrorBin(ERR_DEBUG_MODULE, "Supported Security Types (version 3.3): ", bufReceive, nReceiveBufferSize);
536     switch (bufReceive[3])
537     {
538       case 0x00:  /* connection failure */
539         writeError(ERR_DEBUG_MODULE, "VNC Session Setup - Failed.");
540 
541         if (nReceiveBufferSize > 16)
542           writeError(ERR_DEBUG_MODULE, "VNC Session Setup Failure Message: %s", bufReceive + 8);
543 
544         /* Server is probably in anti-brute force mode (UltraVNC) */
545         if ((nReceiveBufferSize == 42) && (strncmp((char *)bufReceive + 8, "Your connection has been rejected.", 34) == 0))
546           return SESSION_MAX_AUTH_ULTRAVNC;
547         else
548           return SESSION_FAILURE;
549         break;
550 
551       case 0x01:  /* no authentication required */
552         writeError(ERR_DEBUG_MODULE, "VNC Session Setup - Successful - No Authentication Required.");
553         return SESSION_SUCCESS_NO_AUTH;
554         break;
555 
556       case 0x02:  /* authentication required -- set authentication challenge */
557         writeError(ERR_DEBUG_MODULE, "VNC Session Setup - Successful.");
558         if (nReceiveBufferSize == 20)
559         {
560           _psSessionData->szChallenge = malloc(17);
561           memset(_psSessionData->szChallenge, 0, 17);
562           memcpy(_psSessionData->szChallenge, bufReceive + 4, 16);
563           writeError(ERR_DEBUG_MODULE, "VNC authentication challenge: %s", _psSessionData->szChallenge);
564           _psSessionData->nAuthType = AUTH_VNC;
565           return SESSION_SUCCESS;
566         }
567         else
568         {
569           writeError(ERR_ERROR, "[%s] Unknown session challenge. Possible unsupported authentication type.", MODULE_NAME);
570           return SESSION_FAILURE;
571         }
572         break;
573 
574       case 0xFA: /* UltaVNC MS-Logon */
575         writeError(ERR_DEBUG_MODULE, "VNC Session Setup - UltraVNC MS-Logon.");
576 
577         if (nReceiveBufferSize == 28)
578         {
579           _psSessionData->szChallenge = malloc(25);
580           memset(_psSessionData->szChallenge, 0, 25);
581           memcpy(_psSessionData->szChallenge, bufReceive + 4, 24);
582           writeErrorBin(ERR_DEBUG_MODULE, "VNC authentication challenge: ", bufReceive + 4, 24);
583           _psSessionData->nAuthType = AUTH_UVNC_MSLOGIN;
584           return SESSION_SUCCESS;
585         }
586         else
587         {
588           writeError(ERR_ERROR, "[%s] Unknown session challenge. Possible unsupported authentication type.", MODULE_NAME);
589           return SESSION_FAILURE;
590         }
591 
592         break;
593 
594       default: /* unknown response */
595         writeError(ERR_ERROR, "[%s] VNC Session Setup - Unknown Response (3.3): %d", MODULE_NAME, bufReceive[3]);
596         return SESSION_FAILURE;
597         break;
598     }
599   }
600   /* RFB Protocol 3.7, 3.8 - Security Type
601   **
602   ** Server: U8 [number of security types]
603   **         U8 array [security type]
604   **
605   ** If the number of security types is 0, response is followed by:
606   ** Server: U32 [reason-length]
607   **         U8 array [reason for connection failure]
608   */
609   else if ((iServerProtocolVersion == 7) || (iServerProtocolVersion == 8))
610   {
611     writeErrorBin(ERR_DEBUG_MODULE, "Supported Security Types (> version 3.7): ", bufReceive, nReceiveBufferSize);
612 
613     /* connection failure */
614     if (bufReceive[0] == 0)
615     {
616       writeError(ERR_DEBUG_MODULE, "VNC Session Setup - Failed.");
617 
618       //memcpy(nReasonLength + sizeof(int), bufReceive + 1, 4);
619 
620       if (nReceiveBufferSize > 8)
621         writeError(ERR_DEBUG_MODULE, "VNC Session Setup Failure Message: %s", bufReceive + 5);
622 
623       /* Server is probably in anti-brute force mode (UltraVNC) */
624       if (strncmp((char *)bufReceive + 5, "Your connection has been rejected.", 34) == 0)
625         return SESSION_MAX_AUTH_ULTRAVNC;
626       else
627         return SESSION_FAILURE;
628     }
629     /* verify response length */
630     else if (nReceiveBufferSize == 1 + (int)bufReceive[0])
631     {
632       nSecurityTypes = (int)bufReceive[0];
633       szSecurityTypes = malloc(nSecurityTypes + 1);
634       memset(szSecurityTypes, 0, nSecurityTypes + 1);
635       memcpy(szSecurityTypes, bufReceive + 1, nSecurityTypes);
636 
637       for (i = 0; i <= nSecurityTypes; i++)
638       {
639         writeError(ERR_DEBUG_MODULE, "Processing server security type: %d (%d/%d). We will select the first supported type encountered.", szSecurityTypes[i], i + 1, nSecurityTypes);
640         switch (szSecurityTypes[i])
641         {
642           case 0x01:  /* no authentication required */
643             writeError(ERR_DEBUG_MODULE, "VNC Session Setup - Password-only VNC - No Authentication Required");
644 
645             if (medusaSend(hSocket, &szSecurityTypes[i], 1, 0) < 0)
646             {
647               writeError(ERR_ERROR, "[%s] failed: medusaSend was not successful", MODULE_NAME);
648               return FAILURE;
649             }
650 
651             nReceiveBufferSize = 0;
652             bufReceive = medusaReceiveRaw(hSocket, &nReceiveBufferSize);
653             if (bufReceive == NULL)
654               return FAILURE;
655             else if (bufReceive[3] == 0)
656               return SESSION_SUCCESS_NO_AUTH;
657             else
658               return FAILURE;
659 
660             break;
661           case 0x02:  /* authentication required -- set authentication challenge */
662             writeError(ERR_DEBUG_MODULE, "VNC Session Setup - Password-only VNC");
663 
664             if (medusaSend(hSocket, &szSecurityTypes[i], 1, 0) < 0)
665             {
666               writeError(ERR_ERROR, "[%s] failed: medusaSend was not successful", MODULE_NAME);
667               return FAILURE;
668             }
669 
670             nReceiveBufferSize = 0;
671             bufReceive = medusaReceiveRaw(hSocket, &nReceiveBufferSize);
672 
673             if (nReceiveBufferSize == 16)
674             {
675               _psSessionData->szChallenge = malloc(17);
676               memset(_psSessionData->szChallenge, 0, 17);
677               memcpy(_psSessionData->szChallenge, bufReceive, 16);
678               writeError(ERR_DEBUG_MODULE, "VNC authentication challenge: %s", _psSessionData->szChallenge);
679               _psSessionData->nAuthType = AUTH_VNC;
680               return SESSION_SUCCESS;
681             }
682             else
683             {
684               writeError(ERR_ERROR, "[%s] Unknown session challenge. Possible unsupported authentication type.", MODULE_NAME);
685               return SESSION_FAILURE;
686             }
687             break;
688 
689           case 0x05:  /* 5: RealVNC RA2 */
690           case 0x06:  /* 6: RealVNC RA2ne */
691           case 0x81:  /* 129: UNIX Logon Authentication */
692           case 0x82:  /* 130: External Authentication */
693             writeError(ERR_ERROR, "[%s] VNC Session Setup - RealVNC (Type %d). RealVNC native authentication mode is NOT currently supported.", MODULE_NAME, szSecurityTypes[i]);
694             break;
695 
696           case 0x11:  /* 17: UltraVNC */
697             /* http://www.uvnc.com/features/authentication.html */
698             /*
699               [rfb/rfbproto.h]
700               rfbUltraVNC 0x17 - after rfbUltraVNC, auth repeats via rfbVncAuthContinue
701 
702               rfbUltraVNC_SCPrompt 0x68
703               rfbUltraVNC_SessionSelect 0x69
704               rfbUltraVNC_MsLogonIAuth 0x70
705               rfbUltraVNC_MsLogonIIAuth 0x71
706               rfbUltraVNC_SecureVNCPluginAuth 0x72
707             */
708 
709             writeError(ERR_DEBUG_MODULE, "VNC Session Setup - UltraVNC");
710 
711             /*
712               0x11 UltraVNC contains multiple sub-types. If we respond with 0x11, the server
713               should send us a list. For example, 0xffffffff 0x0171 (UltraVNC MS-Logon II).
714               This appears to be sent sometimes as a single packet, sometimes as two. It seems
715               that any sub-types we would enumerate here, however, were also listed in the initial
716               supported security type response. As such, let's just skip this type and move on
717               to the next in the list. If this assumption turns out to be incorrect, we should
718               continue the security type negotiation here.
719             */
720 
721             break;
722 
723           case 0x70:  /* 17: UltraVNC MS-Logon I */
724           case 0x71:  /* 17: UltraVNC MS-Logon II */
725             writeError(ERR_DEBUG_MODULE, "VNC Session Setup - UltraVNC (Type %d)", szSecurityTypes[i]);
726 
727             if (medusaSend(hSocket, &szSecurityTypes[i], 1, 0) < 0)
728             {
729               writeError(ERR_ERROR, "[%s] failed: medusaSend was not successful", MODULE_NAME);
730               return FAILURE;
731             }
732 
733             nReceiveBufferSize = 0;
734             bufReceive = medusaReceiveRaw(hSocket, &nReceiveBufferSize);
735 
736             if (nReceiveBufferSize == 24)
737             {
738               writeError(ERR_DEBUG_MODULE, "VNC Session Setup - UltraVNC MS-Logon II - Process authentication challenge");
739               _psSessionData->szChallenge = malloc(25);
740               memset(_psSessionData->szChallenge, 0, 25);
741               memcpy(_psSessionData->szChallenge, bufReceive, 24);
742               writeErrorBin(ERR_DEBUG_MODULE, "VNC authentication challenge: ", _psSessionData->szChallenge, 24);
743               _psSessionData->nAuthType = AUTH_UVNC_MSLOGIN;
744               return SESSION_SUCCESS;
745             }
746 
747             break;
748 
749           default: /* unknown response - skip and see if we find a supported type */
750             writeError(ERR_ERROR, "[%s] VNC Session Setup - Unknown Response (3.7/3.8): %d", MODULE_NAME, szSecurityTypes[i]);
751             break;
752         }
753       }
754     }
755     else
756     {
757       writeError(ERR_ERROR, "[%s] VNC Session Setup - Unknown Response", MODULE_NAME);
758       return SESSION_FAILURE;
759     }
760   }
761 
762   FREE(szSecurityTypes);
763   return SESSION_FAILURE;
764 }
765 
sendAuthVNC(int hSocket,_VNC_DATA * _psSessionData,char * szPassword)766 int sendAuthVNC(int hSocket, _VNC_DATA* _psSessionData, char* szPassword)
767 {
768   writeError(ERR_DEBUG_MODULE, "[%s] VNC authentication challenge: %s", MODULE_NAME, _psSessionData->szChallenge);
769   vncEncryptBytes(_psSessionData->szChallenge, szPassword);
770   writeError(ERR_DEBUG_MODULE, "[%s] VNC authentication response: %s", MODULE_NAME, _psSessionData->szChallenge);
771 
772   if (medusaSend(hSocket, _psSessionData->szChallenge, 16, 0) < 0)
773   {
774     writeError(ERR_ERROR, "[%s] failed: medusaSend was not successful", MODULE_NAME);
775     return FAILURE;
776   }
777 
778   return SUCCESS;
779 }
780 
781 /*
782     Based on ClientConnection::AuthMsLogonII() [UltraVNC/vncviewer/ClientConnection.cpp]
783 
784     MS Logon authentication supports "domain\user", "user" and "user@domain" logins
785 */
sendAuthMSLogin(int hSocket,_VNC_DATA * _psSessionData,char * szLogin,char * szPassword)786 int sendAuthMSLogin(int hSocket, _VNC_DATA* _psSessionData, char* szLogin, char* szPassword)
787 {
788   unsigned char ms_user[256], ms_passwd[64];
789   unsigned char key[8];
790   int i = 0;
791 
792   int client_priv = 31337; /* arbitrary value -- client would typically randomly generate */
793   uint64_t g, p, resp;
794   char client_pub[8];
795   BIGNUM* server_pub;
796 
797   DH *dh_struct;
798   int dh_error;
799   unsigned char *dh_secret;
800 
801   unsigned char *bufSend = NULL;
802 
803   writeError(ERR_DEBUG_MODULE, "[%s] VNC Authentication - UltraVNC Microsoft Logon", MODULE_NAME);
804 
805   /* parse server challenge -- g, p (mod) and server public key */
806   g = bytesToInt64(_psSessionData->szChallenge);
807   p = bytesToInt64(_psSessionData->szChallenge + 8);
808   resp = bytesToInt64(_psSessionData->szChallenge + 16);
809 
810   writeError(ERR_DEBUG_MODULE, "[%s] Server DH values: g: %d p/mod: %d public key: %d", MODULE_NAME, g, p, resp);
811 
812   /* create and populate DH structure */
813   dh_struct = DH_new();
814 
815 #if OPENSSL_VERSION_NUMBER >= 0x10100005L
816   DH_set0_pqg(dh_struct, (BIGNUM*) &p, (BIGNUM*) &client_priv, (BIGNUM*) &g);
817 #else
818   dh_struct->g = BN_new();
819   BN_set_word(dh_struct->g, g);
820 
821   dh_struct->p = BN_new();
822   BN_set_word(dh_struct->p, p);
823 
824   dh_struct->priv_key = BN_new();
825   BN_set_word(dh_struct->priv_key, client_priv);
826 #endif
827 
828   if (DH_generate_key(dh_struct) == 0)
829     writeError(ERR_ERROR, "[%s] Failed to generate key", MODULE_NAME);
830 
831   DH_check(dh_struct, &dh_error);
832   if (dh_error & DH_CHECK_P_NOT_SAFE_PRIME)
833     writeError(ERR_DEBUG_MODULE, "[%s] Failed to create DH structure: DH_CHECK_P_NOT_SAFE_PRIME", MODULE_NAME);
834   if (dh_error & DH_NOT_SUITABLE_GENERATOR)
835     writeError(ERR_DEBUG_MODULE, "[%s] Failed to create DH structure: DH_NOT_SUITABLE_GENERATOR", MODULE_NAME);
836   if (dh_error & DH_UNABLE_TO_CHECK_GENERATOR)
837     writeError(ERR_DEBUG_MODULE, "[%s] Failed to create DH structure: DH_UNABLE_TO_CHECK_GENERATOR", MODULE_NAME);
838 
839   /* convert client public key into proper format for sending */
840 #if OPENSSL_VERSION_NUMBER >= 0x10100005L
841   DH_set0_key(dh_struct, (BIGNUM*) &client_pub, (BIGNUM*) &client_priv);
842 #else
843   int64ToBytes(BN_get_word(dh_struct->pub_key), client_pub);
844 #endif
845 
846   /* generate shared secret using private DH key and server's public key */
847   server_pub = BN_new();
848   BN_set_word(server_pub, resp);
849 
850   dh_secret = malloc( DH_size(dh_struct) );
851   DH_compute_key(dh_secret, server_pub, dh_struct);
852 
853   /* OpenSSLs DH implementation is compliant with the SSL/TLS requirements that skip
854      leading zeroes on the output. We need our key to be exactly 8 bytes long, so
855      let's prepend it with the necessary number of zeros. */
856   memset(key, 0, 8);
857   if (DH_size(dh_struct) < 8)
858     for (i=0; i < DH_size(dh_struct); i++)
859       key[8 - DH_size(dh_struct) + i] = dh_secret[i];
860 
861   DH_free(dh_struct);
862 
863   writeErrorBin(ERR_DEBUG_MODULE, "Shared secret key: ", key, 8);
864 
865   memset(ms_user, 0, 256);
866   memset(ms_passwd, 0, 64);
867 
868   if ((_psSessionData->szDomain) && (strlen(_psSessionData->szDomain) + 1 + strlen(szLogin) < 256))
869   {
870     strncpy((char *)ms_user, _psSessionData->szDomain, strlen(_psSessionData->szDomain));
871     strncat((char *)ms_user, "\\", 1);
872     strncat((char *)ms_user, szLogin, strlen(szLogin));
873   }
874   else
875     strncpy((char *)ms_user, szLogin, 256);
876 
877   strncpy((char *)ms_passwd, szPassword, 64);
878 
879   writeError(ERR_DEBUG_MODULE, "Username: %s Password: %s", ms_user, ms_passwd);
880   writeErrorBin(ERR_DEBUG_MODULE, "Username: ", ms_user, 256);
881   writeErrorBin(ERR_DEBUG_MODULE, "Password: ", ms_passwd, 64);
882 
883   vncEncryptBytes2((unsigned char*) &ms_user, sizeof(ms_user), key);
884   vncEncryptBytes2((unsigned char*) &ms_passwd, sizeof(ms_passwd), key);
885 
886   writeErrorBin(ERR_DEBUG_MODULE, "Encrypted username: ", ms_user, 256);
887   writeErrorBin(ERR_DEBUG_MODULE, "Encrypted password: ", ms_passwd, 64);
888 
889   /* send client public key, encrypted username, and encrypted password */
890   bufSend = malloc(8 + sizeof(ms_user) + sizeof(ms_passwd) + 1);
891   memset(bufSend, 0, 8 + sizeof(ms_user) + sizeof(ms_passwd) + 1);
892 
893   /*
894     For extra fun, set client_pub to a value of 0x80000000 or greater. No more server...
895     memset(client_pub, 0x0000000080, 5);
896   */
897   memcpy(bufSend, client_pub, 8);
898   memcpy(bufSend + 8, ms_user, sizeof(ms_user));
899   memcpy(bufSend + 8 + sizeof(ms_user), ms_passwd, sizeof(ms_passwd));
900 
901   if (medusaSend(hSocket, bufSend, 8 + sizeof(ms_user) + sizeof(ms_passwd), 0) < 0)
902   {
903     writeError(ERR_ERROR, "[%s] failed: medusaSend was not successful", MODULE_NAME);
904     return FAILURE;
905   }
906 
907   return SUCCESS;
908 }
909 
sendExit(int hSocket)910 int sendExit(int hSocket)
911 {
912   unsigned char szExit[] = { 0x00, 0x00, 0x00, 0x00, 0x05, 0x1D, 0x03, 0x20 };
913 
914   writeError(ERR_DEBUG_MODULE, "[%s] Send VNC connection termination command.", MODULE_NAME);
915 
916   if (medusaSend(hSocket, szExit, 8, 0) < 0)
917   {
918     writeError(ERR_ERROR, "[%s] failed: medusaSend was not successful", MODULE_NAME);
919     return FAILURE;
920   }
921 
922   return SUCCESS;
923 }
924 
tryLogin(int hSocket,sLogin ** psLogin,_VNC_DATA * _psSessionData,char * szLogin,char * szPassword)925 int tryLogin(int hSocket, sLogin** psLogin, _VNC_DATA* _psSessionData, char* szLogin, char* szPassword)
926 {
927   unsigned char* bufReceive;
928   int nReceiveBufferSize = 0;
929   int iRet;
930 
931   /* perform authentication */
932   switch(_psSessionData->nAuthType)
933   {
934     case AUTH_VNC:
935       sendAuthVNC(hSocket, _psSessionData, szPassword);
936       break;
937     case AUTH_UVNC_MSLOGIN:
938       sendAuthMSLogin(hSocket, _psSessionData, szLogin, szPassword);
939       break;
940     default:
941       writeError(ERR_DEBUG_MODULE, "[%s] VNC Authentication - blah", MODULE_NAME);
942       break;
943   }
944 
945   writeError(ERR_DEBUG_MODULE, "[%s] VNC Authentication - Waiting for authentication result", MODULE_NAME);
946   nReceiveBufferSize = 0;
947   bufReceive = medusaReceiveRaw(hSocket, &nReceiveBufferSize);
948   if (bufReceive == NULL)
949     return FAILURE;
950   else if (nReceiveBufferSize == 0)
951   {
952     /* Some VNC servers (e.g. TightVNC 2.0 Beta) simply drop the connection on a bad password */
953     writeError(ERR_DEBUG_MODULE, "[%s] VNC Authentication - Failed (no response from server)", MODULE_NAME);
954     (*psLogin)->iResult = LOGIN_RESULT_FAIL;
955     iRet = MSTATE_NEW;
956   }
957   else if (nReceiveBufferSize >= 4)
958   {
959     switch (bufReceive[3])
960     {
961       case 0x00:
962         writeError(ERR_DEBUG_MODULE, "[%s] VNC Authentication - Success", MODULE_NAME);
963         (*psLogin)->iResult = LOGIN_RESULT_SUCCESS;
964         iRet = MSTATE_EXITING;
965 
966         // TODO: Is this only for UltraVNC?
967         sendExit(hSocket);
968         break;
969       case 0x01:
970         if ((nReceiveBufferSize > 8) && (strstr((char *)bufReceive + 8, "Connection rejected by user") != NULL))
971         {
972           writeError(ERR_DEBUG_MODULE, "[%s] VNC Authentication - Success (User rejected connection)", MODULE_NAME);
973           (*psLogin)->pErrorMsg = malloc( 40 + 1 );
974           memset((*psLogin)->pErrorMsg, 0, 40 + 1 );
975           sprintf((*psLogin)->pErrorMsg, "User rejected connection request.");
976           (*psLogin)->iResult = LOGIN_RESULT_SUCCESS;
977           iRet = MSTATE_EXITING;
978         }
979         else
980         {
981           writeError(ERR_DEBUG_MODULE, "[%s] VNC Authentication - Failed", MODULE_NAME);
982           (*psLogin)->iResult = LOGIN_RESULT_FAIL;
983           iRet = MSTATE_NEW;
984         }
985         break;
986       default:
987         writeError(ERR_ERROR, "[%s] VNC Authentication - Unknown Response: %d", MODULE_NAME, bufReceive[3]);
988         (*psLogin)->iResult = LOGIN_RESULT_ERROR;
989         iRet = MSTATE_EXITING;
990         break;
991     }
992   }
993   else
994   {
995     writeError(ERR_ERROR, "[%s] VNC Authentication - Unknown Response", MODULE_NAME);
996     (*psLogin)->iResult = LOGIN_RESULT_ERROR;
997     iRet = MSTATE_EXITING;
998   }
999 
1000   setPassResult((*psLogin), szPassword);
1001 
1002   return(iRet);
1003 }
1004 
1005 #else
1006 
summaryUsage(char ** ppszSummary)1007 void summaryUsage(char **ppszSummary)
1008 {
1009   // Memory for ppszSummary will be allocated here - caller is responsible for freeing it
1010   int  iLength = 0;
1011 
1012 
1013   if (*ppszSummary == NULL)
1014   {
1015     iLength = strlen(MODULE_SUMMARY_USAGE) + strlen(MODULE_VERSION) + strlen(MODULE_SUMMARY_FORMAT) + strlen(OPENSSL_WARNING) + 1;
1016     *ppszSummary = (char*)malloc(iLength);
1017     memset(*ppszSummary, 0, iLength);
1018     snprintf(*ppszSummary, iLength, MODULE_SUMMARY_FORMAT_WARN, MODULE_SUMMARY_USAGE, MODULE_VERSION, OPENSSL_WARNING);
1019   }
1020   else
1021   {
1022     writeError(ERR_ERROR, "%s reports an error in summaryUsage() : ppszSummary must be NULL when called", MODULE_NAME);
1023   }
1024 }
1025 
showUsage()1026 void showUsage()
1027 {
1028   writeVerbose(VB_NONE, "%s (%s) %s :: %s\n", MODULE_NAME, MODULE_VERSION, MODULE_AUTHOR, MODULE_SUMMARY_USAGE);
1029   writeVerbose(VB_NONE, "** Module was not properly built. Is OPENSSL installed correctly? **");
1030   writeVerbose(VB_NONE, "");
1031 }
1032 
go(sLogin * logins,int argc,char * argv[])1033 int go(sLogin* logins, int argc, char *argv[])
1034 {
1035   writeVerbose(VB_NONE, "%s (%s) %s :: %s\n", MODULE_NAME, MODULE_VERSION, MODULE_AUTHOR, MODULE_SUMMARY_USAGE);
1036   writeVerbose(VB_NONE, "** Module was not properly built. Is OPENSSL installed correctly? **");
1037   writeVerbose(VB_NONE, "");
1038   return FAILURE;
1039 }
1040 
1041 #endif
1042