메뉴 건너뛰기

app

사용자의 손에 맡긴 보안: CWE-807 부적절한 입력값 기반 결정

suritam92026.01.17 20:41조회 수 1댓글 0

    • 글자 크기

1. 보안 결정에 사용되는 부적절한 입력값의 위험성

CWE-807은 애플리케이션이 접근 제어, 인증, 권한 부여와 같은 중요한 보안 결정을 내릴 때, 사용자가 임의로 수정할 수 있는 입력값(HTTP 파라미터, 쿠키, HTTP 헤더, 클라이언트 측 환경 변수 등)에 전적으로 의존할 때 발생합니다. 공격자가 이 값을 조작하면 별도의 인증 없이 타인의 권한을 획득하거나, 유료 기능을 무료로 이용하는 등 시스템의 보안 정책을 완전히 우회할 수 있습니다.

2. 흔히 발생하는 취약한 패턴

가장 대표적인 사례는 클라이언트 측의 숨겨진 필드(Hidden Field)나 쿠키에 권한 정보나 가격 정보를 담아 전송하는 경우입니다.

권한 우회: 쿠키의 role=user 값을 role=admin으로 수정하여 관리자 페이지에 접속.

가격 조작: 상품 결제 시 price=10000 파라미터를 price=1로 수정하여 결제 시도.

IP 기반 인증 우회: X-Forwarded-For 헤더를 조작하여 허용된 내부 IP인 것처럼 속임.

3. 실무적 대응: 서버 측 검증 및 신뢰된 세션 활용

보안 결정은 반드시 공격자가 물리적으로 접근할 수 없는 서버 측의 신뢰된 정보를 바탕으로 이루어져야 합니다.

서버 세션 사용: 사용자의 권한이나 등급 정보는 클라이언트가 아닌 서버 측 세션(Session)에 보관하고 이를 기준으로 판단합니다.

데이터베이스 재검증: 클라이언트로부터 받은 가격이나 아이디 값은 반드시 서버 측 DB에서 다시 조회하여 일치 여부를 확인합니다.

중요 로직의 무결성 검증: 클라이언트가 보낸 데이터가 변조되지 않았음을 증명하기 위해 암호화된 토큰이나 서명(HMAC 등)을 사용합니다.

4. CWE-807 대응 및 안전한 보안 결정 자바 코드 예시

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
 
public class AuthorizationManager {
    private static final Logger logger = LoggerFactory.getLogger(AuthorizationManager.class);
 
    // [CWE-807 조치] 클라이언트 입력값(Cookie)이 아닌 서버 세션을 기반으로 권한 판단
    public boolean isAdmin(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        
        if (session == null) {
            logger.debug("No active session found.");
            return false;
        }
 
        // 클라이언트가 보낸 쿠키나 파라미터가 아닌, 로그인 시 서버 세션에 저장된 값을 신뢰
        String userRole = (String) session.getAttribute("USER_ROLE");
        
        if ("ADMIN".equals(userRole)) {
            logger.debug("Admin access granted based on secure session data.");
            return true;
        }
 
        logger.debug("Access denied: User role is {}", userRole);
        return false;
    }
 
    // [CWE-807 조치] 결제 시 클라이언트가 보낸 가격이 아닌 DB 가격으로 검증
    public void processOrder(String productId, int priceFromClient) {
        // DB에서 실제 가격 조회 (가상 로직)
        int realPrice = productRepository.findPriceById(productId);
 
        if (priceFromClient != realPrice) {
            // [CWE-754, CWE-390] 조작된 입력값에 대한 대응
            logger.debug("Security Violation: Manipulated price detected! Client: {}, DB: {}", priceFromClient, realPrice);
            throw new SecurityException("Invalid order data.");
        }
 
        logger.debug("Order processing for product: {} at price: {}", productId, realPrice);
    }
}

코멘트: 시큐어 코딩의 대원칙은 "클라이언트에서 오는 모든 값은 오염되었다고 가정하는 것"입니다. 사용자의 브라우저를 거쳐온 데이터는 보안 결정의 근거가 될 수 없습니다. logger.debug()를 통해 권한 위반 시도를 꼼꼼히 기록하되, 시스템의 열쇠(보안 결정권)를 절대 사용자의 손에 쥐여주지 않는 것이 설계 단계에서부터 고려해야 할 핵심 방어 전략입니다.

 
    • 글자 크기
경계를 넘어선 데이터의 위협: CWE-119 메모리 버퍼 오버플로우 (by suritam9) 숫자의 한계를 이용한 논리 파괴: CWE-190 정수형 오버플로우 (by suritam9)

댓글 달기

첨부 (0)
위로