function Invoke-PasswordRoll { <# .SYNOPSIS ÀÌ ½ºÅ©¸³Æ®¸¦ »ç¿ëÇÏ¿© ¿ø°Ý ÄÄÇ»ÅÍÀÇ ·ÎÄà °èÁ¤ ¾ÏÈ£¸¦ ÀÓÀÇÀÇ ¾ÏÈ£·Î ¼³Á¤ÇÒ ¼ö ÀÖ½À´Ï´Ù. »ç¿ëÀÚ À̸§/¾ÏÈ£/¼­¹ö Á¶ÇÕÀÌ CSV ÆÄÀÏ¿¡ ÀúÀåµË´Ï´Ù. CSV ÆÄÀÏ¿¡ ÀúÀåµÇ´Â °èÁ¤ ¾ÏÈ£´Â ÀÏ¹Ý ÅؽºÆ® °èÁ¤ ¾ÏÈ£°¡ µð½ºÅ©¿¡ ±â·ÏµÇÁö ¾Ê°Ô º¸ÀåÇϵµ·Ï ¼±ÅÃÇÏ´Â °ü¸®ÀÚÀÇ ¾ÏÈ£¸¦ »ç¿ëÇÏ¿© ¾ÏȣȭÇÏ°í ÇÒ ¼ö ÀÖ½À´Ï´Ù. ¾ÏȣȭµÈ ¾ÏÈ£´Â ÀÌ ÆÄÀÏÀÇ ´Ù¸¥ ÇÔ¼ö¸¦ »ç¿ëÇÏ¿© Çص¶ÇÒ ¼ö ÀÖ½À´Ï´Ù. ConvertTo-CleartextPassword Function: Invoke-PasswordRoll Author: Microsoft Version: 1.0 .DESCRIPTION ÀÌ ½ºÅ©¸³Æ®¸¦ »ç¿ëÇÏ¿© ¿ø°Ý ÄÄÇ»ÅÍÀÇ ·ÎÄà °èÁ¤ ¾ÏÈ£¸¦ ÀÓÀÇÀÇ ¾ÏÈ£·Î ¼³Á¤ÇÒ ¼ö ÀÖ½À´Ï´Ù. »ç¿ëÀÚ À̸§/¾ÏÈ£/¼­¹ö Á¶ÇÕÀÌ CSV ÆÄÀÏ¿¡ ÀúÀåµË´Ï´Ù. CSV ÆÄÀÏ¿¡ ÀúÀåµÇ´Â °èÁ¤ ¾ÏÈ£´Â ÀÏ¹Ý ÅؽºÆ® °èÁ¤ ¾ÏÈ£°¡ µð½ºÅ©¿¡ ±â·ÏµÇÁö ¾Ê°Ô º¸ÀåÇϵµ·Ï ¼±ÅÃÇÏ´Â °ü¸®ÀÚÀÇ ¾ÏÈ£¸¦ »ç¿ëÇÏ¿© ¾ÏȣȭÇÏ°í ÇÒ ¼ö ÀÖ½À´Ï´Ù. ¾ÏȣȭµÈ ¾ÏÈ£´Â ÀÌ ÆÄÀÏÀÇ ´Ù¸¥ ÇÔ¼ö¸¦ »ç¿ëÇÏ¿© Çص¶ÇÒ ¼ö ÀÖ½À´Ï´Ù. ConvertTo-CleartextPassword .PARAMETER ComputerName PowerShell ¿ø°Ý »ç¿ë¿¡ ´ëÇØ ½ºÅ©¸³Æ®¸¦ ½ÇÇàÇÒ ÄÄÇ»ÅÍÀÇ ¹è¿­. .PARAMETER LocalAccounts ¾ÏÈ£¸¦ º¯°æÇØ¾ß ÇÏ´Â ·ÎÄà °èÁ¤ÀÇ ¹è¿­. .PARAMETER TsvFileName »ç¿ëÀÚ À̸§/¾ÏÈ£/¼­¹ö Á¶ÇÕÀ» Ãâ·ÂÇÒ ÆÄÀÏ. .PARAMETER EncryptionKey TSV ÆÄÀÏÀ» ¾ÏȣȭÇϱâ À§ÇÑ ¾ÏÈ£. AES ¾Ïȣȭ¸¦ »ç¿ëÇÕ´Ï´Ù. TSV ÆÄÀÏ¿¡ ÀúÀåµÈ ¾ÏÈ£¸¸ ¾ÏȣȭµÇ¸ç, »ç¿ëÀÚ À̸§ ¹× ¼­¹ö À̸§Àº ÀÏ¹Ý ÅؽºÆ®ÀÔ´Ï´Ù. .PARAMETER PasswordLength ·ÎÄà °èÁ¤¿¡ ´ëÇØ ÀÓÀÇ·Î »ý¼ºµÇ´Â ¾ÏÈ£ÀÇ ±æÀÌ. .PARAMETER NoEncryption TSV ÆÄÀÏ¿¡ ÀúÀåµÈ °èÁ¤ ¾ÏÈ£¸¦ ¾ÏȣȭÇÏÁö ¸¶½Ê½Ã¿À. ±×·¯¸é ÀÏ¹Ý ÅؽºÆ® ¾ÏÈ£°¡ µð½ºÅ©¿¡ ±â·ÏµË´Ï´Ù. .EXAMPLE . .\Invoke-PasswordRoll.ps1 #ÀÌ ½ºÅ©¸³Æ® ÆÄÀÏÀÇ ÇÔ¼ö ·Îµå Invoke-PasswordRoll -ComputerName (Get-Content computerlist.txt) -LocalAccounts @("administrator","CustomLocalAdmin") -TsvFileName "LocalAdminCredentials.tsv" -EncryptionKey "Password1" "computerlist.txt" ÆÄÀÏ¿¡ ÀúÀåµÈ ¸ðµç ÄÄÇ»ÅÍ¿¡ ¿¬°áÇÕ´Ï´Ù. ·ÎÄà °èÁ¤ "administrator" ¹×/¶Ç´Â "CustomLocalAdmin"ÀÌ ½Ã½ºÅÛ¿¡ ÀÖ´Â °æ¿ì ÇØ´ç ¾ÏÈ£´Â ±æÀÌ 20(±âº»°ª)ÀÇ ÀÓÀÇ·Î »ý¼ºµÈ ¾ÏÈ£·Î º¯°æµË´Ï´Ù. »ç¿ëÀÚ À̸§/¾ÏÈ£/¼­¹ö Á¶ÇÕÀÌ LocalAdminCredentials.tsv¿¡ ÀúÀåµÇ°í, °èÁ¤ ¾ÏÈ£´Â ¾ÏÈ£ "Password1"À» »ç¿ëÇÏ¿© AES ¾ÏȣȭµË´Ï´Ù. .EXAMPLE . .\Invoke-PasswordRoll.ps1 #ÀÌ ½ºÅ©¸³Æ® ÆÄÀÏÀÇ ÇÔ¼ö ·Îµå Invoke-PasswordRoll -ComputerName (Get-Content computerlist.txt) -LocalAccounts @("administrator") -TsvFileName "LocalAdminCredentials.tsv" -NoEncryption -PasswordLength 40 "computerlist.txt" ÆÄÀÏ¿¡ ÀúÀåµÈ ¸ðµç ÄÄÇ»ÅÍ¿¡ ¿¬°áÇÕ´Ï´Ù. ·ÎÄà °èÁ¤ "administrator"°¡ ½Ã½ºÅÛ¿¡ ÀÖ´Â °æ¿ì ÇØ´ç ¾ÏÈ£´Â ±æÀÌ 40ÀÇ ÀÓÀÇ·Î »ý¼ºµÈ ¾ÏÈ£·Î º¯°æµË´Ï´Ù. »ç¿ëÀÚ À̸§/¾ÏÈ£/¼­¹ö Á¶ÇÕÀÌ ¾ÏȣȭµÇÁö ¾ÊÀº LocalAdminCredentials.tsv¿¡ ÀúÀåµË´Ï´Ù. .NOTES ¿ä±¸ »çÇ×: -PowerShellv2 ÀÌ»óÀ» ¼³Ä¡ÇØ¾ß ÇÕ´Ï´Ù. -PowerShell ¿ø°ÝÀÌ ½ºÅ©¸³Æ®°¡ ½ÇÇàµÉ ¸ðµç ½Ã½ºÅÛ¿¡¼­ »ç¿ëµÇµµ·Ï ¼³Á¤µÇ¾î ÀÖ¾î¾ß ÇÕ´Ï´Ù. ½ºÅ©¸³Æ® µ¿ÀÛ: -·ÎÄà °èÁ¤ÀÌ ½Ã½ºÅÛ¿¡ ÀÖÁö¸¸ LocalAccounts ¸Å°³ º¯¼ö¿¡¼­ ÁöÁ¤µÇÁö ¾ÊÀº °æ¿ì ÇØ´ç ½ºÅ©¸³Æ®´Â ÀÌ ·ÎÄà °èÁ¤ÀÇ Á¸À縦 ¾Ë¸®±â À§ÇØ È­¸é¿¡ °æ°í¸¦ ÀÛ¼ºÇÕ´Ï´Ù. ÀÌ·¯ÇÑ °æ¿ì ½ºÅ©¸³Æ®°¡ °è¼Ó ½ÇÇàµË´Ï´Ù. -·ÎÄà °èÁ¤ÀÌ LocalAccounts ¸Å°³ º¯¼ö¿¡¼­ ÁöÁ¤µÇ¾úÁö¸¸ ÇØ´ç °èÁ¤ÀÌ ÄÄÇ»ÅÍ¿¡ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì ¾Æ¹« µ¿ÀÛµµ ¼öÇàµÇÁö ¾Ê½À´Ï´Ù(°èÁ¤ÀÌ ¸¸µé¾îÁöÁö ¾ÊÀ½). -ÀÌ ÆÄÀÏ¿¡ Æ÷ÇÔµÈ ConvertTo-CleartextPassword ÇÔ¼ö¸¦ »ç¿ëÇÏ¿© TSV ÆÄÀÏ¿¡ ¾ÏȣȭµÇ¾î ÀúÀåµÈ ¾ÏÈ£¸¦ Çص¶ÇÒ ¼ö ÀÖ½À´Ï´Ù. -ComputerName¿¡¼­ ÁöÁ¤µÈ ¼­¹ö¿¡ ¿¬°áÇÒ ¼ö ¾ø´Â °æ¿ì PowerShellÀÌ ¿À·ù ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÕ´Ï´Ù. -Microsoft´Â ȸ»ç°¡ Á¤±âÀûÀ¸·Î ¸ðµç ·ÎÄà ¹× µµ¸ÞÀÎ °èÁ¤ ¾ÏÈ£¸¦ ·Ñ¸µÇÒ °ÍÀ» ±ÇÀåÇÕ´Ï´Ù. #> [CmdletBinding(DefaultParameterSetName="Encryption")] Param( [Parameter(Mandatory=$true)] [String[]] $ComputerName, [Parameter(Mandatory=$true)] [String[]] $LocalAccounts, [Parameter(Mandatory=$true)] [String] $TsvFileName, [Parameter(ParameterSetName="Encryption", Mandatory=$true)] [String] $EncryptionKey, [Parameter()] [ValidateRange(20,120)] [Int] $PasswordLength = 20, [Parameter(ParameterSetName="NoEncryption", Mandatory=$true)] [Switch] $NoEncryption ) #ÇÊ¿äÇÑ ¸ðµç .net Ŭ·¡½º ·Îµå Add-Type -AssemblyName "System.Web" -ErrorAction Stop #ComputerName¿¡¼­ ÁöÁ¤µÈ ¸ðµç ÄÄÇ»ÅÍ¿¡¼­ ½ÇÇàµÇ´Â scriptblockÀÔ´Ï´Ù. $RemoteRollScript = { Param( [Parameter(Mandatory=$true, Position=1)] [String[]] $Passwords, [Parameter(Mandatory=$true, Position=2)] [String[]] $LocalAccounts, #ÀÌ°ÍÀÌ ¿©±â¿¡ ÀÖÀ¸¹Ç·Î ½ºÅ©¸³Æ®°¡ ¿¬°áµÈ ¼­¹ö À̸§À» ±â·ÏÇÒ ¼ö ÀÖ½À´Ï´Ù. ¶§¶§·Î DNS ·¹Äڵ尡 À߸øµÇ¹Ç·Î ÀÌ°ÍÀÌ ÀÖ´Â °ÍÀÌ À¯¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù. [Parameter(Mandatory=$true, Position=3)] [String] $TargettedServerName ) $LocalUsers = Get-WmiObject Win32_UserAccount -Filter "LocalAccount=true" | Foreach {$_.Name} #ÄÄÇ»ÅÍ¿¡ ÀÌ ½ºÅ©¸³Æ®°¡ ·Ñ¸µÇÏÁö ¾ÊÀ» ¾ÏÈ£¸¦ °¡Áø ·ÎÄà »ç¿ëÀÚ °èÁ¤ÀÌ ÀÖ´ÂÁö È®ÀÎ foreach ($User in $LocalUsers) { if ($LocalAccounts -inotcontains $User) { Write-Warning "Server: '$($TargettedServerName)' has a local account '$($User)' whos password is NOT being changed by this script" } } #ÀÌ ¼­¹ö¿¡ Á¸ÀçÇÏ´Â ÁöÁ¤µÈ ¸ðµç ·ÎÄà °èÁ¤ÀÇ °æ¿ì ¾ÏÈ£ º¯°æ $PasswordIndex = 0 foreach ($LocalAdmin in $LocalAccounts) { $Password = $Passwords[$PasswordIndex] if ($LocalUsers -icontains $LocalAdmin) { try { $objUser = [ADSI]"WinNT://localhost/$($LocalAdmin), user" $objUser.psbase.Invoke("SetPassword", $Password) $Properties = @{ TargettedServerName = $TargettedServerName Username = $LocalAdmin Password = $Password RealServerName = $env:computername } $ReturnData = New-Object PSObject -Property $Properties Write-Output $ReturnData } catch { Write-Error "Error changing password for user:$($LocalAdmin) on server:$($TargettedServerName)" } } $PasswordIndex++ } } #¿ø°Ý ÄÄÇ»ÅÍ°¡ ¾Æ´Ñ, ÀÌ ½ºÅ©¸³Æ®¸¦ ½ÇÇàÇϴ Ŭ¶óÀ̾ðÆ®¿¡¼­ ¾ÏÈ£ »ý¼ºÇÕ´Ï´Ù. System.Web.Security´Â .NET Ŭ¶óÀ̾ðÆ® ÇÁ·ÎÇÊ¿¡¼­ »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù. ÀÌ ½ºÅ©¸³Æ®°¡ ½ÇÇàµÇ´Â Ŭ¶óÀ̾ðÆ®¿¡¼­ ÀÌ È£ÃâÀ» # ¼öÇàÇϸé 1´ëÀÇ ÄÄÇ»ÅÍ¿¡¼­¸¸ ¼³Ä¡µÈ Àüü .NET ·±Å¸ÀÓÀÌ ÇÊ¿äÇϵµ·Ï º¸ÀåÇÕ´Ï´Ù(·Ñ¸µµÈ ¾ÏÈ£°¡ ÀÖ´Â ¸ðµç ½Ã½ºÅÛ°ú ¹Ý´ë·Î). function Create-RandomPassword { Param( [Parameter(Mandatory=$true)] [ValidateRange(20,120)] [Int] $PasswordLength ) $Password = [System.Web.Security.Membership]::GeneratePassword($PasswordLength, $PasswordLength / 4) #ÀÌ°ÍÀº Àý´ë·Î ½ÇÆÐÇÏÁö ¾ÊÁö¸¸, ¾î·µç ¿©±â¿¡ ¿ÂÀü¼º °Ë»ç¸¦ ÁöÁ¤ÇÏ°Ú½À´Ï´Ù. if ($Password.Length -ne $PasswordLength) { throw new Exception("Password returned by GeneratePassword is not the same length as required. Required length: $($PasswordLength). Generated length: $($Password.Length)") } return $Password } #ÁÖ ±â´É - ¾ÏÈ£¸¦ »ý¼ºÇÏ°í ¿ø°Ý ÄÄÇ»ÅÍÀÇ ¾ÏÈ£¸¦ ÁöÁ¤µÈ ·ÎÄà °èÁ¤ÀÇ ¾ÏÈ£·Î º¯°æ if ($PsCmdlet.ParameterSetName -ieq "Encryption") { try { $Sha256 = new-object System.Security.Cryptography.SHA256CryptoServiceProvider $SecureStringKey = $Sha256.ComputeHash([System.Text.UnicodeEncoding]::Unicode.GetBytes($EncryptionKey)) } catch { Write-Error "Error creating TSV encryption key" -ErrorAction Stop } } foreach ($Computer in $ComputerName) { #º¯°æµÉ ¼ö ÀÖ´Â °¢ °èÁ¤ÀÇ ¾ÏÈ£ 1°³¸¦ »ý¼ºÇØ¾ß ÇÔ $Passwords = @() for ($i = 0; $i -lt $LocalAccounts.Length; $i++) { $Passwords += Create-RandomPassword -PasswordLength $PasswordLength } Write-Output "Connecting to server '$($Computer)' to roll specified local admin passwords" $Result = Invoke-Command -ScriptBlock $RemoteRollScript -ArgumentList @($Passwords, $LocalAccounts, $Computer) -ComputerName $Computer #¾Ïȣȭ¸¦ »ç¿ëÇÒ °æ¿ì µð½ºÅ©¿¡ ¾²±â Àü¿¡ »ç¿ëÀÚ °ø±Þ Å°·Î ¾ÏÈ£¸¦ ¾Ïȣȭ if ($Result -ne $null) { if ($PsCmdlet.ParameterSetName -ieq "NoEncryption") { $Result | Select-Object Username,Password,TargettedServerName,RealServerName | Export-Csv -Append -Path $TsvFileName -NoTypeInformation } else { #¹ÝȯµÈ $null Ç׸ñ ÇÊÅ͸µ $Result = $Result | Select-Object Username,Password,TargettedServerName,RealServerName foreach ($Record in $Result) { $PasswordSecureString = ConvertTo-SecureString -AsPlainText -Force -String ($Record.Password) $Record | Add-Member -MemberType NoteProperty -Name EncryptedPassword -Value (ConvertFrom-SecureString -Key $SecureStringKey -SecureString $PasswordSecureString) $Record.PSObject.Properties.Remove("Password") $Record | Select-Object Username,EncryptedPassword,TargettedServerName,RealServerName | Export-Csv -Append -Path $TsvFileName -NoTypeInformation } } } } }function ConvertTo-CleartextPassword { <# .SYNOPSIS ÀÌ ÇÔ¼ö¸¦ »ç¿ëÇÏ¿© Invoke-PasswordRoll ÇÔ¼ö¿¡ ÀÇÇØ ¾ÏȣȭµÇ¾î ÀúÀåµÈ ¾ÏÈ£¸¦ Çص¶ÇÒ ¼ö ÀÖ½À´Ï´Ù. Function: ConvertTo-CleartextPassword Author: Microsoft Version: 1.0 .DESCRIPTION ÀÌ ÇÔ¼ö¸¦ »ç¿ëÇÏ¿© Invoke-PasswordRoll ÇÔ¼ö¿¡ ÀÇÇØ ¾ÏȣȭµÇ¾î ÀúÀåµÈ ¾ÏÈ£¸¦ Çص¶ÇÒ ¼ö ÀÖ½À´Ï´Ù. .PARAMETER EncryptedPassword TSV ÆÄÀÏ¿¡ ÀúÀåµÈ ¾ÏȣȭµÈ ¾ÏÈ£. .PARAMETER EncryptionKey ¾Ïȣȭ¸¦ ¼öÇàÇÏ´Â µ¥ »ç¿ëµÈ ¾ÏÈ£. .EXAMPLE. .\Invoke-PasswordRoll.ps1 #ÀÌ ½ºÅ©¸³Æ® ÆÄÀÏÀÇ ÇÔ¼ö ·Îµå ConvertTo-CleartextPassword -EncryptionKey "Password1" -EncryptedPassword 76492d1116743f0423413b16050a5345MgB8AGcAZgBaAHUAaQBwADAAQgB2AGgAcABNADMASwBaAFoAQQBzADEAeABjAEEAPQA9AHwAZgBiAGYAMAA1ADYANgA2ADEANwBkADQAZgAwADMANABjAGUAZQAxAGIAMABiADkANgBiADkAMAA4ADcANwBhADMAYQA3AGYAOABkADcAMQA5ADQAMwBmAGYANQBhADEAYQBjADcANABkADIANgBhADUANwBlADgAMAAyADQANgA1ADIAOQA0AGMAZQA0ADEAMwAzADcANQAyADUANAAzADYAMAA1AGEANgAzADEAMQA5ADAAYwBmADQAZAA2AGQA" TSV ÆÄÀÏ¿¡ ÀúÀåµÈ ¾ÏȣȭµÈ ¾ÏÈ£¸¦ Çص¶ÇÕ´Ï´Ù. #> Param( [Parameter(Mandatory=$true)] [String] $EncryptedPassword, [Parameter(Mandatory=$true)] [String] $EncryptionKey ) $Sha256 = new-object System.Security.Cryptography.SHA256CryptoServiceProvider $SecureStringKey = $Sha256.ComputeHash([System.Text.UnicodeEncoding]::Unicode.GetBytes($EncryptionKey)) [SecureString]$SecureStringPassword = ConvertTo-SecureString -String $EncryptedPassword -Key $SecureStringKey Write-Output ([System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($SecureStringPassword))) }