목차 열기
05. 보안 챌린지(VQA) 자동 풀이
방어 시스템은 의심 세션에게 캐치볼 형태의 VQA 챌린지를 띄웁니다. 공격 에이전트는 이를 LLM이나 비전 모델 호출 없이 결정론 규칙으로 풀이합니다.
챌린지 구조
| 항목 | 내용 |
|---|---|
| 유형 | 공간·시간 판정 기반 인터랙티브 챌린지 |
| 구성 | 3개 서브 라운드 |
| 과제 | 글러브를 착지 표시까지 드래그 후 타이밍 조건 만족 시 놓기 |
| 판정 축 | 공간 판정 (위치 정확도) + 시간 판정 (타이밍 정확도) |
| 2중 게이트 | 정답 좌표·시각 + 푸는 과정의 마우스 궤적 자연스러움 |
진행 흐름 (방어 측)
- 의심 세션 감지 시 챌린지 팝업 표시
- 사용자가 시작 버튼 클릭
- 글러브가 화면에 등장, 인디케이터가 움직이기 시작
- 사용자가 글러브를 착지 표시까지 드래그 + 타이밍 조건 만족 시 놓기
- 서버가 공간·시간 판정 및 궤적 검증
- 3개 서브 라운드 통과 시 챌린지 완료
왜 결정론 규칙인가 (vs LLM · 비전 모델)
| 기준 | 결정론 규칙 (화면 요소 좌표 기반) | LLM / 비전 모델 |
|---|---|---|
| 결정 지연 | ms 이내 (화면 상태 1회 조회) | 호출당 수백 ms ~ 수 초 → 타이밍 놓침 |
| 정확도 | 픽셀 단위 (요소 경계 상자) | 해상도·배경·폰트에 따라 추론 흔들림 |
| 탐지 회피 | 브라우저 내 완결 | 네트워크·CPU 패턴에 흔적 남김 |
| 재현성 | 완전 결정론 | 같은 입력에 다른 출력 가능성 |
속도의 중요성
챌린지는 타이밍이 생명입니다. 조건이 만족되는 순간은 수십 ms 단위로 지나갑니다. LLM 호출이 중간에 끼어드는 순간 그 시점을 놓칩니다. 화면 요소 좌표를 직접 읽으면 ms 안에 결정이 끝납니다.
풀이 파이프라인
전체 흐름
[챌린지 감지]
↓ (화면 요소 가시성 확인)
[서브 라운드 반복, 최대 5회]
├─ 준비 상태 안정화 대기 (최대 3초, 120ms 폴링)
├─ 시작 버튼 클릭
├─ 글러브 가시화 대기 (최대 12초, 100ms 폴링)
├─ 거리 계산 (글러브 ↔ 착지 마커)
├─ 필요 시 중간 지점(waypoint) 경유 드래그
├─ 타이밍 인디케이터 조건 만족 순간 놓기 (최대 10초 대기)
├─ 드래그 후 위치 재확인 (최대 3회 재드래그)
└─ 결과 판정
├─ 성공 → 다음 라운드
├─ 재시도 가능 실패 → 1.2초 후 다음 시도
└─ 치명적 실패 → 즉시 중단
↓ (3회 성공)
[챌린지 통과] → 이전 상태로 복귀
단계별 세부
1. 감지
- 화면 요소 가시성 확인
- 감지 시
last_non_security_state에 현재 상태 저장 - FlowState를 S3으로 전환
2. 준비 상태 안정화 대기
| 항목 | 값 |
|---|---|
| 최대 대기 | 3초 |
| 폴링 주기 | 120 ms |
| 조건 | 준비 상태 안정화 플래그 감지 |
3. 시작 버튼 클릭
- 첫 라운드는 명시적 "시작" 버튼 클릭
- 이후 라운드는 자동 전이 또는 재클릭
4. 글러브 가시화 대기
| 항목 | 값 |
|---|---|
| 최대 대기 | 12초 |
| 폴링 주기 | 100 ms |
타임아웃 시 glove_timeout 실패 처리.
5. 드래그
글러브와 착지 마커 좌표를 획득해 직선 거리를 계산합니다.
| 거리 | 동작 |
|---|---|
| ≥ 24 px | 엔게이징 포인트(약 12% 지점) 경유해 자연스러운 곡선으로 이동 |
| < 24 px | 직접 이동 |
드래그 동작
시작점 이동 → 8~16ms 대기 → 마우스 누르기
↓
엔게이징 포인트 이동 → 6~14ms 대기
↓
최종 포인트 이동 → 6~14ms 대기
↓
(타이밍 조건 충족 시) 마우스 놓기
6. 타이밍 윈도우 폴링
| 항목 | 값 |
|---|---|
| 최대 폴링 시간 | 10초 |
| 폴링 주기 | 50 ms |
조건식
inWindow ∧ rising ∧ indicatorCY ≤ threshold
inWindow: 인디케이터가 유효 윈도우 안에 있는가rising: 인디케이터가 상승 중인가indicatorCY ≤ threshold: Y 좌표가 임계값 이하인가
7. 드래그 후 재확인 (Drag Verify)
| 동작 | 내용 |
|---|---|
| 조건 | 마우스 누른 직후 글러브 실제 위치 재확인 |
| 허용 오차 | 24 px |
| 초과 시 | 현재 위치에서 재드래그 (최대 3회) |
8. 결과 폴링
마우스 놓기 후 최대 8초 동안 서브 라운드 결과 폴링.
서브 라운드 결과 분류
| 결과 | 의미 | 다음 동작 |
|---|---|---|
success | 공간·시간 판정 모두 통과 | 다음 라운드 |
transitioning | 다음 라운드 전환 중 | 잠시 대기 |
fail | 드롭했지만 판정 빗나감 | 1.2초 후 재시도 |
terminal_fail | 재시도 불가 | 즉시 중단 → SX(BLOCKED) |
drop_timeout | 인디케이터 조건 미충족 | 1.2초 후 재시도 |
glove_timeout | 글러브가 정해진 시간 내 가시화 안 됨 | 1.2초 후 재시도 |
positions_not_found | 글러브·마커 좌표 획득 실패 | 1.2초 후 재시도 |
drag_verify_failed | 드래그 후 위치 재확인 실패 | 1.2초 후 재시도 |
보정 장치
타이밍 엄격화 (Arming)
| 항목 | 내용 |
|---|---|
| 원리 | 인디케이터가 상위 임계값(약 60%)을 한 번 이상 넘긴 기록이 있어야만 놓기 허용 |
| 해결한 문제 | 조건 진입 직후 섣부른 놓기로 인한 판정 실패 |
| 플래그 | vqa-require-arm |
드래그 후 재확인 (Drag Verify)
| 항목 | 내용 |
|---|---|
| 원리 | 마우스 누른 직후 글러브 실제 위치 재확인, 목표와 거리 ≥ 24 px이면 재드래그 (최대 3회) |
| 해결한 문제 | 드래그 중 마우스 위치 오차·손떨림으로 착지 실패 |
| 플래그 | vqa-drag-verify |
동시 풀이 제한
| 항목 | 내용 |
|---|---|
| 원리 | 세마포어로 스웜 차원 직렬화 |
| 해결한 문제 | 동시 다발 풀이의 비정상 노이즈 → 서버 과민반응 회피 |
| 플래그 | vqa-concurrency N |
동시성 제어 흐름
에이전트가 S3(챌린지) 진입
↓
세마포어 획득 시도
├─ 성공 → 챌린지 풀이 시작
└─ 대기 중인 다른 에이전트 있음 → 대기열에 들어감
↓
풀이 완료 또는 실패
↓
세마포어 해제
| 매개변수 | 기본값 | 의미 |
|---|---|---|
vqa-concurrency | 1 | 스웜 내 동시 챌린지 풀이 가능 에이전트 수 |
vqa-start-jitter-ms | 0 | 에이전트별 시작 시각 결정론적 jitter |
종료 처리
| 조건 | 동작 |
|---|---|
| 3회 서브 라운드 성공 | 챌린지 통과 → last_non_security_state로 복귀 |
terminal_fail 발생 | 즉시 중단 → SX(BLOCKED) |
| 5회 재시도 모두 실패 | 풀이 실패 → SX(BLOCKED) |
기록되는 이벤트
| 이벤트 | 내용 |
|---|---|
CHALLENGE_UI_SOLVER_START | 챌린지 풀이 시작 (팝업 감지) |
CHALLENGE_START_CLICKED | 시작 버튼 클릭 |
CHALLENGE_SUB_ROUND_RESULT | 서브 라운드 결과 (각 시도마다) |
CHALLENGE_PASSED | 챌린지 전체 통과 |
CHALLENGE_FAILED | 챌린지 실패 (재시도 불가) |
참조
- 02-workflow-states — 인터럽트 복귀 패턴
- 06-swarm-infrastructure — 동시성 제어 구조