Silverlight를 설치하려면 여기를 클릭합니다.*
Korea 대한민국변경|Microsoft 전체 사이트
MSDN
|개발자 센터
MSDN Home   MSDN Home

알고 계십니까?

.NET Framework 2.0에서 코드 액세스 보안의 새로운 기능


이 기사는 .NET Framework 2.0의 시험판 버전을 기반으로 합니다. 여기에 기록된 모든 정보는 변경될 수 있습니다.

이 문서 내용:
  • CAS 개요
  • 샌드박스 및 신뢰 수준
  • 호스트 및 프레임워크 개발
  • AppDomain 및 보안
이 문서에는 다음 기술이 사용됩니다:
.NET Framework 2.0, Visual Studio 2005


icrosoft® .NET Framework의 보안에는 BCL(기본 클래스 라이브러리)과 ASP.NET의 역할 기반 보안, BCL의 암호화 클래스, 액세스 제어 목록(ACL) 사용을 위한 새로운 지원 기능 등의 여러 기술이 포함됩니다. CLR(공용 언어 런타임)에서 제공하는 .NET 보안 스펙트럼의 기술 중 하나는 CAS(코드 액세스 보안)입니다. 이 기사에서는 .NET 보안에서 CAS의 역할과 .NET Framework 2.0에서 CAS의 일부 중요한 새로운 기능 및 변경 사항에 대해 설명합니다.

.NET Framework을 사용하는 대부분의 개발자는 CAS가 있다는 사실만 알면 됩니다. CAS는 부동 소수점을 사용하는 프레임워크의 기능으로서, 복잡하고 자세한 지식을 갖추면 일부 응용 프로그램에 매우 유용하게 사용할 수 있지만 대부분의 응용 프로그램에서는 이러한 지식이 필요 없습니다.


CAS를 사용하는 이유

액세스 제어에 대해 질문하는 사람들은 종종 사용자 ID에 기초한 역할 기반의 보안 제어 리소스 액세스에 대해 자세히 알고 싶어합니다. CAS는 사용자 ID에 기반하지 않기 때문에 이해하기 어려울 수도 있습니다. CAS는 코드의 출처(예: 로컬 컴퓨터 또는 인터넷), 작성자, 서명자 등의 정보를 포함하는 실행 중인 코드의 ID에 기반합니다. 코드에서 수행할 수 있는 동작과 코드에서 액세스할 수 있는 리소스는 코드 및 해당 ID와 연관된 이러한 "증명 정보"에 기반하여 제한됩니다.

왜 코드에서 수행하는 동작을 해당 ID에 기반하여 제한해야 합니까? 대부분의 경우 제한하지 않습니다. 프로그램 사용자가 액세스할 수 있는 모든 리소스(파일, 레지스트리 설정 등)에 액세스할 수 있는 고가의 멋진 그래픽 편집 프로그램의 경우를 예로 들 수 있습니다. 이 경우 소프트웨어 게시자를 알고 있으며 신뢰하기 때문에 실행되는 플랫폼에서 이 소프트웨어가 높은 액세스 수준을 갖도록 허용할 것입니다. 일반적으로 사용자는 응용 프로그램 자체를 신뢰하는 것과는 별개로, 실수로 컴퓨터를 손상시키지 않는 데 필요한 최소한의 권한을 가진 사용자 계정으로 응용 프로그램을 실행하기를 바랍니다.

그러나 코드를 실행하면서 그 작성자를 모르거나 완전히 신뢰하지 않는 경우가 있습니다. 대표적인 경우가 바로 웹 검색에서 발생합니다. 오늘날의 브라우저는 흔히 방문하는 웹 사이트로부터 코드를 실행합니다. 이러한 코드는 보통 JavaScript나 DHTML이지만 해당 브라우저에서 인식되는 다른 형식의 실행 파일일 수도 있습니다. 브라우저는 컴퓨터에서 이 코드를 실행할 경우 "샌드박스"에서 실행합니다. 샌드박스는 컴퓨터에서 코드가 액세스할 수 있는 리소스를 제어하는 제한된 실행 환경을 의미합니다. 샌드박스는 필수입니다. 샌드박스를 사용하지 않는 경우 상대적으로 익명성을 띠는 인터넷 코드는 사용자의 개인적인 파일을 읽을 수 있고 컴퓨터에 매일 바이러스를 설치할 수 있습니다. 여러 브라우저는 실행 중인 코드의 출처에 따라 다양한 수준의 샌드박스 기능을 제공합니다. 예를 들어 Microsoft Internet Explorer는 '영역'이라는 개념을 정의합니다. 인터넷 영역의 코드의 사용 권한은 신뢰할 수 있는 사이트 영역의 코드보다 낮습니다. 샌드박스 규칙을 적용하는 소프트웨어에 버그가 있거나 사용자가 샌드박스 외부에서의 코드 실행에 동의하도록 만드는 속임수에 넘어가는 경우에 보안 문제가 발생합니다.

브라우저에서 웹 사이트의 코드를 실행하는 경우는 샌드박스 및 코드 ID 기반 보안에서 일반적으로 다루는 시나리오입니다. CLR의 CAS에서는 코드 ID에 따라 코드에 샌드박스를 적용하는 일반적인 메커니즘을 제공합니다. 이것이 바로 CAS를 사용해야 하는 주요 장점이자 시나리오입니다. 현재 CAS는 Internet Explorer가 브라우저에서 실행되는 웹 사이트의 관리 코드(컨트롤 또는 독립 실행형 응용 프로그램)에 샌드박스를 적용하는 데 사용됩니다. 또한 로컬 인트라넷에 있는 네트워크 공유에서 실행되는 응용 프로그램에 샌드박스를 적용하는 데도 사용되며, VSTO(Visual Studio® Tools for Office)에서 Microsoft Office 문서용 관리 추가 기능을 호스트하는 데 사용됩니다. 서버 시나리오의 경우 CAS는 ASP.NET에서 웹 응용 프로그램에, SQL Server™ 2005에서 관리 저장 프로시저에 사용됩니다. CAS는 주로 사용자가 인식하지 못하는 상태에서 수많은 경우에 적용됩니다.


샌드박스 사용 권한의 이해

개발자는 흔히 CAS에 관해 무엇을 알아야 하는지 묻습니다. 여러분이 응용 프로그램 개발자인 경우 Internet Explorer의 관리 컨트롤과 같이 샌드박스를 적용할 응용 프로그램을 작성 중인지 여부에 따라 대답이 달라집니다. 응용 프로그램 개발자의 경우 다음 내용을 알아 두어야 합니다.

  • 샌드박스에서 가능한 작업
  • 기능이 충분하여 응용 프로그램을 성공적으로 실행할 수 있는지 여부
  • 필요한 경우 더 많은 사용 권한을 얻기 위해 응용 프로그램의 신뢰를 높이는 방법

예를 들어 브라우저의 관리 컨트롤에서는 기본 샌드박스 권한 집합, 즉 인터넷 권한 집합을 사용합니다. 리소스 액세스라는 측면에서 볼 때 이 샌드박스를 사용하면 응용 프로그램에서 "안전한" 사용자 인터페이스 요소(예: 투명 창은 스푸핑 또는 man-in-the-middle 공격에 이용될 수 있으므로 안전하지 않음)를 작성하고, 웹 연결을 원래의 사이트로 돌아가도록 할 수 있으며, 사용자 동의를 얻어 파일 시스템 및 프린터에 액세스할 수 있고, Internet Explorer의 쿠키와 유사한 격리된 저장소에 제한된 양의 데이터를 저장할 수 있습니다. 그러나 환경 변수 또는 파일 시스템이나 레지스트리의 임의 부분을 읽을 수는 없습니다. 또한 샌드박스를 사용하면 SQL Server 데이터베이스에 연결할 수 없으며 COM 개체나 다른 비관리 코드를 호출할 수도 없습니다. 호스트마다 서로 다른 샌드박스를 정의합니다. 예를 들어 SQL Server 및 ASP.NET은 낮은 신뢰 응용 프로그램에 대해 각각 서로 다른 권한 집합을 정의합니다. 그림 1은 이러한 샌드박스 권한을 간략히 보여 줍니다.

샌드박스 옵션을 알면 샌드박스 용응 프로그램이 자신에게 적합한지 판단할 수 있습니다. 예를 들어 Internet Explorer에서 관리 컨트롤을 작성하고 SQL 데이터베이스에 연결할 계획이면 해당 컨트롤은 기본적으로 샌드박스에서 실행되지 않습니다. 사용자는 컨트롤의 서버에 배포된 웹 서비스를 사용하여 데이터에 액세스하는 방법 등으로 자신의 계획을 변경하거나 클라이언트 컴퓨터에서 컨트롤의 신뢰 수준을 높여야 합니다. 브라우저에 있는 관리 컨트롤의 경우 신뢰를 높이려면 컨트롤이 있던 원래 사이트 및 컨트롤 자체 모두를 신뢰하기 위한 CAS 정책을 배포해야 합니다. 다른 호스트에는 응용 프로그램을 신뢰하는 다른 메커니즘이 있습니다. ASP.NET 응용 프로그램의 신뢰 수준을 변경하려면 구성 파일의 설정을 변경해야 합니다.

일부 경우에는 사용자가 다른 방식으로 응용 프로그램을 설치 및 실행하지 않으므로 응용 프로그램을 샌드 박스에서 실행해야 합니다. 웹 사이트에 대해 간단한 설문 조사 컨트롤을 작성하고 있다고 가정해 봅시다. 이 컨트롤은 몇 가지 질문을 하고 응답을 기록합니다. 대부분의 사용자는 아주 간단한 작업을 위해 완전 신뢰 응용 프로그램을 다운로드하고 실행하지는 않습니다. 그러나 신뢰할 수 있는 응용 프로그램을 작성하는 경우 해당 응용 프로그램을 샌드박스에서 실행하면 이로운 경우도 있습니다. 그림 2 는 샌드박스를 사용하거나 사용하지 않는 경우의 신뢰 수준을 보여 줍니다. 응용 프로그램을 완전 신뢰로 실행하려면 해당 응용 프로그램이 부분 신뢰 환경에서도 제대로 작동하는지 확인하십시오(자세한 내용은 관련 기사의 "부분 신뢰의 완벽한 처리" 를 참조하십시오).

일반적으로 샌드박스 응용 프로그램을 배포하는 편이 훨씬 더 쉬운 방법입니다. 예를 들어 ClickOnce를 사용하면 샌드박스 응용 프로그램은 실행만 될 뿐 사용자에게 어떤 동작도 요구하지 않습니다. 단, 높은 신뢰 응용 프로그램은 신뢰할 수 있는 인증서로 서명되거나 사용자에게 메시지를 표시해야 합니다(ClickOnce에 대한 자세한 내용은 ClickOnce: 중앙 서버를 사용하여 스마트 클라이언트 프로젝트 배포 및 업데이트 (영문)DLL에서 벗어나기: ClickOnce 및 무료 등록 COM으로 응용 프로그램 개발 단순화 (영문))를 참조하십시오).

또한 응용 프로그램에 샌드박스를 적용하면 안정성을 얻을 수도 있습니다. 예를 들어 가장 낮은 신뢰 수준의 SQL Server에서 가능한한 많은 관리 저장 프로시저를 실행한다는 것은 서버에 대해 모든 액세스 권한을 갖는 코드 수가 적고, 따라서 해당 서버를 악의적으로나 실수로 손상시킬 가능성이 있는 코드 수도 적다는 의미입니다.

Visual Studio 2005에서는 ClickOnce를 사용하여 배포되는 샌드박스 클라이언트 응용 프로그램의 작성을 지원하는 기능이 한층 더 향상되었습니다. 프로젝트 속성 페이지의 보안 창은 대부분의 동작이 발생하는 곳입니다(그림 3). 여기에서 보안 설정을 활성화하고 응용 프로그램의 대상 영역을 설정할 수 있습니다. 샌드박스 응용 프로그램의 경우 일반적으로 인터넷 영역을 선택합니다. 그런 다음 권한 계산 단추를 눌러 해당 응용 프로그램에 필요한 사용 권한을 대략적으로 평가하여 그 결과가 샌드박스에 적합한지 여부를 확인할 수 있습니다. 이 계산 기능은 .NET Framework 2.0 SDK에 포함된 permcalc 명령행 도구를 통해서도 사용할 수 있습니다.

그림 3 Visual Studio 2005 보안 창
그림 3 Visual Studio 2005 보안 창

이 결과는 순수히 통계적 분석에 따른 것으로서 대략적인 계산 결과라는 사실을 잊지 마십시오. 항상 응용 프로그램은 실행 시 사용되는 사용 권한으로 테스트해야 합니다. 대상 영역을 설정한 후에 응용 프로그램을 간단히 디버깅하기만 하면 테스트를 수행할 수 있습니다. Visual Studio는 사용자가 보안 창에 지정한 사용 권한으로 응용 프로그램을 실행합니다.


호스트 및 프레임워크

호스트 또는 프레임워크를 작성할 경우 기본적인 샌드박스 지식 이상을 갖추어야 합니다. 호스트 개발자는 낮은 신뢰 코드를 호스트하는 방법을 알아야 합니다. 프레임워크 개발자는 낮은 신뢰 코드에 기능을 노출하는 라이브러리 또는 프레임워크를 작성하는 방법을 알아야 합니다.

이러한 내용을 설명하기 전에 많은 사람들이 혼동하는 '최소 권한 실행'에 대해 설명하겠습니다. 최소 권한 실행은 작업을 완료하는 데 필요한 최소한의 권한이나 사용 권한으로 코드를 실행하는 것을 의미합니다. 최소 권한 실행은 코드에 악성 버그가 있는 경우에 발생할 수 있는 손상을 방지해 줍니다. Windows®의 경우 보안을 위해 항상 최소 권한의 사용자 ID(예: 관리자가 아닌 일반 사용자)로 실행하는 것이 좋습니다. CAS의 경우 최소 사용 권한으로 실행하는 것은 응용 프로그램 또는 라이브러리가 작업을 수행하는 데 필요한 최소 CAS 권한 집합으로 실행하는 것을 의미합니다. 최소 권한 실행은 일반적으로 좋은 방법이지만 한계를 가지고 있습니다. 예를 들어 대부분의 호스트 또는 프레임워크 코드는 기본 샌드박스 외의 강력한 권한으로 실행해야 합니다. 이 코드는 Win32® API 또는 컴퓨터의 다른 비관리 코드 및 컨트롤 리소스(예: 파일, 레지스트리 키, 프로세스 및 기타 시스템 개체)를 자주 호출해야 합니다. 이런 종류의 코드에는 항상 향상된 사용 권한이 필요하므로, 수많은 강력한 사용 권한이 전체 신뢰로 향상될 수 있는 경우 사용 권한을 한두 개 제거하는 것은 보안 측면에서 큰 의미가 없습니다.

악의적인 호출자가 코드를 사용하더라도 보안이 유지되도록 해당 코드를 감사하고 테스트하는 편이 더 낫습니다. CAS 측면에서 볼 때, 완전 신뢰로 실행한다는 것은 코드를 실행하는 사용자가 시스템에서 수행할 수 있는 모든 작업을 해당 코드가 수행할 수 있다는 의미가 됩니다. 완전 신뢰 코드를 실행 중인 프로세스에 관리자 권한이 없으면 완전 신뢰 코드라 하더라도 컴퓨터 리소스에 대한 무제한 액세스 권한을 갖지는 못합니다. 이런 작업을 위해 .NET Framework 2.0에서는 투명 코드라고 하는 새로운 기술을 제공합니다. 이 기술은 이 글의 뒷부분에 기타 프레임워크 개발 문제와 함께 설명되어 있습니다. 여기서는 우선 호스팅에 대해 다시 생각해 봅시다.

일반적으로 호스팅이란 CLR을 사용하여 다른 응용 프로그램의 컨텍스트에서 코드를 실행하는 것을 의미합니다. 예를 들어 SQL Server 2005는 런타임을 호스트하여 관리 코드로 작성된 저장 프로시저를 실행합니다. 여기서는 AppDomain 검토를 시작으로, 호스팅의 보안 관련 측면에 초점을 맞추어 설명해 보겠습니다. 실제 호스팅 관련 내용은 훨씬 더 많습니다. 자세한 내용은 Stephen Pratschner의 Customizing the Microsoft .NET Framework Common Language Runtime(Microsoft Press®, 2005)을 참조하십시오.


AppDomain 및 보안

AppDomain은 관리 코드의 하위 프로세스를 격리합니다. 이것은 각 AppDomain에 고유의 상태 집합이 있다는 의미입니다. 하나의 AppDomain에 있는 확인할 수 있는 코드는 호스팅 환경에서 작성된 인터페이스가 상호 작용을 허용하지 않는한 다른 AppDomain에 있는 코드나 데이터를 손상시키지 않습니다. 이것이 어떤 방식으로 작동하는지 알아 봅시다. C# 및 Visual Basic® .NET 컴파일러에서 기본적으로 작성되는 형식이 안전한 확인할 수 있는 코드는 어떤 방법으로도 메모리에 액세스할 수 없습니다. 각 명령은 형식이 안전한 방식으로 메모리에 액세스하도록 확인 규칙 집합을 사용하여 런타임으로 검사됩니다. 따라서 런타임 검사을 통해 확인할 수 있는 코드를 실행할 때 AppDomain의 격리를 보장하며 확인할 수 없는 코드의 실행을 막을 수 잇습니다.

호스트는 이러한 격리를 통해 코드를 동일한 프로세스에서 다른 신뢰 수준으로 안전하게 실행할 수 있습니다. 낮은 신뢰 코드는 신뢰할 수 있는 호스트 코드 또는 다른 낮은 신뢰 코드와는 별도로 AppDomain에서 실행할 수 있습니다. 낮은 신뢰 코드의 호스트에 필요한 AppDomain 수는 해당 호스트의 격리 의미에 따라 다릅니다. 예를 들어 Internet Explorer는 관리 컨트롤에 대해 사이트당 하나의 AppDomain을 작성합니다. 한 사이트의 컨트롤은 동일한 AppDomain에서 상호 작용할 수 있지만 다른 사이트의 컨트롤을 간섭하거나 악의적으로 이용할 수 없습니다.

그림 4 AppDomain 방화벽
그림 4 AppDomain 방화벽

CAS를 사용하면 코드의 로드 시 신뢰 수준을 지정할 수 있습니다. 즉, 정책을 통해 증명 정보를 사용 권한에 매핑할 수 있습니다. 또한 CAS를 사용하면 AppDomain의 작성 시 신뢰 수준을 지정할 수 있습니다. .NET Framework 1.1의 경우 AppDomain에서 증명을 설정하여 이 작업을 수행할 수 있습니다. 이러한 증명 정보는 정책에 따라 권한 집합에 매핑됩니다. 컨트롤 흐름이 AppDomain으로 유입될 때마다 어셈블리의 사용 권한과 동일하게 AppDomain의 사용 권한이 스택에 푸시되며 임의의 스택 이동 시 해당 AppDomain의 요구를 평가하는 것으로 간주됩니다. 이러한 메커니즘은 AppDomain 방화벽(그림 4)이라고 하며, AppDomain 간 함정 공격을 방지하고 AppDomains 간에 코드를 격리하는 또 다른 격리 메커니즘을 제공합니다.

CAS를 사용하면 코드(어셈블리)를 다른 신뢰 수준(사용 권한)의 AppDomain으로 로드할 수 있지만 샌드박스 코드 보호에는 좋은 방법이 아닙니다. AppDomain의 모든 코드가 상태를 공유할 경우 AppDomain 내의 여러 어셈블리에서 권한 상승을 막기는 어렵습니다. 예를 들어 실행 권한만 갖는 어셈블리 하나와 LocalIntranet 권한 집합을 갖는 다른 어셈블리를 로드한다고 가정해 봅시다. 실행 권한만 갖는 첫 번째 어셈블리는 이러한 상황에 대비하여 매우 주의 깊게 작성되지 않은한 LocalIntranet 권한 집합으로 상승할 수 있습니다. 또한 AppDomain 방화벽을 활용할 수도 없게 됩니다. 따라서 위에서 설명한 것처럼 해당 코드가 동일한 신뢰 수준에서 실행되는 경우에도 여러 AppDomain을 작성하여 격리할 코드를 호스트하는 것이 좋습니다. 이는 Internet Explorer가 별도의 사이트를 통해 컨트롤을 호스트하는 것과 비슷합니다.

따라서 여러 어셈블리를 하나의 AppDomain에 서로 다른 신뢰 수준으로 로드하는 대신에 낮은 신뢰 코드의 각 논리 청크에 대해 별도의 AppDomain를 사용하여(예: Internet Explorer의 각 사이트) 보안 모델을 간단하게 유지하는 것이 좋습니다. 각 AppDomain에 대해 다음과 같은 두 개의 신뢰 수준이 있어야 합니다.

  • 첫 번째 신뢰 수준은 완전 신뢰 플랫폼 코드입니다. 이 코드에는 .NET Framework 및 낮은 신뢰 코드와 상호 작용하는 호스트의 신뢰할 수 있는 코드가 포함됩니다.
  • 두 번째 신뢰 수준은 낮은 신뢰 코드 자체로서, 혼합 신뢰 수준이 아닌 단일 신뢰 수준에서 실행됩니다.

그림 5 AppDomain 신뢰
그림 5 AppDomain 신뢰

이 모델은 이해하기 쉽고 안전하므로 ClickOnce에서 사용되고 있습니다. 모든 ClickOnce 응용 프로그램에는 AppDomian에서 두 개의 신뢰 수준으로 실행하는 코드가 있습니다. 하나는 완전 신뢰로 실행하는 플랫폼 코드이고 다른 하나는 응용 프로그램의 매니페스트에 지정된 신뢰 수준으로 실행하는 응용 프로그램 코드입니다. CLR 보안 시스템은 이 모드에 최적화되었으며 이 모델에 따른 결과 코드로서 훌륭하게 작동합니다. 두 신뢰 수준의 그림은 그림 5를 참조하십시오.


샌드박스 정의

호스팅의 또 다른 작업은 샌드박스 또는 권한 집합을 정의하는 것이며 이 경우 사용자는 낮은 신뢰 코드로 승인됩니다. 위에서 설명한 것처럼 CLR은 ASP.NET과 같은 다른 호스트와 마찬가지로 일부 샌드박스 권한 집합을 정의합니다. CLR에서 정의하는 두 가지 관련 권한 집합은 Internet 권한 집합 및 LocalIntranet 권한 집합입니다. Internet 권한 집합은 익명의 유해 코드 실행에 대비하여 보안을 유지하도록 설계되었습니다. Microsoft에서는 이런 목적을 위해 이 권한 집합을 감사해 왔습니다. Internet 권한 집합은 이러한 시나리오에 대비하여 철저히 테스트된 유일한 권한 집합입니다. 따라서 낮은 신뢰 코드를 호스트하려면 기본적으로 Internet 권한 집합을 선택해야 합니다. 이에 반해, LocalIntranet 권한 집합은 유해 코드가 컴퓨터를 장악하지 못하도록 방지하기는 하지만 사용자가 익명 코드에 노출되기를 바라지 않는 일부 정보(예: 현재 로그인한 사용자의 사용자 이름)를 공개합니다. 따라서 사실상 LocalIntranet 권한 집합은 조직의 인트라넷에 있는 코드와 같이 다소 신뢰할 수 있는 코드에 더 적합합니다.

이제 ASP.NET과 같이 자체의 권한 집합을 정의한 호스트에 대해서 살펴보겠습니다. 예를 들어 ASP.NET 중간 신뢰 수준에서는 CAS 및 Windows ID 기반 보안을 모두 사용하여 코드를 제한하는 방법으로 보안을 유지합니다. 저희 팀 구성원 한 명이 이러한 상황에 대해 '샌드더닝(sand-duning)'이라는 훌륭한 용어를 만들어냈습니다. "샌드던"은 유해 코드가 컴퓨팅 리소스에 무단 액세스할 수 없도록 자체적으로 차단하지 못하는 제한된 권한 집합입니다. 하지만 "샌드던"은 다른 보안 적용 메커니즘과 결합될 경우와 투명한 코드를 투명하게 유지하는 경우에 유용합니다. 이것은 여러 응용 프로그램에서 컴퓨팅 리소스를 공유하고 있으며 제대로 작동하지 않는 하나의 응용 프로그램으로 인한 서버 다운을 방지하려는 서버 시나리오에서 안정성을 유지할 수 있는 일반적인 기술입니다.


호스팅 방식

이러한 모든 작업을 실제로 어떻게 구현하고 있습니까? .NET Framework 1.1에서는 증명 정보를 기반으로 하는 AppDomain을 작성합니다. 이러한 증명 정보는 AppDomain에 대한 사용 권한을 계산하는 데 사용됩니다. 그런 다음 AppDomain 정책 수준을 설정합니다. 이것은 플랫폼 및 호스트 코드에 완전 신뢰를 부여하고 다른 모든 코드에 낮은 신뢰를 부여해야 합니다. 그리고 AppDomain에서 AppDomain 정책 수준을 설정합니다. 마지막으로 새 AppDomain에서 신뢰할 수 있는 호스트 코드를 호출하여 실행 중인 낮은 신뢰 코드를 부트스트랩합니다.

이 프로세스는 .NET Framework 2.0에서 다음과 같이 단순화되었습니다.

  1. 1. 간단한 새 샌드박스 API를 사용하여 AppDomain을 작성합니다. 이렇게 하면 AppDomain 정책 수준을 작성하지 않고도 AppDomain 신뢰 수준, 샌드박스 권한 집합 및 신뢰할 수 있는 호스트 어셈블리의 목록이 모두 한 번에 설정됩니다.
  2. 2. 새 AppDomain에서 신뢰할 수 있는 호스트 코드를 호출하여 실행 중인 낮은 신뢰 코드를 부트스트랩합니다.

자세한 내용은 이 문제에 대한 Shawn Farkas의 기사를 참조하십시오. Shawn은 이러한 작업을 수행하는 방법과 그 과정에서 보안을 유지하는 모든 기술에 대해 설명해 두었습니다. 많은 시나리오의 경우 간단한 샌드박스 모델로 충분하지만 AppDomainManager 클래스를 사용하면 AppDomains의 작성을 좀 더 효과적으로 관리할 수 있습니다. 필요한 경우 AppDomainManager를 사용하여 사용자 지정 정책 동작을 구현하는 방법은 Shawn의 기사에 설명되어 있습니다.


CAS 및 프레임워크

이제 박차를 가해 CAS를 프레임워크 구축에 사용하는 다른 개발자 시나리오에 대해 살펴 보겠습니다. 프레임워크는 다른 응용 프로그램에서 사용하도록 설계된 다시 사용할 수 있는 클래스의 라이브러리입니다. 프레임워크는 몇몇 유형이 있는 단일 어셈블리이거나 .NET Framework처럼 여러 유형이 있는 대규모 어셈블리 집합이 될 수도 있습니다. 일반적으로 프레임워크는 GAC(전역 어셈블리 캐시)에 배포되므로 여러 응용 프로그램에서 사용할 수 있습니다. 또한 완전 신뢰로 실행하여 시스템에서 제공하는 모든 항목을 활용할 수 있는 플랫폼 구성 요소입니다. 완전한 기능을 갖춘 프레임워크가 아닐 경우 호스트 개발자는 일반적으로 호스트되는 상호 작용할 코드를 위한 최소한의 제한된 프레임워크를 구축해야 하므로, 이 주제는 호스트 개발자와도 관련이 있습니다.

프레임워크 개발자가 완전 신뢰가 없는 코드에 기능을 노출하려면 CAS를 알고 있어야 합니다. 그러한 예로는 사운드 라이브러리를 작성하는 경우가 있습니다. SoundPermission이라고 하는 사용자 지정 권한을 정의하고 사운드 재생 메서드가 호출될 때 해당 권한을 요청한다고 가정해 봅시다. 이 요청이 성공하면 비관리 코드를 호출하고 사운드를 재생할 Win32 API를 호출할 수 있는 사용 권한을 어설션할 수 있습니다.

좀 더 일반적인 또 다른 시나리오는 프레임워크 구축 시 기존의 시스템 사용 권한과 상호 작용하는 경우입니다. 예를 들어 낮은 신뢰 코드에서 액세스할 수 있는 수학 라이브러리를 구현하다고 가정해 봅시다. 라이브러리가 계산만 하고 시스템 리소스에 액세스하지 않는 경우 CAS를 거의 무시할 수 있습니다. 그러나 수학 라이브러리를 초기화할 때 계산을 최적화하는 방법을 좀 더 쉽게 결정할 수 있는 일부 환경 변수를 읽었다고 가정해 봅시다. 이 경우 사용자는 해당 코드를 감사하여 낮은 신뢰 코드의 컨텍스트에서 호출하는 것이 안전한지 확인해야 합니다. 이 호출은 낮은 신뢰 코드에 대해 완전히 불투명해야 합니다. 즉 낮은 신뢰 코드는 확인되는 환경 변수를 제어할 수 없고 환경 변수의 값을 가져올 수 없습니다. 낮은 신뢰 컨텍스트에서 이 작업을 성공적으로 수행하려면 환경 변수를 읽을 수 있는 환경 사용 권한을 어설션해야 합니다.

어설션은 권한 상승입니다. 프레임워크 코드가 어설션을 수행하면 호출자에게는 보통 해당 권한이 없는 작업을 수행하게 됩니다. 그러나 프레임워크에는 어설션 수행 권한뿐만 아니라 해당 권한이 이미 있어야만 합니다. 프레임워크 코드에서 어설션을 수행할 때마다 해당 코드를 주의 깊게 감사하여 어설션이 안전한지 확인해야 합니다. 이 작업은 일반적으로 전달된 매개 변수를 검사하여 해당 매개 변수가 적절한 곳에서 유효성이 검증되고 정규화되었는지 확인하고, 적절하지 않은 데이터가 낮은 신뢰 코드로 누출되지 않았는지 확인하며, 낮은 신뢰 코드에서 높은 신뢰 코드의 상태를 잘못 변경하여 나중에 안전하지 않은 작업을 수행하도록 조작(함정 공격)하지 않도록 검사하는 것을 의미합니다. 일반적으로 어설션은 쉽게 찾을 수 있습니다. 어설션에 대한 소스 코드를 검색할 수 있으며 어설션과 관련된 몇 가지 FxCop 규칙이 있습니다.

보다 섬세하고 잠재적으로 더욱 위험한 권한 상승은 링크 요청을 만족시키는 것입니다. 메서드에 링크 요청이 있으면 메서드가 JIT(Just In Time) 컴파일 시에 즉각적인 호출자가 확인됩니다. 따라서 이 요청은 실제로 한 가지 수준의 요청입니다. 신뢰할 수 있는 코드가 링크 요청을 만족시킨 다음 선회하여 링크 요청을 만족시켰다는 사실을 인식하지 못한 채 해당 기능을 낮은 신뢰 코드에 노출할 수 있으므로 이것은 위험할 수 있습니다. 신뢰할 수 있는 코드가 보안을 유지하기 위해 시도할 수 있는 하나의 전략은 어설션을 수행하지 않고 모든 요청이 호출자에게 흘러 가도록 두는 것입니다. 그러나 링크 요청의 경우 신뢰할 수 있는 코드는 암묵적인 어설션을 수행합니다. 완벽한 보안을 유지하려면 신뢰할 수 있는 코드는 모든 링크 요청을 전체 요청으로 변환해야 합니다. 링크 요청을 만족시키는 코드를 쉽게 찾을 수 있도록 하는 일부 FxCop 규칙이 있지만 해당 코드가 임의의 링크 요청을 만족시키는지 알기 위해 코드를 직접 보면서 감사할 수는 없습니다. 따라서 코드 감사에 오류가 발생할 가능성이 높아집니다.


보안 투명 코드

.NET Framework 2.0의 새로운 기능인 투명성은 프레임워크 개발자가 낮은 신뢰 코드로 기능을 노출하는 보다 안전한 라이브러리를 쉽게 작성할 수 있도록 설계되었습니다. 사용자는 전체 어셈블리, 어셈블리 내 일부 클래스 또는 클래스 내 일부 메서드를 보안 투명으로 표시할 수 있습니다. 보안 투명 코드는 권한을 상승시킬 수 없습니다. 이 문제는 다음 세 가지로 분류됩니다.

  • • 보안 투명 코드는 어설션을 수행할 수 없습니다.
  • • 보안 투명 코드로 만족될 링크 요청은 전체 요청으로 전환됩니다.
  • • 보안 투명 코드로 실행되어야 할 안전하지 않은 코드(확인할 수 없는 코드)로 인해 확인 건너뛰기 보안 권한에 대한 전체 요청이 발생합니다.

이 규칙은 CLR에 의한 실행 중 적용됩니다. 기본적으로 보안 투명 코드는 자신이 호출하는 코드의 모든 보안 요구 사항을 해당 호출자에게 전달합니다. 요청은 단지 보안 투명 코드를 통해 흐르기만 하며 권한을 상승시킬 수 없습니다. 따라서 낮은 신뢰 응용 프로그램에서 높은 권한에 대한 요청을 야기하는 일부 보안 투명 코드를 호출하는 경우 해당 요청은 낮은 신뢰 코드로 흐르고 보안 투명 코드 실패로 인해 요청 중지를 원하더라도 중지되지 않을 수 있습니다. 완전 신뢰 코드에서 호출된 동일한 보안 투명 코드는 요청을 성공적으로 처리합니다.

그림 6에 요약된 바와 같이 투명에는 세 가지 특성이 사용됩니다. 여러분은 투명성을 사용할 때 코드를 보안 투명 및 보안 요구(보안 투명의 반대) 메서드 안에 포함시킵니다. 데이터 조작 및 논리를 처리하는 대량의 코드는 일반적으로 보안 투명으로 표시되며 실제로 권한 상승을 수행하는 코드의 일부는 보안 요구로 표시됩니다. 지금까지, 투명성을 채택한 Microsoft 내 그룹은 80% 이상의 코드를 보안 투명으로 표시할 수 있었습니다. 따라서 해당 그룹은 감사 및 테스트 노력을 나머지 20%의 코드(보안 요구)에 집중할 수 있었습니다. 이전 버전과의 호환성에서, 투명성 특성으로 주석이 달리지 않은 .NET Framework 2.0 및 그 이전 버전의 모든 코드는 보안 요구 코드로 간주됩니다. 이제는 투명성을 선택해야 합니다. 투명성에 대한 FxCop 규칙도 있습니다. 개발자는 이 규칙을 사용하여 나중에 런타임 오류를 디버깅하지 않고도 초기에 코드를 작성할 때 투명성 권한 규칙을 손쉽게 가져올 수 있습니다.

SecurityTreatAsSafe 특성을 사용하는 이유는 처음에는 명확하지 않을 수도 있습니다. 어셈블리 안의 보안 투명 및 보안 요구 코드는 실제로 두 개의 어셈블리로 분리된 것으로 생각하십시오. 보안 투명 코드는 보안 요구 코드의 개인(private) 또는 내부(internal) 멤버를 볼 수 없습니다. 또한 보안 요구 코드는 일반적으로 자체의 공용 인터페이스 액세스에 대해 감사됩니다. 어셈블리 외부에서 개인 또는 내부 상태에 액세스할 수 없으며 해당 상태를 격리된 것으로 유지하는 것이 좋습니다. 따라서 필요할 때 무시할 수 있는 기능을 제공하면서도 보안 투명 코드 및 보안 요구 코드 간에 상태 격리를 유지할 목적으로 SecurityTreatAsSafe 특성이 도입되었습니다. 보안 투명 코드는 해당 멤버가 SecurityTreatAsSafe로 표시되지 않는한 보안 요구 코드의 개인 또는 내부 멤버에 액세스할 수 없습니다. 보안 요구 코드의 작성자는 SecurityTreatAsSafe를 추가하기 전에 해당 멤버를 공개적으로 노출된 것으로 간주하고 감사해야 합니다.


투명성 사용

수학 라이브러리 예를 사용하여 투명성의 구문을 설명하겠습니다. 먼저 투명성을 선택하려면 SecurityCritical 특성을 어셈블리 수준 특성으로 추가해야 합니다.

using System.Security;

// opt in to low-trust callers
[assembly: AllowPartiallyTrustedCallers]
// opt in to transparency, but some code will be critical
[assembly: SecurityCritical]
이제 어셈블리의 모든 유형은 기본적으로 보안 투명으로 설정됩니다. 그러나 수학 라이브러리 클래스의 생성자는 환경 변수를 읽기 위해 어설션을 수행해야 하며 라이브러리의 다른 모든 메서드는 보안 투명으로 설정될 수 있다고 가정해 봅시다. 클래스 정의는 그림 7과 같이 됩니다.

투명성을 사용하면 대부분의 코드가 자체의 호출자의 컨텍스트에서 실행되는 프레임워크를 구축할 수 있으며 권한을 상승시킬 수 있는 코드는 명시적으로 표시됩니다. 이렇게 하면 보안 노력을 가장 중요한 보안에 해당되는 코드에 집중할 수 있으며 이것은 코드베이스가 증대함에 따라 중요해집니다. 또한 작성 및 유지 비용이 더 적게 드는 낮은 신뢰 호출자에 코드를 노출할 수 있습니다.


결론

지금까지 기본 샌드박스에 대한 여러 가능성을 설명했습니다. 낮은 신뢰 코드를 호스트하거나 플랫폼을 확장하려는 개발자는 CAS에 대해 더 많이 알아야 합니다. .NET Framework에는 보다 안전하게 낮은 신뢰 코드를 호스트하고 플랫폼을 확장할 수 있는 새로운 기능이 추가되었습니다. 관리 코드가 다양한 장소로 확산됨에 따라 CAS는 계속 진화하여 낮은 신뢰 코드를 샌드박스로 처리하고 더욱 안전한 플랫폼을 구축하는 작업은 더욱 쉬워지고 있습니다. .NET Framework 2.0에서 CAS에 대한 다른 변경 사항을 보려면 관련 기사 "CAS의 다른 새로운 기능")을 참조하십시오. .NET Framework 2.0의 CAS는 보다 많은 개발자가 이러한 시나리오를 활용하여 보다 안전하게 확장할 수 있도록 설계되었습니다.



Mike Downen 씨는 CLR 팀 내 보안 담당 프로그램 관리자입니다. 그는 코드 액세스 보안, 암호화 클래스 및 ClickOnce 보안 모델 분야에서 일하고 있습니다. blogs.msdn.com/CLRSecurity (영문)에서 Mike씨의 블로그를 볼 수 있고 연락을 취할 수 있습니다.
페이지 맨 위로페이지 맨 위로QJ: 051101

Microsoft