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)
13893정성태2/27/20252225Linux: 115. eBPF (bpf2go) - ARRAY / HASH map 기본 사용법
13892정성태2/24/20252983닷넷: 2325. C# - PowerShell과 연동하는 방법파일 다운로드1
13891정성태2/23/20252500닷넷: 2324. C# - 프로세스의 성능 카운터용 인스턴스 이름을 구하는 방법파일 다운로드1
13890정성태2/21/20252329닷넷: 2323. C# - 프로세스 메모리 중 Private Working Set 크기를 구하는 방법(Win32 API)파일 다운로드1
13889정성태2/20/20253054닷넷: 2322. C# - 프로세스 메모리 중 Private Working Set 크기를 구하는 방법(성능 카운터, WMI) [1]파일 다운로드1
13888정성태2/17/20252498닷넷: 2321. Blazor에서 발생할 수 있는 async void 메서드의 부작용
13887정성태2/17/20253074닷넷: 2320. Blazor의 razor 페이지에서 code-behind 파일로 코드를 분리 및 DI 사용법
13886정성태2/15/20252574VS.NET IDE: 196. Visual Studio - Code-behind처럼 cs 파일을 그룹핑하는 방법
13885정성태2/14/20253236닷넷: 2319. ASP.NET Core Web API / Razor 페이지에서 발생할 수 있는 async void 메서드의 부작용
13884정성태2/13/20253522닷넷: 2318. C# - (async Task가 아닌) async void 사용 시의 부작용파일 다운로드1
13883정성태2/12/20253266닷넷: 2317. C# - Memory Mapped I/O를 이용한 PCI Configuration Space 정보 열람파일 다운로드1
13882정성태2/10/20252581스크립트: 70. 파이썬 - oracledb 패키지 연동 시 Thin / Thick 모드
13881정성태2/7/20252832닷넷: 2316. C# - Port I/O를 이용한 PCI Configuration Space 정보 열람파일 다운로드1
13880정성태2/5/20253172오류 유형: 947. sshd - Failed to start OpenSSH server daemon.
13879정성태2/5/20253407오류 유형: 946. Ubuntu - N: Updating from such a repository can't be done securely, and is therefore disabled by default.
13878정성태2/3/20253198오류 유형: 945. Windows - 최대 절전 모드 시 DRIVER_POWER_STATE_FAILURE 발생 (pacer.sys)
13877정성태1/25/20253249닷넷: 2315. C# - PCI 장치 열거 (레지스트리, SetupAPI)파일 다운로드1
13876정성태1/25/20253708닷넷: 2314. C# - ProcessStartInfo 타입의 Arguments와 ArgumentList파일 다운로드1
13875정성태1/24/20253137스크립트: 69. 파이썬 - multiprocessing 패키지의 spawn 모드로 동작하는 uvicorn의 workers
13874정성태1/24/20253558스크립트: 68. 파이썬 - multiprocessing Pool의 기본 프로세스 시작 모드(spawn, fork)
13873정성태1/23/20252983디버깅 기술: 217. WinDbg - PCI 장치 열거파일 다운로드1
13872정성태1/23/20252885오류 유형: 944. WinDbg - 원격 커널 디버깅이 연결은 되지만 Break (Ctrl + Break) 키를 눌러도 멈추지 않는 현상
13871정성태1/22/20253292Windows: 278. Windows - 윈도우를 다른 모니터 화면으로 이동시키는 단축키 (Window + Shift + 화살표)
13870정성태1/18/20253731개발 환경 구성: 741. WinDbg - 네트워크 커널 디버깅이 가능한 NIC 카드 지원 확대
13869정성태1/18/20253456개발 환경 구성: 740. WinDbg - _NT_SYMBOL_PATH 환경 변수에 설정한 경로로 심벌 파일을 다운로드하지 않는 경우
13868정성태1/17/20253112Windows: 277. Hyper-V - Windows 11 VM의 Enhanced Session 모드로 로그인을 할 수 없는 문제
1  [2]  3  4  5  6  7  8  9  10  11  12  13  14  15  ...