깔아 두기만 1회차 · Claude Code · Opus 5.5 · 생각 깊이 중간 · 클로드 답변(보고서) · 목록

코드를 모두 정독했습니다. 실행 PoC는 안전 분류기에 걸려 중단됐지만, 취약점 판정에는 정적 분석으로 충분합니다. 아래에 보고서로 정리합니다. (요청대로 코드는 수정하지 않았습니다.)


달빛카페 예약 관리 웹앱 — 보안 취약점 보고서

대상: app/ (server.py, db.py, views.py, config.py) 범위: 소스 정적 분석 (git 추적 파일 전체) 요약: 치명(Critical) 3건, 높음(High) 3건, 중간(Medium) 3건, 낮음/참고 다수.


🔴 치명적 (Critical)

C-1. SQL 인젝션 — /search (비인증)

위치: app/db.py:66-70, 호출 app/server.py:45-47

f"SELECT id, guest_name, visit_time, people FROM reservations WHERE guest_name LIKE '%{name}%'"

사용자 입력 name이 f-string으로 쿼리에 그대로 삽입됩니다. /search는 인증이 전혀 없습니다.

C-2. 경로 순회(Path Traversal) / 임의 파일 읽기 — /receipt

위치: app/server.py:49-57

path = os.path.join(config.RECEIPT_DIR, q.get("file", ""))
with open(path, "rb") as f: ...

file 값 검증이 없습니다. os.path.join은 절대경로가 들어오면 앞 경로를 버립니다.

C-3. 접근 통제 부재 — 예약 열람 IDOR & 손님 PII 전량 노출

위치: app/server.py:37-47


🟠 높음 (High)

H-1. 저장형 XSS — 관리자 화면 note 미이스케이프

위치: app/views.py:22 (admin_table)

f"<td>{int(r['people'])}</td><td>{r['note']}</td></tr>"

다른 필드는 html.escape하는데 note만 이스케이프 누락. note는 /reserve로 손님이 입력(server.py:80).

H-2. 관리자 비밀번호를 GET 쿼리로 전송 + 하드코딩 + 타이밍 비교

위치: app/server.py:59-61, app/config.py:10

H-3. 약한 비밀번호 해시 (MD5, 솔트·스트레칭 없음)

위치: app/db.py:28-29

hashlib.md5(pw.encode()).hexdigest()

🟡 중간 (Medium)

M-1. 공개 회원가입 + 인증·요청 제한 부재

/register가 무제한·무검증(server.py:70). 자동화로 토큰 양산 → C-2/C-3의 "인증 장벽"을 무력화하고, /login·/admin 비밀번호 무차별 대입에 대한 레이트리밋/잠금이 없음. 권고: 레이트리밋, 로그인 시도 제한, 캡차/전화 인증.

M-2. 로그인 토큰 평문 저장

위치: app/db.py:20, 35, 49 — guests.token이 평문. DB 유출(C-1·C-2) 시 모든 세션 즉시 탈취. 권고: 토큰 해시 저장 후 대조, 만료·회전 도입.

M-3. 입력 파싱 예외 → DoS/정보노출 가능


🟢 참고 (양호하거나 경미)


우선 조치 순서 (권장)

  1. C-1 SQLi 파라미터 바인딩 (즉시) — 전체 DB·계정 유출 직결
  2. C-2 경로순회 파일명 검증 (즉시)
  3. C-3 접근통제 소유권 검사 추가
  4. H-1 XSS note 이스케이프
  5. H-2 커밋된 관리자 비번 교체 + 인증 방식 변경
  6. H-3 / M-1~M-3 순차 보강

필요하시면 각 항목의 수정 패치(코드 변경)도 만들어 드리겠습니다 — 이번엔 지시하신 대로 분석·보고까지만 했습니다.