What All the Phuzz Is About: A Coverage-guided Fuzzer for Finding Vulnerabilities in PHP Web Applications 논문 리뷰

김윤지·2025년 9월 21일

논문 읽기 전.. 알아둬야 하는 것

커버리지 기반 퍼징이란?

커버리지(Coverage)는 퍼저가 테스트 입력을 보냈을 때 실제로 실행된 코드의 양을 의미한다.

1. 코드 커버리지란?

// 예시 PHP 코드
function processUser($input) {
    if ($input === "admin") {        // 라인 1
        return getAdminData();       // 라인 2  
    } else if ($input === "user") {  // 라인 3
        return getUserData();        // 라인 4
    } else {                         // 라인 5
        return "Invalid user";       // 라인 6
    }
}

커버리지 측정:
processUser("admin") 실행 시: 라인 1, 2 실행 → 2/6 라인 커버리지
processUser("user") 실행 시: 라인 1, 3, 4 실행 → 3/6 라인 커버리지
processUser("hacker") 실행 시: 라인 1, 3, 5, 6 실행 → 4/6 라인 커버리지

커버리지 기반 퍼징의 동작 원리

1단계: 초기 입력으로 시작

입력: checkout("user1", "normal_item", "")
커버리지: 라인 1,2,3,7,8,12,13,17 실행

2단계: 새로운 커버리지를 찾는 입력 우선시

입력: checkout("invalid_user", "normal_item", "")  
새 커버리지: 라인 4,5 추가 실행 → 이 입력을 더 변형해볼 가치가 있음!

입력: checkout("user1", "premium_item", "")
새 커버리지: 라인 14,15,16 추가 실행 → 이것도 흥미로운 경로!

3단계: 취약점 발견

// 만약 이런 코드가 있다면
if ($coupon === "ADMIN_SECRET") {    // 숨겨진 경로
    $price = 0;                      // 무료 구매!
    sql_query("SELECT * FROM users WHERE id = " . $userId);  // SQL 인젝션 취약점!
}

퍼저가 다양한 쿠폰 값을 시도하다가 "ADMIN_SECRET"을 발견하면,
새로운 커버리지 발생 → 이 입력이 특별함을 인식
SQL 인젝션 취약점 발견

즉, 커버리지를 최대화한다 = 프로그램의 모든 가능한 실행 경로를 탐색한다
커버리지 기반 퍼징 = 새로운 코드 경로를 실행하는 입력우선적으로 변형하여 테스트하는 방식
즉, "이 입력이 지금까지 실행 안 된 새로운 코드를 돌렸네? 그럼 이 입력을 기반으로 변형해보자!" 라는 전략!!!

연구 배경 및 목적

문제: 기존 커버리지 가이드 퍼징 연구는 주로 바이너리 애플리케이션에 집중되어 있고, 웹 애플리케이션(특히 PHP)에 대한 연구는 부족함
현실: PHP는 웹사이트의 75% 이상에서 사용되는 중요한 서버사이드 언어
기존 도구의 한계: 상용/무료 웹 애플리케이션 퍼저들은 주로 블랙박스 접근법을 사용하여 취약점 탐지 효과가 제한적

Phuzz 특징

전체 흐름

엔드포인트 수집 → 설정 생성 → 퍼징 실행 → 취약점 탐지

1. 엔드포인트 수집 단계
Browser & Crawler: 웹사이트를 탐색하며 API 엔드포인트 수집
HAR 파일: 수집된 HTTP 요청들을 저장하는 형식

2. 설정 생성 단계
HARgen: HAR 파일을 퍼징 설정으로 변환
Composegen: Docker 환경 설정 파일 생성

3. 퍼징 실행 단계
Fuzzer: 핵심 엔진
테스트 입력(후보) 생성
HTTP 요청으로 변환하여 전송
응답 분석 및 커버리지 수집
Login script: 인증이 필요한 경우 로그인 처리

4. 인프라 구성요소
Web server (Apache): HTTP 요청 처리
Database (MySQL): 웹앱이 필요로 하는 DB
Shared volume: 컨테이너들 간 정보 공유

1. Instrumentation 방식

소스코드 수정 불필요: 대상 애플리케이션이나 PHP 인터프리터, 관련 컴포넌트(데이터베이스 등) 수정 없이 동작
PHP 함수 후킹: UOPZ 확장을 사용하여 PHP 함수들을 런타임에 후킹
예외/에러 캐치: PHP 예외나 에러를 가로채어 취약점 탐지에 활용
인증/인가 우회: 함수 후킹을 통해 인증/인가 기능을 우회하여 더 많은 코드 커버리지 수집

2. 크롤러가 없는 end-point 시딩 방식

수동 접근법: 브라우저 DevTools를 사용해 HTTP 요청을 캡처하여 HAR 파일로 저장
자동 크롤링: Playwright 라이브러리 기반 헤드리스 크로미움 브라우저 사용
세밀한 제어: 퍼징 범위에 대한 더 정밀한 제어 가능

크롤러가 없는 end-point 시딩 방식이란..
일단 크롤러 기반인 기존의 웹 퍼저등의 동작 방식은 다음과 같다.

1. 웹 사이트 홈페이지에서 시작
2. 자동으로 링크를 따라가며 페이지 탐색
3. 발견한 폼이나 파라미터를 자동으로 수집
4. 수집된 정보로 퍼징 시작

예를들어 쇼핑몰 사이트(shop.com)에 크롤러를 돌리면 홈페이지 → 상품목록 → 상품상세 → 장바구니 → 결제페이지 로 자동 탐색 순으로 진행한다. 즉, 각 페이지의 폼 필드들을 자동으로 찾아서 퍼징대상으로 설정한다.

반면 크롤러가 없는 Phuzz의 새로운 방식은! 수동으로 엔드포인트를 수집한다.

1. 개발자/테스터가 직접 웹사이트를 사용
2. 브라우저 개발자도구로 HTTP 요청들을 캡처
3. 캡처된 요청들을 HAR 파일로 저장
4. 이 HAR 파일을 퍼저의 시드로 사용

구체적으로 예를들자면, 온라인 뱅킹 애플리케이션을 테스트 한다고 가정해보자. 다음과 같은 과정으로 퍼징을 진행한다.
1단계: 수동 탐색

개발자가 실제로 뱅킹 사이트를 사용:
- 로그인: POST /login (username, password)
- 계좌조회: GET /account/balance?account_id=12345
- 송금: POST /transfer (from_account, to_account, amount)
- 거래내역: GET /transactions?start_date=2024-01-01&end_date=2024-01-31

2단계: HTTP 요청 캡쳐
브라우저 F12 → Network 탭에서 다음과 같은 요청들이 기록된다.

POST /api/login HTTP/1.1
Content-Type: application/json
{
  "username": "john_doe",
  "password": "secret123"
}

GET /api/account/balance?account_id=12345 HTTP/1.1
Cookie: session=abc123...

POST /api/transfer HTTP/1.1
Cookie: session=abc123...
Content-Type: application/json
{
  "from_account": "12345",
  "to_account": "67890", 
  "amount": "1000"
}

3단계: HAR 파일로 저장
이 모든 요청들이 HAR(HTTP Archive)형식으로 저장된다.

4단계: 퍼징 설정 생성
Phuzz가 HAR 파일을 분석해서 다음과 같은 퍼징 설정을 생성한다.

{
  "target": "/api/transfer",
  "method": "POST",
  "cookies": {"session": "abc123"},
  "body_params": {
    "from_account": {"fuzz": true, "seeds": ["12345"]},
    "to_account": {"fuzz": true, "seeds": ["67890"]}, 
    "amount": {"fuzz": true, "seeds": ["1000"]}
  }
}

이렇게 되면 크롤러가 놓칠 수 있는 복잡한 인증 플로우나 AJAX 요청도 캡처 가능하다!!!

3. 포괄적인 취약점 탐지

서버사이드 취약점
1. SQL injection (SQLi)
Phuzz는 대상이 MySQL 데이터베이스를 쿼리하는 데 사용하는 4개의 함수에 훅을 건다. Fuzzer에 의해 제어되는 입력은 결국 이러한 함수에 전달되는 잘못된 SQL 문을 초래하여 감지 가능한 예외 또는 오류를 발생시킨다.

2. Command injection (RCE)
시스템의 셸(예: /bin/sh)에 입력을 전달하는 4개의 함수를 훅하고 구문 오류, 알 수 없는 명령 또는 잘못된 파일 경로와 같은 잘못된 명령 또는 인수를 나타내는 오류 메시지를 확인하여 이러한 취약점을 식별한다.

3. Path traversal (PaTr)
파일 또는 디렉토리 관련 작업을 수행하기 위해 파일 이름 또는 경로를 인수로 사용하는 총 48개의 함수를 훅하여 경로 탐색 취약점을 발견한다.

4. Insecure deserialization (IDes)
unserialize() 함수에 대한 잘못된 입력은 Phuzz에 의해 감지되는 오류를 발생시켜 잠재적인 PHP 객체 삽입 취약점을 식별한다.

5. External entity injection (XXE)
PHP 내장 XML 파서의 두 함수는 취약한 구성 (LIBXML_NOENT)에서 잘못된 XML 엔티티의 처리를 감지하기 위해 훅이 걸리게 된다.

클라이언트사이드 취약점
1. Cross-site scripting (XSS)
특정 마커가 후보 변형 중에 삽입되고 나중에 반환된 페이지의 DOM에서 존재 여부를 확인하여 Phuzz가 반사 및 영구 XSS 취약점을 탐지할 수 있도록 한다.

2. Open redirection (OpRe)
XSS와 유사하게, open redirection 취약점은 HTTP 응답을 분석하여 탐지된다.
Phuzz는 리디렉션 범위 (300-399)에 대한 상태 코드와 fuzzer에 의해 제어되는 입력에 대한 Location 헤더에서 제공하는 리디렉션 URL을 확인한다.

4. Phuzz Test case

전체 흐름

시드 → 점수 매기기 → 최고 점수 선택 → 변형 → 평가 → 반복

1. 시드 (Seeds)

  • 초기 입력값: 퍼징 시작을 위한 기본 HTTP 요청 정보
  • 설정 가능: 파라미터별로 "고정" 또는 "퍼즈" 지정 가능
  • 예시: username=admin&password=123 → username은 고정, password는 퍼즈

2. 점수 매기기 & 선택

  • 점수 기준: 새로운 코드 경로와 라인을 얼마나 실행했는지
  • 선택 전략: 가장 높은 점수를 받은 입력을 우선적으로 변형
  • 에너지 기반: 좋은 입력은 더 많이 변형, 나쁜 입력은 적게 변형

3. 변형 (Mutation)
기본 변형 (10가지)

  • 문자 추가/삭제/교체/순서바꾸기
  • 예시: admin → admi, xadmin, adm1n

특수 변형 (3가지)

  • 프로토콜 접두사: http://, https:// 추가 (오픈 리다이렉션 탐지용)
  • 경로 순회: ../, /etc/passwd 추가 (경로 순회 탐지용)
  • XSS 페이로드: script 태그 등 추가(XSS 탐지용)

4. 요청 준비

  • HTTP 요청 생성: 변형된 파라미터를 실제 HTTP 요청으로 변환
  • 다양한 형식 지원: GET 쿼리, POST 본문, JSON, 쿠키 등

5. 병렬 동기화

  • 중복 방지: 여러 퍼저가 동시에 돌아도 같은 테스트는 한 번만 수행
  • 해시 기반: 각 테스트 케이스의 고유 해시로 중복 체크

평가 결과

1. 알려진 취약점으로 테스트

테스트 대상: bWAPP, DVWA, XVWA, WackoPicko, WordPress 플러그인 22개 (총 87개 취약점)
비교 도구: BurpSuite Pro, ZAP, Wapiti, WFuzz
결과: Phuzz가 99%의 취약점을 탐지하여 다른 도구들보다 24%-38% 더 효과적

2. zero-day 취약점 발견

대상: 인기 WordPress 플러그인 115개 (3억 활성 설치)
API 엔드포인트: 1090개 퍼징
결과: 24개의 유효한 보안 이슈 발견 (BurpSuite의 2배), 2개의 새로운 CVE 할당 (CVE-2023-6294, CVE-2023-6295)

그래서 Phuzz가 무엇이냐!

Phuzz는 PHP 웹 애플리케이션에 특화된 커버리지 기반 그레이박스 퍼저로, 기존 바이너리 애플리케이션 중심의 퍼징 연구 한계를 극복하고자 개발되었다.
퍼저의 핵심 원리는 대상 애플리케이션의 소스코드나 관련 컴포넌트를 수정하지 않고도 PHP 인터프리터 레벨에서 투명한 계측을 수행하는 것이다. UOPZ 확장을 활용한 함수 후킹 기법을 통해 취약점과 관련된 PHP 함수들을 실시간으로 모니터링하고, 예외나 에러를 캐치하여 서버사이드 취약점을 탐지한다.

PHP 인터프리터 레벨이 무엇인가
우선 PHP의 실행 구조는 PHP 소스코드 → PHP 인터프리터 → 실행 결과 이다.
소스코드가 미리 기계어로 변환되지 않고 실행 시점에 PHP 인터프리터가 코드를 한 줄씩 읽어서 해석하고 실행한다.

UOPZ가 무엇인가
UOPZ는 PHP 확장 모듈로, 실행 중인 PHP 코드의 동작을 런타임에 수정할 수 있게 해준다.

기술적 구현

아키텍처 구성요소

1. Browser & Crawler: 엔드포인트 수집
2. HARgen: HAR 파일에서 퍼저 설정 파일 생성
3. Composegen: Docker Compose 파일 생성
4. Fuzzer: 핵심 퍼징 엔진
5. 공유 볼륨: 컨테이너 간 정보 교환
6. 웹서버 & 데이터베이스: 테스트 환경

취약점 탐지 방법

함수 후킹: 48개의 파일 관련 함수, 4개의 SQL 함수 등을 후킹
예외/에러 분석: PHP 예외나 에러 메시지를 분석하여 취약점 판별
HTTP 응답 분석: XSS, 오픈 리다이렉션 등 클라이언트사이드 취약점 탐지

한계점

복잡한 취약점: 다단계 액션이 필요한 복잡한 취약점 지원 제한
PHP 표현식: eval, require 등 PHP 표현식 기반 취약점은 간접적으로만 탐지
DOM 기반 XSS: UOPZ와 webFuzz 한계로 인한 일부 DOM XSS 탐지 제한

profile
지존해커

0개의 댓글