양식을 실제로 보호하는 것: CAPTCHA, 허니팟, 시간 함정, CSRF
대부분의 문의 양식은 하나의 스팸 방지 기법에 의존하며, 그중 많은 기법은 가장 단순한 봇만 막습니다. 각 보호 계층이 무엇을 막고 어떤 비용을 수반하며 어떤 조합이 합리적인지 알아봅니다.
문의 양식 스팸은 사람이 직접 타이핑해서 보내는 경우가 드뭅니다. 대부분 소프트웨어가 양식을 찾아 모든 필드를 채우고 결과를 수천 번 전송합니다. 여러 방어 수단이 있으며 각각 매우 다른 지점에서 작동합니다. 각 수단의 실제 역할을 알면 두 가지 실수를 피할 수 있습니다. 실질적인 보호가 없는 양식과, 너무 엄격하게 막아서 실제 사용자마저 포기하는 양식입니다.
- 허니팟: 모든 필드를 채우는 단순한 봇
- 시간 함정: 로드 직후 즉시 제출하는 스크립트
- CAPTCHA: 대부분의 범용 자동화
- CSRF 토큰: 엔드포인트로 직접 보내는 요청
- 요청 빈도 제한: 한 출처에서 몰아치는 제출
- 작업 증명: 추적이나 퍼즐 없이 저비용 대량 제출에 대응
- 서버 측 점검: 브라우저를 우회하는 모든 요청
- 표적화된 봇은 건너뜁니다. 잘못 숨기면 화면 낭독기가 읽어줍니다
- 기다리는 봇은 통과합니다. 서버 측 서명이 없으면 쉽게 위조할 수 있습니다
- 모든 사용자에게 장벽이 되고 접근성을 해칩니다. 대개 제삼자가 관여하며 풀이 대행 서비스도 있습니다
- 페이지를 먼저 불러오는 봇도 유효한 토큰을 받습니다
- 여러 IP 주소에 분산된 스팸
- 컴퓨팅 자원을 가진 끈질긴 발신자는 통과할 수 있습니다. JavaScript가 필요합니다
- 단독으로 모든 것을 막지는 못하지만, 이것이 없으면 다른 계층은 모두 장식에 불과합니다
허니팟과 시간 함정: 보이지 않는 필터
허니팟은 CSS로 숨긴 “website” 필드처럼 사람에게 보이지 않는 추가 필드입니다. 단순한 봇은 모든 필드를 채우므로 허니팟이 채워져 있으면 자동화를 의심하고 서버가 조용히 메시지를 버릴 수 있습니다. 해당 사이트를 겨냥해 만든 봇이나 브라우저처럼 페이지를 렌더링하는 봇은 이를 건너뜁니다. 올바르게 숨겨야 합니다. 단지 화면 밖으로 옮긴 필드는 화면 낭독기가 읽거나 Tab 키로 접근하거나 자동 완성이 채울 수 있습니다. aria-hidden, tabindex -1 및 autocomplete off를 사용하고, 우연히 도달한 사람에게 비워 두라고 안내하는 중립적인 레이블도 제공하십시오.
시간 함정은 양식을 전달한 시각을 기록하고 비현실적으로 빠른 제출을 거부합니다. 사람은 읽고 입력하는 데 몇 초가 걸리지만 많은 스크립트는 일 초도 되지 않아 전송합니다. 타임스탬프는 서버에서 확인하고, 예를 들어 서명하거나 세션에 보관하여 조작을 방지해야 합니다. 단순한 숨겨진 시간 필드는 봇이 다시 쓰면 그만입니다. 자동 완성을 사용하는 실제 사용자도 빠를 수 있으므로 기준 시간은 짧게 유지하십시오. 단순히 기다리는 봇은 통과합니다. 시간 함정은 필터이지 벽이 아닙니다.
CAPTCHA: 효과적이지만 대가가 있습니다
CAPTCHA는 이미지 퍼즐부터 백그라운드 검사까지 다양한 방식으로 봇이 아니라는 증명을 요구합니다. 대표적인 서비스는 reCAPTCHA, hCaptcha, Cloudflare Turnstile 및 Friendly Captcha입니다. 대부분의 범용 자동화를 막기 때문에 널리 사용됩니다. 그러나 눈에 보이는 모든 퍼즐은 일부 방문자가 포기하게 되는 장벽입니다. 대부분의 서비스는 제삼자 스크립트를 불러오므로 개인정보 보호와 동의 문제도 생깁니다. CAPTCHA는 올바르게 설정해야만 도움이 됩니다. 공개 테스트 사이트 키, 스크립트 없는 위젯, 서버가 검증하지 않는 토큰은 보호처럼 보일 뿐 보호가 아닙니다. formexposed.com의 무료 점검은 이러한 오류를 외부에서 찾아냅니다.
접근성도 대가의 일부입니다. 이미지 퍼즐은 시각장애인과 많은 저시력 사용자를 배제하고, 오디오 대안은 시청각장애인에게 도움이 되지 않으며, 까다로운 논리 문제는 인지 장애가 있는 사람에게 부담을 줍니다. WCAG 2.2 성공 기준 1.1.1은 CAPTCHA의 목적을 설명하는 텍스트 대체와 서로 다른 감각을 위한 대안 형식을 요구합니다. 백그라운드 검사는 이런 문제 대부분을 피하지만 의심스러운 상황에서는 다시 시각적 퍼즐로 전환하는 경우가 많습니다. 이 경로도 키보드와 화면 낭독기로 테스트하십시오.
CSRF 토큰: 스팸보다 요청 위조를 막는 장치
CSRF 토큰은 서버가 양식에 넣고 되돌려 받기를 기대하는 임의의 값입니다. 다른 웹사이트가 방문자의 브라우저로 의도하지 않은 요청을 보내게 하는 교차 사이트 요청 위조를 막기 위해 설계되었습니다. 공개 문의 양식에서는 부수적인 효과도 있습니다. 페이지를 불러오지 않고 양식 주소로 직접 제출하는 봇을 거부합니다. 페이지를 가져와 토큰을 함께 보내는 봇은 통과합니다. 대부분의 프레임워크와 양식 플러그인은 원래 CSRF 토큰을 포함합니다. 켜 두되 스팸 방지 수단으로 계산하지는 마십시오.
서버에서 수행해야 할 일
- 필수 여부, 길이, 이메일 형식, 그리고 메일 헤더에 들어가는 필드에 줄바꿈이 없는지 등 모든 필드를 서버에서 다시 검증하십시오.
- 매번 제출할 때 발급 서비스 또는 자체 코드로 CAPTCHA와 작업 증명 토큰을 검증하고 재사용된 토큰을 거부하십시오.
- IP 주소와 시간 구간별로 제출 횟수를 제한하십시오. 한 출처의 대량 요청은 막을 수 있지만 여러 주소에 분산된 스팸에는 다른 계층이 필요합니다.
- 작업 증명을 고려하십시오. 브라우저가 전송 전에 작은 연산 과제를 풉니다. 방문자에게 퍼즐이 보이지 않고 추적도 없지만 대량 제출의 비용은 커집니다.
합리적인 조합: 두세 개의 계층
- 1보이지 않는 계층부터 시작하십시오. 접근성을 고려한 허니팟과 서명된 시간 함정을 두고 둘 다 서버에서 확인합니다.
- 2하나의 출처가 양식에 대량 요청을 보내지 못하도록 IP 주소별 요청 빈도 제한을 추가하십시오.
- 3표적화된 스팸이 계속 통과한다면 작업 증명이나 CAPTCHA를 추가하십시오. 가능하면 눈에 보이는 퍼즐이 없고 접근 가능한 대안이 있는 것을 선택하십시오.
- 4프레임워크가 제공하는 CSRF 토큰도 유지하십시오. 방어 수단보다는 추가 이점으로 생각하십시오.
- 5키보드만 사용하거나 화면 낭독기 또는 휴대전화로 방문자처럼 결과를 테스트하고 실제 메시지가 여전히 도착하는지 확인하십시오.
많은 사이트에서는 허니팟, 시간 함정 및 요청 빈도 제한만 조합해도 눈에 보이는 장벽 없이 대부분의 범용 스팸을 제거할 수 있습니다. CAPTCHA는 그것으로 부족할 때를 위한 예비 수단입니다. WordPress에서는 무료 formexposed 플러그인이 Google 없이 허니팟, 시간 검사 및 작업 증명을 결합합니다. 어떤 계층이 존재하는지, CAPTCHA가 유효하게 설정되어 있는지 등 외부에서 양식이 어떻게 보이는지 알아보려면 formexposed.com에서 계정 없이 도메인만으로 무료 점검을 할 수 있습니다. 서버 코드는 볼 수 없으므로 서버 측 부분은 직접 확인해야 합니다.