
DX Security — Bot Challenge Automation Bypass 방어 v1.0.0 안내서
PHP 5.6+ · IIS / Apache / Nginx 완전 호환 코어 DxCaptcha / Secure::rateLimit() 재사용 코어 수정 없음 — 훅으로만 동작
목차
- Bot Automation Bypass란 무엇인가
- DXCMS 코어의 현재 방어 수준
- 이 플러그인의 역할
- 설치 방법
- 방어층 상세 설명
- 보안 로그 읽는 법
- 보안 강점 요약
- 개발자 API 가이드
1. Bot Automation Bypass란 무엇인가
공격자가 CAPTCHA나 Challenge를 우회하거나, UI를 거치지 않고 API를 직접 자동으로 호출하여 대량 요청을 수행하는 공격입니다.
공격 시나리오:
① CAPTCHA 우회:
회원가입 페이지 CAPTCHA → 우회 → /api/register 직접 호출
→ 대량 계정 생성 (Account Farming)
② 로그인 브루트포스:
Rate Limit 없는 로그인 API → 비밀번호 대입 공격
③ 스팸 봇:
회원 계정으로 게시글/댓글 Rate Limit 없이 대량 작성
④ Challenge Token 재사용:
회원가입 CAPTCHA 통과 → 같은 토큰으로 다른 API 호출
핵심 원칙
CAPTCHA 통과 ≠ 로그인 인증
CAPTCHA 통과 ≠ 무제한 API 호출
Challenge는 추가 방어 계층입니다.
최종 구조: Authentication + Authorization + Bot Detection + Rate Limit
2. DXCMS 코어의 현재 방어 수준
코어가 이미 잘 하는 것
| 항목 | 방어 방식 | 평가 |
|---|---|---|
| CAPTCHA 드라이버 | built-in / reCAPTCHA / hCaptcha / Turnstile | ✅ |
| CAPTCHA one-time | used 플래그로 1회만 사용 가능 |
✅ |
| CAPTCHA 만료 | created + expire 설정 (기본 300초) |
✅ |
| Session binding | 세션에 저장 | ✅ |
| 회원가입 CAPTCHA | DxCaptcha::verify() 적용 |
✅ |
| 비회원 글쓰기 Rate Limit | rateLimit('write_guest_...') |
✅ |
코어가 하지 않는 것
| 항목 | 위험도 |
|---|---|
| 로그인 Rate Limit | 높음 |
| 회원 게시글/댓글 Rate Limit | 중간 |
| CAPTCHA Purpose Binding 교차 사용 방어 | 중간 |
| Risk Score 기반 탐지 | 중간 |
| API 직접 호출 탐지 | 중간 |
| 자동화 행동 패턴 감지 | 중간 |
| CAPTCHA Flooding 방어 | 중간 |
3. 이 플러그인의 역할
코어 DxCaptcha와 Secure::rateLimit()을 완전히 재사용합니다. 코어를 교체하거나 수정하지 않고 훅으로 부족한 부분만 보강합니다.
4. 설치 방법
(DXCMS 루트)/
└── plugins/
└── dx-security-bot/
├── manifest.php
└── plugin.php
관리자 → 플러그인 → dx-security-bot → 활성화
5. 방어층 상세 설명
BT1. 로그인 Rate Limit
코어에 로그인 Rate Limit이 없습니다. 이 훅이 보완합니다.
정책:
60초 안에 15회 초과 → 429 반환
IP 기준 제한
11번 authn 플러그인의 LOGIN_FAILED 훅과 이중 방어:
11번: 실패 후 카운트 (10회/600초)
13번: 시도 전 카운트 (15회/60초)
BT2. 회원 게시글/댓글 Rate Limit
코어는 비회원 글쓰기만 Rate Limit합니다. 회원의 반복 작성은 제한이 없어 스팸 봇에 취약합니다.
게시글 Rate Limit:
60초 안에 5회 초과 → 차단
댓글 Rate Limit:
60초 안에 10회 초과 → 차단
관리자는 제외
BT3. CAPTCHA Purpose Binding 보완
코어 DxCaptcha는 ctx 파라미터로 용도를 구분하지만, 다른 용도로 발급된 CAPTCHA를 교차 사용하는 것을 방어하지 않습니다.
취약한 시나리오:
/auth/register CAPTCHA 통과 → 같은 토큰으로 /api/post 호출
이 플러그인:
purpose별 세션 키로 교차 사용 탐지
→ CAPTCHA_PURPOSE_MISMATCH 로그
CAPTCHA Flooding 방어:
/api/captcha_image → 60초에 30회 제한
BT4. Risk Score 기반 탐지
여러 신호를 합산하여 요청의 위험도를 0~100으로 평가합니다.
| 신호 | 점수 |
|---|---|
| User-Agent 없음 | +30 |
| curl/wget/python 등 자동화 UA | +20 |
| POST + Referer 없음 | +10 |
| Accept 헤더 없음 | +10 |
| JSON + X-Requested-With 없음 | +5 |
| 민감 엔드포인트 접근 | +5 |
점수 기준:
30~49 → MEDIUM_RISK_REQUEST 로그
50+ → HIGH_RISK_REQUEST 로그
5회 연속 고위험 → REPEATED_HIGH_RISK 로그
WAF: 탐지·로그만 수행 — 차단 없음
BT5. API 직접 호출 / UI 우회 탐지
Referer 없이 민감 API를 POST로 직접 호출하는 패턴을 탐지합니다.
감시 엔드포인트:
/api/comment, /api/post, /api/upload
/api/friend, /api/like, /auth/register
Referer 없는 POST 탐지 → API_DIRECT_CALL 로그
Rate Limit (IP 기준):
60초에 20회 초과 → 429 반환
BT6. 자동화 행동 패턴 감지
연속적인 고위험 요청 패턴을 세션에 기록하고 분석합니다.
세션에 최근 10개 요청의 Risk Score 저장
→ 최근 5회 연속 고위험(50+) 시
REPEATED_HIGH_RISK 로그 기록
BT7. Bot 감사 로그
모든 Bot 관련 이벤트를 data/security.log에 기록합니다.
6. 보안 로그 읽는 법
이벤트 타입
| 타입 | 의미 |
|---|---|
BOT:LOGIN_RATE_LIMITED |
로그인 Rate Limit 초과 |
BOT:POST_RATE_LIMITED |
게시글 작성 Rate Limit 초과 |
BOT:COMMENT_RATE_LIMITED |
댓글 작성 Rate Limit 초과 |
BOT:CAPTCHA_FAILED |
CAPTCHA 검증 실패 |
BOT:CAPTCHA_SUCCESS |
CAPTCHA 검증 성공 |
BOT:CAPTCHA_FAIL_RATE_LIMITED |
CAPTCHA 실패 Rate Limit 초과 |
BOT:CAPTCHA_PURPOSE_MISMATCH |
CAPTCHA 교차 사용 탐지 |
BOT:CAPTCHA_FLOOD |
CAPTCHA 이미지 Flooding |
BOT:HIGH_RISK_REQUEST |
고위험 요청 탐지 (50+) |
BOT:MEDIUM_RISK_REQUEST |
중위험 요청 탐지 (30+) |
BOT:REPEATED_HIGH_RISK |
연속 고위험 요청 패턴 |
BOT:API_DIRECT_CALL |
API 직접 호출 탐지 |
BOT:API_DIRECT_RATE_LIMITED |
API 직접 호출 Rate Limit |
BOT:RATE_LIMITED |
플러그인 API Rate Limit |
로그 예시
# 로그인 브루트포스
[2026-09-03 09:00:01][BOT:LOGIN_RATE_LIMITED][IP:45.33.x.x][...][UID:0][POST /auth/login]
ip_limit_exceeded
# curl로 API 직접 호출
[2026-09-03 14:22:10][BOT:HIGH_RISK_REQUEST][IP:58.29.x.x][...][UID:0][POST /api/comment]
score=50 uri=/api/comment
[2026-09-03 14:22:10][BOT:API_DIRECT_CALL][IP:58.29.x.x][...][UID:0][POST /api/comment]
uri=/api/comment no_referer
# 회원 댓글 Rate Limit
[2026-09-03 16:45:03][BOT:COMMENT_RATE_LIMITED][IP:121.131.x.x][...][UID:42][POST /board/free]
user_id=42
# CAPTCHA 교차 사용
[2026-09-03 20:11:44][BOT:CAPTCHA_PURPOSE_MISMATCH][IP:103.21.x.x][...][UID:0][POST /api/post]
expected=post stored=register
7. 보안 강점 요약
| 공격 | 결과 | 방어 레이어 |
|---|---|---|
| 로그인 브루트포스 | 60초 15회 후 429 | BT1 |
| 회원 스팸 게시글 | 60초 5회 후 차단 | BT2 |
| 회원 스팸 댓글 | 60초 10회 후 차단 | BT2 |
| CAPTCHA 교차 사용 | Purpose 불일치 탐지 | BT3 |
| CAPTCHA Flooding | 60초 30회 후 차단 | BT3 |
| curl API 직접 호출 | Risk 50+ 로그 + Rate Limit | BT4, BT5 |
| Referer 없는 API | API_DIRECT_CALL 로그 + Rate Limit | BT5 |
| 연속 고위험 패턴 | REPEATED_HIGH_RISK 로그 | BT6 |
| 정상 회원 활동 | 통과 (Rate Limit 내에서) | ✅ |
8. 개발자 API 가이드
플러그인 엔드포인트 Rate Limit
// 특정 작업에 Rate Limit 적용
if (!dx_bot_rate_limit('my_plugin_vote', 3, 60)) {
http_response_code(429);
exit(json_encode(array(
'success' => false,
'message' => '잠시 후 다시 시도해 주세요.',
)));
}
CAPTCHA 검증 + Purpose Binding
// 코어 DxCaptcha::verify() + Purpose 추가 검증
if (!dx_bot_check_captcha('my_form_submit')) {
dx_error('보안 문자를 확인해 주세요.', 400);
}
Risk Score 확인
// 현재 요청의 위험도 확인
$score = dx_bot_risk_score();
if ($score >= 70) {
// 고위험 — 추가 검증 요구
dx_error('비정상적인 요청입니다.', 403);
} elseif ($score >= 40) {
// 중위험 — CAPTCHA 요구
if (!dx_bot_check_captcha('high_risk_action')) {
dx_error('보안 확인이 필요합니다.', 400);
}
}
Bot 감사 로그 기록
dx_bot_log('MY_PLUGIN_BOT_DETECTED', 'action=vote user_id=' . $userId);
DX Security — Bot Challenge Automation Bypass 방어 v1.0.0 — DesignOneX https://designonex.com
라이선스
디자인원엑스 라이선스 참고
https://designonex.com/notice/view/1787577858493247