Week 12 — E-Commerce 보안 컨설팅 시뮬레이션 1/4: 취약 시스템 구축

전체 소스코드는 GitHub에서 확인할 수 있습니다. hojjang98 / skshielders-rookies-28 — projects/week_12

학습 목적으로 구성된 실습입니다. 의도적으로 취약한 시스템을 구축하고, 다음 주에 이를 직접 진단하는 구조의 교육용 프로젝트입니다. 실제 서비스에 대한 무단 공격은 정보통신망법 위반입니다.


프로젝트 배경 — 왜 4주 시리즈인가

파이널 프로젝트 주제를 선정하는 과정에서 관제(SOC)보안 컨설팅 사이에서 고민이 있었다.

Week 10~11 에서 팀 프로젝트로 취약점 진단 경험을 쌓았지만, 당시에는 팀 단위로 역할을 나누어 진행하여 전체 프로세스를 온전히 혼자 경험하지는 못했다. 취약 시스템 구축 → 진단 → 개선 → 모니터링 까지 보안 컨설턴트의 A to Z 업무 흐름을 솔로로 직접 수행 해보고 싶었다.

4주 계획:

Week 12 (1/4) : 취약한 시스템 구축          <- 이번 주
Week 13 (2/4) : 취약점 진단 (모의해킹 + 스캔)
Week 14 (3/4) : 보안 개선 구현
Week 15 (4/4) : 모니터링 체계 + 최종 컨설팅 보고서

프로젝트 개요

항목 내용
시나리오 중소기업 E-Commerce 보안 컨설팅 시뮬레이션
이번 주 목표 의도적 취약점 내포 쇼핑몰 구현
기술 스택 Flask, SQLite3, Jinja2, werkzeug
접속 URL http://localhost:5000
테스트 계정 admin / admin123

시스템 구조

ecommerce_vulnerable/
├── app.py             # Flask 메인 애플리케이션 (취약점 핵심 코드)
├── init_db.py         # DB 초기화 (테스트 계정 + 더미 상품 데이터)
├── database.db        # SQLite 데이터베이스
├── templates/         # Jinja2 HTML 템플릿
│   ├── base.html
│   ├── index.html     # 상품 목록 (검색 기능 포함)
│   ├── login.html
│   ├── register.html
│   ├── product.html   # 상품 상세 + 댓글
│   ├── cart.html
│   ├── checkout.html
│   └── profile.html   # 프로필 + 이미지 업로드
└── static/
    └── uploads/       # 업로드 파일 저장 경로

구현 기능:

  • 회원가입 / 로그인 / 로그아웃
  • 상품 목록 조회 (키워드 검색 포함)
  • 상품 상세 페이지 + 댓글 작성
  • 장바구니 / 주문 / 결제 흐름
  • 프로필 관리 (이미지 업로드 포함)

의도적으로 삽입한 취약점 4종

이번 주의 핵심 목표는 나쁜 코드를 의도적으로 잘 쓰는 것 이다. 다음 주 진단 단계에서 실제로 공격해볼 수 있도록 OWASP Top 10 취약점을 정교하게 심어두었다.


취약점 1 — SQL Injection (로그인)

위치: /login POST 핸들러

취약한 구현 — 사용자 입력을 f-string 으로 직접 쿼리에 삽입:

query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
user = conn.execute(query).fetchone()

공격 예시:

Username : admin' OR '1'='1
Password : anything

실행 쿼리 => SELECT * FROM users WHERE username='admin' OR '1'='1' AND password='anything'
결과       => OR 조건으로 항상 참 => 비밀번호 검증 없이 로그인 성공

취약점 2 — SQL Injection (상품 검색)

위치: / GET 핸들러, search 파라미터

취약한 구현 — LIKE 쿼리에 검색어 직접 삽입:

search = request.args.get('search', '')
if search:
    query = f"SELECT * FROM products WHERE name LIKE '%{search}%'"
    products = conn.execute(query).fetchall()

공격 예시:

검색어 : ' OR '1'='1
실행 쿼리 => SELECT * FROM products WHERE name LIKE '%' OR '1'='1%'
결과       => LIKE 조건 무력화 => 전체 상품 10개 노출

취약점 3 — XSS (댓글)

위치: product.html 댓글 출력 + /product/<id>/comment POST

취약한 구현 — |safe 필터로 HTML 이스케이프를 비활성화:

# 댓글 저장 시: 필터링 없이 DB에 그대로 저장
conn.execute(
    'INSERT INTO comments (product_id, user_id, comment) VALUES (?, ?, ?)',
    (product_id, session['user_id'], comment)
)

# 출력 시 (product.html): |safe 필터 사용
<p>{{ comment.comment|safe }}</p>

공격 예시:

댓글 입력 : <script>alert('XSS')</script>
결과       => 페이지 로드 시 스크립트 실행
           => 쿠키 탈취 / 피싱 페이지 삽입 등으로 확장 가능

취약점 4 — 파일 업로드

위치: /profile 프로필 이미지 업로드

취약한 구현 — 파일 타입 / 확장자 / 크기 검증 전혀 없음:

filename = file.filename   # 원본 파일명 그대로 사용
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)

공격 예시:

업로드 파일 : webshell.php  (또는 .py, .sh 등)
결과        => 서버에 그대로 저장
           => URL 직접 접근 시 서버 명령 실행 가능 (서버 장악)

보조 취약점 — 예측 가능한 시크릿 키:

app.secret_key = 'vulnerable_secret_key_123'

Flask 세션 쿠키는 시크릿 키로 서명되는데, 키가 공개되면 세션 위조가 가능하다.


취약점 설계 원칙

이번 주에서 가장 어려운 부분은 취약하게 만드는 것 이었다.

평소에는 Prepared Statement, HTML Escape, 화이트리스트 검증을 습관적으로 적용했기 때문에, 의식적으로 이를 피해서 코드를 짜야 했다.

취약점 설계 원칙:
- SQL Injection  : ? 바인딩 대신 f-string 직접 삽입
- XSS            : |safe 필터를 명시적으로 사용
- 파일 업로드     : ALLOWED_EXTENSIONS 검증 코드 작성 안 함
- 세션 관리       : 예측 가능한 시크릿 키 사용

역설적으로, 무엇이 위험한지 알아야 의도적으로 취약하게 만들 수 있다. 이 과정 자체가 방어 코드를 이해하는 좋은 방법이었다.


학습 성과 정리

영역 학습 내용
취약점 설계 OWASP Top 10 취약점을 실제 코드로 구현하는 방법 체득
Flask 구조 라우트 설계, 세션 관리, Jinja2 템플릿 렌더링 흐름
공격 벡터 이해 SQL Injection / XSS / 파일 업로드의 동작 원리를 코드 레벨로 확인
컨설팅 준비 진단 대상 시스템을 준비하는 컨설팅 전 단계 경험

다음 주 예고 — Week 13: 취약점 진단

Week 12 에서 구축한 이 쇼핑몰을 대상으로, 실제 보안 컨설턴트처럼 취약점 진단을 수행한다.

진단 도구:
- OWASP ZAP  : 자동화 스캔
- Python 스크립트 : 수동 진단 (SQL Injection, XSS, 파일 업로드)
- Burp Suite : HTTP 요청/응답 분석 (선택)

예상 발견사항:
- Critical : SQL Injection (로그인, 검색)
- High     : XSS, 파일 업로드
- Medium   : CSRF, CSP 미설정, Clickjacking
- Low      : 보안 헤더 누락