diff --git a/ad/GOAD-Light/scripts/constrained_delegation_kerb_only.ps1 b/ad/GOAD-Light/scripts/constrained_delegation_kerb_only.ps1 index 27771189..fc2787c5 100644 --- a/ad/GOAD-Light/scripts/constrained_delegation_kerb_only.ps1 +++ b/ad/GOAD-Light/scripts/constrained_delegation_kerb_only.ps1 @@ -1,4 +1,18 @@ # https://www.thehacker.recipes/ad/movement/kerberos/delegations/constrained#without-protocol-transition -Set-ADComputer -Identity "castelblack$" -ServicePrincipalNames @{Add='HTTP/winterfell.north.sevenkingdoms.local'} -Set-ADComputer -Identity "castelblack$" -Add @{'msDS-AllowedToDelegateTo'=@('HTTP/winterfell.north.sevenkingdoms.local','HTTP/winterfell')} -# Set-ADComputer -Identity "castelblack$" -Add @{'msDS-AllowedToDelegateTo'=@('CIFS/winterfell.north.sevenkingdoms.local','CIFS/winterfell')} +$identity = 'castelblack$' +$spn = 'HTTP/winterfell.north.sevenkingdoms.local' +$delegateTo = @('HTTP/winterfell.north.sevenkingdoms.local', 'HTTP/winterfell') +# $delegateTo = @('CIFS/winterfell.north.sevenkingdoms.local', 'CIFS/winterfell') + +# Re-adding a value a multi-valued attribute already holds is an LDAP constraint +# violation, which fails the play on a lab reset, so only add what is missing. +$computer = Get-ADComputer -Identity $identity -Properties ServicePrincipalNames, 'msDS-AllowedToDelegateTo' + +if ($computer.ServicePrincipalNames -notcontains $spn) { + Set-ADComputer -Identity $identity -ServicePrincipalNames @{Add = $spn } +} + +$missing = @($delegateTo | Where-Object { $computer.'msDS-AllowedToDelegateTo' -notcontains $_ }) +if ($missing.Count -gt 0) { + Set-ADComputer -Identity $identity -Add @{'msDS-AllowedToDelegateTo' = $missing } +} diff --git a/ad/GOAD-Light/scripts/constrained_delegation_use_any.ps1 b/ad/GOAD-Light/scripts/constrained_delegation_use_any.ps1 index 4d33697d..13cb90fe 100644 --- a/ad/GOAD-Light/scripts/constrained_delegation_use_any.ps1 +++ b/ad/GOAD-Light/scripts/constrained_delegation_use_any.ps1 @@ -1,4 +1,20 @@ # https://www.thehacker.recipes/ad/movement/kerberos/delegations/constrained#with-protocol-transition -Set-ADUser -Identity "jon.snow" -ServicePrincipalNames @{Add='CIFS/winterfell.north.sevenkingdoms.local'} -Get-ADUser -Identity "jon.snow" | Set-ADAccountControl -TrustedToAuthForDelegation $true -Set-ADUser -Identity "jon.snow" -Add @{'msDS-AllowedToDelegateTo'=@('CIFS/winterfell.north.sevenkingdoms.local','CIFS/winterfell')} +$identity = 'jon.snow' +$spn = 'CIFS/winterfell.north.sevenkingdoms.local' +$delegateTo = @('CIFS/winterfell.north.sevenkingdoms.local', 'CIFS/winterfell') + +# Re-adding a value a multi-valued attribute already holds is an LDAP constraint +# violation, which fails the play on a lab reset, so only add what is missing. +# jon.snow already carries a kerberoastable SPN from ad-data: add, never replace. +$user = Get-ADUser -Identity $identity -Properties ServicePrincipalNames, 'msDS-AllowedToDelegateTo' + +if ($user.ServicePrincipalNames -notcontains $spn) { + Set-ADUser -Identity $identity -ServicePrincipalNames @{Add = $spn } +} + +Set-ADAccountControl -Identity $identity -TrustedToAuthForDelegation $true + +$missing = @($delegateTo | Where-Object { $user.'msDS-AllowedToDelegateTo' -notcontains $_ }) +if ($missing.Count -gt 0) { + Set-ADUser -Identity $identity -Add @{'msDS-AllowedToDelegateTo' = $missing } +} diff --git a/ad/GOAD-Light/scripts/ntlm_relay.ps1 b/ad/GOAD-Light/scripts/ntlm_relay.ps1 index 1013d97e..c1e42550 100644 --- a/ad/GOAD-Light/scripts/ntlm_relay.ps1 +++ b/ad/GOAD-Light/scripts/ntlm_relay.ps1 @@ -2,14 +2,10 @@ $task = '/c powershell New-PSDrive -Name "Public" -PSProvider "FileSystem" -Root $repeat = (New-TimeSpan -Minutes 5) $taskName = "ntlm_bot" $user = "north.sevenkingdoms.local\eddard.stark" -$password = "FightP3aceAndHonor!" +$password = "{{ lab.domains[lab.hosts.dc02.domain].users['eddard.stark'].password }}" $action = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "$task" $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval $repeat $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd -$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName } -if($taskExists) { - Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -} -Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings +Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings -Force diff --git a/ad/GOAD-Light/scripts/rdp_scheduler.ps1 b/ad/GOAD-Light/scripts/rdp_scheduler.ps1 index b282ac66..90507b39 100644 --- a/ad/GOAD-Light/scripts/rdp_scheduler.ps1 +++ b/ad/GOAD-Light/scripts/rdp_scheduler.ps1 @@ -2,14 +2,10 @@ $task = '/c powershell c:\setup\bot_rdp.ps1' $repeat = (New-TimeSpan -Minutes 1) $taskName = "connect_bot" $user = "north\robb.stark" -$password = "sexywolfy" +$password = "{{ lab.domains[lab.hosts.dc02.domain].users['robb.stark'].password }}" $action = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "$task" $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval $repeat $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd #$settings.CimInstanceProperties.Item('MultipleInstances').Value = 3 # 3 corresponds to 'Stop the existing instance' -$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName } -if($taskExists) { - Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -} -Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings +Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings -Force diff --git a/ad/GOAD-Light/scripts/responder.ps1 b/ad/GOAD-Light/scripts/responder.ps1 index 639d360f..e0c98006 100644 --- a/ad/GOAD-Light/scripts/responder.ps1 +++ b/ad/GOAD-Light/scripts/responder.ps1 @@ -2,14 +2,10 @@ $task = '/c powershell New-PSDrive -Name "Public" -PSProvider "FileSystem" -Root $repeat = (New-TimeSpan -Minutes 2) $taskName = "responder_bot" $user = "north.sevenkingdoms.local\robb.stark" -$password = "sexywolfy" +$password = "{{ lab.domains[lab.hosts.dc02.domain].users['robb.stark'].password }}" $action = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "$task" $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval $repeat $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd -$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName } -if($taskExists) { - Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -} -Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings +Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings -Force diff --git a/ad/GOAD/scripts/constrained_delegation_kerb_only.ps1 b/ad/GOAD/scripts/constrained_delegation_kerb_only.ps1 index 27771189..fc2787c5 100644 --- a/ad/GOAD/scripts/constrained_delegation_kerb_only.ps1 +++ b/ad/GOAD/scripts/constrained_delegation_kerb_only.ps1 @@ -1,4 +1,18 @@ # https://www.thehacker.recipes/ad/movement/kerberos/delegations/constrained#without-protocol-transition -Set-ADComputer -Identity "castelblack$" -ServicePrincipalNames @{Add='HTTP/winterfell.north.sevenkingdoms.local'} -Set-ADComputer -Identity "castelblack$" -Add @{'msDS-AllowedToDelegateTo'=@('HTTP/winterfell.north.sevenkingdoms.local','HTTP/winterfell')} -# Set-ADComputer -Identity "castelblack$" -Add @{'msDS-AllowedToDelegateTo'=@('CIFS/winterfell.north.sevenkingdoms.local','CIFS/winterfell')} +$identity = 'castelblack$' +$spn = 'HTTP/winterfell.north.sevenkingdoms.local' +$delegateTo = @('HTTP/winterfell.north.sevenkingdoms.local', 'HTTP/winterfell') +# $delegateTo = @('CIFS/winterfell.north.sevenkingdoms.local', 'CIFS/winterfell') + +# Re-adding a value a multi-valued attribute already holds is an LDAP constraint +# violation, which fails the play on a lab reset, so only add what is missing. +$computer = Get-ADComputer -Identity $identity -Properties ServicePrincipalNames, 'msDS-AllowedToDelegateTo' + +if ($computer.ServicePrincipalNames -notcontains $spn) { + Set-ADComputer -Identity $identity -ServicePrincipalNames @{Add = $spn } +} + +$missing = @($delegateTo | Where-Object { $computer.'msDS-AllowedToDelegateTo' -notcontains $_ }) +if ($missing.Count -gt 0) { + Set-ADComputer -Identity $identity -Add @{'msDS-AllowedToDelegateTo' = $missing } +} diff --git a/ad/GOAD/scripts/constrained_delegation_use_any.ps1 b/ad/GOAD/scripts/constrained_delegation_use_any.ps1 index 7dcffde0..fc1cbb2b 100644 --- a/ad/GOAD/scripts/constrained_delegation_use_any.ps1 +++ b/ad/GOAD/scripts/constrained_delegation_use_any.ps1 @@ -1,3 +1,19 @@ -Set-ADUser -Identity "jon.snow" -ServicePrincipalNames @{Add='CIFS/thewall.north.sevenkingdoms.local'} -Get-ADUser -Identity "jon.snow" | Set-ADAccountControl -TrustedToAuthForDelegation $true -Set-ADUser -Identity "jon.snow" -Add @{'msDS-AllowedToDelegateTo'=@('CIFS/winterfell.north.sevenkingdoms.local','CIFS/winterfell')} +$identity = 'jon.snow' +$spn = 'CIFS/thewall.north.sevenkingdoms.local' +$delegateTo = @('CIFS/winterfell.north.sevenkingdoms.local', 'CIFS/winterfell') + +# Re-adding a value a multi-valued attribute already holds is an LDAP constraint +# violation, which fails the play on a lab reset, so only add what is missing. +# jon.snow already carries a kerberoastable SPN from ad-data: add, never replace. +$user = Get-ADUser -Identity $identity -Properties ServicePrincipalNames, 'msDS-AllowedToDelegateTo' + +if ($user.ServicePrincipalNames -notcontains $spn) { + Set-ADUser -Identity $identity -ServicePrincipalNames @{Add = $spn } +} + +Set-ADAccountControl -Identity $identity -TrustedToAuthForDelegation $true + +$missing = @($delegateTo | Where-Object { $user.'msDS-AllowedToDelegateTo' -notcontains $_ }) +if ($missing.Count -gt 0) { + Set-ADUser -Identity $identity -Add @{'msDS-AllowedToDelegateTo' = $missing } +} diff --git a/ad/GOAD/scripts/ntlm_relay.ps1 b/ad/GOAD/scripts/ntlm_relay.ps1 index 1013d97e..c1e42550 100644 --- a/ad/GOAD/scripts/ntlm_relay.ps1 +++ b/ad/GOAD/scripts/ntlm_relay.ps1 @@ -2,14 +2,10 @@ $task = '/c powershell New-PSDrive -Name "Public" -PSProvider "FileSystem" -Root $repeat = (New-TimeSpan -Minutes 5) $taskName = "ntlm_bot" $user = "north.sevenkingdoms.local\eddard.stark" -$password = "FightP3aceAndHonor!" +$password = "{{ lab.domains[lab.hosts.dc02.domain].users['eddard.stark'].password }}" $action = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "$task" $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval $repeat $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd -$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName } -if($taskExists) { - Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -} -Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings +Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings -Force diff --git a/ad/GOAD/scripts/rdp_scheduler.ps1 b/ad/GOAD/scripts/rdp_scheduler.ps1 index b282ac66..90507b39 100644 --- a/ad/GOAD/scripts/rdp_scheduler.ps1 +++ b/ad/GOAD/scripts/rdp_scheduler.ps1 @@ -2,14 +2,10 @@ $task = '/c powershell c:\setup\bot_rdp.ps1' $repeat = (New-TimeSpan -Minutes 1) $taskName = "connect_bot" $user = "north\robb.stark" -$password = "sexywolfy" +$password = "{{ lab.domains[lab.hosts.dc02.domain].users['robb.stark'].password }}" $action = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "$task" $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval $repeat $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd #$settings.CimInstanceProperties.Item('MultipleInstances').Value = 3 # 3 corresponds to 'Stop the existing instance' -$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName } -if($taskExists) { - Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -} -Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings +Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings -Force diff --git a/ad/GOAD/scripts/responder.ps1 b/ad/GOAD/scripts/responder.ps1 index 639d360f..e0c98006 100644 --- a/ad/GOAD/scripts/responder.ps1 +++ b/ad/GOAD/scripts/responder.ps1 @@ -2,14 +2,10 @@ $task = '/c powershell New-PSDrive -Name "Public" -PSProvider "FileSystem" -Root $repeat = (New-TimeSpan -Minutes 2) $taskName = "responder_bot" $user = "north.sevenkingdoms.local\robb.stark" -$password = "sexywolfy" +$password = "{{ lab.domains[lab.hosts.dc02.domain].users['robb.stark'].password }}" $action = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "$task" $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval $repeat $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd -$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName } -if($taskExists) { - Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -} -Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings +Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings -Force diff --git a/ansible/roles/ps/tasks/main.yml b/ansible/roles/ps/tasks/main.yml index ee7b98cd..0081b766 100644 --- a/ansible/roles/ps/tasks/main.yml +++ b/ansible/roles/ps/tasks/main.yml @@ -1,5 +1,11 @@ --- +# Scripts are rendered as Jinja templates rather than read verbatim, so they +# can pull values such as bot-account passwords from the lab config instead of +# hardcoding them. lookup('file') returns AnsibleUnsafeText, which Ansible +# never re-templates by design, so a Jinja expression inside a script read that +# way would reach the host literally. No lab script contains a Jinja opening +# sequence of its own, so rendering every script is safe. - name: Play task {{ ps_script }} ansible.windows.win_shell: | - {{ lookup('file', ps_script) }} + {{ lookup('template', ps_script) }} register: ps_result