본문으로 건너뛰기

59. 웹 애플리케이션 퍼징: 숨겨진 버그 찾기

웹 퍼징은 요청 수를 늘리는 일이 아니라 무엇이 달라졌을 때 애플리케이션의 의미가 달라지는지 찾는 실험이다. 승인된 테스트 환경, CTF, 또는 자기 소유 서비스에서만 실행한다. 운영 서비스에 대량 요청을 보내거나 제한을 우회하기 위해 프록시를 돌리는 것은 퍼징이 아니라 장애 유발이다.

질문을 먼저 좁힌다

숨겨진 경로를 찾는지, 파라미터의 타입 경계를 확인하는지, 인증 상태에 따른 차이를 비교하는지에 따라 단어 목록과 판정 기준이 달라진다. 기준 응답을 먼저 저장하고 상태 코드뿐 아니라 길이, 제목, 위치 헤더, JSON 키, 응답 시간의 변화를 비교한다. 404가 모든 미존재 경로에서 같은 모양인지 확인하지 않으면 정상적인 오류 페이지를 결과로 오인한다.

ffuf를 작은 실험으로 사용하기

ffuf -w ./wordlists/common.txt \
-u http://127.0.0.1:8080/FUZZ \
-mc 200,204,301,302,307,401,403 \
-fs 1234 -t 10 -rate 20 -of json -o results.json

-fs 1234는 기준 404의 크기를 확인한 뒤 적용한 예다. 대상마다 달라지므로 복사해 쓰는 상수가 아니다. 결과가 나오면 브라우저나 curl로 재현하고, 인증이 필요한 경로와 공개 경로를 분리한다. 가상 호스트나 헤더 퍼징은 소유한 테스트 DNS와 명시된 범위에서만 한다.

파라미터 이름을 찾을 때도 속도를 목적처럼 취급하지 않는다.

ffuf -w ./wordlists/params.txt \
-u 'http://127.0.0.1:8080/search?FUZZ=test' \
-mc all -fs 987 -t 5 -rate 10

POST 요청은 콘텐츠 타입과 CSRF 토큰을 포함한 실제 요청을 기준으로 만든다. 셸에서 &가 해석되지 않도록 URL을 따옴표로 감싼다.

변형보다 관찰이 중요하다

디렉터리 발견 뒤에는 한 경로의 확장자만 늘어놓기보다 애플리케이션이 실제로 사용하는 파일명 규칙을 추출한다. 자바스크립트 번들, OpenAPI 문서, 라우팅 로그, 테스트 픽스처가 더 좋은 단어 목록을 제공할 수 있다. sort -u로 중복을 줄이되 출처를 기록한다.

중복 파라미터는 보안 우회 문자열이 아니라 파서 간 불일치를 찾는 테스트다. 랩에서 다음 요청을 보내 프런트엔드, 프록시, 백엔드가 같은 값을 보는지 비교한다.

curl -i 'http://127.0.0.1:8080/api/item?id=1&id=2'
curl -i 'http://127.0.0.1:8080/api/item?id[]=1&id[]=2'

응답 차이가 발견되면 어느 계층이 첫 값·마지막 값·배열을 선택했는지 로그로 확인한다. 차이 자체가 취약점은 아니며, 권한·가격·리소스 식별자 같은 보안 결정에 영향을 줄 때 의미가 생긴다.

레이트 리밋과 안전장치

테스트 계획에 요청 예산, 동시성, 중단 조건을 적는다. 429, 오류율 상승, 지연 증가, 서버 자원 경고가 보이면 즉시 줄인다. -rate와 낮은 -t로 시작하고, 대상이 제공한 테스트 창과 연락처를 사용한다. IP 로테이션은 제한 회피가 아니라 승인된 분산 테스트에서만 정당화된다.

ffuf -w ./wordlists/common.txt \
-u http://127.0.0.1:8080/FUZZ \
-p 0.3-0.8 -t 3 -rate 5 -ac

-ac 자동 보정도 기준 응답을 숨길 수 있으므로, 전후의 필터와 기준 응답을 사람이 검토한다. 자동 결과를 취약점 목록으로 바로 변환하지 말고, 각 후보를 최소 요청으로 재현한다.

결과를 증명하는 형식

각 발견에는 범위, 재현 요청, 기준과 다른 관찰값, 보안 영향, 오탐을 배제한 이유, 수정 후 기대하는 회귀 테스트를 남긴다. 예를 들어 /admin403을 반환했다는 사실만으로 접근 제어 우회가 아니다. 인증 없는 요청, 정상 사용자, 관리자 세 상태를 비교해 실제 권한 차이를 확인해야 한다.

퍼징의 성과는 가장 많은 결과가 아니라 가장 적은 요청으로 신뢰할 수 있는 차이를 설명하는 데 있다. 도구는 그 차이를 찾는 손이고, 어떤 차이가 위험한지 판단하는 것은 테스트 설계의 몫이다.