2.4 중요자원 접근통제
개요
접근 통제(Access Control)는 인증된 사용자(또는 시스템)가 허가된 자원(데이터, 기능 등)에만 접근할 수 있도록 제어하는 보안 메커니즘입니다. 중요 자원에 대한 접근 통제가 부적절하게 설계되거나 구현되면, 비인가된 사용자가 민감한 정보에 접근하거나 시스템 기능을 오용하는 심각한 보안 사고로 이어질 수 있습니다.
효과적인 접근 통제를 위해서는 최소 권한 원칙(Principle of Least Privilege)을 준수하여 각 주체에게 필요한 최소한의 권한만 부여해야 합니다. 또한, 역할 기반 접근 통제(RBAC: Role-Based Access Control)나 접근 제어 목록(ACL: Access Control List) 등 적절한 접근 통제 모델을 적용하고, 자원 접근 시마다 권한 검증 절차를 반드시 수행해야 합니다.
이 기준은 중요 자원에 대한 비인가 접근을 차단하고, 각 주체의 권한을 명확히 정의 및 관리하기 위한 필수적인 접근 통제 보안 요구사항을 정의합니다.
보안 대책
- - 최소 권한 원칙 적용: 사용자, 관리자, 서비스 계정 등 모든 주체에게 업무 수행에 필요한 최소한의 권한만 부여합니다. 불필요한 권한은 제거합니다.
- - 역할 기반 접근 통제 (RBAC) 적용: 사용자에게 직접 권한을 부여하는 대신, 역할을 정의하고 역할에 권한을 할당한 후 사용자에게 역할을 부여하는 방식을 적용하여 권한 관리를 용이하게 합니다.
- - 자원 접근 시 권한 검증: 파일, 데이터베이스 레코드, 관리자 페이지 등 중요 자원에 접근하는 모든 요청에 대해 해당 사용자가 적절한 권한을 가지고 있는지 서버 측에서 반드시 검증합니다. 클라이언트 측 검증은 쉽게 우회될 수 있으므로 신뢰하지 않습니다.
- - 접근 통제 설정의 안전한 관리: 권한 설정 정보(예: ACL, 역할 매핑 테이블)는 비인가된 사용자가 임의로 변경할 수 없도록 안전하게 보호 및 관리합니다.
- - 안전한 기본 설정(Secure Defaults): 새로운 사용자나 자원이 생성될 때 기본적으로 최소한의 권한을 가지도록 설정하고, 필요한 경우 명시적으로 권한을 추가 부여합니다.
- - 접근 시도 로깅 및 모니터링: 중요 자원에 대한 접근 시도(성공 및 실패)를 로그로 기록하고, 비정상적인 접근 패턴(예: 과도한 실패, 권한 없는 접근 시도)을 모니터링합니다.
코드 예시 (Java - Servlet Filter를 이용한 기본적인 접근 제어)
웹 애플리케이션에서는 Servlet Filter나 Spring Security Interceptor 등을 사용하여 특정 URL 패턴에 대한 접근 권한을 검사할 수 있습니다.
취약한 코드 (권한 검사 누락):
// AdminServlet.java
// 관리자 기능 서블릿이지만, 접근 권한 검사 로직이 없음
public class AdminServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 인증 여부만 확인하거나, 아예 확인하지 않고 관리자 기능 수행 (취약!)
performAdminTask();
// ...
}
}
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class AdminAuthFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false); // 세션 가져오기
String userRole = null;
if (session != null) {
userRole = (String) session.getAttribute("userRole"); // 세션에서 역할 정보 확인
}
// 역할이 'admin'이 아니면 접근 거부
if (!"admin".equalsIgnoreCase(userRole)) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied"); // 403 Forbidden
return; // 요청 처리 중단
}
// 관리자 역할이 확인되면 다음 필터 또는 서블릿으로 요청 전달
chain.doFilter(request, response);
}
// init() and destroy() methods omitted for brevity
}
// web.xml 또는 @WebFilter 어노테이션을 사용하여 이 필터를 관리자 페이지 URL 패턴(/*/admin/* 등)에 매핑해야 함
Python(Django/Flask Decorators, Middleware), C#(ASP.NET Core Authorization Policies/Filters), JavaScript(Node.js Middleware) 등 다른 웹 프레임워크에서도 유사한 방식으로 요청 처리 전에 권한을 검증하는 메커니즘을 제공합니다.