1 
2 /***************************************************************************
3  * Service.cc -- The "Service" class encapsulates every bit of information *
4  * about the associated target's (Target class) service. Service-specific  *
5  * options, statistical and timing information as well as functions for    *
6  * handling username/password list iteration all belong to this class.     *
7  *                                                                         *
8  ***********************IMPORTANT NMAP LICENSE TERMS************************
9  *                                                                         *
10  * The Nmap Security Scanner is (C) 1996-2019 Insecure.Com LLC ("The Nmap  *
11  * Project"). Nmap is also a registered trademark of the Nmap Project.     *
12  * This program is free software; you may redistribute and/or modify it    *
13  * under the terms of the GNU General Public License as published by the   *
14  * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE   *
15  * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN.  This guarantees your   *
16  * right to use, modify, and redistribute this software under certain      *
17  * conditions.  If you wish to embed Nmap technology into proprietary      *
18  * software, we sell alternative licenses (contact sales@nmap.com).        *
19  * Dozens of software vendors already license Nmap technology such as      *
20  * host discovery, port scanning, OS detection, version detection, and     *
21  * the Nmap Scripting Engine.                                              *
22  *                                                                         *
23  * Note that the GPL places important restrictions on "derivative works",  *
24  * yet it does not provide a detailed definition of that term.  To avoid   *
25  * misunderstandings, we interpret that term as broadly as copyright law   *
26  * allows.  For example, we consider an application to constitute a        *
27  * derivative work for the purpose of this license if it does any of the   *
28  * following with any software or content covered by this license          *
29  * ("Covered Software"):                                                   *
30  *                                                                         *
31  * o Integrates source code from Covered Software.                         *
32  *                                                                         *
33  * o Reads or includes copyrighted data files, such as Nmap's nmap-os-db   *
34  * or nmap-service-probes.                                                 *
35  *                                                                         *
36  * o Is designed specifically to execute Covered Software and parse the    *
37  * results (as opposed to typical shell or execution-menu apps, which will *
38  * execute anything you tell them to).                                     *
39  *                                                                         *
40  * o Includes Covered Software in a proprietary executable installer.  The *
41  * installers produced by InstallShield are an example of this.  Including *
42  * Nmap with other software in compressed or archival form does not        *
43  * trigger this provision, provided appropriate open source decompression  *
44  * or de-archiving software is widely available for no charge.  For the    *
45  * purposes of this license, an installer is considered to include Covered *
46  * Software even if it actually retrieves a copy of Covered Software from  *
47  * another source during runtime (such as by downloading it from the       *
48  * Internet).                                                              *
49  *                                                                         *
50  * o Links (statically or dynamically) to a library which does any of the  *
51  * above.                                                                  *
52  *                                                                         *
53  * o Executes a helper program, module, or script to do any of the above.  *
54  *                                                                         *
55  * This list is not exclusive, but is meant to clarify our interpretation  *
56  * of derived works with some common examples.  Other people may interpret *
57  * the plain GPL differently, so we consider this a special exception to   *
58  * the GPL that we apply to Covered Software.  Works which meet any of     *
59  * these conditions must conform to all of the terms of this license,      *
60  * particularly including the GPL Section 3 requirements of providing      *
61  * source code and allowing free redistribution of the work as a whole.    *
62  *                                                                         *
63  * As another special exception to the GPL terms, the Nmap Project grants  *
64  * permission to link the code of this program with any version of the     *
65  * OpenSSL library which is distributed under a license identical to that  *
66  * listed in the included docs/licenses/OpenSSL.txt file, and distribute   *
67  * linked combinations including the two.                                  *
68  *                                                                         *
69  * The Nmap Project has permission to redistribute Npcap, a packet         *
70  * capturing driver and library for the Microsoft Windows platform.        *
71  * Npcap is a separate work with it's own license rather than this Nmap    *
72  * license.  Since the Npcap license does not permit redistribution        *
73  * without special permission, our Nmap Windows binary packages which      *
74  * contain Npcap may not be redistributed without special permission.      *
75  *                                                                         *
76  * Any redistribution of Covered Software, including any derived works,    *
77  * must obey and carry forward all of the terms of this license, including *
78  * obeying all GPL rules and restrictions.  For example, source code of    *
79  * the whole work must be provided and free redistribution must be         *
80  * allowed.  All GPL references to "this License", are to be treated as    *
81  * including the terms and conditions of this license text as well.        *
82  *                                                                         *
83  * Because this license imposes special exceptions to the GPL, Covered     *
84  * Work may not be combined (even as part of a larger work) with plain GPL *
85  * software.  The terms, conditions, and exceptions of this license must   *
86  * be included as well.  This license is incompatible with some other open *
87  * source licenses as well.  In some cases we can relicense portions of    *
88  * Nmap or grant special permissions to use it in other open source        *
89  * software.  Please contact fyodor@nmap.org with any such requests.       *
90  * Similarly, we don't incorporate incompatible open source software into  *
91  * Covered Software without special permission from the copyright holders. *
92  *                                                                         *
93  * If you have any questions about the licensing restrictions on using     *
94  * Nmap in other works, we are happy to help.  As mentioned above, we also *
95  * offer an alternative license to integrate Nmap into proprietary         *
96  * applications and appliances.  These contracts have been sold to dozens  *
97  * of software vendors, and generally include a perpetual license as well  *
98  * as providing support and updates.  They also fund the continued         *
99  * development of Nmap.  Please email sales@nmap.com for further           *
100  * information.                                                            *
101  *                                                                         *
102  * If you have received a written license agreement or contract for        *
103  * Covered Software stating terms other than these, you may choose to use  *
104  * and redistribute Covered Software under those terms instead of these.   *
105  *                                                                         *
106  * Source is provided to this software because we believe users have a     *
107  * right to know exactly what a program is going to do before they run it. *
108  * This also allows you to audit the software for security holes.          *
109  *                                                                         *
110  * Source code also allows you to port Nmap to new platforms, fix bugs,    *
111  * and add new features.  You are highly encouraged to send your changes   *
112  * to the dev@nmap.org mailing list for possible incorporation into the    *
113  * main distribution.  By sending these changes to Fyodor or one of the    *
114  * Insecure.Org development mailing lists, or checking them into the Nmap  *
115  * source code repository, it is understood (unless you specify            *
116  * otherwise) that you are offering the Nmap Project the unlimited,        *
117  * non-exclusive right to reuse, modify, and relicense the code.  Nmap     *
118  * will always be available Open Source, but this is important because     *
119  * the inability to relicense code has caused devastating problems for     *
120  * other Free Software projects (such as KDE and NASM).  We also           *
121  * occasionally relicense the code to third parties as discussed above.    *
122  * If you wish to specify special license conditions of your               *
123  * contributions, just say so when you send them.                          *
124  *                                                                         *
125  * This program is distributed in the hope that it will be useful, but     *
126  * WITHOUT ANY WARRANTY; without even the implied warranty of              *
127  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the Nmap      *
128  * license file for more details (it's in a COPYING file included with     *
129  * Nmap, and also available from https://svn.nmap.org/nmap/COPYING)        *
130  *                                                                         *
131  ***************************************************************************/
132 
133 #include "Service.h"
134 #include "NcrackOps.h"
135 
136 extern NcrackOps o;
137 
138 
139 Service::
Service()140 Service()
141 {
142   static unsigned long id = 0;
143   name = NULL;
144   target = NULL;
145   proto = IPPROTO_TCP;
146   portno = 0;
147 
148   uid = id++;
149 
150   loginlist_fini = false;
151   list_active = true;
152   list_full = false;
153   list_wait = false;
154   list_pairfini = false;
155   list_finishing = false;
156   list_finished = false;
157   just_started = true;
158   more_rounds = false;
159   skip_username = false;
160 
161   end.orly = false;
162   end.reason = NULL;
163 
164   failed_connections = 0;
165   total_attempts = 0;
166   finished_attempts = 0;
167   supported_attempts = 0;
168   active_connections = 0;
169 
170   min_connection_limit = -1;
171   max_connection_limit = -1;
172   ideal_parallelism = 1;  /* we start with 1 connection exactly */
173   auth_tries = -1;
174   connection_delay = -1;
175   connection_retries = -1;
176   timeout = -1;
177   path = Strndup("/", 2); /* path is '/' by default */
178 
179   db = Strndup("admin", 5); /* databse is 'admin' by default */
180   domain = Strndup("Workstation", 11); /* domain is 'Workstation' by default */
181 
182   ssl = false;
183 
184   module_data = NULL;
185   memset(&last, 0, sizeof(last));
186   UserArray = NULL;
187   PassArray = NULL;
188   hostinfo = NULL;
189   memset(&last_auth_rate, 0, sizeof(last_auth_rate));
190 
191   htn.msecs_used = 0;
192   htn.toclock_running = false;
193   htn.host_start = htn.host_end = 0;
194 
195   linear_state = LINEAR_INIT;
196 }
197 
198 /* copy constructor */
199 Service::
Service(const Service & ref)200 Service(const Service& ref)
201 {
202   name = strdup(ref.name);
203   proto = ref.proto;
204   portno = ref.portno;
205 
206   uid = ref.uid;
207 
208   min_connection_limit = ref.min_connection_limit;
209   max_connection_limit = ref.max_connection_limit;
210   auth_tries = ref.auth_tries;
211   connection_delay = ref.connection_delay;
212   connection_retries = ref.connection_retries;
213   timeout = ref.timeout;
214   ssl = ref.ssl;
215   //if (path)
216   //  free(path);
217   path = Strndup(ref.path, strlen(ref.path));
218 
219   db = Strndup(ref.db, strlen(ref.db));
220 
221   domain = Strndup(ref.domain, strlen(ref.domain));
222 
223   ideal_parallelism = 1;  /* we start with 1 connection exactly */
224 
225   ssl = ref.ssl;
226   UserArray = ref.UserArray;
227   PassArray = ref.PassArray;
228   uservi = UserArray->begin();
229   passvi = PassArray->begin();
230 
231   failed_connections = 0;
232   total_attempts = 0;
233   finished_attempts = 0;
234   supported_attempts = 0;
235   active_connections = 0;
236 
237   loginlist_fini = false;
238   passlist_fini = false;
239   userlist_fini = false;
240   list_active = true;
241   list_full = false;
242   list_wait = false;
243   list_pairfini = false;
244   list_finishing = false;
245   list_finished = false;
246   just_started = true;
247   more_rounds = false;
248   skip_username = false;
249 
250   end.orly = false;
251   end.reason = NULL;
252 
253   module_data = NULL;
254   hostinfo = NULL;
255   memset(&last, 0, sizeof(last));
256   memset(&last_auth_rate, 0, sizeof(last_auth_rate));
257 
258   htn.msecs_used = 0;
259   htn.toclock_running = false;
260   htn.host_start = htn.host_end = 0;
261 
262   linear_state = ref.linear_state;
263 }
264 
265 Service::
~Service()266 ~Service()
267 {
268   if (name)
269     free(name);
270   if (module_data)
271     free(module_data);
272   if (hostinfo)
273     free(hostinfo);
274   if (end.reason)
275     free(end.reason);
276 }
277 
278 const char *Service::
HostInfo(void)279 HostInfo(void)
280 {
281   if (!hostinfo)
282     hostinfo = (char *) safe_malloc(MAX_HOSTINFO_LEN);
283 
284   if (!target)
285     fatal("%s: tried to print hostinfo with uninitialized Target\n", __func__);
286 
287   Snprintf(hostinfo, MAX_HOSTINFO_LEN, "%s://%s:%hu", name,
288       target->NameIP(), portno);
289   return hostinfo;
290 }
291 
292 
293 /* Add discovered credential to private list */
294 void Service::
addCredential(char * user,char * pass)295 addCredential(char *user, char *pass)
296 {
297   loginpair tmp;
298   tmp.user = user;
299   tmp.pass = pass;
300   credentials_found.push_back(tmp);
301 }
302 
303 uint32_t Service::
getUserlistIndex(void)304 getUserlistIndex(void)
305 {
306   return std::distance(UserArray->begin(), uservi);
307 }
308 
309 void Service::
setUserlistIndex(uint32_t index)310 setUserlistIndex(uint32_t index)
311 {
312   uservi = UserArray->begin() + index;
313 }
314 
315 uint32_t Service::
getPasslistIndex(void)316 getPasslistIndex(void)
317 {
318   return std::distance(PassArray->begin(), passvi);
319 }
320 
321 void Service::
setPasslistIndex(uint32_t index)322 setPasslistIndex(uint32_t index)
323 {
324   passvi = PassArray->begin() + index;
325 }
326 
327 
328 /*
329  * returns -1 for end of login list and empty pool
330  * 0 for successful retrieval through lists
331  * 1 for successful retrieval through pool
332  */
333 int Service::
getNextPair(char ** user,char ** pass)334 getNextPair(char **user, char **pass)
335 {
336   if (!UserArray)
337     fatal("%s: uninitialized UserArray\n", __func__);
338 
339   if (!PassArray)
340     fatal("%s: uninitialized PassArray\n", __func__);
341 
342   loginpair tmp;
343 
344   /* If the login pair pool is not empty, then give priority to these
345    * pairs and extract the first one you find. */
346   if (!pair_pool.empty()) {
347 
348     list <loginpair>::iterator pairli = pair_pool.begin();
349     tmp = pair_pool.front();
350     *user = tmp.user;
351     *pass = tmp.pass;
352     pair_pool.erase(pairli);
353     if (o.debugging > 8)
354       log_write(LOG_STDOUT, "%s Pool: extract '%s' '%s'\n", HostInfo(),
355           tmp.user, tmp.pass);
356     return 1;
357   }
358 
359   if (loginlist_fini)
360     return -1;
361 
362   if (!strcmp(name, "redis")) {
363     if (passvi == PassArray->end()) {
364       if (o.debugging > 8)
365         log_write(LOG_STDOUT, "%s Password list finished!\n", HostInfo());
366       loginlist_fini = true;
367       return -1;
368     }
369     *user = *uservi;
370     *pass = *passvi;
371     passvi++;
372     return 0;
373   }
374 
375   if (!strcmp(name, "mongodb")) {
376     if (skip_username == true) {
377       uservi--;
378       if (o.debugging > 5)
379         log_write(LOG_STDOUT, "%s skipping username!!!! %s\n", HostInfo(), *(uservi));
380       uservi = UserArray->erase(uservi);
381       if (uservi == UserArray->end()) {
382         uservi = UserArray->begin();
383         passvi++;
384         if (passvi == PassArray->end()) {
385           if (o.debugging > 8)
386             log_write(LOG_STDOUT, "%s Password list finished!\n", HostInfo());
387           loginlist_fini = true;
388           return -1;
389         }
390       }
391       //printf("next user: %s\n", *uservi);
392       skip_username = false;
393     }
394   }
395 
396   if (!strcmp(name, "ssh")) {
397 
398     /* catches bug where ssh module crashed when user had specified correct username and
399      * password in the first attempt
400      */
401     if (just_started == false && PassArray->size() == 1 && UserArray->size() == 1) {
402       uservi = UserArray->end();
403       passvi = PassArray->end();
404       loginlist_fini = true;
405       return -1;
406     }
407 
408     /* special case for ssh */
409     if (just_started == true) {
410 
411       /* keep using same username for first timing probe */
412       if (passvi == PassArray->end()) {
413         passvi = PassArray->begin();
414         uservi++;
415         if (uservi == UserArray->end()) {
416           if (o.debugging > 8)
417             log_write(LOG_STDOUT, "%s Username list finished!\n", HostInfo());
418           loginlist_fini = true;
419           return -1;
420         }
421       }
422       *user = *uservi;
423       *pass = *passvi;
424       passvi++;
425 
426       return 0;
427     }
428   }
429 
430   if (o.pairwise && strcmp(name, "mongodb")) {
431 
432     if (uservi == UserArray->end() && passvi == PassArray->end()) {
433       if (o.debugging > 8)
434         log_write(LOG_STDOUT, "%s Password list finished!\n", HostInfo());
435       loginlist_fini = true;
436       return -1;
437     }
438     if (uservi == UserArray->end()) {
439       uservi = UserArray->begin();
440       userlist_fini = true;
441     }
442     if (passvi == PassArray->end()) {
443       passvi = PassArray->begin();
444       passlist_fini = true;
445     }
446     if (userlist_fini == true && passlist_fini == true) {
447       if (o.debugging > 8)
448         log_write(LOG_STDOUT, "%s Password list finished!\n", HostInfo());
449       loginlist_fini = true;
450       return -1;
451     }
452     *pass = *passvi;
453     *user = *uservi;
454     uservi++;
455     passvi++;
456 
457   } else if (o.passwords_first && strcmp(name, "mongodb")) {
458     /* Iteration of password list for each username. */
459     /* If password list finished one iteration then reset the password pointer
460      * to show at the beginning and get next username from username list. */
461     if (passvi == PassArray->end()) {
462       passvi = PassArray->begin();
463       uservi++;
464       if (uservi == UserArray->end()) {
465         if (o.debugging > 8)
466           log_write(LOG_STDOUT, "%s Username list finished!\n", HostInfo());
467         loginlist_fini = true;
468         return -1;
469       }
470     }
471     *user = *uservi;
472     *pass = *passvi;
473     passvi++;
474 
475   } else if (!o.passwords_first || !strcmp(name, "mongodb")) {
476     /* Iteration of username list for each password (default). */
477     /* If username list finished one iteration then reset the username pointer
478      * to show at the beginning and get password from password list. */
479     if (uservi == UserArray->end()) {
480       uservi = UserArray->begin();
481       passvi++;
482       if (passvi == PassArray->end()) {
483         if (o.debugging > 8)
484           log_write(LOG_STDOUT, "%s Password list finished!\n", HostInfo());
485         loginlist_fini = true;
486         return -1;
487       }
488     }
489     *pass = *passvi;
490     *user = *uservi;
491     uservi++;
492   }
493 
494 
495   return 0;
496 }
497 
498 
499 void Service::
removeFromPool(char * user,char * pass)500 removeFromPool(char *user, char *pass)
501 {
502   loginpair tmp;
503   list <loginpair>::iterator li;
504 
505   if (!user || !pass)
506     return;
507 
508   tmp.user = user;
509   tmp.pass = pass;
510 
511   for (li = mirror_pair_pool.begin(); li != mirror_pair_pool.end(); li++) {
512     if ((tmp.user == li->user) && (tmp.pass == li->pass))
513       break;
514   }
515   if (li != mirror_pair_pool.end()) {
516     if (o.debugging > 8) {
517       if (!strcmp(name, "redis"))
518         log_write(LOG_STDOUT, "%s Pool: Removed '%s' \n", HostInfo(), tmp.pass);
519       else
520         log_write(LOG_STDOUT, "%s Pool: Removed %s %s\n", HostInfo(),
521             tmp.user, tmp.pass);
522     }
523     mirror_pair_pool.erase(li);
524   }
525 }
526 
527 
528 
529 void Service::
appendToPool(char * user,char * pass)530 appendToPool(char *user, char *pass)
531 {
532   loginpair tmp;
533   list <loginpair>::iterator li;
534 
535   if (!user)
536     fatal("%s: tried to append NULL user into pair pool", __func__);
537   if (!pass)
538     fatal("%s: tried to append NULL password into pair pool", __func__);
539 
540   tmp.user = user;
541   tmp.pass = pass;
542   pair_pool.push_back(tmp);
543 
544   if (o.debugging > 8) {
545     if (!strcmp(name, "redis"))
546       log_write(LOG_STDOUT, "%s Pool: Append '%s' \n", HostInfo(), tmp.pass);
547     else
548       log_write(LOG_STDOUT, "%s Pool: Append '%s' '%s' \n", HostInfo(),
549           tmp.user, tmp.pass);
550   }
551 
552   /*
553    * Try and see if login pair was already in our mirror pool. Only if
554    * it doesn't already exist, then append it to the list.
555    */
556   for (li = mirror_pair_pool.begin(); li != mirror_pair_pool.end(); li++) {
557     if ((tmp.user == li->user) && (tmp.pass == li->pass))
558       break;
559   }
560   if (li == mirror_pair_pool.end())
561     mirror_pair_pool.push_back(tmp);
562 }
563 
564 
565 bool Service::
isMirrorPoolEmpty(void)566 isMirrorPoolEmpty(void)
567 {
568   return mirror_pair_pool.empty();
569 }
570 
571 
572 bool Service::
isPoolEmpty(void)573 isPoolEmpty(void)
574 {
575   return pair_pool.empty();
576 }
577 
578 
579 double Service::
getPercDone(void)580 getPercDone(void)
581 {
582   double ret = 0.0;
583   vector <char *>::iterator usertmp = uservi;
584   vector <char *>::iterator passtmp = passvi;
585 
586   if (!o.passwords_first) {
587     if (passtmp != PassArray->begin())
588       passtmp--;
589     if (uservi == UserArray->end()) {
590       ret = distance(PassArray->begin(), passtmp) * UserArray->size();
591     } else {
592       if (usertmp != UserArray->begin())
593         usertmp--;
594       ret = distance(PassArray->begin(), passtmp) * UserArray->size()
595         + distance(UserArray->begin(), usertmp);
596     }
597   } else {
598     if (usertmp != UserArray->begin())
599       usertmp--;
600     if (passvi == PassArray->end()) {
601       ret = distance(UserArray->begin(), usertmp) * PassArray->size();
602     } else {
603       if (passtmp != PassArray->begin())
604         passtmp--;
605       ret = distance(UserArray->begin(), usertmp) * PassArray->size()
606         + distance(PassArray->begin(), passtmp);
607     }
608   }
609 
610   if (ret) {
611     ret /= (double) (UserArray->size() * PassArray->size());
612     if (ret >= 0.9999)
613       ret = 0.9999;
614   } else
615     ret = 0.0;
616 
617   return ret;
618 }
619 
620 
621 /*
622  * Starts the timeout clock for the host running (e.g. you are
623  * beginning a scan). If you do not have the current time handy,
624  * you can pass in NULL. When done, call stopTimeOutClock (it will
625  * also automatically be stopped of timedOut() returns true)
626  */
627 void Service::
startTimeOutClock(const struct timeval * now)628 startTimeOutClock(const struct timeval *now) {
629   assert(htn.toclock_running == false);
630   htn.toclock_running = true;
631   if (now) htn.toclock_start = *now;
632   else gettimeofday(&htn.toclock_start, NULL);
633   if (!htn.host_start) htn.host_start = htn.toclock_start.tv_sec;
634 }
635 
636 
637 /* The complement to startTimeOutClock. */
638 void Service::
stopTimeOutClock(const struct timeval * now)639 stopTimeOutClock(const struct timeval *now) {
640   struct timeval tv;
641   assert(htn.toclock_running == true);
642   htn.toclock_running = false;
643   if (now) tv = *now;
644   else gettimeofday(&tv, NULL);
645   htn.msecs_used += timeval_msec_subtract(tv, htn.toclock_start);
646   htn.host_end = tv.tv_sec;
647 }
648 
649 /*
650  * Returns whether the host is timedout. If the timeoutclock is
651  * running, counts elapsed time for that. Pass NULL if you don't have the
652  * current time handy. You might as well also pass NULL if the
653  * clock is not running, as the func won't need the time.
654  */
655 bool Service::
timedOut(const struct timeval * now)656 timedOut(const struct timeval *now) {
657   unsigned long used = htn.msecs_used;
658   struct timeval tv;
659 
660   if (!timeout)
661     return false;
662   if (htn.toclock_running) {
663     if (now)
664       tv = *now;
665     else
666       gettimeofday(&tv, NULL);
667 
668     used += timeval_msec_subtract(tv, htn.toclock_start);
669   }
670 
671   return (used > (unsigned long)timeout)? true : false;
672 }
673 
674 void Service::
setLinearState(size_t state)675 setLinearState(size_t state) {
676 
677   linear_state = state;
678 }
679 
680 
681 size_t Service::
getLinearState(void)682 getLinearState(void) {
683 
684   return linear_state;
685 }
686