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

... 136  137  138  139  140  141  [142]  143  144  145  146  147  148  149  150  ...
NoWriterDateCnt.TitleFile(s)
1504정성태9/24/201330158.NET Framework: 387. UDP 브로드캐스팅을 이용해 서비스 측의 IP 주소를 구하는 방법 [1]파일 다운로드1
1503정성태9/21/201335343개발 환경 구성: 199. Visual Studio - github 연동 [7]
1502정성태9/21/201338937개발 환경 구성: 198. Visual Studio - git을 이용한 로컬 소스 컨트롤
1501정성태9/21/201346021개발 환경 구성: 197. Visual Studio를 위한 Git 환경 설정 [5]
1500정성태9/20/201345010.NET Framework: 386. C# 버전의 한글 형태소 분석기 [1]파일 다운로드1
1499정성태9/20/201321614개발 환경 구성: 196. Windows Azure - Cloud Service의 인스턴스 타입 변경하는 방법
1498정성태9/20/201327739Windows: 76. 윈도우 8.1 / 서버 2012 R2 마이그레이션 [5]
1497정성태9/20/201359981웹: 28. IE 11로 바꾼 후 발생하는 문제 정리
1496정성태9/20/201332307Windows: 75. 윈도우 8.1, 2012 R2 설치 후 원격 접속이 안 되는 문제
1495정성태9/20/201323417웹: 27. IE 11 - YBM Sisa.com에서 검색된 영단어의 발음 기호가 안 나오는 문제
1494정성태9/13/201333088.NET Framework: 385. Html Agility Pack 소개 - 웹 문서에서 텍스트만 분리하는 방법 [2]파일 다운로드1
1493정성태9/13/201334843.NET Framework: 384. WebClient.DownloadString 문자열 인코딩 문제
1492정성태9/13/201322277오류 유형: 186. The .NET assembly 'Microsoft.Vsa' could not be found.
1491정성태9/9/201325404.NET Framework: 383. RSAParameters의 ToXmlString과 ExportParameters의 결과 비교
1490정성태9/7/201360430기타: 34. 도서: 시작하세요! C# 프로그래밍: 기본 문법부터 실전 예제까지 [7]
1489정성태9/4/201344884오류 유형: 185. 오피스 워드 파일이 저장되지 않는 문제 [2]
1488정성태8/27/201329002.NET Framework: 382. WCF에서 DataSet을 binary encoding으로 직렬화하는 방법파일 다운로드1
1487정성태8/27/201331311개발 환경 구성: 195. 로컬 PC에서의 WCF 통신을 Fiddler로 보는 방법 [1]
1486정성태8/27/201328819.NET Framework: 381. SqlCommand를 이용해 Microsoft SQL 서버의 쿼리 실행 계획을 구하는 방법파일 다운로드1
1485정성태8/26/201332499.NET Framework: 380. 프로세스 스스로 풀 덤프 남기는 방법 [3]파일 다운로드1
1484정성태8/23/201326723제니퍼 .NET: 24. 제니퍼 닷넷 적용 사례 (4) - GZIP 인코딩으로 인한 성능 하락
1483정성태8/23/201326831.NET Framework: 379. System.IO.MemoryStream, ArraySegment&lt;T&gt; 의 효율적인 사용법 [1]
1482정성태8/23/201320314.NET Framework: 378. Java / C# - 정수의 부호 유무에 따른 16진수 문자열 변환
1481정성태8/22/201321153오류 유형: 184. PaaS 유형(Cloud Services)의 Azure VM에 연결할 때 계정 만료 에러가 발생하는 경우
1480정성태8/22/201337812개발 환경 구성: 194. 윈도우 서버의 80 포트에 대한 port forwarding 설정 방법파일 다운로드1
1479정성태8/14/201325117오류 유형: 183. IIS - 바인딩 추가 시 Object reference not set to an instance of an object 오류 [5]
... 136  137  138  139  140  141  [142]  143  144  145  146  147  148  149  150  ...