ACS 보안 지침

업데이트: 2015년 6월 19일

Azure에 적용합니다.

적용 대상

  • Microsoft Azure Active Directory 액세스 제어(액세스 제어 서비스 또는 ACS라고도 함)

  • WIF(Windows Identity Foundation)

요약

이 항목에서는 ACS에 대한 보안 지침을 통합합니다. 이러한 지침을 활용하면 보안 측면에서 구현의 품질을 개선할 수 있습니다. 응용 프로그램 아키텍처, 코드/로깅 보안 버그 및 프로덕션 배포를 검토할 때 이러한 지침을 사용할 수 있습니다. 이러한 지침은 특정 작업을 수행하기 위한 규범적 단계를 포함하는 방법 및 ACS의 특정 기능 또는 기능에 대해 자세히 알아보기 위한 개념 항목에 대한 자세한 내용을 참조합니다.

목표

  • ACS 컨텍스트에서 애플리케이션의 코드 및 구성과 관련된 보안 문제를 해결합니다.

  • ACS 구성과 관련된 보안 문제를 해결합니다.

  • ACS 컨텍스트에서 Azure 배포와 관련된 보안 문제를 해결합니다.

다음은 응용 프로그램 코드 및 구성과 관련된 보안 지침입니다.

  • 재생 검색 기능(DetectReplayedTokens)을 true로 설정할 것을 고려합니다.

  • wsFederationrequireHttps 특성을 true로 설정합니다.

  • cookieHandlerrequireSsl 특성을 true로 설정합니다.

  • sessionTokenRequirement의 lifetime 특성을 높은 값으로 설정합니다.

  • issuerNameRegistry에 트러스트된 STS(토큰 발급자)를 나열합니다.

  • audienceUri를 사용하여 응용 프로그램에서 허용해야 하는 토큰 범위를 지정합니다.

재생 검색 기능(DetectReplayedTokens)을 true로 설정할 것을 고려

WIF에는 STS(보안 토큰 서비스) 전달자 토큰 전용의 재생 검색 캐시(이전에 사용한 STS 토큰의 캐시)가 있습니다. 클라이언트는 STS 토큰을 사용하여 신뢰 당사자에 처음으로 인증할 때 추가 요청을 위해 신뢰 당사자에 인증하는 데 사용하는 세션 보안 토큰을 받습니다. 이 과정은 SSL(Secure Sockets Layer)을 통해 수행되므로 세션 보안 토큰이 도용되지 않습니다. 클라이언트 또는 공격자가 클라이언트가 이미 사용한 STS 토큰을 사용하여 신뢰 당사자에 인증하려고 하면 신뢰 당사자는 재생 캐시에서 STS 토큰을 조회하여 요청을 거부합니다.

이 캐시를 사용한다고 해서 토큰을 재생할 수 없음이 보장되는 것은 아닙니다. 이 캐시는 캐시 크기, STS 토큰 만료 시간, 그리고 신뢰 당사자가 받은 고유 인증 요청의 속도에 따라 최적의 검색을 수행합니다. 따라서 성능과 보안 간에 적절한 균형을 유지하려면 신뢰 당사자에 대해 캐시 크기와 STS 토큰 만료 시간을 설정하는 것이 좋습니다.

예제:

<securityTokenHandlers>
  <securityTokenHandlerConfiguration>
    <tokenReplayDetection enabled="true" capacity="1000" expirationPeriod="500"/>
  </securityTokenHandlerConfiguration>
</securityTokenHandlers>

참고

이 기능을 사용하면 서버 선호도가 생성되어 Azure를 비롯한 부하 분산된 환경에서는 확장성 문제가 발생할 수 있습니다. 이 문제를 해결하려면 기본 추상 클래스 Microsoft.IdentityModel.Tokens.TokenReplayCache를 사용하여 자체 토큰 재생 검색을 구현한 후에, 다음과 같은 코드를 사용하여 구성 파일에서 해당 구현을 참조할 수 있습니다.

<system.identityModel>
  <identityConfiguration>
    <tokenReplayDetection>
      <replayCache type='FQTN of your type' />
    </tokenReplayDetection>
  </identityConfiguration>
</system.identityModel>

wsFederation의 requireHttps 특성을 true로 설정

requireHttps 특성은 모듈이 STS에 대해 보안 URL만 리디렉션할지 여부를 제어합니다. 이 특성의 기본값은 "true"입니다. 기본값을 사용하는 경우 일반 HTTPS/SSL 트래픽을 통해 STS와 안전하게 통신할 수 있으므로 통신 중의 자격 증명 및 토큰 스니핑 가능성을 완화할 수 있습니다.

예제:

<federatedAuthentication>
  <wsFederation
        passiveRedirectEnabled="true"
        issuer="http://STS URL GOES HERE/"
        realm="http://RP REALM GOES HERE/"
        requireHttps="ture" />
  <cookieHandler requireSsl="true" />
</federatedAuthentication>

cookieHandler의 requireSsl 특성을 true로 설정

이 값은 부울이며 기본값은 false입니다. requireSsl 특성은 작성된 쿠키에 대해 "Secure" 플래그를 내보낼지 여부를 제어합니다. 이 값을 설정하면 HTTPS를 통해서만 로그인 세션 쿠키를 사용할 수 있습니다. 따라서 일반 트래픽을 통해 세션 쿠키를 보낼 수 없으므로 통신 중에 토큰 스니핑 위협을 완화할 수 있습니다.

예제:

<federatedAuthentication>
  <wsFederation
        passiveRedirectEnabled="true"
        issuer="http://STS URL GOES HERE/"
        realm="http://RP REALM GOES HERE/"
        requireHttps="ture" />
  <cookieHandler requireSsl="true" />
</federatedAuthentication>

sessionTokenRequirement의 lifetime 특성을 높은 값으로 설정

수명 제한을 높은 값으로 설정하여 토큰을 발급해야 하도록 지정할 수 있습니다. 이렇게 하면 공격자가 토큰을 도용하는 경우 토큰 재생 기간이 제한됩니다.

예제:

<add type="Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler, Microsoft.IdentityModel">
  <sessionTokenRequirement securityTokenCacheType="Microsoft.IdentityModel.MruSecurityTokenCache, Microsoft.IdentityModel"
                           saveBootstrapTokens="true"
                           securityTokenCacheSize="500"
                           useWindowsTokenService="false"
                           lifetime="10:00" />
</add>

issuerNameRegistry에 트러스트된 STS(토큰 발급자) 나열

모든 발급자 토큰은 IssuerNameRegistry를 사용하여 유효성을 검사합니다. IssuerNameRegistry는 발급자 토큰을 문자열 이름에 매핑하는 용도로 사용됩니다. 유효성 검사가 실패하면 토큰이 허용되지 않습니다. 따라서 트러스트되지 않는 토큰을 허용할 위협을 완화할 수 있습니다. 모든 사용자 지정 형식은 issuerNameRegistry> 요소의 <형식 특성을 사용하여 등록할 수 있습니다. issuerNameRegistry에는 <IssuerNameRegistry> 에 대한 사용자 지정 구성으로 사용할 자식 요소가 하나 있을 수 있습니다. 구성에서 트러스트된 발급자 인증서 집합을 구성하는 데 사용할 수 있는 IssuerNameRegistry 유형 하나(ConfigurationBasedIssuerNameRegistry)가 기본 제공됩니다. 이 형식에는 신뢰할 수 있는 발급자 인증서가 구성된 자식 구성 요소 <trustedIssuers> 가 필요합니다. <trustedIssuers> 구성은 ASN.1로 인코딩된 형식의 인증서 지문을 사용하여 신뢰할 수 있는 인증서를 추가합니다.

예제:

<issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel">
  <trustedIssuers>
    <add thumbprint="97249e1a5fa6bee5e515b82111ef524a4c9158de" name="contoso.com" />
    <remove thumbprint="97249e1a5fa6bee5e515b82111ef524a4c9158de" />
    <clear/>
  </trustedIssuers>
</issuerNameRegistry>

audienceUri만 사용하도록 응용 프로그램의 토큰 범위 지정

<audienceUris는> 이 신뢰 당사자를 식별하는 것으로 허용되는 URI 집합을 지정합니다. 허용 되는 대상 Uri 중 하나에 대해 범위가 지정 되지 않는 한 토큰을 허용 하지 않습니다. 따라서 다른 신뢰 당사자에 대해 발급된 유효한 토큰이 재생될 위험을 완화할 수 있습니다. 기본적으로는 컬렉션에 URI가 추가되지 않습니다. SAML 1.1 및 SAML 2.0 토큰 유형의 SecurityTokenHandler는 이 컬렉션의 값을 사용하여 SamlSecurityTokenRequirement 개체에서 허용되는 대상 uri 제한을 구성합니다.

예제:

<audienceUris>
  <clear/>
  <add value="http://www.example.com/myapp/" />
  <remove value="http://www.example.com/myapp/" />
</audienceUris>

다음은 ACS 관리 포털 구성과 관련된 보안 지침입니다.

  • STS 토큰에 대해 만료 기간을 길게 설정

  • 오류 URL 기능 사용 시 적절한 데이터 유효성 검사 제공

  • 기밀을 철저하게 유지해야 하는 경우 토큰 암호화 고려

STS 토큰에 대해 만료 기간을 길게 설정

토큰 수명 특성은 토큰의 수명을 제어합니다. ACS 포털 또는 관리 서비스를 사용하여 신뢰 당사자를 만들거나 구성할 때 지정됩니다. 토큰 수명 속성을 사용하여 ACS에서 신뢰 당사자 애플리케이션에 발급한 보안 토큰의 유효 기간을 지정할 수 있습니다. 기본적으로 ACS에서 이 값은 10분(600초)으로 설정됩니다. ACS에서 이 값은 0보다 크지만 24시간(86400초)보다 작거나 같아야 합니다.

오류 URL 기능 사용 시 적절한 데이터 유효성 검사 제공

오류 URL을 사용하여 로그인 프로세스 중에 오류가 발생하는 경우 ACS가 사용자를 리디렉션하는 URL을 지정할 수 있습니다. 예를 들어 http://www.fabrikam.com/billing/error.aspx신뢰 당사자 애플리케이션에서 호스트되는 사용자 지정 페이지일 수 있습니다. 리디렉션의 일부로 ACS는 JSON으로 인코딩된 HTTP URL 매개 변수로 신뢰 당사자 애플리케이션에 오류에 대한 세부 정보를 제공합니다. 사용자 지정 오류 페이지에서 JSON 인코딩 오류 정보를 사용하여 실제로 받은 오류 메시지를 렌더링하거나 정적 도움말 텍스트를 표시하도록 지정할 수 있습니다. 페이지에 권한 부여가 필요한 경우 ACS가 액세스하고 JSON 인코딩 오류를 보내려고 하는 경우 무한 리디렉션 루프가 됩니다. 따라서 익명 액세스가 가능하도록 페이지를 구성해야 합니다. 이렇게 하면 페이지에 익명으로 액세스할 수 있으며, 페이지가 HTML를 다시 에코하는 코드를 포함하거나 데이터베이스에 데이터를 쓸 수 있기 때문에 사이트 간 스크립팅 및 SQL 주입 공격을 방지하기 위한 단계를 수행해야 합니다.

기밀을 철저하게 유지해야 하는 경우 토큰 암호화 고려

수동 페더레이션에 대해 기밀을 철저히 유지해야 하는 경우에는 토큰을 암호화할 수 있습니다. 인증서 및 키 항목에서 토큰 암호화 및 암호 해독에 대해 자세히 알아보세요.

다음은 ACS를 사용하고 Azure에 배포되는 애플리케이션과 관련된 보안 고려 사항입니다.

  • RSA를 사용하여 쿠키 암호화

RSA를 사용하여 쿠키 암호화

Azure에서는 각 인스턴스의 키가 다르므로, DPAPI(데이터 보호 응용 프로그래밍 인터페이스)를 사용하는 기본 쿠키 암호화 메커니즘은 적합하지 않습니다. 즉, 특정 웹 역할 인스턴스에서 만든 쿠키를 다른 웹 역할 인스턴스에서 읽을 수 없습니다. 이로 인해 서비스가 실패하여 서비스 거부 현상이 발생할 수 있습니다. 다음은 기본 쿠키 암호화 메커니즘을 사용할 경우 표시되는 오류 메시지입니다.

[CryptographicException: Key not valid for use in specified state.
]
System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy, DataProtectionScope scope) +577
Microsoft.IdentityModel.Web.ProtectedDataCookieTransform.Decode(Byte[] encoded) +80
[InvalidOperationException: ID1073: A CryptographicException occurred when attempting to decrypt the cookie using the ProtectedData API (see inner exception for details). If you are using IIS 7.5, this could be due to the loadUserProfile setting on the Application Pool being set to false. ]
Microsoft.IdentityModel.Web.ProtectedDataCookieTransform.Decode(Byte[] encoded) +433
Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ApplyTransforms(Byte[] cookie, Boolean outbound) +189
Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver) +862
Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(Byte[] token, SecurityTokenResolver tokenResolver) +109
Microsoft.IdentityModel.Web.SessionAuthenticationModule.ReadSessionTokenFromCookie(Byte[] sessionCookie) +356
Microsoft.IdentityModel.Web.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken) +123
Microsoft.IdentityModel.Web.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs) +61
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +80
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +270

이 문제를 해결하려면 모든 웹 역할 인스턴스에서 공유되는 키를 사용하는 쿠키 암호화 메커니즘을 사용합니다. 다음 코드는 기본 SessionSecurityHandler 개체를 바꾸고 RsaEncryptionCookieTransform 클래스를 사용하도록 구성하는 방법을 보여 줍니다.

private void OnServiceConfigurationCreated(object sender, 
    ServiceConfigurationCreatedEventArgs e)
{
    List<CookieTransform> sessionTransforms =
        new List<CookieTransform>(
            new CookieTransform[] 
            {
                new DeflateCookieTransform(), 
                new RsaEncryptionCookieTransform(
                    e.ServiceConfiguration.ServiceCertificate),
                new RsaSignatureCookieTransform(
                    e.ServiceConfiguration.ServiceCertificate)  
            });
   SessionSecurityTokenHandler sessionHandler = 
    new
     SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());

    e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(
        sessionHandler);
}

void Application_Start(object sender, EventArgs e)
{
    FederatedAuthentication.ServiceConfigurationCreated += OnServiceConfigurationCreated;
}

추가 리소스