← 목록으로
● 2013-02 선불카드 프로세서 해킹(두 차례 합산 $45M) 분석 기반

동시에 열 번 요청하면 열 번 다 통과하는 구조,
그걸 막는 코드를 공개합니다

2013년 해커들은 선불카드 프로세서의 인출한도 검증 로직을 공략해, 잔액 확인과 차감 사이의 틈(TOCTOU 경쟁조건)을 이용해 27개국 ATM에서 동시에 현금을 뽑아 $45M을 탈취했습니다. 같은 구조의 버그를 재현하고, 10개의 동시 인출 요청으로 직접 공격해 원자적 잠금 방어가 이를 막는 걸 검증했습니다.

라이브 데모 보기 → 코드 바로보기

누구를 위한 건가

잔액이나 재고 같은 공유 자원을 확인(check) 후 차감(act)하는 로직을 짜본 적 있는 백엔드 개발자용 학습 자료입니다 — 이 둘 사이의 틈이 바로 취약점입니다.

$45M
2013년 해당 사고의 두 차례 작전 합산 피해액
10/10
검증 중 취약한 쪽에 동시 인출 10건을 보냈을 때 성공한 건수
5/10
같은 공격을 방어 로직에 보냈을 때 성공한 건수(잔액 한도까지 정확히)

코드 — race-condition-withdrawal.js

잔액 확인과 차감 사이에 틈이 있는 취약한 인출 API (TOCTOU).

race-condition-withdrawal.js
// 취약한 인출 API — 2013년 선불카드 프로세서 해킹 모델링.
// 잔액을 "확인"하는 것과 "차감"하는 것이 분리된 두 단계라,
// 그 사이의 틈(실제 DB 왕복 지연)에 동시 요청이 끼어들면
// 전부 차감 전의 잔액을 보고 통과해버림.
class RaceConditionWithdrawal {
  constructor(account) {
    this.account = account; // { balance }
  }

  async withdraw(amount) {
    const current = this.account.balance; // CHECK
    await simulatedDbRoundTrip(); // 경쟁 윈도우
    if (current < amount) return { status: 'insufficient_funds' };
    this.account.balance = current - amount; // ACT — 이미 낡은 값 기준
    return { status: 'ok', newBalance: this.account.balance };
  }
}

module.exports = { RaceConditionWithdrawal };

코드 — atomic-withdrawal-guard.js

해결책: 확인과 차감을 하나의 원자적(잠긴) 연산으로 묶는다.

atomic-withdrawal-guard.js
// 해결책: 확인과 차감 사이에 다른 요청이 끼어들 수 없도록
// 계정 단위 잠금으로 둘을 하나의 원자적 연산으로 묶는다.
// (실전에선 DB 행 잠금이나 원자적 UPDATE...WHERE로 구현)
class AtomicWithdrawalGuard {
  constructor(account) {
    this.account = account;
    this.locked = false;
  }

  async withdraw(amount) {
    while (this.locked) await sleep(5);
    this.locked = true;
    try {
      await simulatedDbRoundTrip(); // 같은 지연이지만 잠금 안쪽
      if (this.account.balance < amount) return { status: 'insufficient_funds' };
      this.account.balance -= amount;
      return { status: 'ok', newBalance: this.account.balance };
    } finally {
      this.locked = false;
    }
  }
}

module.exports = { AtomicWithdrawalGuard };

가격

무료 (지금)
심화 버전(분산 락·다중 계좌 트랜잭션 포함) 출시 예정 — 사업자등록 완료 후 자유가격($0부터)으로 공개
goalsgo7574@gmail.com
구매·결제가 아닙니다 — "심화버전 출시알림 받고 싶어요"라고 메일 한 통만 보내주시면, 출시 시 연락드립니다.
주의: 이건 학습용 축소 구현입니다. 단일 프로세스 안의 메모리 잠금이라, 여러 서버 인스턴스가 있는 실전 환경에선 분산 락이 필요합니다.

의견을 남겨주세요

이 상품에 대한 피드백이나 질문이 있으면 알려주세요. 회신을 원하시면 이메일을 남겨주세요(선택).