1.9 보안기능 입력값 검증

개요

소프트웨어의 보안 기능(예: 인증, 접근 제어, 암호화) 자체를 구현할 때 사용되는 입력값에 대한 검증은 매우 중요합니다. 만약 보안 기능이 처리하는 입력값(예: 사용자 ID, 역할 이름, 파일 경로, 암호화 키 길이 등)을 적절히 검증하지 않으면, 공격자는 이를 조작하여 보안 기능을 우회하거나 예상치 못한 방식으로 동작하게 만들 수 있습니다.

예를 들어, 접근 제어 로직에서 사용자의 역할을 나타내는 파라미터를 클라이언트로부터 직접 받아 검증 없이 사용한다면, 공격자는 이 파라미터 값을 `admin` 등으로 변조하여 관리자 권한을 획득할 수 있습니다. 또한, 암호화 함수에 전달되는 키 길이나 초기화 벡터(IV) 값이 검증되지 않으면 취약한 암호화가 수행될 수 있습니다.

이 기준은 보안 기능의 로직 내에서 처리되는 입력값들에 대해 철저한 유효성 검증을 수행하여, 보안 기능 자체가 공격 통로가 되는 것을 방지하기 위한 보안 요구사항을 정의합니다.

보안 대책

  • - 보안 결정에 외부 입력값 직접 사용 금지: 인증, 권한 부여 등 중요한 보안 결정 로직에서는 사용자로부터 직접 전달받은 입력값(파라미터, 쿠키 등)을 신뢰하지 않고, 서버 측 세션 정보나 안전하게 관리되는 내부 데이터를 기반으로 판단해야 합니다.
  • - 입력값 유효성 검증 (Whitelist): 보안 기능에 전달되는 모든 입력값에 대해 데이터 타입, 길이, 형식, 허용된 값의 범위(Whitelist) 등을 엄격하게 검증합니다.
  • - 간접 참조 매핑: 보안 결정에 필요한 식별자(예: 사용자 ID, 역할 ID)를 클라이언트에 직접 노출하는 대신, 내부적으로 관리되는 안전한 식별자를 사용하고 서버 내에서 매핑하여 처리합니다.
  • - 안전한 기본값 사용 및 예외 처리: 입력값 검증 실패 시, 안전한 기본값(Fail-Safe Defaults)을 사용하거나 명시적인 오류 처리를 통해 비정상적인 로직 수행을 차단합니다.
  • - 보안 관련 설정값 보호: 암호화 알고리즘, 키 길이, 접근 제어 규칙 등 보안 관련 설정값들이 외부 입력에 의해 변경되지 않도록 안전하게 관리합니다.

코드 예시 (Java - 접근 제어)

취약한 코드 (요청 파라미터 의존):

// 사용자 요청 파라미터 'role' 값을 그대로 신뢰하여 권한 검사
String userRole = request.getParameter("role"); 

if ("admin".equalsIgnoreCase(userRole)) {
    // 관리자 기능 수행 (취약!)
    performAdminTask(); 
} else {
    // 일반 사용자 기능 수행
    performUserTask();
}
                        
안전한 코드 (서버 세션 정보 사용):

// 서버 측 세션에서 사용자의 역할 정보(안전하게 저장된)를 가져옴
HttpSession session = request.getSession(false); // false: 세션 없으면 null 반환
String userRole = null;
if (session != null) {
    userRole = (String) session.getAttribute("userRole"); // 예: 로그인 시 설정된 역할
}

// 세션의 역할 정보로 권한 검사
if ("admin".equalsIgnoreCase(userRole)) {
    // 관리자 기능 수행 (안전)
    performAdminTask();
} else {
    // 일반 사용자 또는 비로그인 사용자 처리
    performUserTaskOrDenyAccess();
}
                        

Python(Flask/Django 세션), JavaScript(Node.js 세션 미들웨어), C#(ASP.NET Identity/Session), PHP(세션) 등 다른 웹 환경에서도 중요한 보안 결정은 클라이언트 입력값이 아닌 서버 측의 신뢰할 수 있는 정보를 기반으로 수행해야 합니다.