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

Security Briefs

.NET Framework 2.0의 향상된 보안 기능



목차
System.Security
System.Security.Principal
System.Security.AccessControl
System.Net.Security
System.Runtime.Remoting
System.Security.Cryptography
System.Security.Cryptography.X509Certificates 및 PKCS
System.Security.Cryptography.Xml
System.Diagnostics
System.DirectoryServices
System.DirectoryServices.ActiveDirectory
System.Web
코드 액세스 보안의 변경된 내용
요약

icrosoft.NET Framework 2.0 버전이 출시되었습니다. 일년 전, 필자가 베타 2 버전을 처음 접했을 때 간단한 프로그램을 사용하여 전체 프레임워크에서 모든 public 형식의 public 멤버를 덤프하여 2.0 버전뿐 아니라 1.1 버전에서도 실행해 본 적이 있습니다. 그런 다음 WINDIFF.EXE를 사용하여 두 텍스트 파일을 비교하고 몇 시간 동안 특히 보안과 관련된 부분에 주안점을 두고 변경된 내용을 대략적으로 살펴보았습니다.

그 결과 얻은 결론은 .NET Framework의 보안 기능이 2.0 버전에서 많이 향상되었다는 것이고, 이 칼럼에서는 이러한 향상된 보안 기능에 대해서 살펴보고자 합니다. 모든 내용을 다룰 수는 없으나 새롭게 변경된 기능에는 어떤 것이 있으며 어떤 부분이 중요한지 알 수 있을 것입니다. 그러면 추가된 네임스페이스를 하나씩 살펴보도록 하겠습니다.


System.Security

관리되는 문자열은 민감한 정보를 저장하기에 그다지 좋은 저장 매체가 아닙니다. 그 이유는 정보를 지울 수 있는 방법이 없기 때문으로, 가비지 수집이 이루어져도 수집된 메모리를 확실히 덮어쓴다는 보장이 없습니다. 실제로 대다수의 경우, 가비지가 된 문자열이 힙 정리에 의해 덮어써지기 전까지 얼마 동안은 관리되는 힙에 남아 있게 됩니다. 게다가 가비지 수집기가 이러한 문자열을 관리되는 힙 내의 다른 위치로 옮길 수도 있습니다. 즉, 가비지 수집기가 기존 메모리를 깨끗이 비우지 않기 때문에, 보안을 유지해야 할 문자열 인스턴스가 주소 공간에 상당수 남아 있을 수 있습니다. 이러한 문제를 해결하기 위해 SecureString이라는 새로운 클래스가 도입되었습니다.

이 클래스는 DPAPI(Data Protection API)로 보호되는 메모리 모델을 사용하여 데이터를 저장합니다. 따라서 SecureString에 저장된 데이터는 항상 암호화된 형식으로 유지됩니다. 암호화 키는 LSASS.EXE(Local Security Authority Subsystem)에서 관리되며, 이 데이터는 DPAPI의 프로세스 간 통신을 통해 해독될 수 있습니다.

이 클래스를 효과적으로 사용하려면 콘솔의 암호나 web.config의 연결 문자열과 같이 보안이 필요한 데이터를 읽는 모든 .NET Framework 메서드에서 이러한 데이터를 SecureString에 직접 캡슐화하여 반환해야 합니다. 일반 문자열 사이에서 보안이 필요한 데이터를 찾아 SecureString으로 래핑하는 것만으로 안전하다고 안심해서는 안 됩니다. 이 클래스를 효과적으로 사용하려면 보안이 필요한 데이터를 관리되는 일반 문자열에 두어서는 안 됩니다.

.NET Framework로 보안이 필요한 데이터를 반환할 때도 동일한 규칙이 적용됩니다. SecureString 형식의 예로 ProcessStartInfo(자세한 내용은 나중에 설명함)의 새로운 속성인 Password 속성을 살펴보겠습니다. 보안이 필요한 데이터가 필요하면 .NET Framework는 내부적으로 Marshal.SecureStringToBSTR과 같은 Marshal 클래스의 새 기능을 사용하여 실제 내용을 검색합니다. Marshal 클래스의 작업 내용은 관리되지 않는 메모리에 저장되므로 Framework에서 사용을 마치면 적절히 삭제할 수 있습니다. ToString을 사용해서는 SecureString에서 보안이 필요한 데이터를 검색할 수 없습니다. 보안이 필요한 데이터를 일반 문자열 개체에 방치하면 안 된다는 것을 기억하십시오.

필자가 발견한 한 가지 아쉬운 점은 보안이 필요한 데이터가 스왑 파일에 저장되지 않도록 하는 방법이 없다는 것입니다. 보안이 필요한 데이터의 마샬링이 해제되어 원시 메모리에 저장될 때 마샬링이 해제되는 페이지를 VirtualLock을 통해 잠그는 방법은 딱히 없습니다.

또 한가지, RTM 비트에 초기 베타보다 더 많은 비트가 있음에도 SecureString이 Framework에 광범위하게 통합되지는 않았음을 확인했습니다. 이 클래스를 찾을 수 있는 곳 중의 하나로 새롭게 오버로드된 System.Diagnostics.Process.Start가 있으며, 여기에서 사용자 이름과 암호를 지정할 수 있습니다. 이 클래스는 기본 Win32 CreateProcessWithLogonW 함수를 사용하여 프로세스를 생성하며 이 프로세스는 사용자가 지정한 자격 증명을 사용하는 새로운 로그인 세션에서 실행됩니다. 암호는 SecureString을 사용하여 지정할 수 있습니다. System.Security.Cryptography 네임스페이스는 세 개의 클래스(CspParameters와 두 개의 인증서 클래스인 X509Certificate 및 X509Certificate2)에서 SecureString을 사용합니다. SecureString은 MSBuild 작업에도 사용되지만 정말 필요한 것은 다음과 같은 생성자에서 사용되는 것입니다.

public SqlConnection(SecureString connStr);

CredUIPromptForCredentials와 같이 Win32 함수를 래핑하는 관리되는 클래스에서도 사용되어야 합니다. 즉, 사용자에게 암호를 입력하도록 요구하고 그 결과로 SecureString을 반환할 수 있는 방법이 필요합니다. 이 기능의 성공 여부는 Framework와의 통합에 달렸다고 생각됩니다.

SecureString뿐 아니라 이 네임스페이스에는 눈길을 끄는 또 다른 새 클래스인 SecurityContext도 있습니다. 이 클래스는 무척 강력하며 이를 통해 스레드의 보안 컨텍스트를 캡처하여 다른 스레드에 복원할 수 있습니다. 캡처 가능한 보안 컨텍스트에는 Assert 및 PermitOnly와 같은 CAS(코드 액세스 보안) 스레드 마커와 관리되지 않는 스레드의 가장 토큰이 포함됩니다.

이 클래스에는 CAS 마커의 스레드 간 흐름을 제어하는 SuppressFlow와 같은 실제로도 그렇지만 다소 과격해 보이는 함수가 있습니다. 또한 SuppressFlowWindowsIdentity와 같은 놀라운 기능도 있습니다. Windows 환경에서 오랫동안 보안 프로그래밍을 해온 사람이라면 누구나 새로운 스레드를 시작하거나 대리자를 통한 비동기식 호출을 수행할 때 가장 토큰이 새 스레드로 이동하지 않는다는 사실을 알고 있을 것입니다. 이러한 보안 취약점은 수년간 여러 개발자들에게 어려움을 안겨 주고 있습니다. 하지만 SecurityContext에서 스레드 간 WindowsIdentity의 흐름을 제어하는 함수를 제공한다면 .NET Framework에서 가장 토큰을 자동으로 이동시킬 수 있을 것입니다.

이를 테스트해 보기 위해 LogonUser를 호출하고 그 결과로 반환되는 토큰을 가장하는 몇 가지 코드를 만든 다음 WindowsIdentity에 GetCurrent 메서드의 뛰어난 새 오버로드를 사용하여 토큰을 가장하는지 여부를 확인했습니다. 이 오버로드에 대해서는 뒷부분에서 다시 설명하도록 합니다. 이 함수를 호출한 위치는 네 군데로, 주 스레드, Thread.Start를 통해 시작된 새 스레드, 비동기식 대리인을 통한 작업자 스레드 및 Win32의 친숙한 기능인 CreateThread에 의해 시작된 스레드입니다. 특히 CAS 마커와 같이 보안 컨텍스트의 흐름과는 약간 다른 방식으로 작동하던 QueueUserWorkItem도 테스트해 보았습니다. 출력은 다음과 같습니다.

Main thread
Thread 2488 is impersonating V-CAMP-XP\alice
Testing Thread.Start
Thread 2508 is impersonating V-CAMP-XP\alice
Testing QueueUserWorkItem
Thread 2504 is impersonating V-CAMP-XP\alice
Testing Delegate.BeginInvoke
Thread 2516 is impersonating V-CAMP-XP\alice
Testing Native CreateThread
Thread 2520 is not impersonating!

결과는 훌륭합니다. 가장 토큰이 런타임에 스레드 전체에 자동으로 전파됨을 알 수 있습니다. 이 동작은 SecurityContext 클래스를 사용하여 변경할 수 있으나 이 클래스를 사용하지 않는 것이 좋습니다.

관리되지 않는 API CreateThread에 의해 생성된 스레드에서는 가장 토큰이 전달되지 않았으나 이는 운영 체제가 아닌 런타임에 의해 이 작업이 수행되기 때문이며 자연스러운 현상입니다. 따라서 스레딩 모델 불일치로 인해 스레드 전환을 발생시키는 inproc COM 구성 요소를 호출할 경우 여전히 가장 토큰이 삭제되기는 하지만 대다수 응용 프로그램에서 스레드 간 ID 흐름 문제가 해결되었습니다. 이러한 문제 해결로 인해 당황스러운 결과가 반환되는 경우가 줄었으므로 반가운 소식이라 할 수 있습니다. 하지만 이는 중요하면서도 민감한 변화이므로 응용 프로그램에 가장과 비동기 방식을 사용하려는 경우 미리 충분한 정보를 숙지하여 준비하시기 바랍니다.



페이지 맨 위로페이지 맨 위로


System.Security.Principal

대단한 향상은 아닌 것처럼 보이기도 하나 SID(보안 식별자)를 모델링하는 새로운 클래스로 인해 Windows 보안 프로그래밍 인터페이스를 광범하게 지원할 수 있는 길이 열리게 되었습니다. 간격을 메우기 위해 관리되는 C++ 코드를 작성하는 시간이 줄어들게 되므로 작업이 훨씬 수월해집니다. 여기에는 이를 가능하게 해 주는 세 가지 클래스가 있습니다. 첫 번째 두 클래스는 보안 계정(사용자, 그룹 또는 컴퓨터)을 참조하는 두 가지 방법에 해당하는 구체 클래스로, SecurityIdentifier는 컴퓨터에서 판독할 수 있는 SID를 나타내며 NTAccount는 사람이 읽을 수 있는 문자열을 저장합니다. 세 번째는 IdentityReference라는 추상 클래스로, 이 두 클래스를 바인딩합니다.

일반적으로 SID, SID 모음 또는 SID를 포함하는 데이터 구조의 모음을 반환하는 메서드의 서명 부분에 추상 클래스가 사용됩니다. 이 메서드는 추가로 Type 인수를 취하므로 사용자는 메서드에서 SID나 이름 중 원하는 항목을 반환하도록 선택할 수 있습니다. 그런 다음 적절한 형식으로 안전하게 다운캐스트할 수 있습니다. 다음은 파일을 소유한 사용자의 계정 이름을 표시하는 예제입니다.

void printTheOwnerOfThisFile(string path) {
    FileSecurity s = File.GetAccessControl(path);
    NTAccount user = (NTAccount)s.GetOwner(typeof(NTAccount));
    Console.WriteLine(user);
}
...
printTheOwnerOfThisFile(@"c:\autoexec.bat");

필자의 경우 이 코드를 실행하면 다음과 같은 문자열이 출력됩니다.

BUILTIN\Administrators

잘 알려진 SID의 전체 목록이 나열된 WellKnownSidType이라는 새 열거도 지원됩니다. 이를 사용하면 "Administrators"와 같이 널리 쓰이는 계정의 경우 국가별로 철자가 다르다고 하더라도 하드코딩할 필요 없이 쉽게 SID를 만들 수 있습니다.

WindowsIdentity 클래스도 눈길을 끄는 기능 중 하나입니다. 앞에서 언급했듯이 추가된 기능 중에서 가장 마음에 드는 것은 가장 중에 스레드와 프로세스 보안 컨텍스트를 구분할 수 있도록 해주는 GetCurrent의 오버로드입니다.

bool ifImpersonating = true;
WindowsIdentity threadIdentity =
    WindowsIdentity.GetCurrent(ifImpersonating);
if (null == threadIdentity) Console.WriteLine("Not impersonating");
else Console.WriteLine("Impersonating {0}", threadIdentity.Name);



페이지 맨 위로페이지 맨 위로


System.Security.AccessControl

이 네임스페이스 역시 매우 유용합니다. 이제 Framework에서 Windows 보안 설명자를 모델링하므로 프로그래밍 방식으로 ACL(액세스 제어 목록)을 읽고 수정하고, 개체의 소유권을 가지며, SDDL(Security Descriptor Description Language) 문자열과 이진 보안 설명자 간 변환을 수행하는 등의 작업이 가능해졌습니다. 알파 시험판부터 이 네임스페이스 설계의 발전 과정을 계속 지켜본 결과, 알파 버전 이후에 향상된 기능으로 인해 이 네임스페이스는 정말로 강력하고 사용이 편리한 추가 기능으로 발전했음을 확실히 말할 수 있습니다.

이 새로운 기능에 대한 간단한 예제는 파일 소유자를 출력하는 과정에서 이미 살펴보았습니다. System.IO.File 클래스를 통해 파일의 보안 설명자에 어떻게 액세스했는지 눈여겨보시기 바랍니다. 이제 Framework의 보안 개체는 GetAccessControl과 SetAccessControl이라는 두 개의 새로운 메서드를 가집니다. AutoResetEvent, Mutex와 같은 클래스뿐만 아니라 새 클래스인 Semaphore 역시 이 메서드를 가지며, File 및 Directory 클래스도 마찬가지입니다.

서비스의 DACL(Discretionary Access Control List)을 직접 변경할 수 있는 방법은 없습니다. 현재로서는 서비스 개체에 해당하는 관리되는 표현이 없기 때문입니다. 그러나 액세스 제어 인프라의 원리를 알고나서는 서비스 보안을 위한 해답을 찾는 데 15분 정도 밖에 소요되지 않았습니다. System.Security.AccessControl 네임스페이스는 처음부터 확장성을 염두에 두고 개발되었으므로 매우 유용할 것이라 생각됩니다.

ACL을 프로그래밍해 본 적이 있는 사람이라면 코드의 간단함에 놀랄 것입니다(그림 1 참조). System.Security.AccessControl 네임스페이스에 대한 자세한 내용은 MSDNMagazine 2004년 11월호에 수록된 Mark Pustilnik의 기사인 Safety in Windows: Manage Access to Windows Objects with ACLs and the .NET Framework (영문)를 참조하시기 바랍니다.



페이지 맨 위로페이지 맨 위로


System.Net.Security

인증 프로토콜은 필자가 즐겨 다루는 소재이기는 하나 인증 프로토콜에 대한 프로그래밍은 다소 복잡합니다. 특히 SSPI(보안 지원 공급자 인터페이스)에서 하위 수준 함수를 호출하는 응용 프로그램에 Kerberos를 추가하는 작업과 SSL(Secure Sockets Layer) 지원을 추가하는 작업은 훨씬 더 어려웠습니다.

하지만 이제 SSPI에 대한 관리되는 래퍼 덕택에 사용자가 Kerberos나 SSL을 사용하여 클라이언트쪽과 서버쪽 보안 채널을 모두 구현할 수 있습니다. Kerberos 지원은 Kerberos와 NTLM이라는 기존의 challenge-response 방식의 프로토콜 간의 기술적 협상을 담당하는 NegotiateStream에 의해 가능합니다. 클라이언트쪽 핸드셰이크는 동기 방식일 수도 있고 비동기 방식일 수도 있습니다. 다음은 클라이언트를 동기 방식으로 설정하는 예입니다.

NegotiateStream secureChannel = new NegotiateStream(networkStream);
secureChannel.AuthenticateAsClient(
    CredentialCache.DefaultNetworkCredentials,
    "SSPISample/TargetMachine:4242",
    ProtectionLevel.EncryptAndSign,
    TokenImpersonationLevel.Impersonation);

이렇게 설정한 다음에는 일반 NetworkStream과 같이 secureChannel을 사용할 수 있으며 secureChannel을 통과하는 모든 데이터는 MAC(메시지 인증 코드)에 의해 무결성이 보호되고 암호화됩니다. 받은 메시지를 해독하려면 서버쪽에도 NegotiateStream 인스턴스가 필요합니다. 물론 서버는 RemoteIdentity 속성을 통해 클라이언트를 나타내는 WindowsIdentity를 얻을 수 있습니다. 이를 통해 서버는 가장을 수행하거나 역할 기반 액세스 검사를 수행할 수 있습니다.

SslStream은 비슷하게 보이지만 인증 시 Kerberos 티켓이 아닌 X.509 인증서를 사용합니다. 이를 통해 클라이언트가 서버 인증서 해지를 확인하고 상호 인증을 위한 클라이언트 인증서를 제공할 수 있습니다. 동일한 방식으로, 인증 핸드셰이크가 완료되면 파이프를 통해 데이터를 넣거나 가져올 때 무결성이 보호되고 암호화되므로 안심할 수 있습니다.



페이지 맨 위로페이지 맨 위로


System.Runtime.Remoting

또 하나 흥미를 끄는 향상된 기능 중 하나로 TCP 채널에서 보안을 지원하는 것을 들 수 있습니다. 앞에서 설명한 NegotiateStream 클래스를 사용하여 채널에 보안 기능이 추가되었으며 클라이언트 및 서버 원격 구성 파일에 몇 가지 새로운 특성을 지정하면 이를 활성화할 수 있습니다. 이 칼럼에서 이 주제까지 상세하게 설명할 수 없으나, 필자가 저술한 책에 이 주제에 대해 다룬 장이 있습니다. 이 부분은 The .NET Developer's Guide to Windows Security(영문)에서 온라인으로 읽어볼 수 있습니다.



페이지 맨 위로페이지 맨 위로


System.Security.Cryptography

DPAPI는 이제 .NET Framework의 주요 기능으로 확실히 자리 잡았으며 ProtectedData 및 ProtectedMemory라는 두 개의 .NET 클래스로 인해 사용이 매우 쉬워졌습니다. 이러한 클래스를 사용하려면 System.Security.dll에 대한 참조를 추가해야 합니다.

private static byte[] Decrypt(byte[] ciphertext) {
    byte[] applicationEntropy = Encoding.ASCII.GetBytes("AcmeWidgets");
    return ProtectedData.Unprotect(ciphertext, applicationEntropy,
        DataProtectionScope.LocalMachine);
}

.NET Framework를 사용하여 암호화 체계를 구축해온 개발자라면 새로운 추상 클래스인 HMAC(keyed-Hash Message Authentication Code)에서 파생된 완전히 새로운 클래스 모음이 매우 유용할 것입니다. 다양한 SHA(Secure hash Algorithm) 변형이 모두 사용 가능합니다. 다음은 이에 대한 예제입니다.

byte[] CalcMAC(byte[] key, byte[] msg) {
    return new HMACSHA256(key).ComputeHash(msg);
}

암호나 공유 암호에서 키 자료를 생성하는 암호 기반 암호화를 수행할 경우 업계 표준 알고리즘인 PKCS #5를 사용하여 암호에서 바이트 스트림을 생성할 수 있습니다. 이 표준은 RFC 2898에 규정되어 있으며, 이 규정은 Password-Based Cryptography Specification Version 2.0(영문)에서 볼 수 있습니다. 새로운 Rfc2898DeriveBytes 클래스를 사용하면 2004년 10월호 칼럼 Security Briefs: Password Minder Internals(영문)에서 설명했듯이 편리하게 암호를 줄이거나 늘릴 수 있습니다. 이 클래스는 내부적으로 HMAC-SHA-1과 함께 PBKDF2 함수를 사용합니다.

void CreateNewUserAccount(string name, string pwd) {
    Rfc2898DeriveBytes db = new Rfc2898DeriveBytes(pwd, 32, 1000);
    byte[] hash = db.GetBytes(32);
    addUserAccountToDatabase(name, db.Salt, hash);
}



페이지 맨 위로페이지 맨 위로


System.Security.Cryptography.X509Certificates 및 PKCS

더 이상 CAPICOM이 필요하지 않습니다. 이 네임스페이스를 사용하여 CAPI(암호화 API)에 대한 관리되는 래퍼를 얻을 수 있으며, 이 래퍼가 있으면 모든 관리되는 언어에서 직접 인증서를 관리하고 CMS/PKCS #7로 포장 또는 서명된 메시지를 만들 수 있습니다.

이젠 다음과 같은 방법으로 사용자의 개인 저장소에서 인증서를 선택하도록 요청하는 작업을 쉽게 할 수 있습니다.

X509Store store = new X509Store("My", StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection certs =
    X509Certificate2UI.SelectFromCollection(store.Certificates, 
        "MyTitle", "MyMessage", X509SelectionFlag.SingleSelection);
if (1 == certs.Count) {
    Console.WriteLine("You selected \"{0}\"",
        certs[0].SubjectName.Name);
}
else Console.WriteLine("You canceled my dialog!");

그림 2는 결과 대화 상자를 보여 줍니다.

그림 2 인증서 선택
그림 2 인증서 선택



페이지 맨 위로페이지 맨 위로


System.Security.Cryptography.Xml

이 네임스페이스는 XML 암호화 지원과 함께 추가되었습니다. XML 서명 및 XML 암호화를 사용하여 데이터를 안전하게 교환하는 방법에 대한 자세한 내용은 MSDN Magazine 2004년 11월호에 수록된 Mike Downen과 Shawn Farkaat의 공동 저술 기사 Trustworthy Code: Exchange Data More Securely with XML Signatures and Encryption (영문)을 참조하시기 바랍니다.



페이지 맨 위로페이지 맨 위로


System.Diagnostics

새로운 추적 및 디버깅 기능, 향상된 이벤트 로그 지원과 초시계 기능뿐 아니라 Process 클래스에는 명시적으로 P/Invoke를 사용하지 않고도 CreateProcessWithLogonW를 호출할 수 있는 유용한 기능도 숨어 있습니다. 이는 개발자들이 테스트 시 다른 자격 증명을 사용하여 프로그램을 실행할 때 항상 사용하는 Windows의 "다음 계정으로 실행" 기능에 해당합니다. 이제 관리되는 코드에서 이 기능을 프로그래밍 방식으로 쉽게 사용할 수 있습니다.

void RunNotepadAsThisUser(string authority,
    string principal, SecureString password) 
{
    Process.Start(@"c:\windows\notepad.exe",
        principal, password, authority).Dispose();
}

SecureString이 사용되었음을 유의하십시오. 이 값을 얻는 과정에는 약간의 트릭이 필요합니다. 한 가지 방법은 CredUIPromptForCredentials와 같은 Win32 자격 증명 API 중 하나를 사용하여 사용자에게 암호를 입력하도록 요청한 다음 관리되지 않는 문자열을 SecureString 인스턴스에 넣어 Process.Start 메서드로 전달하는 것입니다. 그런 다음 암호가 담긴 버퍼를 비워주면 됩니다.



페이지 맨 위로페이지 맨 위로


System.DirectoryServices

가장 큰 변화는 VLV(Virtual List View)가 추가된 것입니다. Windows Server 2003의 이 기능을 사용하면 대규모 검색을 수행하고 검색 결과를 효율적으로 탐색할 수 있습니다. 전체 결과 집합은 한 번에 가져올 필요가 없으며 VLV를 사용하여 원하는 결과 창을 지정한 다음 해당 창만 스크롤할 수 있습니다. 다음은 포리스트의 모든 사용자를 검색하여 처음 25개의 레코드만 반환하는 예제입니다.

DirectorySearcher search = new DirectorySearcher(
    "(&(objectClass=user)" + "(objectCategory=person))");
search.VirtualListView = new DirectoryVirtualListView(25);
foreach (SearchResult result in search.FindAll()) {
    Console.WriteLine(result.Path);
}

VLV를 만들어 검색 프로그램에 추가하면 Offset(레코드 번호에 따라 결과 집합에 지정되는 인덱스), TargetPercentage(레코드 수 비율에 따라 결과 집합에 지정되는 인덱스) 또는 Target(원하는 결과가 어떤 문자열로 시작되어야 하는지 지정하는 문자열에 따라 결과 집합에 지정되는 인덱스)과 같은 속성을 설정하여 결과 창에 표시될 내용을 제어할 수 있습니다.



페이지 맨 위로페이지 맨 위로


System.DirectoryServices.ActiveDirectory

이는 Active Directory의 물리적/논리적 구성을 편리하게 보고 조작할 수 있도록 해주는 새로운 네임스페이스입니다. 모델링되는 항목에 대한 힌트를 제공하기 위해 몇 가지 클래스 이름을 나열해 보면 Forest, Site, Domain, DomainController, GlobalCatalog 등이 있으며 이 밖에도 모델링되는 클래스는 매우 많습니다. 또한 Active Directory 스키마를 읽고 조작하기 위한 클래스 집합도 제공됩니다. 이 네임스페이스를 설명하는 데 전체 칼럼을 할애할 수도 있을 만큼 이 네임스페이스에는 훌륭한 기능이 매우 많으므로 반드시 확인해 보시기 바랍니다. 보다 자세한 내용은 Joe Kaplan과 Ryan Dunn이 공동 저술한 저서 The .NET Developers Guide to Directory Services Programming(Addison-Wesley Professional 출판, 2006년 5월)을 읽어보시기 바랍니다.



페이지 맨 위로페이지 맨 위로


System.Web

2004년 6월에 필자가 ASP.NET 2.0의 보안 기능에 대한 글을 투고한 적이 있습니다(Security: Security Headaches? Take ASP.NET 2.0! (영문) 참조). 그 당시 다루지 못했던 주제가 하나 있었는데 바로 구성 파일 암호화에 관한 것이었습니다. .NET Framework에서 DPAPI를 사용하여 구성 파일의 모든 섹션, 그리고 AppSettings 섹션까지도 암호화할 수 있게 된다면 훌륭하지 않겠습니까? 다음 명령줄을 사용하면 가능합니다.

aspnet_regiis -prov DataProtectionConfigurationProvider
  -pef appSettings c:\web

이 명령을 실행하면 다음과 같은 내용의 web.config 파일이

<configuration>
  <appSettings>
    <add key='MySecret' value='Attack at dawn'/>
  </appSettings>
</configuration>

다음과 같은 형태로 변환됩니다. 여기에서 암호 텍스트는 읽기 좋도록 생략했습니다.

<configuration>
  <appSettings configProtectionProvider="DataProtectionConfigurationProvider">
    <EncryptedData>
      <CipherData>
        <CipherValue>AQAAANCMnd...</CipherValue>
      </CipherData>
    </EncryptedData>
  </appSettings>
</configuration>

이제 어떻게 "MySecret" 데이터에 액세스할 수 있을까요? 정말 좋은 것이 다음과 같은 방법으로 기존과 똑같이 액세스할 수 있으며 암호 해독은 보이지 않게 이루어진다는 것입니다.

Console.WriteLine(ConfigurationSettings.AppSettings["MySecret"]);

CAPI 키 컨테이너에 암호화 키를 저장하는 RSA 공급자도 사용할 수 있습니다. 예를 들어 구성 파일 하나를 웹 팜의 여러 컴퓨터에 배포해야 할 경우 이 클래스를 사용하면 됩니다. DPAPI가 컴퓨터에 따라 달라지는 암호화 기술인데 반해 CAPI를 사용하면 전체 팜을 대상으로 암호화 키를 동기화할 수 있습니다. patterns & practices 팀에서는 이 기능을 비롯하여 버전 2.0의 기타 보안 기능의 사용법을 다룬 문서를 한 곳에 모았습니다. 이 문서 모음은 Security Guidance for Applications Index (영문) 에서 볼 수 있습니다.



페이지 맨 위로페이지 맨 위로


코드 액세스 보안의 변경된 내용

.NET Framework 2.0 버전에서는 CAS(코드 액세스 보안) 인프라에 많은 기능이 추가되었습니다. 투명(transparent)과 불투명(opaque) 어셈블리라는 새로운 개념은 부분 신뢰 시나리오에서 보안 검사를 보다 편리하게 진행하는 데 도움이 될 것입니다. Shawn Farkas의 블로그인 Marking Your Code Transparent (영문)에서 이러한 개념에 대한 명쾌한 설명과 사용 방법에 대해 읽을 수 있습니다.

이제 새 클래스를 사용하여 어셈블리가 GAC(전역 어셈블리 캐시)에서 로드되었는지를 더욱 확실히 알 수 있게 되었습니다. GAC와 관련한 보안 정책에도 상당한 변화가 있었으며, 이제 2.0 버전에서는 GAC에서 로드된 모든 어셈블리에 보안 정책과 상관없이 암시적으로 FullTrust가 부여됩니다. 이는 GAC에서 로드된 어셈블리를 부분 신뢰 환경에서 실행하는 사람이 거의 없었기 때문에 가능한 성능 최적화였습니다. 하지만 예외적인 경우도 있을 수 있으므로 이러한 변화에 의해 보안에 문제가 생기지 않도록 주의하기 바랍니다.

.NET Framework 2.0의 새로운 기능에 대한 액세스를 제한하는 몇 가지 권한이 있습니다. 새로운 System.Net.Mail 네임스페이스가 제공하는 클라이언트쪽 SMTP 기능에 대한 액세스를 규제하는 SmtpPermission을 예로 들 수 있습니다.

정말 훌륭하다고 생각되는 새로운 권한 중 하나는 DPAPI 클래스인 ProtectedData와 ProtectedMemory를 코드에서 사용할 수 있는지를 제어하는 DataProtectionPermission입니다. 정성 들여 암호화한 구성 파일이 신뢰할 수 없는 소스로부터 다운로드한 임의 코드에 의해 해독되도록 놔두면 안 되기 때문에 이 권한은 중요합니다.



페이지 맨 위로페이지 맨 위로


요약

.NET Framework 2.0 버전은 보안을 염려하는 개발자들에게는 축복입니다. 새로 추가된 기능에 대해 개괄적으로 살펴보았으며 ASP.NET 2.0 관련 기능만 보더라도 이러한 향상은 매우 반가운 일이라 할 수 있습니다.

Keith에게 질문이나 의견이 있으시면 briefs@microsoft.com으로 보내시기 바랍니다.



Keith Brown은 Microsoft .NET 교육 제공업체인 Pluralsight의 공동 창립자입니다. Keith는 Pluralsight에서 제공하는 .NET 보안 관련 과정뿐 아니라 The .NET Developer's Guide to Windows Security와 같은 몇 권의 책을 저술하기도 했습니다. 이 책은 출판물(Addison-Wesley Professional 출판, 2004)로 볼 수도 있고 웹에서도 볼 수 있습니다. www.pluralsight.com/keith (영문)에서 자세한 내용을 알아보십시오.


페이지 맨 위로페이지 맨 위로QJ: 060307

Microsoft