1. 개념

  일반적인 사람들 입장에서 처음 컴퓨터를 사고 설치할 때 계정을 생성하고 등록할 것이다. 중요한 것은 이 계정이 관리자 그룹(Administrators)에 속한다는 점이다. 참고로 표준 사용자 그룹(Users)에도 동시에 속해 있다. 이후 다른 계정을 생성할 때가 있을텐데 이 때도 관리자 계정을 만들 수도 있고 대신 표준 사용자 계정을 만들 수도 있다. 만약 관리자 계정으로 새로운 계정을 만든다면 이 계정도 Administrators, Users 두 가지에 속해있는 것을 볼 수 있을 것이다. 대신 표준 사용자 계정을 선택하여 만든다면 단지 Users에만 속해있다.


  윈도우는 표준 사용자 계정으로 로그온한 경우 거기에 맞는 적절한 보안 토큰을 준다. 관리자 계정으로 로그온한 경우에는 2개의 토큰을 받는데, 앞서 말한 표준 사용자 계정이 받는 토큰과 비슷한 권한을 가진 보안 토큰 그리고 관리자 토큰 이렇게 2개를 받는다. 


  조금 더 자세히 설명해 보겠다. Integrity 메커니즘은 커널의 SRM(보안 참조 모니터)에 기반한 윈도우 보안 아키텍처이다. SRM은 보안 접근 토큰에 존재하는 (유저와 그룹의) SID를 객체의 보안 디스크립터의 접근 권한과 비교해서 접근 제어를 강제한다. Integriry level에는 System, High, Medium, Low, Untrusted가 있다. 정리하자면 LocalSystem, LocalService 등의 경우 System Integrity level이 할당되며, Administrators의 경우 High, Standard Users의 경우에는 Medium이 할당된다.


  이를 통해 앞의 설명을 보충하자면 표준 사용자(Standard Users Group)로 로그온한 경우에는 표준 사용자 접근 토큰을 받는다. 이 접근 토큰은 Medium Integrity Level이 할당되어 있다. 관리자 계정(Administrators group)으로 로그온한 경우 표준 사용자 접근 토큰과 관리자 접근 토큰 2개를 받는다. 표준 사용자 접근 토큰은 위와 같고 관리자 접근 토큰은 High Integrity Level이 할당되어 있다.


  이제 응용 프로그램을 실행한다고 하자. 현재 계정이 표준 사용자던지 관리자던지 실행은 Medium Integrity Level의 접근 토큰을 가지고 하게된다. 왜냐하면 애플리케이션 실행 시에 explorer.exe의 자식 프로세스로 실행되는데 이 explorer.exe가 Medium 레벨을 가지고 실행 중이기 때문이다. 그래서 대부분의 프로그램은 이렇게 실행될 것이다. 하지만 문제가 있는데 만약 응용 프로그램 내부에 관리자 권한이 필요한 부분이 있다고 하자. 이 경우에는 현재 접근 토큰이 Medium이기 때문에 High Integrity Level의 권한을 갖지 못하여 권한이 필요한 루틴이 에러를 반환하고 프로그램이 제대로 동작할 수 없을 것이다. 이럴때는 보통 마우스 우클릭 후 "관리자 권한으로 실행"을 통해 관리자 권한으로 실행할 수 있다. 가끔 오래된 프로그램의 경우 제대로 실행되지 않을 때 관리자 권한으로 실행하라는 답변을 얻을 수 있는데 이것이 그 때문이다. 일반적으로 UAC 메커니즘이 생기기 전인 Windows XP 시절에 만든 프로그램일 것이다.


  또한 사족으로 관리자 권한으로 실행된 프로그램에는 드래그 앤 드랍이 통하지 않는다는 사실이 있다. 예를들어 CMD를 관리자 권한으로 실행한 후 특정 파일을 실행시키고 싶어서 드래그 앤 드랍으로 CMD에 끌어다 놓으면 경로명이 자동으로 올라오지 않는 것을 볼 수 있다. 이것은 단지 CMD만 해당하는 것이 아니고 OllyDbg를 관리자 권한으로 실행하거나 HxD를 관리자 권한으로 실행한 후 바이너리를 끌어다 놓을 때 통하지 않는 것을 확인할 수 있다. 드래그 앤 드랍은 exeplorer.exe가 관리하는 것으로 추정되며 이것이 Medium 레벨을 가지므로 High 레벨을 갖는 프로세스에 영향을 끼칠 수 없기 때문이다. 그래서 드래그 앤 드랍 방식 외에 직접 파일을 읽어들이거나 최악의 경우 Windows XP에서 해당 작업을 수행하던지, 아니면 explorer.exe를 관리자 권한으로 실행시키는 방식이 사용되기도 한다.


  현재 계정이 표준 사용자라고 하자. 그렇다면 관리자 권한으로 실행시킬 때 UAC가 나타난다. 이 UAC를 보면 관리자의 비밀번호를 입력해야 한다. 즉 당연히 관리자의 비밀번호가 있어야만 관리자 접근 토큰을 받아 관리자 권한으로 프로그램을 실행시킬 수 있다. 하지만 현재 계정이 관리자라고 하더라도 관리자 권한으로 실행시키면 UAC가 뜨는 것을 볼 수 있다. 관리자 계정으로 로그온한 경우에도 explorer.exe가 Medium 권한으로 실행되며 이것의 자식 프로세스로 실행되는 것은 똑같기 때문에 Medium 접근 토큰으로 실행할 것다. 그리고 관리자 권한으로 실행한다면 High Integrity Level의 접근 토큰으로 실행할 것이다. 관리자 계정이 비록 관리자 접근 토큰을 소유하고 있지만 UAC가 뜨는 것은 같다. 물론 이 때는 비밀번호를 입력할 필요 없이 간단하게 확인 버튼만 누르면 된다. 사실 이것이 UAC의 핵심인데 관리자 권한을 가진 관리자 계정이라고 하더라도 평소에는 축소된 표준 사용자 권한을 가지며 지내다가 관리자 권한으로 프로그램을 실행할 때에는 사용자의 확인을 받고 실행하는 것이다. 그래서 비밀번호의 입력 차이만 있을 뿐 관리자 권한을 사용하여 프로그램을 실행할 때에는 UAC가 뜨는 것은 같게 된다. 참고로 이미 관리자 권한으로 실행 중인 프로세스가 관리자 권한을 필요로 하는 작업을 하는 경우에는 당연히 UAC가 뜨지 않을 것이다. UAC는 단지 더 높은 권한을 필요로 할 때에만 뜨는 메커니즘이다.


  윈도우 7부터는 UAC도 설정이 가능한데 당연히 UAC의 설정을 바꾸기 위해서도 관리자 권한이 필요하므로 UAC가 뜨는 것을 볼 수 있다. UAC 뿐만 아니라 다른 중요한 설정을 바꿀 때에도 마찬가지이다. 예를들면 UAC를 우회하여 방화벽의 설정을 바꾸는 악성코드도 존재한다. 언제 관리자 권한이 필요한지에 대해 더 알아보자면 아마 가장 흔한 경우가 응용 프로그램을 설치할 때일 것이다. 아니면 시스템 파일을 수정하거나 디바이스 드라이버를 설치할 때도 그렇다. 또한 속한 그룹에 따라 가질 수 있는 권한도 다른데, SeDebugPrivilege 같은 권한의 경우에는 관리자 그룹에 속한 계정이 가질 수 있다. 참고로 이 권한은 접근 통제를 우회할 수 있게 해준다. 만약 관리자 권한으로 실행 중인 어떤 프로세스가 이 권한을 활성화하였다면 System Integrity Level을 가지고 실행 중인 프로세스에 CreateRemoteThread(), WriteProcessMemory() 같은 함수를 사용할 수 있게 된다. 다시 말해서 (LocalSystem에 의해 생성되어) System Integrity level을 가진 프로세스의 경우 일반적으로는 (관리자 계정에 의해 실행되어) High Integrity level을 가진 프로세스에게 접근 권한이 없지만 비활성화된 SeDebugPrivilege를 활성화시킨다면 이것을 우회하여 System 권한을 가진 프로세스들에 접근할 수 있다는 것이다. 즉 관리자 계정의 경우 해당 과정을 거쳐 실질적으로는 (현재 High Integrity level임에도 불구하고 더 높은 권한인) System Integrity level에도 접근할 수 있는 권한이 존재한다고 볼 수 있다.


  어쨌든 이런 중요한 작업에 관리자 권한이 필요하다는 것은 당연할 것이고 만약 응용 프로그램이 관리자 권한을 필요로 할 경우에 어떻게 할 것인가에 대해서도 알아보자. 앞에서도 언급하였듯이 마우스 우클릭 후 "관리자 권한으로 실행"을 클릭할 수 있다. 또는 속성의 호환성 탭을 누른 후 "관리자 권한으로 이 프로그램 실행"을 선택해도 된다. 


  하지만 이것은 사용자의 입장이고 개발자로서도 개발한 프로그램이 관리자 권한을 필요로할 경우에는 실행 시에 자동으로 관리자 권한으로 실행되도록 프로그램을 개발할 필요가 있다. 이것은 VC++ 프로젝트 옵션에서 링크 -> Manifest file을 클릭하면 설정이 가능하다. level에는 asInvoker (응용 프로그램을 시작한 프로세스와 동일한 권한으로 응용 프로그램 시작), highestAvailable (최대한 높은 권한 수준으로 응용 프로그램 실행), requireAdministrator (관리자 권한으로 실행)이 있다. 이렇게 설정한 후 생성된 응용 프로그램을 보면 리소스 섹션에 xml 형태의 문자열이 설정한 레벨에 써져있는 것을 볼 수 있다. 프로그램 실행 시 이 레벨을 참고하여 실행하는데 만약 레벨이 requireAdministrator로 설정되어 있다면 UAC가 뜨는 것을 볼 수 있을 것이다. 


  참고로 highestAvailable는 조금 더 설명이 필요하다. 만약 현재 표준 사용자 계정으로 로그온한 경우라면 UAC가 뜨지 않을 것이다. Medium이 최대 권한이므로 관리자 권한을 요구하지 않을 것이기 때문이다. 하지만 관리자 계정이라면 최대 권한인 관리자 권한으로 실행되기 때문에 UAC가 뜨는 것을 볼 수 있다. 굳이 이러한 메커니즘을 만든 이유를 알아보자. 이것은 개발한 프로그램이 관리자 권한을 가진 경우에는 모든 기능을 사용할 수 있고 만약 표준 사용자 계정이라도 제한적인 기능을 사용할 수 있게 하려는 경우에 사용된다. 예를들면 regedit.exe (레지스트리 편집기)가 있다. 일반 사용자의 경우에도 HKCU 하이브의 어떤 값들은 수정할 권한이 있기 때문이다. 물론 관리자 권한이 없으므로 HKLM 하이브의 경우에는 손댈 수 없다.





2. UAC 우회

  앞에서도 설명하였듯이 사용자가 관리자 계정을 가지고 있더라도 관리자 권한이 필요한 프로그램을 실행할 경우에는 UAC가 뜨게 된다. UAC Bypass 즉 UAC 우회는 관리자 권한으로 실행 시 UAC가 뜨는 것을 우회하여 사용자가 인지하지 못하게 악성코드를 설치하거나 악의적인 작업을 하기 위해 사용된다. 악성코드 설치 시에 레지스트리 수정 같이 설치 시에 관리자 권한이 필요한 경우가 많기 때문일 것이고 악의적인 작업도 Medium 권한으로는 한계가 있다. UAC 메커니즘이 만들어지기 전인 Windows XP에서는 지금처럼 대부분 관리자 계정을 사용하였을 것이고 UAC 메커니즘도 없었기 때문에 악성코드는 사용자가 인식하지 못하게 관리자 권한을 가지고 악성코드를 설치하는 일이 훨씬 편했을 것이다.


  물론 앞에서도 설명했지만 굳이 관리자 권한 없이도 악의적인 행위를 수행할 수 있다. 어떤 랜섬웨어의 경우에는 자신이 SeDebugPrivilege 권한을 가지고 실행 중인지를 판단한 후 가지고 있지 않다면 단지 사용자 파일을 암호화하며 가지고 있다면 추가적으로 MBR도 암호화시키는 루틴을 가지고 있다. 하지만 자동 시작을 위해 레지스트리의 AutoRun에 값을 집어넣거나 서비스 및 드라이버 설치, 시스템 디렉터리에 손대기, 방화벽 설정 변경 등 악성코드로서 할 수 있는 많은 부분에 제약이 생기기 때문에 많은 악성코드들은 관리자 권한을 원한다.


  이제부터는 UAC bypass를 설명하고자 한다. UAC 우회는 전제 조건으로 먼저 사용자가 관리자 계정이어야 한다. 또한 대부분 UAC 옵션이 디폴트 옵션인 "Notify me only when programs try to make changes to my computer" (앱에서 사용자 모르게 컴퓨터를 변경하려는 경우에만 알림)를 선택한 경우에만 통하는 편이다. 공개된 방법들 중에는 UAC의 가장 강한 옵션인 "Always Notify"로 설정된 경우에는 제대로 동작하지 않는 기법들이 많다. 물론 위에서 언급하였듯이 대부분의 사용자는 관리자 계정을 가지고 컴퓨터를 사용할 것이며 UAC도 디폴트 설정으로 머물러 있을 것이기 때문에 버전에 맞고 취약점이 패치되지 않았다면 대부분 통할 것이다.


  그리고 공통적으로 사용되는 메커니즘이 있다. 윈도우 시스템 파일들은 Microsoft Windows publisher에서 서명한 사인이 존재하는데 (그렇기 때문에 사인받았다고 해도 3rd party 애플리케이션은 이와 관련이 없다) 이 중에서 리소스의 manifest에 <autoElevate>true<autoElevate> 즉 자동 권한 상승 속성이 삽입되어 있는 프로그램이 있다. 이 프로그램들은 당연히 관리자 권한으로 실행되지만 UAC 옵션이 "Notify me only when programs/apps try to make changes to my computer"로 설정되어 있다면(Always Notify와 Never Notify의 중간) 이름처럼 실행 시에 UAC가 뜨지 않는다. Administrators group에 속해 있다면 관리자 권한으로 실행되지만 UAC가 뜨지 않는 것이다. UAC bypass는 이러한 프로그램들을 대상으로 한다. 즉 악성코드가 이것이 설정된 애플리케이션을 실행시킬 때는 UAC가 뜨지 않으며 관리자 권한을 가진 이 프로그램이 악성코드를 실행하게 만들어서 자동으로 상승된 권한을 상속받은 악성코드를 실행하는 것이다.


  UAC Bypass 취약점의 경우 다양한 프로그램들을 이용하지만 기본적인 방식은 비슷한 경우가 많다. 먼저 앞에서도 언급하였지만 auto-elevate 속성을 가지며 취약점을 통해 악성코드를 실행하게 될 프로그램들로는 sysprep.exe, cliconfg.exe, mmc.exe 등이 있으며 이 프로그램들 외에도 최근에는 다른 프로그램들도 많이 발견되고 있는 중이다. 또한 이 프로그램이 가진 즉 UAC bypass에서 사용되는 취약점은 대부분 DLL Hijacking 방식이다. 다시말해 이 프로그램이 취약하여 로드할 DLL을 안전하게 검사하지 않아서 공격자가 만든 DLL을 로드하게 만드는 방식이다. 이제부터는 실제 예를들어서 설명할 것이다. 여기서 언급하는 취약점들은 모두 패치되어 더 이상 사용이 불가능하지만 메커니즘을 공부할 수는 있다.


  먼저 Mcx2Prov.exe를 이용하는 방식을 통해 설명해 보겠다. 이 프로그램은 cryptbase.dll에 대해 DLL Hijacking 취약점을 갖는데 이 취약점은 애플리케이션이 dll을 로드하기 위해 찾을 때 현재 디렉터리에서 가장 먼저 찾기 때문에 벌어진다. 그러므로 만약 우리가 악의적인 행위를 수행하는 dll을 만들어서 cryptbase.dll이라는 이름을 붙이고 그 디렉토리에 교체해 넣으면 이 dll을 로드할 것이다. 하지만 이 프로그램은 C:\Windows\System32에 존재하기 때문에 공격자가 만든 dll을 여기에 옮기는 것부터 문제가 생긴다. 왜냐하면 애초에 해당 디렉토리에 파일을 옮기는 것도 관리자 권한이 필요하기 때문이다. 여기서는 wusa.exe(Windows Update Standalone Installer)를 이용한다. 먼저 악의적인 dll을 만들고 이름을 cryptbase.dll로 짓는다. 이후 makecab 프로그램을 이용해 이 dll을 cabinet 파일로 만든다. 이제 wusa를 사용하여 이 파일을 /extract 옵션을 주고 Mcx2Prov.exe가 존재하는 디렉터리에 풀면 된다. 관리자 권한이 필요한 동작인 C:\Windows\System32에 파일을 이동시키는 행위를 auto-elevate 프로그램인 wusa를 이용하여 가능케 한 것이다. 참고로 wusa.exe의 이러한 문제점 때문에 이후 /extract 옵션이 제거되었다. 이제 Mcx2Prov.exe를 실행하면 변경된 cryptbase.dll을 로드하기 때문에 UAC 없이 dll로 만들었던 내용이 관리자 권한을 가지고 실행되는 것을 볼 수 있다.


  더 흔한 예시를 들어보겠다. 앞에서는 Mcx2Prov.exe를 가지고 설명했지만 사실 가장 많이 사용되었던 프로그램은 sysprep.exe이다. 이것도 위와 비슷하게 DLL Hijacking 취약점을 사용한 방식이고 앞에서 말했던 cryptbase.dll도 해당하는 dll 중 하나였다. 물론 이렇게 간단한 차이를 설명하기 위해 예시를 든 것은 아니고 이번에는 wusa 대신 IFileOperation 방식을 위주로 설명하고자 한다. 또한 다른 프로세스들도 마찬가지이지만 explorer.exe 같은 윈도우 자체 프로세스도 Medium Integrity Level을 가지고 있기 때문에 dll 인젝션이 가능하다는 것을 알 수 있다. CreateRemoteThread() 함수는 XP에서와 달리 제약 사항이 많아졌지만 대상 프로세스가 같은 세션에 존재하고 (explorer.exe 프로세스는 당연히 로그온 시에 생성됨과 동시에 실행할 프로세스의 부모이므로) 같거나 낮은 Integrity Level을 가지고 있다면 과거와 같이 DLL 인젝션에 사용될 수 있다.


  먼저 explorer.exe에 dll을 인젝션한다. 인젝션되는 dll에서는 IFileOperation이라는 COM 인터페이스를 이용하는데 여기에는 파일을 복사하고 삭제하는 메소드가 들어있다. 여기와 관련된 부분은 뒤에 추가하기로 한다. 이를 통해 보호된 디렉터리에(C:\Windows\System32 같은) 존재하는 cryptbase.dll을 지우고 공격자가 제작한 dll로 변경한다. UAC 없이 이 방식이 어떻게 관리자 권한을 갖을 수 있냐면 COM 오브젝트는 MS 서명이 되어있는 프로세스에서 사용되는 경우 UAC 없이 auto-elevated되기 때문이다. 즉 구체적으로 말하자면 IFileOperation 오브젝트는 만약 explorer.exe 같이 MS 서명이 되어있는 프로세스에서 (dll이 인젝션되었으므로 dll의 내용은 explorer와 같은 권한으로 실행된다) 사용되는 경우 auto elevated되어서 실행된다. 그래서 UAC 없이 관리자 권한으로 시스템 디렉터리에 쓸 수 있는 것이다.


  이 방식의 단점은 IFileOperation COM 오브젝트를 사용할 경우 UAC 옵션이 "Always Notify"라면 UAC가 뜬다는 점과, 과정 중 DLL 인젝션이 수반되기 때문에 보안 프로그램에서 탐지될 수 있다는 점이 있다.


  마지막으로 지금까지 봐왔던 것과는 조금 다른 방식을 설명하려고 한다. IFileOperation의 경우에는 dll 파일 및 이것을 프로세스에 인젝션하는 과정이 필요했다. wusa를 이용한 방식도 결국 DLL Hijack 방식이라는 것은 같기 때문에 dll이 필요하며 이것을 시스템 디렉터리로 이동시키는 작업이 필요했다. 이런 방식들은 보안 솔루션을 통해 탐지될 확률이 높다. 여기서는 레지스트리를 이용하는 방식을 다룬다. 먼저 취약점에 이용되는 레지스트리에 대한 배경 지식을 설명하자면 HKEY_CLASSES_ROOT(HKCR)HKEY_LOCAL_MACHINE\SOFTWARE\ClassesHKEY_CURRENT_USER\Software\Classes의 조합이다. 그리고 표준 사용자는(Medium Integrity Level) 관리자 권한이(High Integrity Level) 없어도 자신의 HKCU 레지스트리를 수정할 수 있다.


  여기서 사용되는 eventvwr.exe도 당연히 auto-elevate 속성을 가지고 있다. 이 프로그램은 실행 시 RegOpenKey()를 이용해 HKCU\Software\Classes\mscfile\shell\open\command를 읽지만 “NAME NOT FOUND”라는 결과를 받는다. 실패 이후에는 HKCR\mscfile\shell\open\command를 읽는데 값을 보면 mmc.exe의 경로이며 이것을 실행시키는 것을 볼 수 있다. 중요한 점은 eventvwr.exe가 auto-elevate 속성을 가지므로 UAC 없이 관리자 권한을 통해 실행된다는 점이고 이에 따라 mmc.exe도 관리자 권한으로 실행된다는 것이다. 우리가 이용할 취약점은 eventvwr가 HKCR을 읽기 전에 먼저 HKCU를 읽으며 표준 사용자로서 HKCU의 레지스트리를 조작할 수 있다는 점이다. 만약 우리가 HKCU\Software\Classes\mscfile\shell\open\command에 원하는 악성코드의 경로를 집어넣는다면 이 악성코드는 UAC 없이 관리자 권한으로 실행될 것이다.





3. 참고사항

- UAC는 디지털 서명의 유무에 따라 다르게 보여지는데, 응용 프로그램이 서명된 경우에는 윗 부분이 파랗게, 아닌 경우에는 노랗게 뜬다.


- 디폴트로 비활성화되어 있는 계정 중 Administrator라는 계정이 있다. 헷갈릴 수 있지만 그룹 Administrators에 속하는 이름이 Administrator라는 계정이다. 과거와 달리 현재는 디폴트로 비활성화되어 있기 때문에 볼 일이 없겠지만 굳이 이것을 언급하는 이유는 이 계정을 사용하면 UAC가 디폴트로 비활성화되어 있다는 특징 때문이다. 과거 XP의 자료들과 비교하여 혼동의 여지가 있을 수 있으므로 적어놓는다.


- 실행 도중에 관리자 권한 획득에 대해서 생각해볼 수 있다. 일반적으로 CreateProcess()를 사용하여 가능할 방법을 찾겠지만 불가능하다. 대신 ShellExecute() 또는 ShellExecuteEx()의 인자 또는 구조체에 "runas"를 넣고 호출한 경우에만 가능하다.


- 먼저 COM 등과 관련된 문서의 링크이다. [ http://sanseolab.tistory.com/49 ] 그리고 여기와 관련된 추가적인 내용은 다음과 같다.

  IUnknown 인터페이스는 COM에서 가장 기본적인 인터페이스이다. 그러므로 모든 COM 객체들은 만드시 최소한 이 인터페이스는 구현해야 하며 나아가 모든 COM 인터페이스는 반드시 여기에서 나온다. 그러므로 ActiveX 하에 설계된 컴포넌트들도 반드시 IUnknown 인터페이스를 구현해야 한다.

  IFileOperation 인터페이스는 IUnknown 인터페이스를 상속하며 Shell 아이템들에 대한 복사, 이동, 생성, 삭제 등의 메소드를 제공한다.


- Window XP에서는 Integrity Level 메커니즘이 존재하지 않으므로 당연히 UAC 관련된 기능도 없다. 그래도 비슷한 점이 많이 있는데 현재 관리자 그룹 즉 Administrators Group에 속한 계정이라면 SeDebugPrivilege를 Enable시킬 수 있다는 점이다. XP도 일반적으로는 이 권한이 Disabled되어 있다.

Posted by SanseoLab

블로그 이미지
Malware Analyst
SanseoLab

태그목록

공지사항

Yesterday
Today
Total

달력

 « |  » 2024.3
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

최근에 올라온 글

최근에 달린 댓글

글 보관함