diff --git a/.gitignore b/.gitignore index 7a3e2fd..c2a78b7 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,9 @@ override.tf.json # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan # example: *tfplan* +terraform/keys/* +terraform/.terraform.lock.hcl +terraform/.terraform/ +dsc/Lab/* +terraform/terraform* +terraform/.terraform* \ No newline at end of file diff --git a/dsc/adlab.ps1 b/dsc/adlab.ps1 new file mode 100644 index 0000000..7c23236 --- /dev/null +++ b/dsc/adlab.ps1 @@ -0,0 +1,1021 @@ +configuration Lab { + + param + ( + [Parameter(Mandatory)] + [pscredential]$safemodeAdministratorCred, + [Parameter(Mandatory)] + [pscredential]$domainCred, + [Parameter(Mandatory)] + [string]$firstDomainName, + [Parameter(Mandatory)] + [string]$secondDomainName, + [Parameter(Mandatory)] + [pscredential]$firstDomainCred + ) + + Import-DscResource -ModuleName ActiveDirectoryDsc + Import-DscResource -ModuleName NetworkingDsc + Import-DscResource -ModuleName ComputerManagementDSC + Import-DscResource -ModuleName PSDesiredStateConfiguration + + Node "First" { + + Computer NewName { + Name = "First-DC" + } + + WindowsFeature ADDSInstall { + Ensure = "Present" + Name = "AD-Domain-Services" + } + + WindowsFeature ADDSTools { + Ensure = "Present" + Name = "RSAT-ADDS" + } + + FirewallProfile DisablePublic { + Enabled = "False" + Name = "Public" + } + + FirewallProfile DisablePrivate { + Enabled = "False" + Name = "Private" + } + + FirewallProfile DisableDomain { + Enabled = "False" + Name = "Domain" + } + + User AdminUser { + Ensure = "Present" + UserName = $domainCred.UserName + Password = $domainCred + } + + Group Administrators { + GroupName = "Administrators" + MembersToInclude = $domainCred.UserName + DependsOn = "[User]AdminUser" + } + + ADDomain CreateDC { + DomainName = $firstDomainName + Credential = $domainCred + SafemodeAdministratorPassword = $safemodeAdministratorCred + DatabasePath = 'C:\NTDS' + LogPath = 'C:\NTDS' + DependsOn = "[WindowsFeature]ADDSInstall" + } + + WaitForADDomain waitFirstDomain { + DomainName = $firstDomainName + DependsOn = "[ADDomain]CreateDC" + } + + DnsServerAddress DnsServerAddress + { + Address = '127.0.0.1', '10.0.2.100' + InterfaceAlias = 'Ethernet' + AddressFamily = 'IPv4' + Validate = $false + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script SetConditionalForwardedZone { + GetScript = { return @{ } } + + TestScript = { + $zone = Get-DnsServerZone -Name $using:secondDomainName -ErrorAction SilentlyContinue + if ($zone -ne $null -and $zone.ZoneType -eq 'Forwarder') { + return $true + } + + return $false + } + + SetScript = { + $ForwardDomainName = $using:secondDomainName + $IpAddresses = @("10.0.2.100") + Add-DnsServerConditionalForwarderZone -Name "$ForwardDomainName" -ReplicationScope "Domain" -MasterServers $IpAddresses + } + + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + ADGroup DomainAdmin { + Ensure = "Present" + GroupName = "Domain Admins" + MembersToInclude = $domainCred.UserName + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + ADUser 'regular.user' + { + Ensure = 'Present' + UserName = 'regular.user' + Password = (New-Object System.Management.Automation.PSCredential("regular.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + ADUser 'dnsadmin.user' + { + Ensure = 'Present' + UserName = 'dnsadmin.user' + Password = (New-Object System.Management.Automation.PSCredential("dnsadmin.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + ADGroup DnsAdmin { + Ensure = "Present" + GroupName = "DnsAdmins" + MembersToInclude = "dnsadmin.user" + DependsOn = "[WaitForADDomain]waitFirstDomain", "[ADUser]dnsadmin.user" + } + + ADUser 'unconstrained.user' + { + Ensure = 'Present' + UserName = 'unconstrained.user' + Password = (New-Object System.Management.Automation.PSCredential("unconstrained.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script "unconstrained.user Unconstrained Delegation Set" + { + SetScript = { + Set-ADAccountControl -Identity "unconstrained.user" -TrustedForDelegation $True + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADUser "unconstrained.user" ) } + } + DependsOn = "[WaitForADDomain]waitFirstDomain", "[ADUser]unconstrained.user" + } + + ADUser 'constrained.user' + { + Ensure = 'Present' + UserName = 'constrained.user' + Password = (New-Object System.Management.Automation.PSCredential("constrained.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script "constrained.user constrained Delegation Set" + { + SetScript = { + $user = (Get-ADUser -Identity "constrained.user").DistinguishedName + Set-ADObject -Identity $user -Add @{"msDS-AllowedToDelegateTo" = @("CIFS/First-DC","CIFS/First-DC.First.local","CIFS/First-DC.first.local/first.local")} + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADUser "constrained.user" ) } + } + DependsOn = "[WaitForADDomain]waitFirstDomain", "[ADUser]constrained.user" + } + + ADComputer "Constrained.Computer" + { + Ensure = "Present" + ComputerName = "Suspicious-PC" + Path = "CN=Computers,DC=first,DC=local" + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script "Suspicious-PC constrained Delegation Set" + { + SetScript = { + $comp = (Get-ADComputer -Identity "Suspicious-PC").DistinguishedName + Set-ADObject -Identity $comp -Add @{"msDS-AllowedToDelegateTo" = @("HTTP/First-DC","HTTP/First-DC.First.local","HTTP/First-DC.first.local/first.local")} + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADComputer "Suspicious-PC" ) } + } + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + ADUser 'userwrite.user' + { + Ensure = 'Present' + UserName = 'userwrite.user' + Password = (New-Object System.Management.Automation.PSCredential("userwrite.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script "userwrite.user Write Permissions on User Node" + { + SetScript = { + $Destination = (Get-ADUser -Identity "constrained.user").DistinguishedName + $Source = (Get-ADUser -Identity "userwrite.user").sid + $Rights = "GenericWrite" + $ADObject = [ADSI]("LDAP://" + $Destination) + $identity = $Source + $adRights = [System.DirectoryServices.ActiveDirectoryRights]$Rights + $type = [System.Security.AccessControl.AccessControlType] "Allow" + $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "All" + $ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $identity,$adRights,$type,$inheritanceType + $ADObject.psbase.ObjectSecurity.AddAccessRule($ACE) + $ADObject.psbase.commitchanges() + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADUser "userwrite.user" ) } + } + DependsOn = "[WaitForADDomain]waitFirstDomain", "[ADUser]userwrite.user" + } + + ADUser 'userall.user' + { + Ensure = 'Present' + UserName = 'userall.user' + Password = (New-Object System.Management.Automation.PSCredential("userall.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script "userall.user GenericAll Permissions on User Node" + { + SetScript = { + $Destination = (Get-ADUser -Identity "userwrite.user").DistinguishedName + $Source = (Get-ADUser -Identity "userall.user").sid + $Rights = "GenericAll" + $ADObject = [ADSI]("LDAP://" + $Destination) + $identity = $Source + $adRights = [System.DirectoryServices.ActiveDirectoryRights]$Rights + $type = [System.Security.AccessControl.AccessControlType] "Allow" + $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "All" + $ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $identity,$adRights,$type,$inheritanceType + $ADObject.psbase.ObjectSecurity.AddAccessRule($ACE) + $ADObject.psbase.commitchanges() + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADUser "userall.user" ) } + } + DependsOn = "[WaitForADDomain]waitFirstDomain", "[ADUser]userall.user" + } + + ADUser 'compwrite.user' + { + Ensure = 'Present' + UserName = 'compwrite.user' + Password = (New-Object System.Management.Automation.PSCredential("compwrite.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script "compwrite.user Write Permissions on Comp Node" + { + SetScript = { + $Destination = (Get-ADComputer -Identity "First-DC").DistinguishedName + $Source = (Get-ADUser -Identity "compwrite.user").sid + $Rights = "GenericWrite" + $ADObject = [ADSI]("LDAP://" + $Destination) + $identity = $Source + $adRights = [System.DirectoryServices.ActiveDirectoryRights]$Rights + $type = [System.Security.AccessControl.AccessControlType] "Allow" + $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "All" + $ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $identity,$adRights,$type,$inheritanceType + $ADObject.psbase.ObjectSecurity.AddAccessRule($ACE) + $ADObject.psbase.commitchanges() + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADUser "compwrite.user" ) } + } + DependsOn = "[WaitForADDomain]waitFirstDomain", "[ADUser]compwrite.user" + } + + ADUser "gpowrite.user" + { + Ensure = 'Present' + UserName = 'gpowrite.user' + Password = (New-Object System.Management.Automation.PSCredential("gpowrite.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script "gpowrite.user Write Permissions on GPO" + { + SetScript = { + Set-GPPermission -Name "Default Domain Controllers Policy" -TargetName "gpowrite.user" -TargetType "User" -PermissionLevel "GpoEdit" + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADUser "gpowrite.user" ) } + } + DependsOn = "[WaitForADDomain]waitFirstDomain", "[ADUser]gpowrite.user" + } + + ADUser 'lapsread.user' + { + Ensure = 'Present' + UserName = 'lapsread.user' + Password = (New-Object System.Management.Automation.PSCredential("lapsread.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + Description = 'LAPS yet to be implemented' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + ADUser 'groupwrite.user' + { + Ensure = 'Present' + UserName = 'groupwrite.user' + Password = (New-Object System.Management.Automation.PSCredential("groupwrite.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script "groupwrite.user Write Permissions on Group" + { + SetScript = { + $Destination = (Get-ADGroup -Identity "Domain Admins").DistinguishedName + $Source = (Get-ADUser -Identity "groupwrite.user").sid + $Rights = "GenericAll" + $ADObject = [ADSI]("LDAP://" + $Destination) + $identity = $Source + $adRights = [System.DirectoryServices.ActiveDirectoryRights]$Rights + $type = [System.Security.AccessControl.AccessControlType] "Allow" + $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "All" + $ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $identity,$adRights,$type,$inheritanceType + $ADObject.psbase.ObjectSecurity.AddAccessRule($ACE) + $ADObject.psbase.commitchanges() + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADUser "groupwrite.user" ) } + } + DependsOn = "[WaitForADDomain]waitFirstDomain", "[ADUser]groupwrite.user" + } + + ADUser 'writedacldc.user' + { + Ensure = 'Present' + UserName = 'writedacldc.user' + Password = (New-Object System.Management.Automation.PSCredential("writedacldc.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script "writedacldc.user WriteDACL Permissions on DC" + { + SetScript = { + $Destination = (Get-ADComputer -Identity "First-DC").DistinguishedName + $Source = (Get-ADUser -Identity "writedacldc.user").sid + $Rights = "WriteDACL" + $ADObject = [ADSI]("LDAP://" + $Destination) + $identity = $Source + $adRights = [System.DirectoryServices.ActiveDirectoryRights]$Rights + $type = [System.Security.AccessControl.AccessControlType] "Allow" + $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "All" + $ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $identity,$adRights,$type,$inheritanceType + $ADObject.psbase.ObjectSecurity.AddAccessRule($ACE) + $ADObject.psbase.commitchanges() + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADUser "writedacldc.user" ) } + } + DependsOn = "[WaitForADDomain]waitFirstDomain", "[ADUser]writedacldc.user" + } + + ADUser 'readgmsa.user' + { + Ensure = 'Present' + UserName = 'readgmsa.user' + Password = (New-Object System.Management.Automation.PSCredential("readgmsa.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + Description = 'GMSA yet to be implemented' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + ADUser 'clearpass.user' + { + Ensure = 'Present' + UserName = 'clearpass.user' + Password = (New-Object System.Management.Automation.PSCredential("clearpass.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script "clearpass.user Password in AD" + { + SetScript = { + Set-ADUser -Identity "clearpass.user" -Description "Remember to remove this! Password@1" + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADUser "clearpass.user" ) } + } + DependsOn = "[WaitForADDomain]waitFirstDomain", "[ADUser]clearpass.user" + } + + ADUser 'roast.user' + { + Ensure = 'Present' + UserName = 'roast.user' + Password = (New-Object System.Management.Automation.PSCredential("roast.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + ServicePrincipalNames = "MSSQL/sql.first.local" + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + ADUser asrep + { + Ensure = 'Present' + UserName = 'asrep.user' + Password = (New-Object System.Management.Automation.PSCredential("asrep.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'first.local' + Path = 'CN=Users,DC=first,DC=local' + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script "asrep.user PreAuth Disable" + { + SetScript = { + Set-ADAccountControl -Identity "asrep.user" -DoesNotRequirePreAuth $true + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADUser "asrep.user" ) } + } + DependsOn = "[WaitForADDomain]waitFirstDomain", "[ADUser]asrep" + } + + Script "User-Server-RDP" + { + SetScript = { + Start-Sleep -Seconds 300 + Invoke-Command -ComputerName "User-Server" -Scriptblock {net localgroup "Remote Desktop Users" "first\domain users" /add} + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADComputer "User-Server" ) } + } + PsDscRunAsCredential = $firstDomainCred + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script "User-Workstation-RDP" { + SetScript = { + Start-Sleep -Seconds 300 + Invoke-Command -ComputerName "User-Workstation" -Scriptblock { net localgroup "Remote Desktop Users" "first\domain users" /add } + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADComputer "User-Workstation" ) } + } + PsDscRunAsCredential = $firstDomainCred + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script "User-Server constrained Delegation Set" + { + SetScript = { + $comp = (Get-ADComputer -Identity "User-Server").DistinguishedName + Set-ADObject -Identity $comp -Add @{"msDS-AllowedToDelegateTo" = @("HOST/First-DC","HOST/First-DC.First.local","HOST/First-DC.first.local/first.local")} + } + TestScript = { + $false + } + GetScript = { + @{ Result = (Get-ADComputer "User-Server" ) } + } + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + + Script DisableSMBSign + { + GetScript = { + return @{ } + } + + TestScript = { + $false + } + + SetScript = { + Set-SmbClientConfiguration -RequireSecuritySignature 0 -EnableSecuritySignature 0 -Confirm -Force + } + } + + Script DisableDefender + { + GetScript = { + return @{ Result = (Get-Content C:\Windows\Temp\DefenderDisable.txt) } + } + + TestScript = { + Test-Path "C:\Windows\Temp\DefenderDisable.txt" + } + + SetScript = { + Uninstall-WindowsFeature -Name Windows-Defender + $sw = New-Object System.IO.StreamWriter("C:\Windows\Temp\DefenderDisable.txt") + $sw.WriteLine("Defender has been uninstalled") + $sw.Close() + $global:DSCMachineStatus = 1 + } + } + } + + Node "UserServer" { + + WaitForAll DC + { + ResourceName = '[ADUser]asrep' + NodeName = 'First-DC' + RetryIntervalSec = 60 + RetryCount = 15 + } + + FirewallProfile DisablePublic { + Enabled = "False" + Name = "Public" + } + + FirewallProfile DisablePrivate { + Enabled = "False" + Name = "Private" + } + + FirewallProfile DisableDomain { + Enabled = "False" + Name = "Domain" + } + + User localuser { + Ensure = "Present" + UserName = "local-user" + Password = $DomainCred + } + + Group Administrators { + GroupName = "Administrators" + MembersToInclude = "local-user" + DependsOn = "[User]localuser" + } + + DnsServerAddress DnsServerAddress + { + Address = '10.0.1.100' + InterfaceAlias = 'Ethernet' + AddressFamily = 'IPv4' + Validate = $false + DependsOn = "[Group]Administrators" + } + + Script DisableDefender + { + GetScript = { + return @{ Result = (Get-Content C:\Windows\Temp\DefenderDisable.txt) } + } + + TestScript = { + Test-Path "C:\Windows\Temp\DefenderDisable.txt" + } + + SetScript = { + Uninstall-WindowsFeature -Name Windows-Defender + $sw = New-Object System.IO.StreamWriter("C:\Windows\Temp\DefenderDisable.txt") + $sw.WriteLine("Defender has been uninstalled") + $sw.Close() + } + } + + Script DisableSMBSign + { + GetScript = { + return @{ } + } + + TestScript = { + $false + } + + SetScript = { + Set-SmbClientConfiguration -RequireSecuritySignature 0 -EnableSecuritySignature 0 -Confirm -Force + } + } + + Script EnablePSRemoting { + GetScript = { + return @{ } + } + + TestScript = { + $false + } + + SetScript = { + Enable-PSRemoting -SkipNetworkProfileCheck -Force -ErrorAction Stop + } + } + + WaitForADDomain waitFirstDomain { + DomainName = $firstDomainName + Credential = $firstDomainCred + WaitForValidCredentials = $true + WaitTimeout = 300 + DependsOn = "[DnsServerAddress]DnsServerAddress" + } + + Computer JoinDomain { + Name = "User-Server" + DomainName = $firstDomainName + Credential = $firstDomainCred + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + } + + Node "UserWorkstation" { + + WaitForAll DC + { + ResourceName = '[ADUser]asrep' + NodeName = 'First-DC' + RetryIntervalSec = 60 + RetryCount = 15 + } + + FirewallProfile DisablePublic { + Enabled = "False" + Name = "Public" + } + + FirewallProfile DisablePrivate { + Enabled = "False" + Name = "Private" + } + + FirewallProfile DisableDomain { + Enabled = "False" + Name = "Domain" + } + + User localuser { + Ensure = "Present" + UserName = "local-user" + Password = $DomainCred + } + + Group Administrators { + GroupName = "Administrators" + MembersToInclude = "local-user" + DependsOn = "[User]localuser" + } + + DnsServerAddress DnsServerAddress + { + Address = '10.0.1.100' + InterfaceAlias = 'Ethernet' + AddressFamily = 'IPv4' + Validate = $false + DependsOn = "[Group]Administrators" + } + + Script DisableDefender + { + GetScript = { + return @{ Result = (Get-Content C:\Windows\Temp\DefenderDisable.txt) } + } + + TestScript = { + Test-Path "C:\Windows\Temp\DefenderDisable.txt" + } + + SetScript = { + Uninstall-WindowsFeature -Name Windows-Defender + $sw = New-Object System.IO.StreamWriter("C:\Windows\Temp\DefenderDisable.txt") + $sw.WriteLine("Defender has been uninstalled") + $sw.Close() + } + } + + Script DisableSMBSign + { + GetScript = { + return @{ } + } + + TestScript = { + $false + } + + SetScript = { + Set-SmbClientConfiguration -RequireSecuritySignature 0 -EnableSecuritySignature 0 -Confirm -Force + } + } + Script EnableWinRM { + GetScript = { + return @{ } + } + + TestScript = { + $false + } + + SetScript = { + Set-WSManQuickConfig -Force + Set-Service -Name "WinRM" -StartupType Automatic + } + } + + Script EnablePSRemoting { + GetScript = { + return @{ } + } + + TestScript = { + $false + } + + SetScript = { + Enable-PSRemoting -SkipNetworkProfileCheck -Force -ErrorAction Stop + } + } + + WaitForADDomain waitFirstDomain { + DomainName = $firstDomainName + Credential = $firstDomainCred + WaitForValidCredentials = $true + WaitTimeout = 300 + DependsOn = "[DnsServerAddress]DnsServerAddress" + } + + Computer JoinDomain { + Name = "User-Workstation" + DomainName = $firstDomainName + Credential = $firstDomainCred + DependsOn = "[WaitForADDomain]waitFirstDomain" + } + } + + Node "Second" { + + Computer NewName { + Name = "Second-DC" + } + + WindowsFeature ADDSInstall { + Ensure = "Present" + Name = "AD-Domain-Services" + } + + WindowsFeature ADDSTools { + Ensure = "Present" + Name = "RSAT-ADDS" + } + + FirewallProfile DisablePublic { + Enabled = "False" + Name = "Public" + } + + FirewallProfile DisablePrivate { + Enabled = "False" + Name = "Private" + } + + FirewallProfile DisableDomain { + Enabled = "False" + Name = "Domain" + } + + User AdminUser { + Ensure = "Present" + UserName = $domainCred.UserName + Password = $domainCred + } + + Group Administrators { + GroupName = "Administrators" + MembersToInclude = $domainCred.UserName + DependsOn = "[User]AdminUser" + } + + ADDomain CreateDC { + DomainName = $secondDomainName + Credential = $domainCred + SafemodeAdministratorPassword = $safemodeAdministratorCred + DatabasePath = 'C:\NTDS' + LogPath = 'C:\NTDS' + DependsOn = "[WindowsFeature]ADDSInstall" + } + + WaitForADDomain waitSecondDomain { + DomainName = $secondDomainName + DependsOn = "[ADDomain]CreateDC" + } + + DnsServerAddress DnsServerAddress + { + Address = '127.0.0.1', '10.0.1.100' + InterfaceAlias = 'Ethernet' + AddressFamily = 'IPv4' + Validate = $false + DependsOn = "[WaitForADDomain]waitSecondDomain" + } + + Script SetConditionalForwardedZone { + GetScript = { return @{ } } + + TestScript = { + $zone = Get-DnsServerZone -Name $using:firstDomainName -ErrorAction SilentlyContinue + if ($zone -ne $null -and $zone.ZoneType -eq 'Forwarder') { + return $true + } + + return $false + } + + SetScript = { + $ForwardDomainName = $using:firstDomainName + $IpAddresses = @("10.0.1.100") + Add-DnsServerConditionalForwarderZone -Name "$ForwardDomainName" -ReplicationScope "Domain" -MasterServers $IpAddresses + } + } + + ADGroup DomainAdmin { + Ensure = "Present" + GroupName = "Domain Admins" + MembersToInclude = $domainCred.UserName + DependsOn = "[WaitForADDomain]waitSecondDomain" + } + + ADUser 'regular.user' + { + Ensure = 'Present' + UserName = 'regular.user' + Password = (New-Object System.Management.Automation.PSCredential("regular.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'second.local' + Path = 'CN=Users,DC=second,DC=local' + DependsOn = "[WaitForADDomain]waitSecondDomain" + } + + ADUser 'roast.user' + { + Ensure = 'Present' + UserName = 'roast.user' + Password = (New-Object System.Management.Automation.PSCredential("roast.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'second.local' + Path = 'CN=Users,DC=second,DC=local' + ServicePrincipalNames = "MSSQL/sql.second.local" + DependsOn = "[WaitForADDomain]waitSecondDomain" + } + + ADUser 'asrep.user' + { + Ensure = 'Present' + UserName = 'asrep.user' + Password = (New-Object System.Management.Automation.PSCredential("asrep.user", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + DomainName = 'second.local' + Path = 'CN=Users,DC=second,DC=local' + DependsOn = "[WaitForADDomain]waitSecondDomain" + } + + WaitForADDomain waitFirstDomain { + DomainName = $firstDomainName + Credential = $firstDomainCred + WaitTimeout = 600 + RestartCount = 2 + DependsOn = "[Script]SetConditionalForwardedZone" + } + + ADDomainTrust DomainTrust { + TargetDomainName = $firstDomainName + TargetCredential = $firstDomainCred + TrustType = "External" + TrustDirection = "Bidirectional" + SourceDomainName = $secondDomainName + DependsOn = "[WaitForADDomain]waitFirstDomain" + Ensure = "Present" + } + + Script DisableSMBSign + { + GetScript = { + return @{ } + } + + TestScript = { + $false + } + + SetScript = { + Set-SmbClientConfiguration -RequireSecuritySignature 0 -EnableSecuritySignature 0 -Confirm -Force + } + } + + Script DisableDefender + { + GetScript = { + return @{ Result = (Get-Content C:\Windows\Temp\DefenderDisable.txt) } + } + + TestScript = { + Test-Path "C:\Windows\Temp\DefenderDisable.txt" + } + + SetScript = { + Uninstall-WindowsFeature -Name Windows-Defender + $sw = New-Object System.IO.StreamWriter("C:\Windows\Temp\DefenderDisable.txt") + $sw.WriteLine("Defender has been uninstalled") + $sw.Close() + $global:DSCMachineStatus = 1 + } + } + } +} + +$ConfigData = @{ + AllNodes = @( + @{ + Nodename = "First" + Role = "First DC" + RetryCount = 0 + RetryIntervalSec = 0 + PsDscAllowPlainTextPassword = $true + }, + @{ + Nodename = "UserServer" + Role = "User Server" + RetryCount = 0 + RetryIntervalSec = 0 + PsDscAllowPlainTextPassword = $true + PsDscAllowDomainUser = $true + }, + @{ + Nodename = "UserWorkstation" + Role = "User Workstation" + RetryCount = 0 + RetryIntervalSec = 0 + PsDscAllowPlainTextPassword = $true + PsDscAllowDomainUser = $true + }, + @{ + Nodename = "Second" + Role = "Second DC" + RetryCount = 0 + RetryIntervalSec = 0 + PsDscAllowPlainTextPassword = $true + } + ) +} + +Lab -ConfigurationData $ConfigData ` + -firstDomainName "first.local" ` + -secondDomainName "second.local" ` + -domainCred (New-Object System.Management.Automation.PSCredential("admin", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) ` + -safemodeAdministratorCred (New-Object System.Management.Automation.PSCredential("admin", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) ` + -firstDomainCred (New-Object System.Management.Automation.PSCredential("first-admin", (ConvertTo-SecureString "DoesntMatter" -AsPlainText -Force))) + diff --git a/terraform/aws.tf b/terraform/aws.tf new file mode 100644 index 0000000..2955dee --- /dev/null +++ b/terraform/aws.tf @@ -0,0 +1,792 @@ +# Basic AWS configuration which will grab our keys from the AWS CLI +# If you are not using the keys in the default profile of aws cli, then change below to the profile name +provider "aws" { + profile = "default" + region = "us-east-1" +} + +# Our AWS keypair +resource "aws_key_pair" "terraformkey" { + key_name = "${terraform.workspace}-terraform-lab" + public_key = file(var.PATH_TO_PUBLIC_KEY) +} + +# Our VPC definition, using a default IP range of 10.0.0.0/16 +resource "aws_vpc" "lab-vpc" { + cidr_block = var.VPC_CIDR + enable_dns_support = true + enable_dns_hostnames = true +} + +# Default route required for the VPC to push traffic via gateway +resource "aws_route" "first-internet-route" { + route_table_id = aws_vpc.lab-vpc.main_route_table_id + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.lab-vpc-gateway.id +} + +# Gateway which allows outbound and inbound internet access to the VPC +resource "aws_internet_gateway" "lab-vpc-gateway" { + vpc_id = aws_vpc.lab-vpc.id +} + +# Create our first subnet (Defaults to 10.0.1.0/24) +resource "aws_subnet" "first-vpc-subnet" { + vpc_id = aws_vpc.lab-vpc.id + + cidr_block = var.FIRST_SUBNET_CIDR + availability_zone = "us-east-1a" + + tags = { + Name = "First Subnet" + } +} + +# Create our second subnet (Defaults to 10.0.2.0/24) +resource "aws_subnet" "second-vpc-subnet" { + vpc_id = aws_vpc.lab-vpc.id + + cidr_block = var.SECOND_SUBNET_CIDR + availability_zone = "us-east-1a" + + tags = { + Name = "Second Subnet" + } +} + +# Set DHCP options for delivering things like DNS servers +resource "aws_vpc_dhcp_options" "first-dhcp" { + domain_name = "first.local" + domain_name_servers = [var.FIRST_DC_IP, var.PUBLIC_DNS] + ntp_servers = [var.FIRST_DC_IP] + netbios_name_servers = [var.FIRST_DC_IP] + netbios_node_type = 2 + + tags = { + Name = "First DHCP" + } +} + +# Associate our DHCP configuration with our VPC +resource "aws_vpc_dhcp_options_association" "first-dhcp-assoc" { + vpc_id = aws_vpc.lab-vpc.id + dhcp_options_id = aws_vpc_dhcp_options.first-dhcp.id +} + +# Our first domain controller of the "first.local" domain +resource "aws_instance" "first-dc" { + ami = data.aws_ami.latest-windows-server.image_id + instance_type = "t2.small" + key_name = aws_key_pair.terraformkey.key_name + associate_public_ip_address = true + subnet_id = aws_subnet.first-vpc-subnet.id + private_ip = var.FIRST_DC_IP + iam_instance_profile = aws_iam_instance_profile.ssm_instance_profile.name + + tags = { + Workspace = "${terraform.workspace}" + Name = "${terraform.workspace}-First-DC" + } + + vpc_security_group_ids = [ + aws_security_group.first-sg.id, + ] +} + +# The User server which will be main foothold +resource "aws_instance" "user-server" { + ami = data.aws_ami.latest-windows-server.image_id + instance_type = "t2.small" + key_name = aws_key_pair.terraformkey.key_name + associate_public_ip_address = true + subnet_id = aws_subnet.first-vpc-subnet.id + private_ip = var.USER_SERVER_IP + iam_instance_profile = aws_iam_instance_profile.ssm_instance_profile.name + + tags = { + Workspace = "${terraform.workspace}" + Name = "${terraform.workspace}-User-Server" + } + + vpc_security_group_ids = [ + aws_security_group.first-sg.id, + ] +} +/* resource "time_sleep" "wait_30_mins" { + depends_on = [aws_instance.user-server] + create_duration = "30m" +} +resource "null_resource" "user-server-setup" { + depends_on = [time_sleep.wait_30_mins] + + connection { + type = "winrm" + user = var.WinRM_USER + password = var.WinRM_PASSWORD + host = aws_instance.user-server.public_ip + port = 5985 + insecure = true + https = true + timeout = "10m" + use_ntlm = true + } + provisioner "remote-exec" { + inline = [ + "mkdir toolz", + ] + } + provisioner "local-exec" { + command = "Get-Date > completed.txt" + interpreter = ["PowerShell", "-Command"] + } +} */ + +# The User Windows 10 workstation which will be main foothold +resource "aws_instance" "user-workstation" { + ami = data.aws_ami.windows-10.image_id + instance_type = "t2.small" + key_name = aws_key_pair.terraformkey.key_name + associate_public_ip_address = true + subnet_id = aws_subnet.first-vpc-subnet.id + private_ip = var.USER_WORKSTATION_IP + iam_instance_profile = aws_iam_instance_profile.ssm_instance_profile.name + + tags = { + Workspace = "${terraform.workspace}" + Name = "${terraform.workspace}-User-Workstation" + } + + vpc_security_group_ids = [ + aws_security_group.first-sg.id, + ] +} +/* resource "time_sleep" "wait_30_mins" { + depends_on = [aws_instance.user-server] + create_duration = "30m" +} +resource "null_resource" "user-server-setup" { + depends_on = [time_sleep.wait_30_mins] + + connection { + type = "winrm" + user = var.WinRM_USER + password = var.WinRM_PASSWORD + host = aws_instance.user-server.public_ip + port = 5985 + insecure = true + https = true + timeout = "10m" + use_ntlm = true + } + provisioner "remote-exec" { + inline = [ + "mkdir toolz", + ] + } + provisioner "local-exec" { + command = "Get-Date > completed.txt" + interpreter = ["PowerShell", "-Command"] + } +} */ + +# First Web Server +resource "aws_instance" "web-server-1" { + ami = data.aws_ami.latest-debian.image_id + instance_type = "t2.small" + key_name = aws_key_pair.terraformkey.key_name + associate_public_ip_address = true + subnet_id = aws_subnet.first-vpc-subnet.id + private_ip = var.WEB_SERVER_1_IP + iam_instance_profile = aws_iam_instance_profile.ssm_instance_profile.name + + tags = { + Workspace = "${terraform.workspace}" + Name = "${terraform.workspace}-Web-Server-1" + } + + vpc_security_group_ids = [ + aws_security_group.first-sg.id, + ] +} + +resource "null_resource" "web-server-1-setup" { + connection { + type = "ssh" + host = aws_instance.web-server-1.public_ip + user = var.SSH_USER + port = "22" + private_key = file(var.PATH_TO_PRIVATE_KEY) + agent = false + } + /* provisioner "file" { + source = "vuln-install.sh" + destination = "/tmp/vuln-install.sh" + } */ + + provisioner "remote-exec" { + inline = [ + "export DEBIAN_FRONTEND=noninteractive", + "sudo apt-get -qy -o \"Dpkg::Options::=--force-confdef\" -o \"Dpkg::Options::=--force-confold\" upgrade", + "sudo apt-get remove docker docker-engine docker.io containerd runc", + "curl -fsSL https://get.docker.com -o get-docker.sh", + "sudo sh get-docker.sh", + "sudo apt install git -y", + "sudo curl -L https://github.com/docker/compose/releases/download/1.25.3/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose", + "sudo chmod +x /usr/local/bin/docker-compose", + "git clone https://github.com/vulhub/vulhub.git", + "sudo docker pull bkimminich/juice-shop", + "sudo docker run -d -p 3000:3000 bkimminich/juice-shop", + ] + } +} + +# Second Web Server +resource "aws_instance" "web-server-2" { + ami = data.aws_ami.latest-debian.image_id + instance_type = "t2.small" + key_name = aws_key_pair.terraformkey.key_name + associate_public_ip_address = true + subnet_id = aws_subnet.first-vpc-subnet.id + private_ip = var.WEB_SERVER_2_IP + iam_instance_profile = aws_iam_instance_profile.ssm_instance_profile.name + + tags = { + Workspace = "${terraform.workspace}" + Name = "${terraform.workspace}-Web-Server-2" + } + + vpc_security_group_ids = [ + aws_security_group.first-sg.id, + ] +} + +resource "null_resource" "web-server-2-setup" { + connection { + type = "ssh" + host = aws_instance.web-server-2.public_ip + user = var.SSH_USER + port = "22" + private_key = file(var.PATH_TO_PRIVATE_KEY) + agent = false + } + + provisioner "remote-exec" { + inline = [ + "export DEBIAN_FRONTEND=noninteractive", + "sudo apt-get -qy -o \"Dpkg::Options::=--force-confdef\" -o \"Dpkg::Options::=--force-confold\" upgrade", + "sudo apt-get remove docker docker-engine docker.io containerd runc", + "curl -fsSL https://get.docker.com -o get-docker.sh", + "sudo sh get-docker.sh", + "sudo apt install git -y", + "sudo curl -L https://github.com/docker/compose/releases/download/1.25.3/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose", + "sudo chmod +x /usr/local/bin/docker-compose", + "git clone https://github.com/vulhub/vulhub.git", + "cd vulhub/tomcat/tomcat8/", + "sudo docker-compose up -d", + ] + } +} + +# Our second domain controller of the "second.local" domain +resource "aws_instance" "second-dc" { + ami = data.aws_ami.latest-windows-server.image_id + instance_type = "t2.small" + key_name = aws_key_pair.terraformkey.key_name + associate_public_ip_address = true + subnet_id = aws_subnet.second-vpc-subnet.id + private_ip = var.SECOND_DC_IP + iam_instance_profile = aws_iam_instance_profile.ssm_instance_profile.name + + tags = { + Workspace = "${terraform.workspace}" + Name = "${terraform.workspace}-Second-DC" + } + + vpc_security_group_ids = [ + aws_security_group.second-sg.id, + ] +} + +# Guacamole Server +resource "aws_instance" "guac-server" { + ami = data.aws_ami.latest-debian.image_id + instance_type = "t2.small" + key_name = aws_key_pair.terraformkey.key_name + associate_public_ip_address = true + subnet_id = aws_subnet.first-vpc-subnet.id + private_ip = var.GUAC_SERVER_IP + iam_instance_profile = aws_iam_instance_profile.ssm_instance_profile.name + + tags = { + Workspace = "${terraform.workspace}" + Name = "${terraform.workspace}-Guac-Server" + } + + vpc_security_group_ids = [ + aws_security_group.first-sg.id, + ] +} + +resource "null_resource" "guac-server-setup" { + connection { + type = "ssh" + host = aws_instance.guac-server.public_ip + user = var.SSH_USER + port = "22" + private_key = file(var.PATH_TO_PRIVATE_KEY) + agent = false + } + + provisioner "remote-exec" { + inline = [ + "export DEBIAN_FRONTEND=noninteractive", + "sudo apt-get -qy -o \"Dpkg::Options::=--force-confdef\" -o \"Dpkg::Options::=--force-confold\" upgrade", + "sudo apt-get remove docker docker-engine docker.io containerd runc", + "curl -fsSL https://get.docker.com -o get-docker.sh", + "sudo sh get-docker.sh", + "sudo apt install git -y", + "sudo curl -L https://github.com/docker/compose/releases/download/1.25.3/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose", + "sudo chmod +x /usr/local/bin/docker-compose", + "git clone https://github.com/q0phi80/guacamole.git", + "cd guacamole", + "sudo ./bin/prepare_initdb.sh", + "sudo docker-compose up -d guacamole mysql guacd", + "sudo docker-compose up -d", + ] + } +} + +# Kali Linux Install +resource "aws_instance" "attacker-kali" { + #count = "1" ? 1 : 0 + ami = data.aws_ami.latest-kali-linux.image_id + instance_type = "t3.medium" + key_name = aws_key_pair.terraformkey.key_name + associate_public_ip_address = true + subnet_id = aws_subnet.first-vpc-subnet.id + private_ip = var.ATTACKER_KALI_IP + iam_instance_profile = aws_iam_instance_profile.ssm_instance_profile.name + + tags = { + Workspace = "${terraform.workspace}" + Name = "${terraform.workspace}-Attacker-Kali" + } + + vpc_security_group_ids = [ + aws_security_group.first-sg.id, + ] + root_block_device { + delete_on_termination = true + volume_size = 100 + } +} + +resource "null_resource" "attacker-kali-setup" { + connection { + type = "ssh" + host = aws_instance.attacker-kali.public_ip + user = "kali" + port = "22" + private_key = file(var.PATH_TO_PRIVATE_KEY) + agent = false + } + + provisioner "remote-exec" { + inline = [ + "sudo apt update", + "DEBIAN_FRONTEND=noninteractive sudo apt-get --yes --force-yes install kali-desktop-xfce xorg xrdp", + "sudo sed -i 's/port=3389/port=3390/g' /etc/xrdp/xrdp.ini", + "sudo systemctl enable xrdp --now", + # Install dotnet + "wget https://packages.microsoft.com/config/debian/10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb", + "sudo dpkg -i packages-microsoft-prod.deb", + "sudo apt-get update", + "sudo apt-get install -y apt-transport-https", + "sudo apt-get update", + "sudo apt-get install -y dotnet-sdk-3.1", + "sudo apt-get install -y git", + "sudo apt install -y python3-pip", + # Change the password to the default ‘kali’ account + "echo kali:kali | sudo chpasswd", + "mkdir -p toolz", + "cd toolz/", + # Install Impacket + "git clone https://github.com/SecureAuthCorp/impacket.git", + "cd impacket", + "sudo python3 -m pip install --upgrade pip", + "sudo python3 -m pip install .", + "cd ../", + # Get Covenant C2 framework + "git clone --recurse-submodules https://github.com/cobbr/Covenant", + ] + } +} + +# IAM Role required to access SSM from EC2 +resource "aws_iam_role" "ssm_role" { + name = "${terraform.workspace}_ssm_role_default" + count = 1 + assume_role_policy = < /dev/null 2>&1 + if [[ $? -ne 0 ]] + then + echo "Docker is not installed. Read: https://docs.docker.com/get-docker/ " + exit 3 + fi + + # Check whether docker-compose is installed + docker-compose version > /dev/null 2>&1 + if [[ $? -ne 0 ]] + then + echo "Docker-compose is not installed. Read: https://docs.docker.com/compose/install/" + exit 3 + fi +} + +# Start each container with docker-compose +start () { + for i in "${CONTAINERS[@]}" + do + docker-compose -f "${i}" up -d + if [[ $? -ne 0 ]] + then + exit 1 # Exit docker engine is not running + fi + done +} + +stop () { + for i in "${CONTAINERS[@]}" + do + docker-compose -f "${i}" down -v + if [[ $? -ne 0 ]] + then + echo "You may need to manually disable container(s) using docker." + echo "To show running containers type: docker ps" + #exit 1 # Exit docker engine is not running + fi + done +} + +if [[ $1 == "start" ]] +then + init_check + echo "Starting all docker containers..." + start +elif [[ $1 == "stop" ]] +then + init_check + echo "Stopping all docker containers ..." + stop +elif [[ $1 == "list" ]] +then + echo -e "Listing all available Docker containers from vulhub." + # TODO: List all the available Docker containers. Check if they are running. +else + echo -e "\n\e[31m\e[1mVulnerables\e[0m: a quick and simple way of starting multiple Docker containers from vulhub.\n" + echo -e "Usage: $0 [start or stop]\n" +fi \ No newline at end of file