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
정성태

1  2  3  4  5  6  7  8  9  [10]  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13693정성태7/24/20247244개발 환경 구성: 717. Visual Studio - C# 프로젝트에서 레지스트리에 등록하지 않은 COM 개체 참조 및 사용 방법파일 다운로드1
13692정성태7/24/20248026디버깅 기술: 199. Windbg - 리눅스에서 뜬 닷넷 응용 프로그램 덤프 파일에 포함된 DLL의 Export Directory 탐색
13691정성태7/23/20247385디버깅 기술: 198. Windbg - 스레드의 Win32 Message Queue 정보 조회
13690정성태7/23/20247019오류 유형: 919. Visual C++ 리눅스 프로젝트 - error : ‘u8’ was not declared in this scope
13689정성태7/22/20248524디버깅 기술: 197. Windbg - PE 포맷의 Export Directory 탐색
13688정성태7/21/20247630닷넷: 2281. C# - Lock / Wait 상태에서도 일부 Win32 메시지 처리파일 다운로드1
13687정성태7/19/20248060닷넷: 2280. C# - PostThreadMessage로 보낸 메시지를 Windows Forms에서 수신하는 방법파일 다운로드1
13686정성태7/19/20247855오류 유형: 918. Visual Studio - ATL Simple Object 추가 시 error C2065: 'IDR_...': undeclared identifier
13685정성태7/19/20248002스크립트: 66. Windows 디렉터리 경로를 WSL의 /mnt 포맷으로 구하는 방법 - 두 번째 이야기
13684정성태7/19/20248181닷넷: 2279. C# - 문자열 보간식 사례 (예: 조건 연산자 사용)
13683정성태7/18/20247651오류 유형: 917. ClrMD - Linux 환경의 .NET 5 덤프 분석 시 hang 현상
13682정성태7/18/20247869닷넷: 2278. WPF - 스레드에 종속되는 DependencyObject파일 다운로드1
13681정성태7/17/20247471닷넷: 2277. C# 13 - (2) 메서드 그룹의 자연 타입 개선 (메서드 추론 개선)파일 다운로드1
13680정성태7/16/20247857닷넷: 2276. C# - Method Group, Natural Type, function_type파일 다운로드1
13679정성태7/16/20246934Linux: 76. Linux - C++ (getaddrinfo 등을 담고 있는) libnss 정적 링크
13678정성태7/15/20247065VS.NET IDE: 191. Visual Studio 2022 - .NET 5 프로젝트를 Docker Support로 실행했을 때 오류
13677정성태7/15/20247155오류 유형: 916. MSBuild - CheckEolTargetFramework (warning NETSDK1138)
13676정성태7/14/20247327Linux: 75. gdb에서 glibc의 함수에 Breakpoint 걸기
13675정성태7/13/20249121C/C++: 166. C/C++ - DLL에서 template 함수를 export하는 방법 [1]파일 다운로드1
13674정성태7/13/20248003오류 유형: 915. Unhandled Exception: Microsoft.Diagnostics.NETCore.Client.ServerNotAvailableException: Unable to connect to Process
13673정성태7/11/20248443닷넷: 2275. C# 13 - (1) 신규 이스케이프 시퀀스 '\e'파일 다운로드1
13672정성태7/10/20247152닷넷: 2274. IIS - (프로세스 종료 없는) AppDomain Recycle
13671정성태7/10/20247261오류 유형: 914. Package ca-certificates is not installed.
13669정성태7/9/20247381오류 유형: 913. C# - AOT StaticExecutable 정적 링킹 시 빌드 오류
13668정성태7/8/20247398개발 환경 구성: 716. Hyper-V - Ubuntu 22.04 Generation 2 유형의 VM 설치
13667정성태7/7/20246621닷넷: 2273. C# - 리눅스 환경에서의 Hyper-V Socket 연동 (AF_VSOCK)파일 다운로드1
1  2  3  4  5  6  7  8  9  [10]  11  12  13  14  15  ...