설명
불충분한 권한 또는 권한의 부적절한 처리(Improper Handling of Insufficient Permissions or Privileges)는 애플리케이션이 사용자에게 부여된 권한을 제대로 검증하지 않거나 권한이 없는 요청을 거부하지 않는 경우 발생하는 취약성입니다. 이는 비인가 사용자가 제한된 리소스나 기능에 접근할 수 있게 하여 보안 위험을 초래할 수 있습니다.
잠재적 영향
- 권한 상승: 비인가 사용자가 관리자 권한을 획득하여 시스템을 조작할 수 있습니다.
- 데이터 유출: 민감한 데이터가 비인가 사용자에게 노출될 수 있습니다.
- 서비스 중단: 비인가 사용자가 시스템 리소스에 접근하여 서비스가 중단될 수 있습니다.
해결 방법
- 권한 검증: 모든 중요한 기능과 리소스 접근에 대해 적절한 권한 검증을 수행합니다.
- 요청 거부: 권한이 없는 요청은 작업을 수행하기 전에 거부하고, 적절한 HTTP 오류 상태를 반환합니다. 오류 문구만 바꾸는 것으로 접근 제어를 대신할 수 없습니다.
- 보안 라이브러리 사용: Django, Flask, FastAPI 등과 같은 프레임워크에서 제공하는 인증 및 권한 부여 기능을 사용합니다.
예시
인증 설정, 세션 관리와 사용자 조회는 생략한 발췌입니다. Flask-Login은 검증된 사용자 로더와 로그인 구성이 필요하며, is_admin은 클라이언트 입력이 아닌 신뢰할 수 있는 권한 정보여야 합니다.
Django
변경 전
python
# Unsafe Django code
from django.http import HttpResponse
def view_sensitive_data(request):
if request.user.username != 'admin':
return HttpResponse("Not authorized")
# 민감한 데이터 처리 로직
return HttpResponse("Sensitive data")
변경 후
python
# Safe Django code
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required, user_passes_test
@login_required
@user_passes_test(lambda u: u.is_superuser)
def view_sensitive_data(request):
# 민감한 데이터 처리 로직
return HttpResponse("Sensitive data")
설명:
- 변경 전: 사용자 이름을 관리자 권한과 동일시합니다. 이 문자열 비교만으로 사용자 등록·이름 변경 정책과 필요한 권한을 안전하게 관리할 수 있다고 가정하지 마세요.
- 변경 후: Django의
login_required및user_passes_test데코레이터를 사용하여 적절한 권한을 가진 사용자만 민감한 데이터에 접근할 수 있도록 합니다.
Flask
변경 전
python
# Unsafe Flask code
from flask import Flask, request
app = Flask(__name__)
@app.route('/sensitive')
def view_sensitive_data():
if request.args.get('user') != 'admin':
return "Not authorized"
# 민감한 데이터 처리 로직
return "Sensitive data"
변경 후
python
# Safe Flask code
from flask import Flask, request, abort
from flask_login import login_required, current_user
app = Flask(__name__)
@app.route('/sensitive')
@login_required
def view_sensitive_data():
if not current_user.is_admin:
return abort(403)
# 민감한 데이터 처리 로직
return "Sensitive data"
설명:
- 변경 전: URL 파라미터로 전달된 사용자 이름을 검증하여 권한을 확인하며, 비인가 사용자가 민감한 데이터에 접근할 수 있습니다.
- 변경 후: Flask-Login의
login_required데코레이터와current_user객체를 사용하여 적절한 권한을 가진 사용자만 민감한 데이터에 접근할 수 있도록 합니다.
FastAPI
변경 전
python
# Unsafe FastAPI code
from fastapi import FastAPI, Request, HTTPException
app = FastAPI()
@app.get("/sensitive")
async def view_sensitive_data(request: Request):
if request.query_params.get('user') != 'admin':
return {"detail": "Not authorized"}
# 민감한 데이터 처리 로직
return {"detail": "Sensitive data"}
변경 후
python
# Safe FastAPI code
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel
app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
class User(BaseModel):
username: str
is_admin: bool
def get_current_user(token: str = Depends(oauth2_scheme)):
# 실제 토큰 검증과 사용자 조회를 구현하기 전에는 접근을 거부합니다.
raise HTTPException(status_code=401, detail="Token verification is not configured")
@app.get("/sensitive")
async def view_sensitive_data(current_user: User = Depends(get_current_user)):
if not current_user.is_admin:
raise HTTPException(status_code=403, detail="Not authorized")
# 민감한 데이터 처리 로직
return {"detail": "Sensitive data"}
설명:
- 변경 전: URL 파라미터로 전달된 사용자 이름을 검증하여 권한을 확인하며, 비인가 사용자가 민감한 데이터에 접근할 수 있습니다.
- 변경 후:
OAuth2PasswordBearer는 Bearer 토큰을 추출할 뿐 유효성을 검증하지 않습니다. 이 발췌는 검증이 구현될 때까지 접근을 거부합니다.get_current_user에서 토큰의 유효성을 검증하고 신뢰할 사용자 저장소에서 권한을 조회한 뒤에만User를 반환하도록 구현하세요.