가이드라인

인증 및 권한 부여

인증(AuthN)과 권한 부여(AuthZ)는 관련 취약점이 매우 빈번하게 발생하기 때문에 매우 중요한 주제입니다. 이 문제가 지속적으로 발생하는 이유는 두 개념이 무엇인지, 혹은 무엇이 취약점을 유발하는지에 대해 여전히 불확실한 부분이 많기 때문입니다.

각 용어의 정의를 다시 한번 상기해 보겠습니다.

  • 인증: 사용자는 누구인가?
  • 권한 부여: 사용자가 무엇에 접근할 수 있어야 하는가?

아래에서 각각 나누어 살펴보겠습니다.

인증 (식별 및 인증 실패)

부적절한 인증은 다음과 같은 다양한 취약점을 포함할 수 있습니다.

  • 특정 페이지/엔드포인트에 인증 절차가 없음
  • 무차별 대입 공격(크리덴셜 스터핑)에 대한 방어 체계 미흡
  • 안전하지 않은 계정/비밀번호 복구 프로세스
  • 인증 토큰의 생성, 검증, 만료, 전송 또는 저장 방식의 취약성
  • 2단계 인증(2FA) 적용 시 사용자 인증 검증 누락 또는 부적절한 처리

목록의 첫 번째 항목인 '인증 부재'는 실제 환경에서 가장 흔하게 발견되는 문제입니다. 개발자가 페이지나 엔드포인트에 필요한 인증 수준을 명시적으로 설정하거나 주석을 달아야 하는 경우가 많은데, 이 단계를 간과하기가 매우 쉽습니다.

시스템은 실패 시 차단(closed)되는 방식으로 설계하는 것이 좋습니다. 따라서 모든 엔드포인트에 인증된 사용자 세션이 필요하다고 일일이 주석을 다는 대신, 기본적으로 모든 경로가 인증된 사용자 세션을 요구하도록 설정하고 예외적인 경우에만 이를 재정의하는 방식을 권장합니다. 이렇게 하면 오류 발생 가능성을 크게 줄일 수 있습니다.

권한 부여 (접근 제어 취약점)

권한 부여 문제는 매우 흔하게 발생하는 다음과 같은 여러 형태로 나타날 수 있습니다.

  • 안전하지 않은 직접 객체 참조(IDOR)
  • 기능 수준의 접근 제어 누락(권한 부여 누락)
  • 권한 상승(수평적 또는 수직적)

안전하지 않은 직접 객체 참조

객체는 보통 고유 식별자(ID)를 키로 사용하여 참조합니다. 사용자가 주문 내역이나 계정 정보 등을 조회하려고 요청을 보낼 때, 일반적으로 이 ID가 포함됩니다. '안전하지 않은 직접 객체 참조'는 애플리케이션이 해당 사용자가 특정 객체에 접근할 권한이 있는지 검증하지 않을 때 발생합니다.

기능 수준의 접근 제어 누락

또 다른 매우 흔한 취약점은 (객체가 아닌) 페이지나 엔드포인트에 대한 권한 부여 검사가 누락되는 경우입니다.

사용하는 프레임워크에 따라 개발자가 핸들러 내에서 권한을 직접 확인하거나, 엔드포인트에 주석을 달아 호출에 필요한 요구 사항을 명시해야 하는 경우가 많습니다.

안타깝게도 이러한 추가 단계를 잊어버리는 경우가 많으며, 이것이 바로 권한 부여 취약점이 발생하는 주된 원인입니다.

권장 사항

기본값을 '허용'이 아닌 '차단'으로 설정

인증(Authentication)과 권한 부여(Authorization) 모두에서 기본값을 '허용'이 아닌 '차단'으로 설정하는 원칙은 매우 중요합니다.

사용 중인 언어나 프레임워크에 따라, 애플리케이션으로 들어오는 모든 경로에 대해 가장 높은 수준의 권한이나 인증된 세션을 요구하도록 기본값을 설정하는 것이 좋습니다. 이렇게 하면 개발자가 경로별 요구 사항을 명시적으로 재정의해야만 접근이 가능해집니다.

cs

// 요청 인증을 기본 동작으로 설정하고 관리자 권한 여부를 확인
[Authenticate]
[Authorize("Admin")]
public class SecureController : Controller
{

}

public class MyController : SecureController
{

    // 상속된 Authorize 속성을 재정의하여 모든 사용자가 페이지에 접근할 수 있도록 허용
    [Authorize("User")]
    public Page ShowUserProfile() {
        
    }   

    // 관리자 사용자만 접근 가능
    public Page ShowAdminPage() { 

   }

    // 인증 및 권한 부여 속성을 재정의하여 익명 접근 허용
    [AllowAnonymous]
    public Page ShowLoginPage() {
       
    } 

}

서비스 내 권한 부여 검사 강제

데이터에 접근할 때는 모든 데이터 접근 방식이 관련 접근 제어 및 권한 부여 검사를 일관되게 수행하도록 보장하는 것이 매우 중요합니다. 이는 일반적으로 도메인 서비스를 사용하여 구현됩니다.

추가 예시

아래는 안전한 인증 및 권한 부여와 그렇지 않은 경우의 차이를 잘 보여주는 몇 가지 예시입니다.

C# - 보안 취약

인증 누락

public class AdminController : Controller
{

    // 보안 취약: 관리자 페이지를 표시하기 전에 사용자가 로그인했는지 확인하지 않음
    public Page ShowAdminPage() {

    }

}

권한 부여 누락

[Authenticate]
public class AdminController : Controller
{

    // 보안 취약: 관리자 페이지를 표시하기 전에 사용자의 권한을 확인하지 않음 public Page ShowAdminPage() {

    }
‍
}

C# - 보안 적용

[Authenticate]
[Authorize("Admin")]
public class AdminController : Controller
{
‍
    // 안전함: 사용자가 로그인했는지 확인하고 관리자 권한을 가졌는지 모두 검사
    public Page ShowAdminPage() {

    }

}
태그라인

실무에 바로 적용하는 보안 코딩

OWASP Top 10과 같은 소프트웨어 취약점을 이해하고 완화하기 위한 보안 코딩 가이드라인을 살펴보고, 실제 앱 시뮬레이션을 통해 실습할 수 있는 가이드형 교육 미션을 시작해 보세요.

추가 가이드라인
데모 예약하기