Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일

(시리즈 글이 8개 있습니다.)
Windows: 14. 보호 모드와 필수 무결성 제어(MIC: Mandatory Integrity Control)
; https://www.sysnet.pe.kr/2/0/433

Windows: 15. MIC 환경 구성 - Windows XP와 유사한 보안 설정
; https://www.sysnet.pe.kr/2/0/434

Windows: 16. 개발자를 위한 UAC 환경 설정
; https://www.sysnet.pe.kr/2/0/437

Windows: 17. 보안 데스크톱에서 활성화되지 않은 UAC 창이 안전할까?
; https://www.sysnet.pe.kr/2/0/441

Windows: 20. UAC 이모저모
; https://www.sysnet.pe.kr/2/0/449

Windows: 22. 가상화에 대해서.
; https://www.sysnet.pe.kr/2/0/456

.NET Framework: 297. 특정 EXE 파일의 실행을 Internet Explorer처럼 "Protected Mode"로 실행하는 방법
; https://www.sysnet.pe.kr/2/0/1225

개발 환경 구성: 571. UAC - 관리자 권한 없이 UIPI 제약을 없애는 방법
; https://www.sysnet.pe.kr/2/0/12633




특정 EXE 파일의 실행을 Internet Explorer처럼 "Protected Mode"로 실행하는 방법

예전에, MIC(Mandatory Integrity Control)에 대해서 소개해 드렸는데요.

보호 모드와 필수 무결성 제어(신뢰도 등급)(MIC: Mandatory Integrity Control)
; https://www.sysnet.pe.kr/2/0/433

이에 따르면, Internet Explorer가 "보호 모드"로 실행된다는 것은 곧, MIC 등급이 "Low"에 해당하는 프로세스로 실행된다는 것과 같은 말입니다.

보통 여러분들이 Vista/7에서 로그인 한 후 실행하는 대부분의 프로그램들이 "Medium" 등급에서 동작됩니다. 일반적으로 "Medium" 등급은 '관리자 권한'으로 실행되지 않는 프로세스들에 부여되는데, "Internet Explorer"는 웹 상에서 가져오는 모든 데이터들에 대해서 기본적으로 신뢰를 하지 않기 때문에 자신의 프로세스 자체를 "Low" 레벨로 낮춰서 실행해 줌으로써 보안성을 높인 것입니다.

일단, 마이크로소프트가 만든 프로그램은 그렇다 치고... 그럼 우리가 만드는 프로그램은 어떻게 해야 할까요?

예를 들어, 여러분들이 '메일 클라이언트'를 만들었다고 가정해 보겠습니다. 거기에는 온갖 스팸 메일과 출처를 알 수 없는 exe 파일들이 첨부되어 올 텐데... 이에 대한 보안을 어떻게 높일 수 있을까요?

우선, 해당 '메일 클라이언트'를 IE처럼 "Low" 레벨로 실행하는 것을 예로 들 수 있겠지요. 하지만... 해보신 분은 아시겠지만 Low 레벨로는 할 수 있는 일이 거의 없습니다. (순수 UI 용이나, 계산 정도만 가능하다고 봐야 할 것입니다.)

자... 그럼 이건 어떨까요? '메일 클라이언트'는 그냥 그대로 실행하고 메일로 첨부된 파일들을 로컬에 저장할 때 모두 "Low" 등급이라는 딱지를 붙여두는 것입니다. 그렇게 되면 사용자가 실수로 그 첨부 파일을 실행한다고 해도 시스템에 위해를 가하는 것이 불가능합니다.

이번 글에서는 이에 대해 알아보겠습니다.




우선, 해당 파일에 대해 "Low" MIC 권한을 부여할 수 있는 코드가 필요한데, 이는 C/C++ 코드로 이미 다음과 같이 공개되어 있습니다.

Understanding and Working in Protected Mode Internet Explorer
; https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/

#include <sddl.h>
#include <AccCtrl.h>
#include <Aclapi.h>

void SetLowLabelToFile()
{
  // The LABEL_SECURITY_INFORMATION SDDL SACL to be set for low integrity 
  #define LOW_INTEGRITY_SDDL_SACL_W L"S:(ML;;NW;;;LW)"
  DWORD dwErr = ERROR_SUCCESS;
  PSECURITY_DESCRIPTOR pSD = NULL;    

  PACL pSacl = NULL; // not allocated
  BOOL fSaclPresent = FALSE;
  BOOL fSaclDefaulted = FALSE;
  LPCWSTR pwszFileName = L"Sample.txt";

  if (ConvertStringSecurityDescriptorToSecurityDescriptorW(
         LOW_INTEGRITY_SDDL_SACL_W, SDDL_REVISION_1, &pSD, NULL)) 
  {
    if (GetSecurityDescriptorSacl(pSD, &fSaclPresent, &pSacl, 
         &fSaclDefaulted))
    {
      // Note that psidOwner, psidGroup, and pDacl are 
      // all NULL and set the new LABEL_SECURITY_INFORMATION
      dwErr = SetNamedSecurityInfoW((LPWSTR) pwszFileName, 
                 SE_FILE_OBJECT, LABEL_SECURITY_INFORMATION, 
                 NULL, NULL, NULL, pSacl);
    }
    LocalFree(pSD);
  }
}

그런데, 실제로 위의 코드를 Windows 7에서 실행시켜 보면 SetNamedSecurityInfoW 함수 실행에서 오류가 발생합니다. dwErr == 5라고 하니 "Access is denied"일 텐데... 가만 보니, 위의 기능을 하는 프로세스를 "Run as administrator"로 실행시키면 정상적으로 동작을 했습니다.

^^; 아니... 보안을 높이려고 했는데, 오히려 우리가 만들 프로그램 자체의 실행 권한을 높여야 하다니 말이 안됩니다.

그래서, 조금 더 살펴보았는데 해당 파일의 "Users" 접근 권한이 "Full Control"을 가지고 있으면 정상적으로 동작한다는 것을 알았습니다.

mic_process_start_1.png

산 넘어 산이군요. ^^; "Low" 등급을 지정하는 코드는 간단한데 이를 위해 파일 권한에서 "Users"의 DACL 권한을 조정해야 하는 코드를 넣어야 합니다.

하지만 ^^ 너무 걱정하지 마십시오. 다행히 윈도우의 기본 명령행에서 ACL 권한을 조정하는 유틸리티를 제공하고 있으니 이를 이용해서 처리를 해주면 됩니다. 바로 cacls.exe가 그것입니다.

==== USERS 그룹에 "Full Control" 부여
D:\Debug>cacls test.exe /E /P USERS:F
processed file: D:\Debug\test.exe

==== USERS 그룹에 다시 "Read" 권한만 부여
D:\Debug>cacls test.exe /E /P USERS:R
processed file: D:\Debug\test.exe

자... 그럼 테스트를 해볼까요? 간단하게 C#으로 만들어 보았습니다.
(물론, 소스 코드는 첨부해 두었으니 참고하십시오. ^^)

mic_process_start_2.png

위의 이미지에서 "Download" 버튼을 누르면 지정된 "File URL"로부터 파일을 다운로드 받습니다. 받자마자 다음과 같이 Low 등급을 부여하는 코드를 실행해 줍니다.

Uri uri = new Uri(txtUri.Text);

string fileName = Path.GetFileName(uri.LocalPath);
WebClient wc = new WebClient();

Directory.CreateDirectory(txtSaveFolder.Text);

Directory.Exists(txtSaveFolder.Text);

filePath = Path.Combine(txtSaveFolder.Text, fileName);

// URL로부터 파일 다운로드
wc.DownloadFile(uri, filePath);

// Low 등급 부여
SetAccessControl(filePath, "F");
SetLowLevelSecurity(filePath);
SetAccessControl(filePath, "R");

위의 예제에서 다운로드 받도록 한 ConsoleApplication1.exe 프로그램은 내부에 다음과 같은 코드만을 포함하고 있습니다.

class Program
{
    static void Main(string[] args)
    {
        File.WriteAllText(@"C:\temp\test.txt", "test");
        Console.WriteLine("TEST, press any key to exit...");
        Console.ReadLine();
    }
}

보시는 것처럼, "C:\temp\test.txt" 파일을 생성하는데 보통의 과정을 통해서 이 파일을 다운로드 받았다면 정상적으로 실행이 될텐데요. 자, 그럼 프로그램에서 "Run" 버튼을 눌러서 확인을 해보도록 하겠습니다.

우선, Windows 7은 해당 프로그램을 실행하려고 하면 다음과 같이 한번 더 묻게 됩니다.

mic_process_start_3.png

저 창이 떠야 확실하게 "Low" 등급으로 MIC 설정이 된 것입니다. 이 상태에서 사용자가 계속해서 Run 버튼을 누르면 어떻게 될까요?

Low 등급의 프로세스는 "C:\temp" 폴더에서조차 파일을 생성할 수 있는 권한이 없으므로 다음과 같은 예외를 발생하게 됩니다.

mic_process_start_4.png

어떠세요? 마음에 드시나요? ^^

이처럼, 조금만 신경을 더 써준다면... 여러분들의 프로그램을 안전하게 만드실 수 있습니다.

참고로, Low 등급으로 실행되는 프로세스 구조는 Internet Explorer뿐만 아니라 Google Chrome도 채택하고 있습니다. (아쉽게도 Firefox는 여전히 Medium 등급으로 실행됩니다.)

mic_process_start_5.png

마지막으로, 여러분들이 웹 상에서 혹시 exe 파일을 다운로드 해야 할 때 안전하게 실행할 수 있도록 위의 기능을 한 ClickOnce 프로그램을 작성해 두었으니 생각날 때 활용하시기 바랍니다. ^^

SafetyDownloader
; https://www.sysnet.pe.kr/temp/app/safetydownloader/SafetyDownloader.application




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 1/9/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2016-11-18 01시29분
특정 폴더의 Integrity 수준을 Low로 설정하는 방법

icacls "...path..." /setintegritylevel(oi)(ci) low /t
정성태

... 106  107  108  109  [110]  111  112  113  114  115  116  117  118  119  120  ...
NoWriterDateCnt.TitleFile(s)
11174정성태4/3/201719378VC++: 116. Visual Studio 단위 테스트 - Failed to set up the execution context to run the test
11173정성태4/3/201722964VC++: 115. Visual Studio에서 C++ DLL을 대상으로 단위 테스트할 때 비정상 종료한다면?파일 다운로드1
11172정성태4/3/201722095.NET Framework: 651. C# - 특정 EXE 프로세스를 종료시킨 EXE를 찾아내는 방법파일 다운로드1
11171정성태3/31/201718792VS.NET IDE: 114. Visual Studio 디버깅 경고 창 - You are debugging a Release build of ...
11170정성태3/31/201720658.NET Framework: 650. C# - CachedAnonymousMethodDelegate 유형의 코드 생성
11169정성태3/30/201720536VC++: 114. C++ vtable의 가상 함수 호출 가로채기파일 다운로드1
11168정성태3/29/201723878VC++: 113. C++ 클래스 상속 관계의 vtable 생성 과정
11167정성태3/28/201724174VC++: 112. C++의 가상 함수 테이블 (vtable)은 언제 생성될까요? [2]
11166정성태3/28/201718395오류 유형: 382. System.Data.SqlClient.SqlException - Arithmetic overflow error converting IDENTITY to data type int.
11165정성태3/27/201721683오류 유형: 381. Visual C++에서 min, max 함수를 사용한 경우 C2589, C2059 컴파일 오류 발생
11164정성태3/27/201730014VC++: 111. C++ 클래스의 상속에 따른 메모리 구조 [2]파일 다운로드1
11163정성태3/25/201719795VC++: 110. CreateThread Win32 API에 C++ 클래스의 멤버 함수를 전달하는 방법파일 다운로드1
11162정성태3/24/201724019오류 유형: 380. Visual Studio 빌드 실패 - The OutputPath property is not set for project
11161정성태3/24/201716763오류 유형: 379. ICOMAdminCatalog.GetCollection 호출 시 0x80070422 예외 발생
11160정성태3/23/201721678.NET Framework: 649. ASP.NET - Server cannot append header after HTTP headers have been sent. (HTTP 헤더를 보낸 후에는 서버에서 헤더를 추가할 수 없습니다.)파일 다운로드1
11159정성태3/23/201718946Windows: 136. Memory-mapped File은 Private Bytes 크기에 포함될까요?파일 다운로드1
11158정성태3/22/201718615디버깅 기술: 85. Windbg - SOS 디버깅 사례 System.NullReferenceException 예외 추적
11157정성태3/22/201721843.NET Framework: 648. Dictionary<TKey, TValue>를 deep copy하는 방법파일 다운로드1
11156정성태3/21/201722472.NET Framework: 647. 닷넷(C#) 코드로 인증서 요청 코드 만드는 방법파일 다운로드1
11155정성태3/21/201722684.NET Framework: 646. SslStream의 CipherAlgorithm 선택이 가능할까요?파일 다운로드1
11154정성태3/5/201729687VC++: 109. DLL에서 STL 객체를 인자/반환값으로 갖는 함수를 제공할 때, 그 함수를 외부에서 사용하는 경우 비정상 종료한다면? [2]파일 다운로드1
11153정성태3/5/201729056VC++: 108. DLL에 정의된 C++ template 클래스의 복사 생성자 문제파일 다운로드1
11152정성태3/4/201722708VC++: 107. VirtualAlloc, HeapAlloc, GlobalAlloc, LocalAlloc, malloc, new의 차이점파일 다운로드1
11151정성태3/3/201723316VC++: 106. DLL 개발자가 주의해야 할 Secure CRT 함수 사용 [1]파일 다운로드1
11150정성태2/21/201719252.NET Framework: 645. Visual Studio Fakes 기능에서 Shim... 클래스가 생성되지 않는 경우 [5]
11149정성태2/21/201722909오류 유형: 378. A 64-bit test cannot run in a 32-bit process. Specify platform as X64 to force test run in X64 mode on X64 machine.
... 106  107  108  109  [110]  111  112  113  114  115  116  117  118  119  120  ...