입력 보안과 웹 보안
- 6.1 입력 유효성 검사
- 6.2 문자열 취약점
- 6.3 인젝션 취약점
- 6.4 인젝션 공격의 완화 조치
- 6.5 프레임워크 기반 구축
- 6.6 웹 보안 모델
- 6.7 일반적인 웹 취약점
- 6.8 기타 취약점과 완화 방법
보안에서 가장 많이 반복되는 말 — "절대로 사용자 입력을 신뢰하지 마라." 입력 보안의 원리부터 웹이라는 전장까지 한 번에 보자.
SQL 인젝션을 보면 명확해. "SELECT * FROM users WHERE name = '" + username + "'"에서 username에 ' OR '1'='1을 넣으면 모든 사용자 정보가 튀어나와. 사용자가 제공한 데이터가 SQL 코드로 해석된 거지. 커맨드 인젝션, LDAP 인젝션, 템플릿 인젝션(SSTI) — 형태는 다 달라도 원리는 똑같아. 신뢰할 수 없는 데이터가 인터프리터에게 코드의 일부로 전달되는 것. OWASP Top 10에서 오랫동안 1위 한 이유가 있어.
그래서 방어도 그 원리에서 출발해야 해. 매개변수화된 쿼리가 SQL 인젝션 방어의 정석인 이유는, 쿼리 구조와 데이터를 아예 분리해서 데이터베이스 엔진에 전달하니까 데이터가 절대 코드로 해석될 수가 없어. 2026년이든 2036년이든, 문자열 결합으로 SQL을 만들지 마라 — 이건 영원히 유효한 규칙이야.
입력 검증은 그 위에 쌓는 추가 방어선이야. 허용 목록(Allowlist) 방식이 핵심이고, 차단 목록(Blocklist)은 우회가 너무 쉬워서 권장 안 돼. 타입 검사, 범위 검사, 길이 제한, 정규화 후 검증 — 이런 것들. 그리고 클라이언트 측 검증은 UX용이지, 보안은 무조건 서버 측이야. 문자열 처리에서도 함정이 많은데, C의 strcpy 같은 경계 검사 안 하는 함수, 포맷 스트링 공격(printf(user_input)), UTF-8 인코딩 트릭, 널 바이트 인젝션 — 전부 데이터가 의도와 다르게 해석되는 문제야.
인젝션 방어를 개별 개발자의 주의력에 의존하면 실패한다. 프레임워크가 안전한 기본값을 제공하고, 위험한 건 의도적으로 opt-in해야 하는 구조를 만들어야 해. React가 JSX에서 기본적으로 HTML 이스케이핑을 하잖아. dangerouslySetInnerHTML을 의도적으로 쓰지 않는 한 XSS가 안 생겨. Django의 ORM은 기본이 매개변수화된 쿼리고, 템플릿 엔진들은 자동 이스케이핑이 기본이야. "안전하지 않은 걸 하려면 명시적으로 선택"하게 만드는 이 설계가 핵심이야.
그 위에 웹 보안의 근간인 **동일 출처 정책(SOP)**이 있어. 프로토콜 + 호스트 + 포트가 같아야 같은 출처고, 다른 출처의 DOM 접근이나 AJAX 요청은 차단돼. CORS로 선택적으로 풀 수 있는데, Access-Control-Allow-Origin: *을 인증 필요한 API에 쓰면 안 돼. 쿠키의 Secure, HttpOnly, SameSite 속성, CSP로 인라인 스크립트 차단 — 이런 게 SOP를 보완하는 레이어들이야.
이 모델을 이해해야 XSS와 CSRF가 왜 발생하는지 납득이 돼. XSS는 공격자의 JavaScript가 피해자 브라우저에서 실행되는 건데, 세션 쿠키 탈취부터 키로깅까지 사용자가 할 수 있는 모든 걸 공격자가 할 수 있게 만들어. 저장형이 가장 위험하고, 방어는 출력 이스케이핑 + CSP. CSRF는 로그인 상태의 쿠키를 이용해서 공격자 사이트가 원래 사이트에 요청을 보내는 건데, CSRF 토큰 + SameSite 쿠키로 막아. 클릭재킹은 투명한 iframe으로 덮어씌우는 거고, X-Frame-Options로 방어하고. 오픈 리다이렉트, 세션 고정 공격 같은 것도 마찬가지 — 결국 전부 브라우저의 신뢰 모델을 악용하는 공격이야.
보안 헤더(HSTS, X-Content-Type-Options, Referrer-Policy), CDN 스크립트의 SRI 해시 검증, API의 속도 제한과 에러 정보 노출 방지 — 이런 것들이 심층 방어 레이어를 구성해. 하나하나는 완벽하지 않지만, 겹겹이 쌓이면 공격이 훨씬 어려워져.
정리
6장 읽고 기억할 거 세 가지:
- 인젝션의 본질은 데이터와 코드의 경계 붕괴야. 매개변수화된 쿼리로 구조와 데이터를 분리하고, 허용 목록 기반으로 검증해. 문자열 결합으로 쿼리 만들지 마.
- 프레임워크의 안전한 기본값이 웹 보안의 출발점이다. 위험한 동작을 하려면 명시적으로 opt-in해야 하는 설계가 핵심이고, SOP/CORS/CSP가 그 위의 방어 레이어야.
- 심층 방어가 답이야. 보안 헤더, SRI, 쿠키 속성, 속도 제한 — 하나하나는 완벽하지 않지만 겹겹이 쌓으면 공격 난이도가 기하급수적으로 올라가.