🎚️ 신뢰되지 않은 입력값 기반 보안결정 KISA #15 · 부적절한 입력값 보안결정
서버가 권위 있는 서버 상태가 아니라 클라이언트가 제어하는 데이터(숨김 필드·쿠키·헤더)로 보안/업무 결정을 내립니다. 아래 값을 조작해 권한 상승과 가격 변조가 성공하는 것을 확인하세요.
① 취약: 클라이언트 전송값을 신뢰 VULNERABLE
시나리오를 선택하세요. 아래 값은 브라우저가 실제로 조작 가능한 데이터(숨김 입력·쿠키·요청 헤더)입니다. mock 서버는 이 값을 그대로 읽어 동작을 인가합니다. 값을 바꿔 실행하세요.
② 안전: 서버 권위 데이터 조회 SECURE
수정본은 클라이언트가 보낸 role/price를 완전히 무시합니다. 서명된 세션으로 사용자를 식별한 뒤, 서버 DB에서 권위 있는 role과 카탈로그 가격을 조회합니다. 조작된 클라이언트 값은 아무 영향이 없습니다.
③ 취약 vs 안전 코드
VULNERABLE
# Python (Flask) — 클라이언트 값으로 인가 결정
@app.post("/admin/delete")
def delete_user():
role = request.form.get("role") # 숨김필드
# 또는 request.cookies.get("role")
if role == "admin": # 클라이언트가 마음대로 admin
do_delete() # 권한 상승!
price = float(request.form["price"])# 클라이언트 가격
charge(price) # 가격 변조!
SECURE
# 서버 세션·DB 기준 권위적 조회
@app.post("/admin/delete")
def delete_user():
uid = session["uid"] # 서명된 세션
role = db.get_role(uid) # DB 가 권위
if role != "admin":
abort(403) # 위조 불가
do_delete()
pid = request.form["product_id"] # ID 만 신뢰
price = db.get_price(pid) # 가격은 서버 조회
charge(price)
방어 핵심: 클라이언트가 수정 가능한 데이터(숨김 필드·쿠키·
X-Forwarded-For 같은 헤더·JS 변수)로 인가/가격 결정을 내리지 말 것 · 신원은 서명된 서버 세션에서 도출 · role·가격·한도·소유권은 인증된 id로 서버 DB에서 조회 · 클라이언트 값은 사실이 아니라 요청으로 취급.
⚠️ 교육용 시뮬레이션입니다. 모든 요청은 페이지 내부 mock 서버에 대해서만 동작하며 실제 시스템에 접근하지 않습니다.