이 시리즈의 첫 게시물에서 Active Directory (AD) 서비스 계정이 무엇인지 살펴보고, 이러한 권한 있는 계정이 왜 심각한 보안 위험인지 설명했으며, 향후 게시물에서 서비스 계정을 대상으로 한 4가지 유형의 공격을 자세히 다루겠다고 약속했습니다. 이번 게시물에서는 그 첫 번째 공격인 LDAP 정찰을 다룹니다. LDAP 정찰은 공격자가 탐지를 피하면서 IT 환경에서 서비스 계정을 찾아내는 데 사용할 수 있는 기법입니다.
엄선한 관련 콘텐츠:
특히 이 글에서는 Domain Admin이나 로컬 Administrator 권한처럼 특별한 권한이 없는 공격자가 Bloodhound 같은 전문 도구를 설치하거나 배울 필요 없이, 간단한 PowerShell 쿼리만으로 서비스 계정을 찾는 방법을 살펴봅니다.
특권 계정 찾기
Active Directory는 보안과 관리 측면에서 많은 이점을 제공하지만, 호기심 많은 공격자에게는 일이 조금 너무 쉽게 느껴질 수도 있습니다. AD의 구조상, 공격자가 도메인에 연결된 어떤 컴퓨터에 침투하기만 하면 디렉터리와 그 객체를 쿼리할 수 있습니다. 또한 기본적으로 Active Directory는 의심스러운 활동을 감사하고 경고하기 위한 메커니즘을 제공하지 않기 때문에, 공격자는 종종 탐지를 피할 수 있습니다.
다음은 공격자가 LDAP를 쿼리하여 서비스 계정을 알아내는 방법 중 일부입니다.
서비스 프린시플 이름(Service Principal Name, SPN) 검색
서비스 계정은 Kerberos 인증을 지원하기 위해 SPN을 활용합니다. 이는 보안을 개선하지만, 동시에 이러한 계정이 어디에서 사용되고 무엇에 사용되는지에 대한 흔적을 그대로 남기기도 합니다. 이 정보는 공격자가 쉽게 악용할 수 있습니다. SPN은 Microsoft SQL Server 및 SharePoint 같은 애플리케이션을 지원하기 위해 서비스를 실행하는 데 흔히 사용됩니다.
다른 blog post에서는 고급 AD 정찰을 수행하는 방법을 설명하지만, 여기에서는 목적에 필요한 정보를 더 간단한 방식으로 얻을 수 있습니다. 다음의 간단한 LDAP 쿼리를 사용하면 공격자는 등록된 SPN을 보유한 AD 계정 목록뿐 아니라, 해당 계정이 접근을 제공하는 컴퓨터, 애플리케이션 및 데이터까지도 확인할 수 있습니다:
#Build LDAP filters to look for users with SPN values registered for current domain
$ldapFilter = "(&(objectclass=user)(objectcategory=user)(servicePrincipalName=*))"
$domain = New-Object System.DirectoryServices.DirectoryEntry
$search = New-Object System.DirectoryServices.DirectorySearcher
$search.SearchRoot = $domain
$search.PageSize = 1000
$search.Filter = $ldapFilter
$search.SearchScope = "Subtree"
#Execute Search
$results = $search.FindAll()
#Display SPN values from the returned objects
foreach ($result in $results)
{
$userEntry = $result.GetDirectoryEntry()
Write-Host "User Name = " $userEntry.name
foreach ($SPN in $userEntry.servicePrincipalName)
{
Write-Host "SPN = " $SPN
}
Write-Host ""
}
결과에 포함된 SPN 값은 각 계정이 어디에 등록되어 있는지, 그리고 해당 시스템에서 어떤 서비스에 대해 등록되어 있는지를 보여줍니다. 예를 들어, 다음은 SQL 서비스 계정의 SPN 값입니다:
일반 개체 속성을 사용한 서비스 계정 검색
SPN은 매우 신뢰할 수 있고 유용한 정보를 제공하지만, 많은 계정이 SPN을 통해 Kerberos와 통합되지 않으며 SPN 값이 설정되어 있지 않기 때문에 서비스 계정의 포괄적인 목록을 생성하지는 못합니다. 하지만 도메인 권한이 없는 공격자라도 다른 방법을 통해 서비스 계정을 찾는 경우가 많습니다. 특히 대부분의 조직은 모든 서비스 계정 이름이 “SVC”로 시작하거나 이와 유사한 규칙을 따르는 등 네이밍 컨벤션을 사용하며, 서비스 계정은 보통 별도의 조직 단위(OU) 또는 그룹에 배치됩니다.
계정 네이밍 컨벤션을 기반으로 서비스 계정 찾기
다음은 이름에 “svc”가 포함된 모든 계정을 찾는 PowerShell 스크립트입니다:
#Build LDAP filter to find service accounts based on naming conventions
$ldapFilter = "(&(objectclass=Person)(cn=*svc*))"
$domain = New-Object System.DirectoryServices.DirectoryEntry
$search = New-Object System.DirectoryServices.DirectorySearcher
$search.SearchRoot = $domain
$search.PageSize = 1000
$search.Filter = $ldapFilter
$search.SearchScope = "Subtree"
#Add list of properties to search for
$objProperties = "name"
Foreach ($i in $objProperties){$search.PropertiesToLoad.Add($i)}
#Execute Search
$results = $search.FindAll()
#Display values from the returned objects
foreach ($result in $results)
{
$userEntry = $result.GetDirectoryEntry()
Write-Host "User Name = " $userEntry.name
Write-Host ""
}
OU를 기반으로 서비스 계정 찾기
다음은 앞의 스크립트에 대입하여 이름에 “Service” 또는 “svc”가 포함된 모든 OU를 찾을 수 있는 LDAP 필터입니다:
$ldapFilter = "(&(objectClass=organizationalUnit)(|name=*Service*)(name=*svc*)))"
The attacker can then search those OUs for all user objects to find your service accounts. This script focuses on one OU with “Service” in its name:
$search = New-Object System,DirecoryServices.DirectorySearcher
$search.SearchRoot = "LDAP://OU=Service Accounts,OU=JEFFLAB,DC=local"
$search.PageSize = 1000
$search.Filter = $ldapFilter
$search.SearchScope = "Subtree"
사용자 계정 제어를 통한 서비스 계정 검색
서비스 계정은 일반 사용자 계정과 설정이 다를 때가 많기 때문에, 서비스 계정에 대해 Active Directory를 검색하는 또 다른 교묘한 방법은 계정 제어 설정을 살펴보는 것입니다. 이를 가장 잘 보여주는 예가 “password never expires” 설정입니다. 즉, 서비스 계정의 비밀번호는 만료되지 않도록 설정될 수 있는데, 비밀번호를 재설정하는 작업이 번거롭고 애플리케이션 또는 서비스 장애로 이어질 수 있기 때문입니다.
PowerShell을 사용하면 조금 더 복잡한 LDAP 필터를 통해 이 값이 활성화된 모든 계정을 찾을 수 있습니다:
$ldapFilter = "(&(objectclass=user)(objectcategory=user)(useraccountcontrol:1.2.840.113556.1.4.803:=65536))"
권한을 활용한 검색
이 글은 어떤 권한도 활용하지 않고 서비스 계정을 찾는 방법에만 초점을 맞췄지만, 공격자가 네트워크 내의 하나 이상의 시스템에서 권한을 가진 계정을 찾는다면 서비스 계정을 발견할 수 있는 다른 효과적인 방법이 많이 있습니다. 여기에는 다음이 포함됩니다:
- 엔드포인트에서 서비스 목록을 열거하고 startname 계정을 추출
- web.config, 스크립트 및 서비스 계정이 하드코딩될 수 있는 기타 위치에서 연결 문자열을 검색
- “Log on as a Service” 권한이 부여된 사용자의 로컬 정책을 탐색
- 비대화형 로그온 유형에 대한 이벤트 로그를 추출
- 애플리케이션 풀 및 기타 웹 애플리케이션 서비스 계정을 찾기
발견된 계정을 악용하기
공격자가 서비스 계정 목록을 확보하면, 다음 단계는 이를 악용하는 것입니다. 다음 게시물에서 그들이 사용할 수 있는 방법 몇 가지를 확인해 보세요:
LDAP 정찰 및 기타 공격 기법에 대해 더 알아보려면 Netwrix attack catalog 를 참고하세요.
공유하기
더 알아보기
저자 소개
Jeff Warren
최고 제품 책임자
Jeff Warren은 Netwrix의 제품 포트폴리오를 총괄하며, 보안에 초점을 둔 제품 관리 및 개발 분야에서 10년이 넘는 경험을 바탕으로 기여하고 있습니다. Netwrix에 합류하기 전 Jeff는 Stealthbits Technologies에서 제품 조직을 이끌었으며, 소프트웨어 엔지니어로서의 경험을 활용해 혁신적이고 엔터프라이즈 규모의 보안 솔루션을 개발했습니다. 직접적인 실행 중심의 접근 방식과 까다로운 보안 과제를 해결하는 데 강점을 지닌 Jeff는 실제로 효과가 있는 실용적인 솔루션을 구축하는 데 집중하고 있습니다. 그는 델라웨어 대학교에서 정보 시스템(Information Systems) 학사 학위를 취득했습니다.