From d2e79150ffc9818193538bef7d48911d47ffd2cd Mon Sep 17 00:00:00 2001 From: Alex Flores Date: Sat, 14 Dec 2019 21:22:28 -0500 Subject: [PATCH] global delay flag added to support slower brute/enum (#18) * adds global delay flag * global delay flag added to support slower brute/enum * adds delay to each subcommand * added some logging and updated help, readme --- README.md | 9 ++++++--- cmd/bruteforce.go | 7 ++++--- cmd/bruteuser.go | 5 +++-- cmd/kerbrute.go | 5 +++++ cmd/passwordspray.go | 1 + cmd/setup.go | 4 ++++ cmd/userenum.go | 1 + 7 files changed, 24 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 9fc45d9..05e6085 100644 --- a/README.md +++ b/README.md @@ -31,14 +31,13 @@ The `help` command can be used for more information ``` $ ./kerbrute - __ __ __ / /_____ _____/ /_ _______ __/ /____ / //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \ / ,< / __/ / / /_/ / / / /_/ / /_/ __/ /_/|_|\___/_/ /_.___/_/ \__,_/\__/\___/ -Version: v1.0.0 (43f9ca1) - 03/06/19 - Ronnie Flathers @ropnop +Version: dev (n/a) - 12/14/19 - Ronnie Flathers @ropnop This tool is designed to assist in quickly bruteforcing valid Active Directory accounts through Kerberos Pre-Authentication. It is designed to be used on an internal Windows domain with access to one of the Domain Controllers. @@ -48,6 +47,7 @@ Usage: kerbrute [command] Available Commands: + bruteforce Bruteforce username:password combos, from a file or stdin bruteuser Bruteforce a single user's password from a wordlist help Help about any command passwordspray Test a single password against a list of users @@ -56,6 +56,7 @@ Available Commands: Flags: --dc string The location of the Domain Controller (KDC) to target. If blank, will lookup via DNS + --delay int Delay in millisecond between each attempt. Will always use single thread if set -d, --domain string The full domain to use (e.g. contoso.com) -h, --help help for kerbrute -o, --output string File to write logs to. Optional. @@ -187,4 +188,6 @@ kerbrute_darwin_amd64 kerbrute_linux_amd64 kerbrute_windows_amd64.exe ``` ## Credits -Huge shoutout to jcmturner for his pure Go implementation of KRB5: https://github.com/jcmturner/gokrb5 . An amazing project and very well documented. Couldn't have done any of this without that project. +Huge shoutout to jcmturner for his pure Go implementation of KRB5: https://github.com/jcmturner/gokrb5 . An amazing project and very well documented. Couldn't have done any of this without that project. + +Shoutout to [audibleblink](https://github.com/audibleblink) for the suggestion and implementation of the `delay` option! diff --git a/cmd/bruteforce.go b/cmd/bruteforce.go index 37f81e5..89aa094 100644 --- a/cmd/bruteforce.go +++ b/cmd/bruteforce.go @@ -64,14 +64,15 @@ Scan: break Scan default: comboline := scanner.Text() - if comboline == "" { - continue - } + if comboline == "" { + continue + } username, password, err := util.FormatComboLine(comboline) if err != nil { logger.Log.Debug("[!] Skipping: %q - %v", comboline, err.Error()) continue } + time.Sleep(time.Duration(delay) * time.Millisecond) combosChan <- [2]string{username, password} } } diff --git a/cmd/bruteuser.go b/cmd/bruteuser.go index e13f342..ad7bb7e 100644 --- a/cmd/bruteuser.go +++ b/cmd/bruteuser.go @@ -44,7 +44,7 @@ func bruteForceUser(cmd *cobra.Command, args []string) { var wg sync.WaitGroup wg.Add(threads) - + var scanner *bufio.Scanner if passwordlist != "-" { file, err := os.Open(passwordlist) @@ -61,7 +61,7 @@ func bruteForceUser(cmd *cobra.Command, args []string) { for i := 0; i < threads; i++ { go makeBruteWorker(ctx, passwordsChan, &wg, username) } - + start := time.Now() var password string @@ -72,6 +72,7 @@ Scan: break Scan default: password = scanner.Text() + time.Sleep(time.Duration(delay) * time.Millisecond) passwordsChan <- password } } diff --git a/cmd/kerbrute.go b/cmd/kerbrute.go index 5882812..7774522 100644 --- a/cmd/kerbrute.go +++ b/cmd/kerbrute.go @@ -29,5 +29,10 @@ func init() { rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Log failures and errors") rootCmd.PersistentFlags().BoolVar(&safe, "safe", false, "Safe mode. Will abort if any user comes back as locked out. Default: FALSE") rootCmd.PersistentFlags().IntVarP(&threads, "threads", "t", 10, "Threads to use") + rootCmd.PersistentFlags().IntVarP(&delay, "delay", "", 0, "Delay in millisecond between each attempt. Will always use single thread if set") + + if delay != 0 { + threads = 1 + } } diff --git a/cmd/passwordspray.go b/cmd/passwordspray.go index 0a43436..b016abb 100644 --- a/cmd/passwordspray.go +++ b/cmd/passwordspray.go @@ -88,6 +88,7 @@ Scan: logger.Log.Debugf("[!] %q - %v", usernameline, err.Error()) continue } + time.Sleep(time.Duration(delay) * time.Millisecond) usersChan <- username } } diff --git a/cmd/setup.go b/cmd/setup.go index 04204a0..24583d9 100644 --- a/cmd/setup.go +++ b/cmd/setup.go @@ -15,6 +15,7 @@ var ( logFileName string verbose bool safe bool + delay int threads int stopOnSuccess bool userAsPass = false @@ -43,4 +44,7 @@ func setupSession(cmd *cobra.Command, args []string) { for _, v := range kSession.Kdcs { logger.Log.Infof("\t%s\n", v) } + if delay != 0 { + logger.Log.Infof("Delay set. Using single thread and delaying %dms between attempts\n", delay) + } } diff --git a/cmd/userenum.go b/cmd/userenum.go index 258ed43..3469ff9 100644 --- a/cmd/userenum.go +++ b/cmd/userenum.go @@ -66,6 +66,7 @@ Scan: logger.Log.Debug("[!] %q - %v", usernameline, err.Error()) continue } + time.Sleep(time.Duration(delay) * time.Millisecond) usersChan <- username } }