3 Commits

Author SHA1 Message Date
tomas.kracmar af945f529e Release v2.4.3: fix tokenGroups retrieval and DirectoryEntry LDAP paths
Test-ReplicationPermissions:
- Replaced DirectoryEntry.RefreshCache tokenGroups retrieval with
  Get-ADUser -Properties tokenGroups. DirectoryEntry does not
  understand URI percent-encoding, so the v2.4.1 EscapeDataString
  fix caused 'invalid dn syntax' errors.
- Removed EscapeDataString from the ACL DirectoryEntry path as
  well; DirectoryEntry expects raw LDAP ADSI path syntax.

All versions bumped to unified v2.4.3.
2026-06-09 14:14:45 +02:00
tomas.kracmar 03aa72f999 Release v2.4.2: replace em-dashes with ASCII hyphens to fix encoding parse errors
UTF-8 em-dashes (U+2014) in Elysium.Common.ps1 string literals were
being misinterpreted by Windows PowerShell as containing quote
characters when the file was read without a UTF-8 BOM. This caused
cascading parse errors: unexpected tokens, missing closing braces,
and missing catch blocks.

All em-dashes in .ps1 files have been replaced with ASCII hyphens.
All versions bumped to unified v2.4.2.
2026-06-09 13:51:13 +02:00
tomas.kracmar 10cbf0285d Release v2.4.1: URI-escape DNs in DirectoryEntry LDAP URLs
Test-ReplicationPermissions and Test-DCClockSkew now escape
Distinguished Names via [System.Uri]::EscapeDataString before
constructing DirectoryEntry LDAP URLs. This prevents URL
mis-parsing when DNs contain /, #, or other reserved characters.

All versions bumped to unified v2.4.1.
2026-06-09 13:42:34 +02:00
11 changed files with 42 additions and 24 deletions
+2 -2
View File
@@ -8,7 +8,7 @@
################################################## ##################################################
## Project: Elysium ## ## Project: Elysium ##
## File: Bump-Version.ps1 ## ## File: Bump-Version.ps1 ##
## Version: 2.4.0 ## ## Version: 2.4.3 ##
## Support: support@cqre.net ## ## Support: support@cqre.net ##
################################################## ##################################################
@@ -149,7 +149,7 @@ if (-not $SkipChangelog) {
--- ---
## [$NewVersion] $today ## [$NewVersion] - $today
### Changed ### Changed
- (describe your change here) - (describe your change here)
+22
View File
@@ -6,6 +6,28 @@ Starting with **v2.2.0**, Elysium uses a **unified project version**. All script
--- ---
## [2.4.3] — 2026-06-09
### Fixed
- Replaced the `DirectoryEntry` + `RefreshCache` tokenGroups retrieval in `Test-ReplicationPermissions` with `Get-ADUser -Properties tokenGroups`. The previous `DirectoryEntry` approach was broken by the v2.4.1 URI-escaping "fix" (`EscapeDataString` produces percent-encoded paths that ADSI `DirectoryEntry` cannot parse, causing "invalid dn syntax" errors).
- Removed `EscapeDataString` from the ACL-reading `DirectoryEntry` path in `Test-ReplicationPermissions` as well, since `DirectoryEntry` expects raw LDAP path syntax, not URI encoding.
---
## [2.4.2] — 2026-06-09
### Fixed
- Replaced UTF-8 em-dashes (`\u2014`) in `Elysium.Common.ps1` and `Bump-Version.ps1` with ASCII hyphens. On Windows PowerShell without a UTF-8 BOM, the three-byte em-dash sequence was misinterpreted as containing a quote character, causing cascading parse errors (unexpected token, missing closing `)`/`}`/`catch`, etc.).
---
## [2.4.1] — 2026-06-09
### Fixed
- `Test-ReplicationPermissions` and `Test-DCClockSkew` now URI-escape Distinguished Names via `[System.Uri]::EscapeDataString` before embedding them in `DirectoryEntry` LDAP URLs. DNs containing `/`, `#`, or other reserved characters previously caused URL mis-parsing and constructor failures.
---
## [2.4.0] — 2026-06-09 ## [2.4.0] — 2026-06-09
### Added ### Added
+10 -14
View File
@@ -1,4 +1,4 @@
$script:ElysiumVersion = '2.4.0' $script:ElysiumVersion = '2.4.3'
function Invoke-RestartWithExecutable { function Invoke-RestartWithExecutable {
param( param(
@@ -342,15 +342,11 @@ function Test-ReplicationPermissions {
[void]$callerSids.Add($adUser.SID.Value) [void]$callerSids.Add($adUser.SID.Value)
# tokenGroups is a constructed attribute containing all SIDs in the user's token, # tokenGroups is a constructed attribute containing all SIDs in the user's token,
# including nested group memberships more reliable than walking MemberOf recursively # including nested group memberships - more reliable than walking MemberOf recursively
$userDe = New-Object System.DirectoryServices.DirectoryEntry( $adUserWithTokenGroups = Get-ADUser -Identity $samName -Server $Server -Credential $Credential `
"LDAP://$Server/$($adUser.DistinguishedName)", -Properties tokenGroups -ErrorAction Stop
$Credential.UserName, foreach ($sidBytes in $adUserWithTokenGroups.tokenGroups) {
$Credential.GetNetworkCredential().Password $sid = New-Object System.Security.Principal.SecurityIdentifier(@([byte[]]$sidBytes), 0)
)
$userDe.RefreshCache(@('tokenGroups'))
foreach ($sidBytes in $userDe.Properties['tokenGroups']) {
$sid = New-Object System.Security.Principal.SecurityIdentifier($sidBytes, 0)
[void]$callerSids.Add($sid.Value) [void]$callerSids.Add($sid.Value)
} }
@@ -364,7 +360,7 @@ function Test-ReplicationPermissions {
$domainSidStr = $adUser.SID.Value.Substring(0, $adUser.SID.Value.LastIndexOf('-')) $domainSidStr = $adUser.SID.Value.Substring(0, $adUser.SID.Value.LastIndexOf('-'))
$protectedUsersSid = "$domainSidStr-525" $protectedUsersSid = "$domainSidStr-525"
if ($callerSids.Contains($protectedUsersSid)) { if ($callerSids.Contains($protectedUsersSid)) {
Write-Warning ("Account '{0}' is a member of Protected Users. This group restricts Kerberos delegation and RC4 authentication that DSInternals requires for DRS replication access will be denied regardless of assigned rights." -f $Credential.UserName) Write-Warning ("Account '{0}' is a member of Protected Users. This group restricts Kerberos delegation and RC4 authentication that DSInternals requires for DRS replication - access will be denied regardless of assigned rights." -f $Credential.UserName)
} }
} catch { } catch {
Write-Warning ("Could not resolve account SIDs for replication permission pre-check: {0}. Skipping." -f $_.Exception.Message) Write-Warning ("Could not resolve account SIDs for replication permission pre-check: {0}. Skipping." -f $_.Exception.Message)
@@ -392,7 +388,7 @@ function Test-ReplicationPermissions {
$aceExistsForGuid = $false $aceExistsForGuid = $false
foreach ($ace in $acl) { foreach ($ace in $acl) {
if ($ace.AccessControlType -ne [System.Security.AccessControl.AccessControlType]::Allow) { continue } if ($ace.AccessControlType -ne [System.Security.AccessControl.AccessControlType]::Allow) { continue }
# InheritOnly ACEs apply to child objects only the domain root itself is not covered # InheritOnly ACEs apply to child objects only - the domain root itself is not covered
if ([bool]($ace.PropagationFlags -band [System.Security.AccessControl.PropagationFlags]::InheritOnly)) { continue } if ([bool]($ace.PropagationFlags -band [System.Security.AccessControl.PropagationFlags]::InheritOnly)) { continue }
$rights = $ace.ActiveDirectoryRights $rights = $ace.ActiveDirectoryRights
$hasExtended = [bool]($rights -band [System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight) $hasExtended = [bool]($rights -band [System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight)
@@ -441,9 +437,9 @@ function Test-DCClockSkew {
[System.Globalization.DateTimeStyles]::AssumeUniversal).ToUniversalTime() [System.Globalization.DateTimeStyles]::AssumeUniversal).ToUniversalTime()
$skewSeconds = [Math]::Abs(([datetime]::UtcNow - $dcTime).TotalSeconds) $skewSeconds = [Math]::Abs(([datetime]::UtcNow - $dcTime).TotalSeconds)
if ($skewSeconds -gt 300) { if ($skewSeconds -gt 300) {
Write-Warning ("Clock skew of {0:N0}s with '{1}' exceeds Kerberos limit of 300s authentication will fail. Sync the clock: w32tm /resync /force" -f $skewSeconds, $Server) Write-Warning ("Clock skew of {0:N0}s with '{1}' exceeds Kerberos limit of 300s - authentication will fail. Sync the clock: w32tm /resync /force" -f $skewSeconds, $Server)
} elseif ($skewSeconds -gt 60) { } elseif ($skewSeconds -gt 60) {
Write-Warning ("Clock skew of {0:N0}s detected with '{1}'. Kerberos allows up to 300s approaching the limit." -f $skewSeconds, $Server) Write-Warning ("Clock skew of {0:N0}s detected with '{1}'. Kerberos allows up to 300s - approaching the limit." -f $skewSeconds, $Server)
} else { } else {
Write-Host ("[+] Clock skew with '{0}': {1:N0}s (OK)." -f $Server, $skewSeconds) Write-Host ("[+] Clock skew with '{0}': {1:N0}s (OK)." -f $Server, $skewSeconds)
} }
+1 -1
View File
@@ -7,7 +7,7 @@
################################################## ##################################################
## Project: Elysium ## ## Project: Elysium ##
## File: Elysium.ps1 ## ## File: Elysium.ps1 ##
## Version: 2.4.0 ## ## Version: 2.4.3 ##
## Support: support@cqre.net ## ## Support: support@cqre.net ##
################################################## ##################################################
+1 -1
View File
@@ -8,7 +8,7 @@
################################################## ##################################################
## Project: Elysium ## ## Project: Elysium ##
## File: ElysiumSettings.txt ## ## File: ElysiumSettings.txt ##
## Version: 2.4.0 ## ## Version: 2.4.3 ##
## Support: support@cqre.net ## ## Support: support@cqre.net ##
################################################## ##################################################
+1 -1
View File
@@ -7,7 +7,7 @@
################################################## ##################################################
## Project: Elysium ## ## Project: Elysium ##
## File: Extract-NTHashes.ps1 ## ## File: Extract-NTHashes.ps1 ##
## Version: 2.4.0 ## ## Version: 2.4.3 ##
## Support: support@cqre.net ## ## Support: support@cqre.net ##
################################################## ##################################################
+1 -1
View File
@@ -7,7 +7,7 @@
################################################## ##################################################
## Project: Elysium ## ## Project: Elysium ##
## File: Prepare-KHDBStorage.ps1 ## ## File: Prepare-KHDBStorage.ps1 ##
## Version: 2.4.0 ## ## Version: 2.4.3 ##
## Support: support@cqre.net ## ## Support: support@cqre.net ##
################################################## ##################################################
+1 -1
View File
@@ -8,7 +8,7 @@
################################################## ##################################################
## Project: Elysium ## ## Project: Elysium ##
## File: Test-WeakADPasswords.ps1 ## ## File: Test-WeakADPasswords.ps1 ##
## Version: 2.4.0 ## ## Version: 2.4.3 ##
## Support: support@cqre.net ## ## Support: support@cqre.net ##
################################################## ##################################################
+1 -1
View File
@@ -7,7 +7,7 @@
################################################## ##################################################
## Project: Elysium ## ## Project: Elysium ##
## File: Uninstall.ps1 ## ## File: Uninstall.ps1 ##
## Version: 2.4.0 ## ## Version: 2.4.3 ##
## Support: support@cqre.net ## ## Support: support@cqre.net ##
################################################## ##################################################
+1 -1
View File
@@ -7,7 +7,7 @@
################################################## ##################################################
## Project: Elysium ## ## Project: Elysium ##
## File: Update-KHDB.ps1 ## ## File: Update-KHDB.ps1 ##
## Version: 2.4.0 ## ## Version: 2.4.3 ##
## Support: support@cqre.net ## ## Support: support@cqre.net ##
################################################## ##################################################
+1 -1
View File
@@ -7,7 +7,7 @@
################################################## ##################################################
## Project: Elysium ## ## Project: Elysium ##
## File: Update-LithnetStore.ps1 ## ## File: Update-LithnetStore.ps1 ##
## Version: 2.4.0 ## ## Version: 2.4.3 ##
## Support: support@cqre.net ## ## Support: support@cqre.net ##
################################################## ##################################################