
AD 그룹 정책에서 취약한 설정을 찾는 데 도움이 되는 PowerShell 스크립트입니다. (지원 중단됨, 대신 Grouper2를 사용하세요!)
더 이상 GROUPER를 사용하지 마세요. GROUPER2를 사용하세요! https://github.com/l0ss/Grouper2
Active Directory 그룹 정책에서 취약한 설정을 찾는 데 도움이 되는 PowerShell 스크립트입니다.

Grouper는 침투 테스터와 레드팀을 위해 설계된 PowerShell 모듈입니다 (물론 시스템 관리자에게도 유용할 수 있습니다). 이 모듈은 Get-GPOReport cmdlet (Microsoft의 그룹 정책 모듈의 일부)의 (보통 매우 시끄러운) XML 출력을 걸러내고, GPO(그룹 정책 개체)에 정의된 모든 설정 중에서 누군가 재미있는/악의적인 일을 하려는 경우 유용할 수 있는 설정을 식별합니다.
GPO에서 찾을 수 있는 것들의 예:
물론 꽤 조잡하지만, 그 끔찍한 150MB HTML GPO 보고서를 읽는 엄청난 시간을 절약해 줍니다. 저에게 효과가 있다면 여러분에게도 효과가 있을 수 있습니다.
참고: 일부 함수 이름에 'audit'이라는 단어가 포함될 수 있지만, Grouper는 명시적으로 모범 사례 구성 등을 위한 완전한 감사 도구가 아닙니다. 그런 기능이 필요하다면 Microsoft SCT와 LGPO.exe 등을 사용해야 합니다.
그룹 정책 cmdlet이 설치된 Windows 시스템에서 GPO 보고서를 생성합니다. 이 cmdlet은 도메인 컨트롤러에 기본 설치되어 있으며, RSAT를 사용하여 Windows 클라이언트에 설치하거나 Windows 서버의 "기능 추가" 마법사를 통해 활성화할 수 있습니다.
Get-GPOReport -All -ReportType xml -Path C:\temp\gporeport.xml
Grouper 모듈을 가져옵니다.
Import-Module .\grouper.psm1
Grouper를 실행합니다.
Invoke-AuditGPOReport -Path C:\temp\gporeport.xml
Grouper가 표시할 정책 설정을 변경하는 몇 가지 매개변수도 있습니다.
-showDisabled
기본적으로 Grouper는 현재 사용 가능하고 AD의 OU에 연결된 GPO만 표시합니다. 이 매개변수는 해당 동작을 전환합니다.
-Online
기본적으로 Grouper는 Get-GPOReport의 실제 XML 출력만 사용하며 네트워크 통신을 전혀 수행하지 않아 "opsec safe"합니다. 다만 저는 그 용어를 싫어합니다.
-Online을 사용하여 호출하면 Grouper는 (최소한) 보고서가 생성된 AD 도메인과 통신해야 하는 검사를 활성화하지만, 파일 서버 등과도 통신해야 할 가능성이 높습니다. 이를 통해 Grouper는 GPO가 대상으로 하는 파일의 ACL을 보고하거나 현재 사용자가 해당 파일에 쓸 수 있는지 확인하는 등의 유용한 작업을 수행할 수 있습니다.
-Level
Grouper는 출력에 적용할 수 있는 3가지 필터링 수준을 가지고 있습니다.
사용법은 간단합니다. -Level 3, -Level 2 등.
Get-GPOReport는 runas /netonly를 통해 도메인에 가입되지 않은 머신에서도 잘 작동합니다. 낮은 권한의 자격 증명이 필요하지만, 그건 예상된 일입니다.
이렇게 하세요:
runas /netonly /user:domain\user powershell.exe
도메인 컨트롤러와 통신할 수 있는 도메인에 가입되지 않은 머신에서 실행합니다.
그런 다음 생성된 PowerShell 세션에서 다음과 같이 합니다:
Get-GpoReport -Domain example.com -All -ReportType xml -Path C:\temp\gporeport.xml
쉽죠?
Grouper가 작동하는 데 필요한 것은 PowerShell 2.0과 Get-GPOReport의 XML 파일 출력뿐입니다. 걱정된다면 네트워크 카드가 없는 VM에서 실행해도 잘 작동합니다.
또한 코드가 매우 기본적이므로 원격으로 의심스러운 작업을 수행하지 않는다는 것을 쉽게 알 수 있습니다.
짧은 답변: 맞습니다.
긴 답변: 네, 그 중 하나를 하는 것이 더 좋겠지만, 아직 그렇게 하지 못하게 하는 몇 가지 이유가 있습니다.
이상적으로는 SYSVOL에서 직접 정책 파일을 파싱하고 싶지만, 다양한 파일 형식으로 저장되어 있으며 일부는 독점 형식이고 읽기가 정말 어렵습니다. 또한 Microsoft에서 이미 그 작업을 훌륭하게 수행하는 cmdlet을 제공하는데, 처음부터 많은 파서를 작성할 시간도 의향도 없습니다.
멀지 않은 미래에 Microsoft의 Get-GPOReport를 Grouper에 통합하여 RSAT가 전혀 필요 없게 만들고 싶지만, 그것이 저작권 위반이 될지 알아내야 합니다. 또한 방금 말한 그 일을 실제로 수행하는 방법도 알아내야 합니다.
Grouper는 취약점 스캐너가 아닙니다. Grouper는 그룹 정책 보고서의 엄청난 양의 잡음과 불필요한 내용을 필터링하여 악용 가능한 방식으로 구성될 수 있는 정책 설정만 표시합니다.
가능한 한 각 검사 범주를 작업하여 명백히 취약하지 않은 구성을 제거하고 노이즈 수준을 더욱 낮추기 위한 추가 필터링을 추가하고 있지만, 그룹 정책은 매우 유연하며 관리자가 만들 수 있는 모든 실수를 예측하기는 매우 어렵습니다.
좋습니다. Grouper를 개선할 방법을 찾으셨네요! 아래로 스크롤하면 Grouper에 새 검사를 추가하는 방법에 대한 간단한 가이드가 있습니다.
준비했습니다, 친구. 리포지토리에 test_report.xml 파일이 있으니 시험해볼 수 있습니다. 여러 가지 나쁜 설정이 포함되어 있어 어떤 모습인지 확인할 수 있습니다.
실험실 환경에서도 GPO를 활성화하고 싶지 않을 정도로 정말 끔찍한 구성으로 가득 차 있기 때문에 -showDisabled 플래그와 함께 실행해야 합니다.
알겠습니다.

짧은 답변: PowerView가 이 작업을 꽤 잘 수행합니다.
긴 답변: 언젠가 이 기능을 추가하려고 노력하겠지만, 그동안은 닥치고 PowerView를 사용하세요.
좋습니다. 쉽게 고칠 수 있습니다.
grouper.ps1을 열고 "$polchecks" 배열을 찾아 해당 검사가 배열에 추가되는 줄을 주석 처리하세요.
끝.
물론입니다, 좋아요.
Grouper가 찾을 수 있도록 하려는 정책/설정 유형이 포함된 GPOReport xml 출력을 얻으세요. 실험실 환경에서 적절한 정책을 만들어야 할 수도 있습니다.
대상 정책과 일치하는 <GPO> xml 개체를 찾으세요.
정책에서 추출하려는 정보와 일치하는 xml 하위 섹션을 찾으세요. 정책 설정은 사용자 또는 컴퓨터 정책으로 나뉘므로 일반적으로 다음 중 하나에 있습니다.
GPO.Computer.ExtensionData.Extension
또는
GPO.User.ExtensionData.Extension
이제 성가신 부분입니다. 이 코드가 이렇게 지저분한 이유는 각 정책 설정 섹션이 구조가 다르고 매우 다른 명명 규칙을 사용하기 때문입니다. 따라서 대상 정책이 어떻게 구성되어 있는지 파악해야 합니다. 행운을 빕니다?
다음은 시작할 수 있는 검사 함수의 뼈대입니다. 흥미로운 내용이 없으면 아무것도 반환하지 않거나 $null을 반환해야 합니다.
Function Get-GPOThing {
[cmdletbinding()]
Param (
[Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()] [System.Xml.XmlElement]$polXML,
[Parameter(Mandatory=$true)][ValidateSet(1,2,3)][int]$level
)
######
# 설명: 사물을 검사합니다.
# 취약: Level -eq 3 일 때 표시되는 내용 설명
# 흥미: Level -eq 2 일 때 표시되는 내용 설명
# 지루: 모든 사물.
######
$settingsThings = ($polXml.Thing.ExtensionData.Extension.Thing | Sort-Object GPOSettingOrder)
if ($settingsThings) {
foreach ($setting in $settingsThings) {
if ($level -eq 1) {
$output = @{}
$output.Add("Name", $setting.Name)
if ($setting.SettingBoolean) {
$output.Add("SettingBoolean", $setting.SettingBoolean)
}
if ($setting.SettingNumber) {
$output.Add("SettingNumber", $setting.SettingNumber)
}
$output.Add("Type", $setting.Type.InnerText)
Write-Output $output
""
}
}
}
}
다음 분들께 감사드립니다:
형편없는 코드에 대해 말하자면, 네 이것이 좀 지저분하다는 것을 알고 있습니다. 다른 사람들이 큰 어려움 없이 추가 검사를 추가할 수 있도록 최대한 모듈화하려고 노력했지만, 여전히 많은 개선이 필요합니다. 제가 저지른 실수 중 반드시 고쳐야 할 것이 보이면 알려주세요.
Ctrl-f로 "$polchecks"를 찾아 다른 검사들과 함께 배열에 추가하세요.
테스트하세요.
작동하면 풀 리퀘스트를 보내세요!
막히면 연락 주세요. 시간을 내서 도와드리겠습니다.