다음을 통해 공유


주요 보안 개념

비고

이 문서는 Windows에 적용됩니다.

ASP.NET Core에 대한 자세한 내용은 ASP.NET Core 보안 개요를 참조하세요.

.NET은 모바일 코드에 대한 보안 문제를 해결하고 구성 요소가 사용자에게 권한이 부여된 작업을 결정할 수 있도록 지원하는 역할 기반 보안을 제공합니다.

형식 안전 및 보안

형식 안전 코드는 액세스 권한이 부여된 메모리 위치에만 액세스합니다. (이 논의의 경우 형식 안전은 특히 메모리 형식 안전을 의미하며 보다 광범위한 측면에서 형식 안전성과 혼동해서는 안 됩니다.) 예를 들어 형식 안전 코드는 다른 개체의 개인 필드에서 값을 읽을 수 없습니다. 잘 정의된 허용 가능한 방법으로만 형식에 액세스합니다.

JIT(Just-In-Time) 컴파일 중에 선택적 확인 프로세스는 형식이 안전한지 확인하기 위해 JIT를 네이티브 머신 코드로 컴파일할 메서드의 메타데이터 및 CIL(공용 중간 언어)을 검사합니다. 코드에 확인을 바이패스할 수 있는 권한이 있는 경우 이 프로세스를 건너뜁습니다. 확인에 대한 자세한 내용은 관리되는 실행 프로세스를 참조하세요.

형식 안전성 확인은 관리 코드를 실행하기 위해 필수는 아니지만 형식 안전은 어셈블리 격리 및 보안 적용에서 중요한 역할을 합니다. 코드 형식이 안전한 경우 공용 언어 런타임은 어셈블리를 서로 완전히 격리할 수 있습니다. 이러한 격리는 어셈블리가 서로에 부정적인 영향을 주지 않도록 하고 애플리케이션 안정성을 높이는 데 도움이 됩니다. 형식이 안전한 구성 요소는 서로 다른 수준에서 신뢰할 수 있더라도 동일한 프로세스에서 안전하게 실행할 수 있습니다. 코드 형식이 안전하지 않은 경우 원치 않는 부작용이 발생할 수 있습니다. 예를 들어 런타임은 관리 코드가 네이티브(관리되지 않는) 코드로 호출하고 악의적인 작업을 수행하는 것을 막을 수 없습니다. 코드 형식이 안전한 경우 런타임의 보안 적용 메커니즘은 그렇게 할 수 있는 권한이 없는 한 네이티브 코드에 액세스하지 않도록 합니다. 형식이 안전하지 않은 모든 코드는 실행하려면 전달된 SecurityPermission 열거형 멤버 SkipVerification 와 함께 부여되어야 합니다.

비고

CAS(코드 액세스 보안)는 .NET Framework 및 .NET의 모든 버전에서 더 이상 사용되지 않습니다. 최신 버전의 .NET은 CAS 주석을 준수하지 않으며 CAS 관련 API를 사용하는 경우 오류가 발생합니다. 개발자는 보안 작업을 수행하는 대체 수단을 찾아야 합니다.

교장

프린시펄은 사용자의 정체성과 역할을 나타내며 사용자를 대신하여 행동합니다. .NET의 역할 기반 보안은 세 가지 종류의 보안 주체를 지원합니다.

  • 일반 원칙은 Windows 사용자 및 역할과 독립적으로 존재하는 사용자와 역할을 나타냅니다.

  • Windows 주체는 Windows 사용자 및 해당 역할(또는 해당 그룹)을 나타냅니다. Windows 보안 주체는 다른 사용자를 가장할 수 있습니다. 즉, 보안 주체가 해당 사용자에 속한 ID를 제시하는 동안 사용자를 대신하여 리소스에 액세스할 수 있습니다.

  • 사용자 지정 보안 주체는 특정 애플리케이션에 필요한 모든 방식으로 애플리케이션에서 정의할 수 있습니다. 주체의 정체성과 역할에 대한 기본 개념을 확장할 수 있습니다.

자세한 내용은 주체 및 ID 개체를 참조하세요.

인증

인증은 사용자의 자격 증명을 확인하고 해당 자격 증명의 유효성을 특정 권위 있는 기관에 대조하여 보안 주체의 신원을 확인하고 검증하는 과정입니다. 인증 중에 얻은 정보는 코드에서 직접 사용할 수 있습니다. .NET 역할 기반 보안을 사용하여 현재 사용자를 인증하고 해당 보안 주체가 코드에 액세스할 수 있도록 허용할지 여부를 결정할 수도 있습니다. 특정 역할에 대한 주체를 인증하는 방법 예제를 보려면 WindowsPrincipal.IsInRole 메서드의 오버로드를 참조하세요. 예를 들어 오버로드를 WindowsPrincipal.IsInRole(String) 사용하여 현재 사용자가 Administrators 그룹의 구성원인지 확인할 수 있습니다.

오늘날에는 다양한 인증 메커니즘이 사용되고 있으며, 그 중 상당수는 .NET 역할 기반 보안과 함께 사용할 수 있습니다. 가장 일반적으로 사용되는 메커니즘 중 일부는 기본, 다이제스트, Passport, 운영 체제(예: NTLM 또는 Kerberos) 또는 애플리케이션 정의 메커니즘입니다.

예시

다음 예제를 실행하는 데는 현재 사용자가 관리자여야 합니다. name 매개 변수는 null관리자인 모든 사용자가 요구를 전달할 수 있도록 하는 매개 변수입니다.

비고

Windows Vista에서 UAC(사용자 계정 컨트롤)는 사용자의 권한을 결정합니다. 기본 제공 관리자 그룹의 구성원인 경우 표준 사용자 액세스 토큰과 관리자 액세스 토큰이라는 두 개의 런타임 액세스 토큰이 할당됩니다. 기본적으로 표준 사용자 역할에 있습니다. 관리자여야 하는 코드를 실행하려면 먼저 표준 사용자에서 관리자로 권한을 상승시켜야 합니다. 애플리케이션 아이콘을 마우스 오른쪽 단추로 클릭하고 관리자 권한으로 실행하려는 경우 애플리케이션을 시작할 때 이 작업을 수행할 수 있습니다.

using System;
using System.Threading;
using System.Security.Permissions;
using System.Security.Principal;

class SecurityPrincipalDemo
{

    public static void Main()
    {
        AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
        PrincipalPermission principalPerm = new PrincipalPermission(null, "Administrators");
        principalPerm.Demand();
        Console.WriteLine("Demand succeeded.");
    }
}
Imports System.Threading
Imports System.Security.Permissions
Imports System.Security.Principal



Class SecurityPrincipalDemo


    Public Shared Sub Main()
        AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)
        Dim principalPerm As New PrincipalPermission(Nothing, "Administrators")
        principalPerm.Demand()
        Console.WriteLine("Demand succeeded.")

    End Sub
End Class

다음 예제에서는 주체의 신원과 주체가 사용할 수 있는 역할을 확인하는 방법을 보여 줍니다. 이 예제의 애플리케이션은 현재 사용자가 애플리케이션 사용을 허용하는 역할에 있는지 확인하는 것일 수 있습니다.

using System;
using System.Threading;
using System.Security.Permissions;
using System.Security.Principal;

class SecurityPrincipalDemo
{
    public static void DemonstrateWindowsBuiltInRoleEnum()
    {
        AppDomain myDomain = Thread.GetDomain();

        myDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
        WindowsPrincipal myPrincipal = (WindowsPrincipal)Thread.CurrentPrincipal;
        Console.WriteLine($"{myPrincipal.Identity.Name.ToString()} belongs to: ");
        Array wbirFields = Enum.GetValues(typeof(WindowsBuiltInRole));
        foreach (object roleName in wbirFields)
        {
            try
            {
                // Cast the role name to a RID represented by the WindowsBuildInRole value.
                Console.WriteLine($"{roleName}? {myPrincipal.IsInRole((WindowsBuiltInRole)roleName)}.");
                Console.WriteLine("The RID for this role is: " + ((int)roleName).ToString());
            }
            catch (Exception)
            {
                Console.WriteLine($"{roleName}: Could not obtain role for this RID.");
            }
        }
        // Get the role using the string value of the role.
        Console.WriteLine($"'Administrators'? {myPrincipal.IsInRole("BUILTIN\\" + "Administrators")}.");
        Console.WriteLine($"'Users'? {myPrincipal.IsInRole("BUILTIN\\" + "Users")}.");
        // Get the role using the WindowsBuiltInRole enumeration value.
        Console.WriteLine($"{WindowsBuiltInRole.Administrator}? {myPrincipal.IsInRole(WindowsBuiltInRole.Administrator)}.");
        // Get the role using the WellKnownSidType.
        SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
        Console.WriteLine($"WellKnownSidType BuiltinAdministratorsSid  {sid.Value}? {myPrincipal.IsInRole(sid)}.");
    }

    public static void Main()
    {
        DemonstrateWindowsBuiltInRoleEnum();
    }
}
Imports System.Threading
Imports System.Security.Permissions
Imports System.Security.Principal

Class SecurityPrincipalDemo

    Public Shared Sub DemonstrateWindowsBuiltInRoleEnum()
        Dim myDomain As AppDomain = Thread.GetDomain()

        myDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)
        Dim myPrincipal As WindowsPrincipal = CType(Thread.CurrentPrincipal, WindowsPrincipal)
        Console.WriteLine("{0} belongs to: ", myPrincipal.Identity.Name.ToString())
        Dim wbirFields As Array = [Enum].GetValues(GetType(WindowsBuiltInRole))
        Dim roleName As Object
        For Each roleName In wbirFields
            Try
                ' Cast the role name to a RID represented by the WindowsBuildInRole value.
                Console.WriteLine("{0}? {1}.", roleName, myPrincipal.IsInRole(CType(roleName, WindowsBuiltInRole)))
                Console.WriteLine("The RID for this role is: " + Fix(roleName).ToString())

            Catch
                Console.WriteLine("{0}: Could not obtain role for this RID.", roleName)
            End Try
        Next roleName
        ' Get the role using the string value of the role.
        Console.WriteLine("{0}? {1}.", "Administrators", myPrincipal.IsInRole("BUILTIN\" + "Administrators"))
        Console.WriteLine("{0}? {1}.", "Users", myPrincipal.IsInRole("BUILTIN\" + "Users"))
        ' Get the role using the WindowsBuiltInRole enumeration value.
        Console.WriteLine("{0}? {1}.", WindowsBuiltInRole.Administrator, myPrincipal.IsInRole(WindowsBuiltInRole.Administrator))
        ' Get the role using the WellKnownSidType.
        Dim sid As New SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, Nothing)
        Console.WriteLine("WellKnownSidType BuiltinAdministratorsSid  {0}? {1}.", sid.Value, myPrincipal.IsInRole(sid))

    End Sub

    Public Shared Sub Main()
        DemonstrateWindowsBuiltInRoleEnum()

    End Sub
End Class

승인

권한 부여는 주체가 요청된 행동을 수행할 수 있는지 여부를 결정하는 프로세스입니다. 권한 부여는 인증 후에 발생하며 보안 주체의 ID 및 역할에 대한 정보를 사용하여 보안 주체가 액세스할 수 있는 리소스를 결정합니다. .NET 역할 기반 보안을 사용하여 권한 부여를 구현할 수 있습니다.

참고하십시오