들어가며
LLM 가드레일(#129)과 중앙 MCP 허브(#130)까지 올리고 나면 한 가지 질문이 남습니다. "AI 방어선은 올렸는데, 정작 우리 백엔드 웹 애플리케이션 자체의 보안은 어디까지 됐지?"
SQL Injection, XSS, 인증 우회, 취약한 의존성 같은 고전 취약점은 AI가 등장했다고 사라지지 않습니다. 오히려 AI가 생성한 코드에서 더 자주 등장하고, LLM 에이전트가 호출하는 내부 API가 공격 표면이 되면서 위험이 커졌습니다.
이 "고전적 웹 보안"의 사실상 표준이 OWASP(Open Worldwide Application Security Project)입니다. 오늘은 현직 백엔드 개발자가 바로 써야 할 OWASP 오픈소스 프로젝트들을 한 번에 정리합니다.
- 1부 - OWASP 조직과 주요 프로젝트 지도
- 2부 - OWASP Top 10 / API Top 10 / LLM Top 10 핵심 요약
- 3부 - Dependency-Check로 취약 라이브러리 자동 탐지(Gradle/CI)
- 4부 - ZAP으로 동적 보안 스캔 자동화
- 5부 - ASVS·Cheat Sheets·SAMM을 실무 리뷰 체크리스트로 쓰기
- 6부 - Spring Boot 적용 예시와 CI/CD 파이프라인 통합
1. OWASP가 뭐길래
OWASP는 2001년에 설립된 비영리 재단으로, 웹 애플리케이션 보안에 관한 문서·도구·표준을 전부 무료·오픈소스로 공개합니다. 회사 소속 보안팀이 없는 팀이라도 OWASP만 제대로 활용하면 "최소한의 합리적 보안" 수준은 맞출 수 있습니다.
수십 개 프로젝트가 있지만 현장에서 실제로 쓰이는 것은 몇 가지로 좁혀집니다.
| 프로젝트 | 유형 | 한 줄 용도 |
|---|---|---|
| OWASP Top 10 | 문서 | 가장 위험한 웹 취약점 10개 리스트 |
| API Security Top 10 | 문서 | REST/GraphQL 등 API 전용 Top 10 |
| LLM Top 10 | 문서 | LLM·에이전트 애플리케이션 전용 |
| ASVS | 표준 | 보안 요구사항 체크리스트(Level 1~3) |
| Cheat Sheets | 문서 | 주제별 실무 구현 가이드 |
| SAMM | 모델 | 팀/조직 보안 성숙도 평가 |
| Dependency-Check | 도구(SCA) | 라이브러리 CVE 자동 탐지 |
| ZAP | 도구(DAST) | 실행 중인 웹앱 동적 스캐닝 |
| Juice Shop | 실습 | 취약점 100여 개 심어둔 연습용 앱 |
| CRS(ModSecurity) | 룰셋 | WAF용 공통 룰셋 |
팀에 처음 도입한다면 Top 10 → Dependency-Check → ZAP → ASVS 순으로 들어오는 것이 가장 자연스럽습니다.
2. OWASP Top 10 (2021) 요약
4년 주기로 개정되며 가장 최근 안정판은 2021년 버전입니다. 2025년 개정안도 공개 리뷰 중이지만 실무 기준은 여전히 2021입니다.
| # | 항목 | 대표 사례 |
|---|---|---|
| A01 | Broken Access Control | IDOR, 권한 우회 |
| A02 | Cryptographic Failures | 평문 저장, 약한 해시 |
| A03 | Injection | SQLi, XSS, 명령어 주입 |
| A04 | Insecure Design | 비율 제한 부재, 위협 모델 부재 |
| A05 | Security Misconfiguration | 디폴트 비번, 노출된 actuator |
| A06 | Vulnerable & Outdated Components | log4shell, 오래된 라이브러리 |
| A07 | Identification & Auth Failures | 크리덴셜 스터핑, 세션 탈취 |
| A08 | Software & Data Integrity Failures | 공급망 공격, 서명 없는 업데이트 |
| A09 | Security Logging & Monitoring Failures | 감사 로그 부재 |
| A10 | SSRF | 내부 메타데이터 서버 접근 |
백엔드 개발자 관점에서 가장 자주 부딪히는 상위 3개는 A01·A03·A05입니다. 이 셋은 코드 리뷰 단계에서 잡아야 후행 비용이 없습니다.
API Security Top 10 (2023)
REST API를 쓰는 현대 백엔드라면 Top 10보다 API Top 10이 더 가까운 체크리스트입니다. OAuth 2.0/OIDC와 같이 봐야 이해가 빠릅니다.
- API1 BOLA - 객체 수준 인가 실패(
GET /users/123에 남의 id를 넣어도 됨) - API2 Broken Authentication - JWT 시크릿 노출, 리프레시 토큰 미관리
- API3 BOPLA - 속성 수준 인가 실패(
role="admin"바디 주입으로 권한 상승) - API4 Unrestricted Resource Consumption - 비율 제한·페이지네이션 부재
- API5 Broken Function Level Authorization -
/admin/*에 일반 사용자 접근 가능 - API6 Unrestricted Access to Sensitive Business Flows - 자동화된 구매·적립 악용
- API7 SSRF
- API8 Security Misconfiguration
- API9 Improper Inventory Management - v1·v2·v3 섞여 있고 v1이 인증 없음
- API10 Unsafe Consumption of APIs - 외부 API 응답을 검증 없이 신뢰
LLM Top 10 (2025)
LLM·에이전트 전용 Top 10도 정식 프로젝트로 올라왔습니다. 프롬프트 인젝션부터 민감 정보 유출까지 10개 항목으로 정리돼 있는데, 자세한 대응 코드는 이미 #129 LLM 보안 가드레일과 #130 MCP 가드레일 허브에서 다뤘습니다. 여기서는 "OWASP 문서 한 장으로 요약돼 있다" 정도만 기억해 두세요.
3. Dependency-Check - 취약 라이브러리 자동 탐지
Top 10 중 A06(취약한 컴포넌트)은 가장 자동화하기 쉬운 항목입니다. Dependency-Check가 NVD의 CVE 데이터베이스를 긁어와 프로젝트 의존성과 매칭합니다.
3-1. Gradle 플러그인 설정
// build.gradle.kts
plugins {
id("org.owasp.dependencycheck") version "10.0.4"
}
dependencyCheck {
failBuildOnCVSS = 7.0f // High 이상이면 빌드 실패
formats = listOf("HTML", "JSON")
suppressionFile = "config/owasp-suppressions.xml"
nvd {
apiKey = System.getenv("NVD_API_KEY") // 필수(2023년부터)
}
analyzers {
assemblyEnabled = false // .NET 분석 비활성
nodeAuditEnabled = true
}
}
3-2. 실행과 리포트
$ ./gradlew dependencyCheckAnalyze
$ open build/reports/dependency-check-report.html
리포트에는 CVE 번호, CVSS 점수, 영향받는 JAR, 수정 버전 정보가 나옵니다. log4shell이 터졌을 때 이 도구 하나로 수천 개 레포의 영향 범위를 30분 안에 파악한 팀이 많았습니다.
3-3. 오탐 억제 파일
CVE가 사실은 우리 코드 경로에 해당되지 않는 경우가 있습니다. 무조건 업그레이드 대신 suppress를 쓰되 반드시 notes에 이유와 재확인 일자를 남깁니다.
<!-- config/owasp-suppressions.xml -->
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
<suppress>
<notes>CVE-2024-XXXX: 서버사이드에서만 사용하며 해당 취약 코드 경로는 미사용. 2026-07 재확인 필요.</notes>
<gav regex="true">^com\.example:safe-lib:.*$</gav>
<cve>CVE-2024-XXXX</cve>
</suppress>
</suppressions>
3-4. GitHub Actions 통합
# .github/workflows/security.yml
name: security
on:
push: {branches: [main]}
schedule: [{cron: "0 5 * * *"}] # 매일 새벽 5시
jobs:
depcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with: {distribution: temurin, java-version: 21}
- name: Run Dependency-Check
env:
NVD_API_KEY: ${{ secrets.NVD_API_KEY }}
run: ./gradlew dependencyCheckAnalyze
- uses: actions/upload-artifact@v4
with:
name: depcheck-report
path: build/reports/dependency-check-report.*
일일 스케줄 실행이 핵심입니다. 새 CVE는 매일 공개되므로 어제 안전했던 라이브러리가 오늘 아침에 취약해질 수 있습니다.
4. OWASP ZAP - 동적 보안 스캐너
Dependency-Check가 "소스코드·의존성"을 본다면, ZAP(Zed Attack Proxy)은 실행 중인 웹 애플리케이션을 바깥에서 공격해 보는 DAST 도구입니다. Burp Suite의 오픈소스 대안이라고 보면 됩니다.
4-1. 베이스라인 스캔 (가장 빠른 도입)
$ docker run --rm -v $(pwd):/zap/wrk/:rw \
-t zaproxy/zap-stable zap-baseline.py \
-t https://staging.myapp.internal \
-r baseline-report.html \
-J baseline-report.json
약 2~5분 안에 기본적인 잘못된 헤더, 디렉토리 노출, 쿠키 속성 누락 등을 체크해 줍니다. CI에서 스테이징 서버를 대상으로 돌리기에 적당합니다.
4-2. API 스캔 (OpenAPI 기반)
현대 백엔드 대부분은 Swagger/OpenAPI 스펙을 노출합니다. ZAP은 이 스펙을 먹여주면 전체 엔드포인트를 자동 크롤링·공격합니다.
$ docker run --rm -v $(pwd):/zap/wrk/:rw \
-t zaproxy/zap-stable zap-api-scan.py \
-t https://staging.myapp/api/v3/api-docs \
-f openapi \
-r api-report.html
4-3. 인증이 필요한 스캔
로그인 뒤 페이지까지 보려면 컨텍스트 파일에 스크립트 인증을 정의해야 합니다.
# auth-context.yaml (자체 간략 포맷)
env:
contexts:
- name: myapp
urls: ["https://staging.myapp"]
authentication:
method: script
parameters:
scriptName: login.js
users:
- name: qa-bot
credentials:
username: qa-bot@example.com
password: ${QA_BOT_PASSWORD}
$ docker run --rm -v $(pwd):/zap/wrk/:rw \
-e QA_BOT_PASSWORD \
-t zaproxy/zap-stable zap.sh -cmd \
-autorun /zap/wrk/auth-context.yaml
4-4. GitHub Actions에 붙이기
zap:
needs: deploy-staging
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.12.0
with:
target: "https://staging.myapp.internal"
fail_action: true
cmd_options: "-a -j -m 5 -T 10"
주의할 점은 반드시 스테이징을 겨냥해야 한다는 것입니다. 프로덕션에 직접 돌리면 속도 저하·DB 쓰레기 데이터·알림 폭주가 한꺼번에 옵니다.
5. ASVS·Cheat Sheets·SAMM
5-1. ASVS를 PR 체크리스트로
ASVS(Application Security Verification Standard)는 수백 항목의 보안 요구사항을 Level 1~3로 나눠 둔 문서입니다. 팀이 "모두 지키자"고 하면 지치지만, 항목 번호를 PR 템플릿에 박아두면 강제력이 생깁니다.
<!-- .github/pull_request_template.md -->
## Security checklist (ASVS Level 1 부분 적용)
- [ ] V2.1 비밀번호는 최소 12자 이상, 공통 사전 단어 거부
- [ ] V3.3 세션 토큰은 로그아웃/비번 변경 시 무효화
- [ ] V4.1 수평/수직 권한 체크(BOLA/BFLA)를 단위 테스트로 검증
- [ ] V5.1 모든 입력 검증은 서버 측에서
- [ ] V8.3 민감정보는 URL/로그에 남기지 않음
- [ ] V12.1 업로드 파일은 MIME + 확장자 + 바이너리 시그니처 3중 검증
Level 1(필수), Level 2(민감 서비스), Level 3(고보안)로 단계적 확장이 가능합니다.
5-2. Cheat Sheets - 구현 시 바로 열어보는 참고서
Cheat Sheet Series는 주제별로 "이렇게 구현하라"를 한 페이지로 정리한 레퍼런스 모음입니다. 특히 많이 참고되는 것은 다음과 같습니다.
- Authentication Cheat Sheet
- Password Storage Cheat Sheet (bcrypt/argon2 파라미터 권고)
- JWT Cheat Sheet (알고리즘 고정,
none차단 등) - SQL Injection Prevention
- XSS Prevention
- CSRF Prevention
- REST Security
- File Upload
구현 중 막히면 "OWASP [주제] cheat sheet"로 검색하는 습관만 들여도 엉뚱한 블로그 복붙을 피할 수 있습니다.
5-3. SAMM - 조직 성숙도 평가
SAMM(Software Assurance Maturity Model)은 팀의 보안 활동을 4개 비즈니스 기능(Governance·Design·Implementation·Verification·Operations)으로 나눠 0~3 레벨로 평가합니다. 연 1회 자체 평가해서 어느 영역이 뒤처졌는지를 보는 데 유용합니다.
| 레벨 | 의미 |
|---|---|
| 0 | 활동 없음 |
| 1 | 초기/비공식 |
| 2 | 체계적 적용 |
| 3 | 조직 전반 지속 개선 |
현실적으로 스타트업은 전 영역 Level 1, 중견 조직은 Level 2를 목표로 잡는 경우가 많습니다.
6. Spring Boot 실전 적용
OWASP Top 10 주요 항목을 Spring Boot에서 어떻게 막는지 Spring Security 6 가이드와 연결해 정리합니다.
6-1. A01 Broken Access Control
// IDOR 방지: 항상 "본인 것"인지 확인
@GetMapping("/orders/{id}")
@PreAuthorize("isAuthenticated()")
public OrderResponse get(@PathVariable Long id,
@AuthenticationPrincipal UserDetails me) {
Order o = orderRepository.findById(id)
.orElseThrow(NotFoundException::new);
if (!o.getOwnerEmail().equals(me.getUsername())) {
throw new AccessDeniedException("not your order");
}
return OrderResponse.from(o);
}
URL 파라미터만으로 접근을 허용하는 API는 전수 감사를 돌려야 합니다. BOLA 한 건이 SNS에 올라가면 사고 등급이 바로 올라갑니다.
6-2. A03 Injection
// JPA: 파라미터 바인딩 항상 사용
@Query("select u from User u where u.email = :email")
Optional<User> findByEmail(@Param("email") String email);
// 절대 금지: 문자열 합치기
// "select * from users where email = '" + email + "'"
Thymeleaf 같은 템플릿 엔진은 기본 이스케이프가 켜져 있지만, th:utext는 명시적으로 원문 출력이라 입력을 그대로 넣는 순간 저장형 XSS가 됩니다.
6-3. A05 Security Misconfiguration - Actuator
# application.yml
management:
endpoints:
web:
exposure:
include: health, info # 최소 노출
endpoint:
health:
show-details: when_authorized
server:
port: 9090 # 관리 포트 분리
디폴트로 /actuator/env, /actuator/heapdump가 열린 채로 프로덕션에 올라가면 비밀번호·JDBC URL이 그대로 노출됩니다. 관리 포트 분리 + 내부망만 허용 + 인증 필수가 3종 세트입니다.
6-4. A07 Auth Failures - 비율 제한
// 로그인 엔드포인트에만 Bucket4j 적용
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {
private final Bucket bucket = Bucket.builder()
.addLimit(Bandwidth.simple(10, Duration.ofMinutes(1)))
.build();
@PostMapping("/login")
public TokenResponse login(@RequestBody LoginRequest req) {
if (!bucket.tryConsume(1)) {
throw new TooManyRequestsException("rate limit");
}
return authService.login(req);
}
}
실제로는 IP/계정 두 축으로 각각 버킷을 둬야 크리덴셜 스터핑을 막을 수 있습니다.
6-5. 공통 응답 헤더
// SecurityConfig
http.headers(h -> h
.contentSecurityPolicy(csp -> csp.policyDirectives(
"default-src 'self'; object-src 'none'; frame-ancestors 'none'"))
.httpStrictTransportSecurity(hsts -> hsts
.includeSubDomains(true).maxAgeInSeconds(31536000))
.xssProtection(xss -> xss.headerValue(
XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK))
.frameOptions(f -> f.deny())
.referrerPolicy(r -> r.policy(
ReferrerPolicyHeaderWriter.ReferrerPolicy.SAME_ORIGIN))
);
7. CI/CD 보안 게이트 통합
도구가 아무리 좋아도 PR을 블록하지 않으면 아무도 안 본다는 게 현장 진리입니다. 단계별 게이트를 정합니다.
| 단계 | 도구 | 차단 기준 |
|---|---|---|
| 코드 커밋 | pre-commit(secrets scan) | 키/토큰 패턴 발견 시 |
| PR 빌드 | Dependency-Check | CVSS 7.0 이상 |
| PR 빌드 | SpotBugs + Find Sec Bugs | High 이상 |
| 스테이징 배포 후 | ZAP Baseline | High 경고 1건 이상 |
| 스테이징 정기 | ZAP API Scan | 리포트 Slack 전송 |
| 프로덕션 배포 | Cosign 서명 검증 | 서명 없음 시 차단 |
| 운영 | SIEM 알림 | 비정상 인증 패턴 |
7-1. pre-commit 예시(시크릿 유출 방지)
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.24.0
hooks:
- id: gitleaks
7-2. 종합 GitHub Actions 샘플
jobs:
sast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with: {distribution: temurin, java-version: 21}
- run: ./gradlew check spotbugsMain
- run: ./gradlew dependencyCheckAnalyze
env: {NVD_API_KEY: ${{ secrets.NVD_API_KEY }}}
- uses: actions/upload-artifact@v4
with: {name: sast, path: build/reports/}
dast:
needs: [sast, deploy-staging]
runs-on: ubuntu-latest
steps:
- uses: zaproxy/action-api-scan@v0.7.0
with:
target: https://staging.myapp/api/v3/api-docs
format: openapi
fail_action: true
8. Juice Shop으로 팀 훈련
OWASP Juice Shop은 "일부러 취약하게 만든 Node.js 쇼핑몰"입니다. 신규 입사자 온보딩 주에 2시간만 투자해 몇 가지 챌린지를 풀게 해도 보안 감수성이 완전히 달라집니다.
$ docker run --rm -p 3000:3000 bkimminich/juice-shop
# http://localhost:3000
- 쉬움: 관리자 이메일 찾기, 포럼에 스크립트 실행시키기(XSS)
- 중간: 남의 장바구니 조작(BOLA), JWT 알고리즘 교체
- 어려움: 서버 측 템플릿 인젝션, Blind SQLi
진도 체크는 내장 /#/score-board에서 자동으로 이뤄지므로 사내 교육 KPI로 잡기도 좋습니다.
9. OWASP를 쓸 때 흔히 하는 실수
- Top 10만 보고 끝내기 - Top 10은 입문용 리스트입니다. 실제 요구사항은 ASVS, 구현은 Cheat Sheet로 이어가야 완결됩니다.
- ZAP을 프로덕션에 돌리기 - DB에 쓰레기 데이터와 사용자 알림 폭주를 부릅니다. 반드시 스테이징 전용.
- Dependency-Check를 주간으로만 돌리기 - 새 CVE는 매일 뜹니다. 일일 스케줄 + PR 블로킹이 기본.
- suppressions 남발 - 사유 없이 억제한 CVE는 6개월 뒤 사고의 원인이 됩니다. 반드시
notes+ 재확인 일자. - SAMM을 한 번 평가하고 끝 - 최소 반기·연 1회 재평가하지 않으면 의미 없음.
- 보안팀에만 맡기기 - OWASP의 핵심 철학은 "개발자 중심"입니다. 개발자가 읽고 PR 단계에서 적용해야 가치가 나옵니다.
10. 30일 도입 로드맵
| 기간 | 목표 | 산출물 |
|---|---|---|
| 1주차 | Top 10 스터디, 자체 레포 감사 | 위험도 매트릭스 |
| 2주차 | Dependency-Check 도입, CI 연동 | 일일 리포트 Slack 전송 |
| 3주차 | ZAP Baseline 자동 스캔 | 스테이징 주간 리포트 |
| 4주차 | ASVS Level 1 체크리스트를 PR 템플릿에 내장 | PR 체크리스트 |
| 2~3개월 | SAMM 자체 평가, 보안 챔피언 제도 | 조직 성숙도 리포트 |
팀 규모에 따라 늘이고 줄일 수 있지만, 순서를 뒤집으면 피로도가 크게 올라갑니다. "눈에 보이는 효과"가 빠른 Dependency-Check부터 시작하는 것이 도입 성공률이 가장 높습니다.
마치며
OWASP 오픈소스 생태계 도입의 핵심 포인트를 정리합니다.
- OWASP는 문서·표준·도구가 한 세트로 연결된 프로젝트 집합입니다. Top 10으로 감을 잡고, Dependency-Check·ZAP으로 자동화하고, ASVS·Cheat Sheet로 코드 리뷰 기준을 세우는 흐름이 가장 자연스럽습니다. 따로 놓고 쓰지 말고 서로 연결해서 운영해야 효과가 납니다.
- Top 10만으론 부족합니다. 백엔드 API 개발자는 API Top 10을, LLM 에이전트를 붙인 서비스라면 LLM Top 10까지 함께 봐야 현재 위협 지형이 맞게 잡힙니다. #129·#130과 같이 보면 "고전+AI" 축이 한 번에 덮입니다.
- Dependency-Check는 오늘 당장 붙일 수 있는 가장 ROI 높은 도구입니다. 30분이면 Gradle 플러그인과 CI 연동이 끝나고, 다음 날 새벽 리포트부터 실제 CVE가 보입니다. 일일 스케줄 + CVSS 7.0 이상 PR 블로킹을 권장합니다.
- ZAP은 Baseline → API Scan → 인증 스캔 순으로 단계적으로 올리세요. 스테이징 전용으로 제한하고, 인증이 필요한 플로우까지 커버되면 외부 펜테스트 비용의 상당 부분을 내재화할 수 있습니다.
- ASVS와 Cheat Sheet는 "읽는 문서"가 아니라 "PR 템플릿과 리뷰 체크리스트에 박는 문서"입니다. 프로젝트 위키 구석에 링크만 두면 아무도 안 봅니다. Level 1 필수 항목부터
.github/pull_request_template.md에 넣으세요. - Juice Shop은 온보딩 주 2시간짜리 보안 감수성 훈련으로 최적입니다. 신규 입사자가 직접 BOLA와 XSS를 성공시켜 보면, 이후 코드 리뷰 품질이 눈에 띄게 올라갑니다. 보안 교육 예산이 0원인 팀에도 가능한 옵션입니다.
AI 시대에도 웹 보안의 상당 부분은 여전히 "지루하지만 알려진 문제"입니다. 새 CVE를 매일 따라잡고, 자동화로 피로도를 낮추는 인프라만 깔아두면 조직 전체의 보안 바닥이 한 계단 올라갑니다. 다음 글에서는 이 OWASP 기반 파이프라인 위에 SBOM(소프트웨어 자재명세서)과 공급망 서명(Sigstore/cosign)을 얹어 A08(Software & Data Integrity Failures)까지 닫는 방법을 다뤄볼 예정입니다.
'최신 트렌드' 카테고리의 다른 글
| Secrets Management 실전 - Vault·AWS Secrets Manager로 런타임 크리덴셜 안전하게 다루기 (0) | 2026.04.23 |
|---|---|
| SBOM과 Sigstore 실전 - 공급망 공격 시대의 A08 방어선 구축 (0) | 2026.04.23 |
| 사내 MCP 가드레일 레이어 구축 - 모든 에이전트가 공유하는 중앙 방어 허브 설계 (1) | 2026.04.22 |
| LLM 보안 가드레일 실전 - PII 스캐너·프롬프트 인젝션 탐지·탈옥 방어를 코드 레벨로 (0) | 2026.04.22 |
| LLM-as-Judge 실전 구축 - AI 에이전트 품질을 자동 채점하는 판사 모델 파이프라인 (0) | 2026.04.21 |