제공 서비스
웹 보안 점검 소스코드 분석 (SAST) 외부 공격표면 진단 (EASM)
요금제 스토어 블로그 파트너 마이페이지 무료 보안 점검
API 보안 2026.05.19 · 조회 494

Webhook 서명 검증 누락 — 결제·CI SaaS의 인증 결함 [2026]

Webhook 엔드포인트의 60% 이상이 서명 검증을 생략하거나 잘못 구현한다. 결제 위조, CI 파이프라인 탈취, 알림 스푸핑이 한 줄의 검증 누락으로 가능해진다. HMAC-SHA256 검증 표준 코드와 5가지 실수 패턴을 정리했다.

Webhook 서명 검증은 외부에서 도착한 HTTP 요청이 진짜 발신자(Stripe·GitHub·PortOne 등)에게서 왔는지 HMAC-SHA256으로 확인하는 인증 절차다.
AI 코딩 도구가 만든 결제·CI·알림 통합 코드에서 가장 흔히 생략되는 보안 분기이며, 누락 시 공격자가 위조 요청 하나로 결제 완료를 가짜로 트리거하거나 CI 파이프라인을 탈취할 수 있다.
이 글은 Stripe·PortOne·GitHub Webhook의 표준 검증 코드, 5가지 자주 발생하는 실수, 그리고 30초 자가진단 + 24시간 패치 절차를 정리했다.

한눈에 보는 Webhook 서명 검증

Q. Webhook 서명 검증을 안 하면 어떤 일이 벌어지나요? A. 공격자가 결제 완료 Webhook을 위조해 무료로 상품을 받거나, CI Webhook을 위조해 임의 코드를 main 브랜치에 배포할 수 있습니다. HTTPS만으로는 발신자 인증이 안 됩니다. Q. HTTPS면 충분하지 않나요? A. HTTPS는 통신 경로 암호화만 보장합니다. 공격자가 자기 서버에서 위조 Webhook을 직접 호출하면 HTTPS도 정상 동작합니다. 서명 검증은 페이로드 + 비밀키 기반 HMAC으로 발신자 신원을 확인합니다. Q. 30초 안에 검증 누락을 확인할 수 있나요? A. 자기 Webhook 엔드포인트에 임의 페이로드 + Signature 헤더 없이 POST를 보내고 200 OK가 떨어지면 검증 누락입니다. 401·400이 떨어져야 정상입니다. Q. 검증 코드는 어디에 작성해야 하나요? A. 모든 비즈니스 로직(주문 처리·DB 업데이트) 이전에 미들웨어나 데코레이터로 강제해야 합니다. 라우트 핸들러 본문에 두면 누락 위험이 큽니다.

5가지 자주 발생하는 실수 패턴

#패턴예시위험도
1검증 자체 생략Stripe/PortOne 비밀키 사용 안 함, 페이로드만 신뢰치명
2raw body 대신 parsed body 사용JSON.parse 후 다시 stringify 한 값으로 HMAC 계산 → 서명 불일치 또는 우회치명
3타이밍 어택 가능한 비교signature == calculated 일반 비교 사용 (constant-time 미적용)높음
4timestamp 미검증오래된 서명을 재전송(replay)해도 통과높음
5비밀키 하드코딩·노출코드에 박혀 GitHub 공개 → 분 단위 자동 봇이 수집치명

표준 검증 코드 — Stripe (Python·Django)

import hmac
import hashlib
import time
from django.http import HttpResponseBadRequest
from django.conf import settings

def verify_stripe_webhook(request):
    sig_header = request.headers.get('Stripe-Signature', '')
    raw_body = request.body  # ★ JSON.parse 전 raw bytes 필수
    secret = settings.STRIPE_WEBHOOK_SECRET

    # 1. 헤더 파싱: "t=1234567890,v1=abc..."
    parts = dict(p.split('=', 1) for p in sig_header.split(','))
    timestamp = parts.get('t')
    signature = parts.get('v1')

    if not timestamp or not signature:
        return HttpResponseBadRequest('서명 헤더 누락')

    # 2. timestamp 5분 이내 검증 (replay 차단)
    if abs(int(time.time()) - int(timestamp)) > 300:
        return HttpResponseBadRequest('서명 만료')

    # 3. HMAC-SHA256 계산
    payload = f"{timestamp}.{raw_body.decode()}"
    expected = hmac.new(
        secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()

    # 4. constant-time 비교 (타이밍 어택 방지)
    if not hmac.compare_digest(expected, signature):
        return HttpResponseBadRequest('서명 불일치')

    return None  # 검증 통과

핵심 4요소: (1) raw body 사용 (2) timestamp 검증 (3) HMAC-SHA256 (4) constant-time 비교.
하나라도 빠지면 결함이다. AI 코딩 도구가 만든 코드에서는 ①④가 가장 자주 누락된다.
미들웨어로 강제해 라우트별 누락 위험을 원천 차단하는 것이 표준이다.

지금 1분만 — 자기 Webhook 엔드포인트를 CodeScan 무료 스캔에 입력하면 서명 헤더 미설정 / TLS 약점 / 비밀키 추정 가능한 패턴을 자동 점검합니다.
무료 등급 결과 + 17개 스캐너 통합 진단.

PortOne (한국 결제) 검증 표준

PortOne V2는 결제 완료 Webhook에 Webhook-Signature 헤더를 동봉한다.
검증 알고리즘은 Stripe와 거의 동일하나, 한국 환경 특이점이 있다.

  • 비밀키는 PortOne 콘솔 → 채널 → Webhook 설정에서 발급
  • 페이로드는 raw bytes 그대로, JSON 재직렬화 금지
  • 서버검증 API(/payments/{paymentId}) 호출로 이중 확인 권장 — Webhook은 보조, 결제 상태는 결제 검증 API가 진실

한국 PG 결제 위변조 사고 사례는 SaaS 결제 통합 보안 함정 — PortOne·Toss 가이드에서 별도 정리했다.

GitHub Actions / Webhook 검증 표준

GitHub Webhook은 X-Hub-Signature-256 헤더로 HMAC-SHA256 서명을 전달한다. GitHub 공식 가이드에 따른 표준 검증:

def verify_github_webhook(request):
    sig = request.headers.get('X-Hub-Signature-256', '')
    secret = settings.GITHUB_WEBHOOK_SECRET

    expected = 'sha256=' + hmac.new(
        secret.encode(),
        request.body,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(expected, sig):
        return HttpResponseBadRequest('GitHub 서명 불일치')

CI Webhook 검증 누락 시 임의 페이로드로 배포 트리거가 가능하다.
공격자는 자기 컨테이너 빌드 이미지를 main에 흘릴 수 있고, 비밀 환경변수가 빌드 로그에 누설된다.
관련: 공급망 공격 시즌2 — npm CI/CD 5점검.

알림 SaaS (Slack·Discord) 서명 검증

Slack은 X-Slack-Signature + X-Slack-Request-Timestamp 조합, Discord는 Ed25519 공개키 서명을 사용한다. 알고리즘이 달라도 4요소 원칙(raw body·timestamp·HMAC/공개키·constant-time)은 동일하다.

알림 Webhook이 위조되면 운영팀에 가짜 장애 알림을 흘려 실제 사고를 가리는 사회공학 공격이 가능하다.
2025년 Discord 봇 위장 사례에서 동일 패턴이 확인됐다.
OWASP A07: 식별·인증 실패 범주에 해당한다.

30초 자가진단 — 새고 있는지 즉시 확인

다음 3가지 명령으로 1차 점검 가능. 하나라도 200 OK가 떨어지면 검증 누락이다.

# 1. 서명 헤더 없이 호출
curl -X POST https://yourdomain.com/webhook/stripe   -H "Content-Type: application/json"   -d '{"type":"payment_intent.succeeded","amount":100000}'

# 2. 위조 서명으로 호출
curl -X POST https://yourdomain.com/webhook/stripe   -H "Stripe-Signature: t=1234567890,v1=fakefakefake"   -d '{"type":"payment_intent.succeeded"}'

# 3. 오래된 timestamp로 호출 (1시간 전)
TS=$(($(date +%s) - 3600))
curl -X POST https://yourdomain.com/webhook/stripe   -H "Stripe-Signature: t=$TS,v1=anysig"   -d '{"type":"payment_intent.succeeded"}'

정상 응답은 모두 400 또는 401이어야 한다.

발견 시 24시간 패치 절차

순위조치이유
1비밀키 회전 — 콘솔에서 즉시 재발급이미 유출됐을 가능성 차단
2검증 함수 작성 + 미들웨어로 강제모든 Webhook 엔드포인트 일괄 적용
3raw body 처리 확인 — body-parser 미들웨어 순서 점검parsed body 사용 시 서명 불일치
4timestamp + replay 차단 (5분 윈도우)재전송 공격 차단
5로그에 검증 실패 시각·IP 기록공격 시도 모니터링
6결제 Webhook은 결제 검증 API 이중 확인Webhook 자체에 의존하지 않음

지금 해야 할 것 — 30초 자가진단 + 1:1 상담

실무자라면: 자기 Webhook 엔드포인트 URL을 CodeScan 무료 스캔에 입력 → TLS·헤더·노출 패턴 자동 점검. 검증 누락 시 위 표준 코드로 패치.

CISO·임원이라면: Webhook 검증은 자동 스캔으로 부분만 잡힌다. 실제 페이로드 위조 시뮬레이션은 수동 점검이 필요하다. SENTRIX 30분 1:1 보안 상담 신청 → 결제·CI·알림 통합 전반의 인증 결함을 함께 점검한다.

관련 글

{ "@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [ {"@type":"Question","name":"Webhook 서명 검증을 안 하면 어떤 일이 벌어지나요?","acceptedAnswer":{"@type":"Answer","text":"공격자가 결제 완료 Webhook을 위조해 무료로 상품을 받거나, CI Webhook을 위조해 임의 코드를 main 브랜치에 배포할 수 있습니다. HTTPS만으로는 발신자 인증이 안 됩니다."}}, {"@type":"Question","name":"HTTPS면 충분하지 않나요?","acceptedAnswer":{"@type":"Answer","text":"HTTPS는 통신 경로 암호화만 보장합니다. 공격자가 자기 서버에서 위조 Webhook을 직접 호출하면 HTTPS도 정상 동작합니다. 서명 검증은 페이로드와 비밀키 기반 HMAC으로 발신자 신원을 확인합니다."}}, {"@type":"Question","name":"30초 안에 검증 누락을 확인할 수 있나요?","acceptedAnswer":{"@type":"Answer","text":"자기 Webhook 엔드포인트에 임의 페이로드와 Signature 헤더 없이 POST를 보내고 200 OK가 떨어지면 검증 누락입니다. 401 또는 400이 떨어져야 정상입니다."}}, {"@type":"Question","name":"검증 코드는 어디에 작성해야 하나요?","acceptedAnswer":{"@type":"Answer","text":"모든 비즈니스 로직(주문 처리·DB 업데이트) 이전에 미들웨어나 데코레이터로 강제해야 합니다. 라우트 핸들러 본문에 두면 누락 위험이 큽니다."}} ] }
Webhook 보안 HMAC 서명 검증 Stripe Webhook PortOne Webhook GitHub Actions OWASP A07

내 사이트도 점검해보세요

CodeScan으로 보안 취약점을 무료로 점검할 수 있습니다.

무료 스캔 시작하기 →
🛒
추천 상품
웹서비스 런칭 전 보안 세팅
런칭 전에 반드시 해야 하는 보안 설정을 원격으로 직접 해드립니다. HTTPS, 환경변수 분리, 보안 헤더…
220,000원 150,000원

🔒 바이브코딩 보안 체크리스트 받기

바이브코딩 보안 체크리스트(PDF)를 무료로 받아보세요.