🎚️ 신뢰되지 않은 입력값 기반 보안결정 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 서버에 대해서만 동작하며 실제 시스템에 접근하지 않습니다.