
Internal Monologue Attack: LSASS를 건드리지 않고 NTLM 해시 검색
Benjamin Delpy(@gentilkiwi)가 개발한 Mimikatz는 널리 알려진 사후 침투 도구로, 공격자가 메모리에서 일반 텍스트 비밀번호, NTLM 해시 및 Kerberos 티켓을 추출할 수 있게 하며, pass-the-hash, pass-the-ticket 또는 골든 티켓 생성과 같은 공격을 수행할 수 있게 합니다. 틀림없이, Mimikatz의 주요 용도는 사후 침투 측면 이동을 위해 LSASS 프로세스 메모리에서 사용자 자격 증명을 검색하는 것입니다.
최근 Microsoft는 Windows 10 Enterprise 및 Windows Server 2016에 Credential Guard를 도입했습니다. 이는 가상화 기반 보안을 사용하여 비밀을 격리하며, Mimikatz가 메모리에서 직접 해시를 검색하는 것을 방지하는 데 매우 효과적입니다. 또한 Mimikatz는 대부분의 엔드포인트 보호 솔루션의 주요 표적이 되었으며, 이를 탐지하고 방지하기 위한 노력이 매우 적극적입니다. 이러한 노력은 결국 실패할 수밖에 없지만 점점 더 골칫거리가 되고 있습니다.
NetNTLM은 주로 Kerberos가 지원되지 않는 환경에서 사용되는 Windows의 challenge-response 프로토콜입니다. NetNTLM에서 서버는 클라이언트에게 8바이트 난수 nonce를 challenge로 보내고, 클라이언트는 NTLM 해시(사용자 비밀번호의 MD4 해시)를 키로 사용하여 challenge를 처리하는 응답을 계산합니다. NetNTLM 인증 프로토콜에는 두 가지 버전이 있으며, 둘 다 특정 공격에 취약합니다. 당연히 버전 1은 버전 2보다 훨씬 약하며, 따라서 Windows Vista/2008부터 NetNTLM 버전 1은 기본적으로 비활성화되어 있습니다.
NTLM 해시가 응답 계산의 키이므로, 공격자는 반드시 피해자의 일반 텍스트 비밀번호를 얻을 필요가 없습니다. 따라서 Mimikatz를 사용하여 LSASS 메모리에서 해시를 검색하는 것은 일반 텍스트 비밀번호를 훔치는 것과 거의 동일합니다. Chris Hummel은 2009년에 이 기술을 설명하는 기사를 게시하고 "Pass the Hash"라고 명명했습니다 [https://www.sans.org/reading-room/whitepapers/testing/crack-pass-hash-33219].
2012년 Defcon에서 Moxie Marlinspike와 David Hulton은 NetNTLMv1에 대한 "분할 정복" 공격을 발표했습니다 [https://www.youtube.com/watch?v=sIidzPntdCM]. NetNTLMv1에서 클라이언트는 8바이트 challenge를 받고, NTLM 해시의 다른 부분을 키로 사용하여 DES로 세 번 암호화하여 응답을 계산합니다. DES의 키 길이는 사실상 56비트(7바이트)이며, NTLM 해시는 16바이트입니다. NetNTLMv1은 먼저 NTLM 해시의 처음 7바이트를 키로 사용하여 challenge를 암호화한 다음, NTLM 해시의 다음 7바이트를 키로 사용하여 challenge를 암호화하고, 마지막으로 NTLM 해시의 마지막 2바이트를 널 바이트로 패딩하여 키로 사용하여 challenge를 암호화합니다. 결과적으로, 주어진 NetNTLMv1 challenge와 응답으로 NTLM 해시를 검색하려면 공격자는 두 개의 56비트 DES 키를 크랙해야 하며, 이는 단일 128비트 키를 크랙하는 것보다 기하급수적으로 쉽습니다. Moxie와 Hulton은 이 작업을 위해 맞춤형 하드웨어를 개발했으며, 24시간 이내에 전체 DES 키 공간을 브루트포스할 수 있었습니다. 이는 합리적인 시간 내에 NTLM 해시를 성공적으로 검색할 수 있음을 보장합니다. 참고로, 비밀번호에 대한 사전 공격이나 브루트포스 공격이 성과를 거두지 못할 수 있는 반면, 이 공격은 NTLM 해시의 성공적인 검색을 보장합니다.
ToorCon이 https://crack.sh에서 시연한 바와 같이, 선택된 challenge(예: 0x1122334455667788)에 대한 가능한 모든 NetNTLMv1 응답에 대한 완전한 레인보우 테이블을 만드는 것이 가능하며, 이를 통해 주어진 응답에 대한 NTLM 해시를 몇 분 안에 크랙할 수 있습니다. 이는 선택된 challenge에 대한 NetNTLMv1 응답을 캡처하면 거의 즉시 해당 NTLM 해시로 변환될 수 있음을 의미하며, Pass the Hash로 인해 비밀번호를 얻는 것과 거의 동일합니다.
Mimikatz는 일반적으로 공격자가 대상 호스트에 대한 상승된 접근 권한을 획득한 후에 실행됩니다. 이 시점에서 공격자는 LMCompatibilityLevel과 같은 레지스트리 키를 변경할 수도 있습니다. 이 키는 호스트가 NetNTLMv1 또는 NetNTLMv2를 협상할지 여부를 지정합니다. 공격자는 값을 0, 1 또는 2로 변경하여 클라이언트가 NetNTLMv1을 사용하도록 설정한 다음, Optiv의 블로그 게시물 [https://www.optiv.com/blog/post-exploitation-using-netntlm-downgrade-attacks]에 설명된 대로 클라이언트의 응답을 캡처할 가짜 SMB 서버에 인증을 시도할 수 있습니다.
피해자가 NetNTLMv1 응답을 협상하지 못하도록 하는 두 가지 추가 설정이 있습니다:
Mimikatz를 실행해서는 안 되는 보안 환경에서 공격자는 Internal Monologue 공격을 수행할 수 있습니다. 이 공격에서는 확장된 NetNTLM 다운그레이드를 수행한 후, 사용자 모드 애플리케이션에서 SSPI를 통해 NTLM 인증 패키지(MSV1_0)에 대한 로컬 프로시저 호출을 호출하여 로그온한 사용자의 컨텍스트에서 NetNTLM 응답을 계산합니다.
Internal Monologue 공격 흐름은 아래와 같습니다:
최근에 Credential Guard가 활성화된 환경에서 Internal Monologue를 다시 테스트했으며 부정적인 결과를 얻었습니다. 초기 테스트 중에 내 테스트 환경에서 Credential Guard가 제대로 작동하지 않았는지, 아니면 그 이후로 무언가 변경되었는지 확실하지 않습니다. 로컬 인증 트랩을 피하기 위해 AcceptSecurityContext에서 서버 토큰을 동적으로 획득하고 이를 조작하도록 구현을 업데이트했습니다. 따라서 확장된 세션 보안 없이 NetNTLMv1이 실패하더라도 최소한 NetNTLMv2 challenge-response를 캡처할 수 있습니다.
Internal Monologue 공격은 Mimikatz를 실행하는 것보다 은밀하다고 할 수 있습니다. 보호된 프로세스에 코드를 주입하거나 메모리를 덤프할 필요가 없기 때문입니다. NetNTLMv1 응답은 로컬로 NTLM SSP와 상호 작용하여 이끌어지기 때문에 네트워크 트래픽이 생성되지 않으며, 선택된 challenge가 쉽게 표시되지 않습니다. 성공적인 NTLM 인증 이벤트가 로그에 기록되지 않습니다. NetNTLM 다운그레이드 및 토큰 도용/다른 사용자 가장을 위한 레지스트리 변경은 지표를 유발할 수 있습니다.
이 도구는 C#으로 Internal Monologue 공격을 구현한 개념 증명입니다. 코드를 PowerShell로 포팅하면 감사 추적의 특정 이벤트 로그가 다른 것으로 대체될 수 있습니다. PoC 코드는 완벽과는 거리가 멉니다. 긍정적인 기여와 개선 사항을 환영합니다.
Elad Shamir, The Missing Link Security