애플리케이션 보안

인증 기초

meellon 2026. 6. 21. 08:00

학습 목표

인증(Authentication)인가(Authorization) 를 구분할 수 있다.

세션·쿠키 기반 로그인 흐름을 설명할 수 있다.

비밀번호를 평문 저장하지 않는 이유와 솔트·해싱 원칙을 설명할 수 있다.

쿠키 속성(HttpOnly, Secure, SameSite)이 세션 탈취 방어에 어떻게 쓰이는지 설명할 수 있다.

문제 상황

  • DB 유출 후 users.password 컬럼이 그대로 노출됐다
    • 평문이면 즉시 계정 탈취, 다른 사이트에서도 재사용 공격
  • 로그인은 되는데 XSS 한 줄로 document.cookie가 털린다
    • 세션 ID가 JS에서 읽히면 인증 우회
  • HTTP로 로그인 폼을 보냈다
    • TLS 없이 credential이 네트워크에 노출
  • "세션"과 "JWT"를 같은 말로 쓴다
    • 저장 위치·검증 주체·로그아웃 방식이 다른데 설계가 꼬인다

TLS로 전송 구간은 봤다. 이번 편은 서버가 사용자를 어떻게 기억하고, 비밀번호를 어떻게 보관하는지다.

1. 인증이란

인증 — "너 누구야?"를 확인하는 과정.

단계 질문
Identification 누구라고 주장? username, email
Authentication 증명했나? password, OTP, WebAuthn
Authorization 뭘 할 수 있나? RBAC, resource owner check
  • TLS는 전송 기밀성·서버 인증
  • 앱 인증은 사용자 신원 확인 — 계층이 다르다

2. 세션 기반 인증

가장 흔한 웹 패턴. 로그인 성공 후 서버가 세션을 만들고, 클라이언트는 세션 ID만 들고 다닌다.

  1. POST /login — username + password (HTTPS)
  2. 서버 — credential 검증, 서버 측 세션 저장소에 세션 생성
  3. 응답 — Set-Cookie: session_id=...; HttpOnly; Secure; SameSite=Lax
  4. 이후 요청 — 쿠키의 session_id로 사용자 식별
구성 역할
Session store Redis, DB, in-memory — session_id → user_id, expiry
Session ID 예측 불가능한 랜덤 값 (UUID, crypto random)
Cookie 브라우저가 자동으로 붙이는 전달 수단
  • 로그아웃 — 서버에서 세션 삭제 + 쿠키 만료
  • 서버 상태 — 세션 수·무효화를 서버가 통제 (JWT와 대비, 다음 편)

3. 쿠키 보안 속성

세션 ID는 비밀번호와 같은 비밀이다. 쿠키 설정이 방어선이다.

속성 효과
HttpOnly JavaScript document.cookie 접근 차단 — XSS 완화
Secure HTTPS에서만 전송
SameSite Strict/Lax/None — CSRF 완화 (CSRF는 이후 편)
Path / Domain 전송 범위 최소화
Set-Cookie: session_id=s%3A...; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=3600
  • SameSite=NoneSecure 필수
  • 서브도메인 공유(Domain=.example.com)는 범위를 넓힌다 — 필요할 때만

4. 비밀번호 저장 — 절대 평문 금지

유출은 언제든 일어날 수 있다. 저장 형식이 마지막 방어선이다.

하면 안 되는 것

  • 평문 저장
  • 단순 MD5/SHA-256 한 번만 (레인보우 테이블·GPU 크랙)
  • 모든 사용자 동일 솔트

해야 하는 것

요소 설명
Salt 사용자마다 랜덤 — 동일 비밀번호도 다른 해시
Slow hash bcrypt, scrypt, Argon2 — brute-force 비용 증가
Work factor CPU/메모리 비용 파라미터 — 주기적 상향
# 개념 예시 (Python passlib / bcrypt)
import bcrypt
salt = bcrypt.gensalt(rounds=12)
stored = bcrypt.hashpw(password.encode(), salt)
# 로그인 시 bcrypt.checkpw(password.encode(), stored)
  • Pepper — 앱 전역 비밀을 추가 (HSM/Vault에 보관, DB와 분리)
  • 비밀번호 정책만으로는 부족 — 저장 방식이 핵심

5. 인증 실패와 fail secure

보안 원칙과 연결한다.

상황 나쁜 동작 권장
잘못된 비밀번호 "user not found" vs "wrong password" 구분 동일 메시지 — 계정 열거 방지
로그인 API 장애 인증 스킵 503 · fail closed
세션 만료 무한 연장 재로그인 요구
brute force 무제한 시도 rate limit, lockout, CAPTCHA
HTTP/1.1 401 Unauthorized
{"error": "invalid credentials"}
  • 성공/실패 로그는 보안 감사에 필요 (PII 마스킹은 이후 편)

6. 세션 vs 토큰 (미리보기)

  세션 (쿠키) 토큰 (JWT 등)
상태 서버 저장 often stateless
로그아웃 서버에서 즉시 무효화 만료·블록리스트 설계 필요
적합 전통 웹, BFF SPA, 모바일 API
XSS HttpOnly로 완화 localStorage 저장 시 위험

다음 편부터 JWT·OAuth로 확장한다. 세션 기초 없이 토큰만 쓰면 설계가 얕아진다.

7. 정리

  • 인증은 사용자 신원 확인 — TLS와 별개 계층
  • 세션 ID는 서버가 발급·검증, 쿠키는 전달 수단
  • HttpOnly, Secure, SameSite로 쿠키 보호
  • 비밀번호는 솔트 + 느린 해시 — 평문·단순 해시 금지
  • fail secure — 불확실하면 거부

다음에 다룰 것

  • JWT
  • 구조, 서명, 만료, 저장 위치 트레이드오프

해당 내용은 OWASP Authentication Cheat Sheet 및 OWASP Password Storage Cheat Sheet 를 기반으로 합니다.

'애플리케이션 보안' 카테고리의 다른 글

OAuth 2.0  (0) 2026.06.23
JWT  (0) 2026.06.22
TLS 심화  (0) 2026.06.20
보안 원칙  (0) 2026.06.19
보안 오리엔테이션  (0) 2026.06.18