교차 검증의 맹점 - OWASP에서 배운 보안 설계 관점

교차 검증의 맹점 - OWASP에서 배운 보안 설계 관점

교차 검증 플러그인 4축에 보안 관점이 빠져 있었습니다. OWASP Top 10을 도구 영역과 판단 영역으로 분류하고, 기존 축에 보안 설계 질문을 최소한으로 추가한 과정을 기록합니다.

교차 검증의 맹점 - OWASP에서 배운 보안 설계 관점

TL;DR
교차 검증 플러그인을 운영하면서 OWASP Top 10을 접했습니다. 4축 어디에도 보안 관점이 없다는 맹점을 발견했습니다.
OWASP 10개 항목을 “도구가 잡는 영역”과 “개발자의 판단이 필요한 영역”으로 분류한 뒤, 기존 축에 보안 설계 질문을 최소한으로 추가했습니다. 독립 축 신설은 하지 않았고, 그 판단의 근거도 기록합니다.


들어가며

이전 글에서 교차 검증 체계를 플러그인으로 구현하고, 실전에서 검증했습니다. 이번 글은 그 도구를 쓰다가 발견한 맹점(보안 관점의 부재)을 기록합니다.

OWASP Top 10을 처음 제대로 읽었을 때, 한 가지가 눈에 들어왔습니다.

A04: Insecure Design (2021년에 새로 추가된 항목입니다.)

“An insecure design cannot be fixed by a perfect implementation.” OWASP A04:2021 소개문

보안 도구는 구현 결함은 잡지만, 설계 자체가 안전하지 않으면 아무리 구현을 잘 고쳐도 소용없다는 뜻입니다.

이것을 읽는 순간, 교차 검증 플러그인의 4축을 떠올렸습니다.

검증 질문
의사결정왜 이 선택인가?
설계엣지 케이스는?
문서읽는 사람이 이해할 수 있는가?
구현코드가 설계를 반영하는가?

4개의 축 어디에도 “이 설계가 공격에 안전한가?”라는 질문이 없었습니다.

1. 맹점의 발견

교차 검증 플러그인은 “기존 도구가 잡을 수 없는 의미적 판단에 집중한다”를 핵심 원칙으로 삼고 있습니다. lint가 잡는 코드 스타일, test가 잡는 동작 오류, 정적 분석 도구(SAST)가 잡는 SQL 인젝션, 이런 것은 교차 검증의 영역이 아닙니다.

그런데 보안에는 도구가 잡을 수 없는 영역이 분명히 존재합니다.

  • “이 API가 인증 없이 공개되어야 하는 이유는 무엇인가?”
  • “인증 서버가 다운되면 요청을 거부할 것인가, 허용할 것인가?”
  • “이 데이터가 로그에 평문으로 남아도 되는가?”

이 질문들은 SAST나 동적 분석 도구(DAST)로 답할 수 없습니다. 개발자가 설계 단계에서 의식적으로 판단해야 하는 영역입니다. 그리고 이것은 교차 검증이 원래 다루겠다고 선언한 영역, “의미적 판단”과 정확히 겹칩니다.

문제는 교차 검증이 이 영역을 완전히 무시하고 있었다는 것입니다.

2. OWASP Top 10을 교차 검증의 눈으로 분류하기

맹점을 발견했다고 바로 고칠 수는 없습니다. 교차 검증의 핵심 원칙은 “기존 도구와 중복하지 않는다”입니다. OWASP 10개 항목 전부를 교차 검증에 넣으면 이 원칙을 위반합니다.

먼저 분류가 필요합니다: OWASP 10개 중 어떤 것이 도구의 영역이고, 어떤 것이 개발자 판단의 영역인가?

도구가 잡을 수 있는 영역 (교차 검증이 다루지 않는 것)

OWASP 항목왜 도구의 영역인가대표 도구
A03: Injection (인젝션)SQL 인젝션, XSS 등은 코드 패턴으로 탐지합니다. 파라미터화된 쿼리를 쓰는지 여부는 정적 분석으로 판별 가능합니다.Semgrep, SonarQube, CodeQL
A05: Security Misconfiguration (보안 설정 오류)디버그 모드 활성화, 기본 비밀번호 사용 등은 규칙 기반으로 정확히 탐지됩니다.Checkov, trivy
A06: Vulnerable Components (취약한 컴포넌트)의존성 버전과 CVE 데이터베이스 비교는 완전히 자동화된 영역입니다.Dependabot, Snyk
A10: SSRF (서버 측 요청 위조)URL 화이트리스트, 내부 IP 차단 등은 패턴 기반 탐지가 가능합니다. 다만 네트워크 세그멘테이션 같은 아키텍처 수준 방어는 설계 판단에 가깝습니다.Semgrep 커스텀 규칙

이 4개를 교차 검증에 넣으면 SAST/DAST와 중복됩니다. 넣지 않습니다.

개발자의 판단이 필요한 영역 (교차 검증이 다뤄야 하는 것)

OWASP 항목왜 도구가 못 잡는가교차 검증의 어떤 축과 연결되는가
A01: Broken Access Control (접근 제어 실패)“이 사용자가 이 데이터에 접근할 수 있어야 하는가?”는 비즈니스 정책의 문제입니다. SAST는 @PreAuthorize 어노테이션이 있는지는 확인하지만, 그 안의 표현식이 비즈니스 요구사항과 맞는지는 판단할 수 없습니다.축 2(설계) + 축 4(구현)
A04: Insecure Design (안전하지 않은 설계)OWASP가 2021년에 이 항목을 신설한 이유 자체가 “설계 결함은 도구로 잡을 수 없다”는 인식입니다. 위협 모델, 신뢰 경계 정의는 본질적으로 사람의 판단이 필요합니다.축 1(의사결정) + 축 2(설계)
A07: Auth Failures (인증 실패)세션 타임아웃 시간, 다중 인증(MFA) 적용 범위, 비밀번호 정책의 적절성은 서비스 맥락에 따라 다릅니다. “15분 타임아웃이 이 서비스에 적절한가?”는 도구가 답할 수 없습니다.축 1(의사결정)
A08: Data Integrity Failures (데이터 무결성 실패)CI/CD 파이프라인 설계, 외부 서비스 신뢰 여부 등은 아키텍처 의사결정입니다.축 1(의사결정) + 축 2(설계)
A09: Logging Failures (로깅 실패)“어떤 이벤트를 기록해야 하는가?”는 위협 모델에서 나오는 설계 판단입니다. 로깅 프레임워크 설정은 기계적이지만, 감사 로그 설계(무엇을, 왜, 어디까지)는 의미적 판단입니다.축 2(설계) + 축 4(구현)

A02 (암호화 실패)는 경계선에 있습니다

약한 알고리즘(MD5, SHA1) 사용이나 하드코딩된 키는 SAST가 탐지합니다. 그러나 “이 데이터가 암호화 대상인가?”, “전송 중 보호와 저장 시 보호 중 어디까지 필요한가?”는 데이터 분류 판단입니다. 기계적 부분은 도구에 맡기고, 데이터 분류 판단만 교차 검증에 포함합니다.

3. 비판적 평가 - 넣는 것이 정말 옳은가?

맹점을 발견하고 분류를 마쳤습니다. 그런데 한 발 물러서야 합니다. “넣을 수 있다”와 “넣어야 한다”는 다른 질문입니다.

선택지 세 가지

선택지설명
A: 5축 신설 (보안 축 추가)의사결정·설계·문서·구현·보안
B: 기존 축 보강 (각 축에 보안 질문 추가)4축 유지, 각 축의 검증 포인트에 보안 관점 추가
C: 프로필에만 제공 (플러그인 코어 변경 없음)customChecks로 프로젝트별 보안 질문 설정

선택지 A를 기각한 이유

정체성이 흔들립니다. “4축 교차 검증”이라는 핵심 서사가 깨집니다. 이미 조건부 5축(아키텍처)이 존재하는 상태에서 보안까지 추가하면 6축이 됩니다. 숫자 자체가 의미를 잃기 시작합니다.

범위 팽창의 선례가 됩니다. 보안을 독립 축으로 넣으면 다음은 성능? 접근성? 축 추가의 기준이 불명확해집니다.

아키텍처 축과 경계가 모호합니다. 헥사고날 아키텍처의 “포트 추상화 경계”를 검증하는 것과 보안의 “신뢰 경계”를 검증하는 것은 구조적으로 같은 질문입니다. 별도 축으로 분리하면 같은 것을 두 곳에서 묻게 됩니다.

선택지 C만으로 부족한 이유

기본값이 없으면 보안이 빠집니다. 프로필을 만들지 않은 프로젝트에서는 보안 질문이 전혀 나오지 않습니다. 보안은 “의식적으로 켜는 것”이 아니라 “기본적으로 켜져 있고 의식적으로 끄는 것”이어야 합니다.

프로필에만 의존하면, 결국 대부분의 프로젝트에서 비슷한 보안 질문을 복사해서 붙여넣게 됩니다. 그것은 기본값에 포함되어야 할 것을 사용자에게 떠넘긴 것입니다.

선택지 B를 택한 이유

플러그인의 정체성을 유지합니다. “4축 교차 검증”이라는 핵심 서사가 그대로입니다. 보안이라는 새로운 관심사가 아니라, 기존 축이 놓치고 있던 관점을 채우는 것입니다.

자연스럽게 들어갑니다. 위 분류에서 보았듯이, A01·A04·A07·A08·A09는 이미 존재하는 축의 검증 포인트를 확장하는 것으로 커버됩니다. 억지로 끼워넣는 것이 아닙니다.

프로젝트별 심화는 여전히 프로필로 합니다. 금융 서비스의 보안 체크리스트와 내부 도구의 보안 체크리스트는 다릅니다. 기본값으로 최소한의 보안 질문을 넣고, 깊이가 필요하면 프로필의 customChecks로 확장합니다.

4. 범위 팽창을 막는 기준

보안을 넣었으니 다음은 성능? 접근성? 이 유혹을 막으려면 기준이 필요합니다.

“이 관점이 빠졌을 때, 기존 4축이 간접적으로라도 해당 결함을 발견할 수 있는가?”

이 질문으로 걸러봅니다.

관점기존 4축이 간접적으로 커버하는가?판정
보안아니오. 4축 어디에서도 “공격에 안전한가?”를 묻지 않음보강 필요
성능예. 축 2(설계)의 “확장성/변경 용이성에 대한 고려”가 간접 커버보강 불필요
접근성부분적. 축 3(문서)의 “대상 독자가 이해할 수 있는가?”가 일부 커버보강 불필요
규정 준수아니오. 그러나 이것은 법무/컴플라이언스 팀의 영역이지 개발 도구의 영역이 아님영역 밖

보안이 이 기준을 통과하는 이유는 명확합니다. 현재 4축의 질문 중 단 하나도 “이 결정이 보안에 어떤 영향을 미치는가?”를 묻지 않습니다.

5. 실제 변경 - 무엇을 추가했는가

축 1 (의사결정)에 추가한 질문

질문OWASP 연결
“이 선택이 외부 공격에 노출되는 범위를 넓히는가? 그 비용을 인지하고 수용하는가?”A04, A08
“인증/인가 방식의 선택 근거는? (예: API 키 vs OAuth, 역할 기반(RBAC) vs 속성 기반(ABAC))”A07

기능 추가나 API 공개 같은 의사결정은 편의성을 높이지만 동시에 공격 가능 지점을 늘립니다. 현재 축 1은 “트레이드오프를 명시했는가”를 묻지만, 보안 비용이 빠져 있었습니다.

축 2 (설계)에 추가한 질문

질문OWASP 연결
“외부에서 들어오는 입력을 신뢰하는 근거는? 시스템 경계를 넘어올 때 검증 단계가 있는가?”A01, A04
“실패 시 보안 상태는? 인증/인가 서비스가 다운되면 요청을 거부하는가, 허용하는가?”A04
“이 데이터의 민감도는? 보호 수준이 그에 맞는가?”A02

프로그램의 안쪽과 바깥쪽 사이에는 “여기부터는 믿을 수 없는 데이터”라는 경계가 있습니다. 이 경계를 의식하지 않으면 외부 입력이 내부 로직을 오염시킬 수 있습니다.

축 4 (구현)에 추가한 질문

질문OWASP 연결
“다른 사용자의 데이터에 접근할 때 소유권/권한을 확인하는 코드가 있는가?”A01
“보안 관련 이벤트(로그인 실패, 권한 거부, 비정상 접근)가 기록되는가?”A09

OWASP 1위 항목(접근 제어 실패)의 가장 흔한 원인은 단순합니다. API에서 /users/123/profile을 호출할 때 “123이 정말 요청자의 데이터인가?”를 확인하지 않는 것입니다.

추가하지 않은 것

축 3(문서)에는 보안 질문을 추가하지 않았습니다. “보안 가정이 문서화되어 있는가?”라는 질문을 넣을 수도 있었지만, 이것은 축 1(의사결정)의 “근거가 명시되어 있는가?”와 축 2(설계)의 보안 질문이 이미 커버합니다. 중복을 피했습니다.

“하지 않는 것”에 추가한 경계

  • SAST/DAST가 탐지하는 기계적 보안 취약점(SQL 인젝션, XSS 등)을 점검하지 않는다
  • 위협 모델링이나 보안 감사를 대체하지 않는다. 보안 설계를 했는지 상기시키는 역할이다

이 경계가 중요합니다. 교차 검증에 보안 질문이 있다고 해서 “보안 점검을 했다”고 생각하면 안 됩니다. 교차 검증의 보안 질문은 “보안 설계를 의식적으로 했는가?”를 상기시키는 것이지, 위협 모델링이나 보안 아키텍처 설계 그 자체가 아닙니다.

6. 보강의 가치와 한계

가치 있는 이유

교차 검증이 자기 자신에게 작동한 증거입니다.

교차 검증의 첫 번째 축은 “빠진 관점이 없는가?”를 묻습니다. 보안이 빠졌다는 발견은 바로 그 질문을 도구 자체에 적용한 결과입니다. 도구를 만들고 실전에서 돌리고, 돌리면서 도구 자신의 맹점을 발견하는 과정, 이것이 교차 검증이 설계된 대로 작동한다는 증거입니다.

OWASP가 같은 구조의 깨달음을 얻기까지 수십 년이 걸렸습니다.

OWASP는 오랫동안 구현 수준의 취약점(SQL 인젝션, XSS 등)에 집중했습니다. 그러다 2021년에 “아무리 구현을 잘 고쳐도, 설계 자체가 안전하지 않으면 소용없다”는 것을 인정하고 A04(Insecure Design)을 신설했습니다. 교차 검증이 “4축으로 검증해왔는데 보안 설계가 빠져 있었다”고 발견한 것은 규모는 다르지만 같은 구조의 깨달음입니다.

2편의 @Transactional 사례와 같은 패턴이 보안에도 적용됩니다.

2편에서 가장 설득력 있었던 사례를 떠올려 봅니다. 자동화 도구라면 “@Transactional이 없다”고 경고를 띄웠을 것입니다. 교차 검증은 “왜 없는가?”를 물었고, 의도적 설계임을 확인했습니다.

보안에서도 같은 패턴이 성립합니다:

자동화 도구의 경고교차 검증의 질문
“이 엔드포인트에 인가 체크가 없다”“이 엔드포인트가 인가 없이 공개되어야 하는가? 그 결정의 근거는?”
“이 데이터가 암호화되지 않고 저장된다”“이 데이터의 민감도 분류가 무엇인가? 평문 저장이 의도적인가?”
“로그인 실패 시 로깅이 없다”“보안 이벤트의 감사 기록이 설계에 포함되어 있는가?”

다만 한 가지 차이가 있습니다. @Transactional의 경우 “있어야 하는 곳”이 비교적 명확합니다(데이터를 변경하는 서비스 메서드). 보안의 경우 “인가 체크가 있어야 하는 곳”은 위협 모델에 의존합니다. 따라서 교차 검증의 보안 질문은 “여기에 체크가 필요하다”가 아니라 “여기에 체크가 필요한지 검토했는가?” 수준이어야 합니다. 한 단계 더 간접적입니다.

위험한 이유

“교차 검증을 돌렸으니 보안도 됐다”는 착각을 만들 수 있습니다.

교차 검증에 보안 질문을 추가하면, 개발자가 “보안 점검을 했다”고 생각할 수 있습니다. 그러나 이 질문들은 “보안 설계를 했는가?”를 상기시키는 것이지, 위협 모델링이나 보안 감사를 대체하지 않습니다.

위협 모델 없이 “권한 체크가 있는가?”를 물으면 “모든 곳에 체크를 넣어라”가 되어 의미 없는 잡음만 늘어납니다. 이 차이를 명시하지 않으면, 오히려 보안에 대한 잘못된 안심을 만들 수 있습니다.

체크리스트에 보안 질문을 넣는 것과 보안을 이해하는 것은 다릅니다.

이것을 인정하는 것이 중요합니다. 교차 검증에 보안 질문 7개를 추가한 것은 보안 전문성의 증거가 아닙니다. “내 도구에 보안 관점이 빠져 있다는 것을 인식했고, 보강의 범위와 한계를 명시적으로 정리했다.” 이것이 정직한 표현입니다.

마치며

교차 검증의 첫 번째 질문은 “빠진 관점이 없는가?”입니다. 보안이 빠져 있었다는 발견은, 이 질문이 도구 자체에도 유효하다는 증거입니다.

OWASP Top 10 중 4개는 도구가 잡을 수 있는 기계적 영역이고, 5개는 개발자의 판단이 필요한 의미적 영역이며, 1개(A02: 암호화 실패)는 양쪽에 걸쳐 있습니다. 교차 검증은 후자만 다룹니다. 독립 축을 만들지 않고 기존 축에 최소한의 질문을 추가한 것은, “기존 도구와 중복하지 않는다”는 원칙을 보안에도 일관되게 적용한 결과입니다.

완벽해진 것은 아닙니다. 교차 검증의 보안 질문은 위협 모델링의 자리를 대신하지 못합니다. 그러나 “보안 설계를 의식적으로 했는가?”를 매번 상기시키는 것, 이 정도가 이 도구가 할 수 있는, 그리고 해야 하는 역할입니다.

이 글은 Claude와 함께 작업했습니다.

This post is licensed under CC BY 4.0 by the author.