테마
01. 웹 위협 모델과 시큐어 코딩 원칙
시큐어 코딩은 취약점 이름을 나열하는 작업이 아니라, 웹 애플리케이션이 신뢰하지 말아야 할 경계를 코드에서 분명히 세우는 작업이다.
학습 목표
- 웹 애플리케이션에서 어떤 경계가 깨질 때 보안 문제가 발생하는지 설명할 수 있다.
- OWASP Top 10 2021을 웹 개발자 관점에서 읽을 수 있다.
- 시큐어 코딩을 구현 단계만의 문제가 아니라 설계와 운영까지 포함한 과정으로 이해할 수 있다.
Secure by Default와Defense in Depth가 왜 중요한지 설명할 수 있다.
1. 왜 웹 개발자가 보안을 알아야 할까?
원문 강의가 강조한 핵심은 맞다.
웹 서비스는 여전히 가장 넓은 공격 표면 중 하나이고, 기능만 빠르게 구현한 뒤 나중에 보안을 덧붙이는 방식은 비용이 크다.
다만 지금 기준에서 더 정확하게 말하면 다음과 같다.
- 웹은 외부 사용자가 직접 닿는 진입점이다
- 브라우저, API, 파일 처리, 외부 연동, 쿠키, 세션이 한 번에 만난다
- 현대 공격은 단일 취약점 하나보다
권한 체크 부재 + 민감 정보 노출 + 로그 미비같은 조합으로 커진다
즉, 시큐어 코딩은 "해킹 기술을 많이 아는 것"보다 어떤 입력을 신뢰하지 말아야 하는지, 어떤 연산을 서버가 직접 검증해야 하는지를 정확히 아는 문제에 가깝다.
2. 웹 애플리케이션의 신뢰 경계
웹 보안의 대부분은 위 그림에서 경계를 넘는 순간 발생한다.
- 사용자 입력을 검증 없이 로직이나 쿼리에 넘길 때
- 로그인만 확인하고 권한은 확인하지 않을 때
- 파일 경로나 외부 URL을 그대로 사용할 때
- 민감 동작을 로그나 알림 없이 처리할 때
3. OWASP Top 10 2021을 개발자 시선으로 읽기
| 분류 | 개발자 관점에서 보면 | 자주 나오는 실수 |
|---|---|---|
A01 Broken Access Control | 로그인 여부가 아니라 자원 접근 권한 검증 문제 | URL 숨기기만 하고 서버 검증 생략 |
A02 Cryptographic Failures | 민감정보 저장·전송·키 관리 문제 | 비밀번호를 약한 해시로 저장 |
A03 Injection | 입력이 명령, 쿼리, 템플릿으로 해석되는 문제 | 문자열 결합으로 SQL/쉘 명령 생성 |
A04 Insecure Design | 구현 전 설계 단계의 통제 부재 | 관리자 기능에 재인증 없음 |
A05 Security Misconfiguration | 기본값, 헤더, 에러 메시지, 권한 설정 문제 | 디버그 모드 운영 반영 |
A06 Vulnerable and Outdated Components | 라이브러리, 프레임워크, 런타임 버전 문제 | 보안 업데이트 미적용 |
A07 Identification and Authentication Failures | 계정 보호와 세션 수명 관리 문제 | 세션 재생성 누락 |
A08 Software and Data Integrity Failures | 공급망과 배포 무결성 문제 | 검증 없는 스크립트 로딩 |
A09 Security Logging and Monitoring Failures | 침해 징후를 놓치는 문제 | 인증 실패, 권한 실패 로그 미기록 |
A10 Server-Side Request Forgery | 서버가 대신 요청할 수 있다는 점을 악용 | 사용자 입력 URL을 서버가 그대로 호출 |
원문에는 SQL 인젝션, XSS, CSRF, 파일 업로드, URL 접근 제한이 중심이었는데, 현재는 Broken Access Control과 SSRF 비중이 더 크다는 점을 같이 봐야 한다.
4. 시큐어 코딩은 개발 생애주기 전체 문제다
취약점은 구현 단계에서만 생기지 않는다.
- 요구사항에서 관리자 재인증이 빠질 수 있다
- 설계에서 객체 소유권 검증을 빼먹을 수 있다
- 구현에서 ORM을 쓰면서도 Raw SQL을 섞을 수 있다
- 리뷰에서 위험한 API 사용을 놓칠 수 있다
- 운영에서 오래된 라이브러리를 계속 배포할 수 있다
그래서 시큐어 코딩은 함수 몇 개 추가하는 작업이 아니라 **SSDLC(Secure Software Development Lifecycle)**의 일부로 보는 것이 맞다.
특히 현재는 애플리케이션 코드만 보는 것으로 부족하다.
- SCA(Software Composition Analysis)로 의존성 취약점을 점검한다
- CI에서
npm audit,composer audit,pip-audit, Dependabot 같은 흐름을 기본 게이트로 둔다 - 필요하면 SBOM까지 연결해 배포 자산 구성을 추적한다
5. 현대적인 시큐어 코딩 원칙
5.1 Secure by Default
프레임워크가 기본으로 막아주는 기능을 끄지 않는 것이 첫 번째 방어다.
- ORM의 파라미터 바인딩 사용
- 템플릿 엔진의 자동 이스케이프 유지
- CSRF 보호 기본값 유지
- HTTPS 강제와 보안 헤더 기본 적용
5.2 Defense in Depth
한 줄짜리 만능 방어는 없다.
- 입력 검증
- 출력 인코딩
- 프레임워크 기본 기능
- 권한 검증
- 헤더 정책
- 로그와 알림
이 여러 층이 겹쳐야 사고를 줄일 수 있다.
5.3 Fail Closed
검증에 실패하면 허용하는 것이 아니라 차단해야 한다.
- 파일 형식을 확신할 수 없으면 업로드 거부
- 권한을 확인할 수 없으면 접근 거부
- 토큰이 이상하면 다시 인증 요구
5.4 Least Privilege
DB 계정, 파일 저장 경로, 관리자 기능 모두 최소 권한으로 제한한다.
- 읽기 전용 작업은 읽기 전용 권한 사용
- 업로드 디렉터리는 실행 권한 제거
- 운영 계정과 관리자 계정 분리
6. 원문을 현재 기준으로 읽을 때 주의할 점
원문은 학습 목적 자료로 가치가 있지만, 아래 항목은 그대로 따라 하면 안 된다.
| 원문 맥락 | 현재 기준 해석 |
|---|---|
APM Setup으로 취약 실습 환경 구성 | 현재는 유지되지 않는 오래된 실습 환경이다. 목적형 교육 플랫폼을 쓰는 편이 낫다. |
magic_quotes_gpc 토글 | 이미 오래전에 제거된 PHP 기능이다. 역사적 배경으로만 본다. |
| 오래된 MySQL 패스워드 변경 방식 | 현재는 ALTER USER 기반이 표준이다. |
| 공격 페이로드 중심 설명 | 현대 학습 자료로 옮길 때는 방어 패턴과 코드 리뷰 포인트 중심으로 재구성해야 한다. |
7. 실습은 어디서 해야 할까?
원문처럼 로컬에 취약한 PHP 앱을 직접 깔아 두는 방식보다, 목적형 학습 환경을 쓰는 편이 안전하다.
- PortSwigger Web Security Academy
- OWASP Juice Shop
- 허가된 사내 교육 환경
반대로 피해야 할 방향은 아래와 같다.
- 운영 서비스나 타인 시스템에서 실험
- 오래된 취약 환경을 인터넷에 노출
- 공격 절차를 그대로 자동화해 재사용
8. PR 리뷰 체크리스트
- 입력값이 신뢰되지 않는다는 전제가 코드에 반영되어 있는가
- 로그인 확인과 권한 확인이 분리되어 있는가
- 쿼리, 템플릿, 파일 경로, 외부 URL을 문자열 결합으로 만들지 않는가
- 보안 기능이 프레임워크 기본값에서 꺼져 있지 않은가
- 민감 동작에 로그, 감사 흔적, 재인증이 필요한가
- 외부 라이브러리 버전과 보안 패치 상태를 확인했는가
핵심 정리
- 웹 보안은 신뢰 경계를 어디서 끊느냐의 문제다
- 현재 가장 중요한 축은 입력 검증만이 아니라 접근 통제와 설계 품질이다
- 시큐어 코딩은 구현 단계만의 문제가 아니라 설계, 리뷰, 운영을 포함한다
- 오래된 실습 자료는 원리를 배우는 데는 쓸 수 있지만, 구현 방식은 반드시 현재 기준으로 다시 해석해야 한다