Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
PHP-Fuzzer — PHP 라이브러리용 에지 커버리지 기반 퍼저로, 크래시, 타임아웃, 경고를 통해 버그를 탐지합니다. 코퍼스 관리, 크래시 최소화, 코드 커버리지 보고서를 지원합니다. | Kitploit
도구/GitHubGitHub/nikic/php-fuzzer
Dynamic Analysis (Sandboxing)Vulnerability AnalysisCode AnalysisFuzzing
GitHubnikic/php-fuzzer

PHP-Fuzzer

PHP 라이브러리용 에지 커버리지 기반 퍼저로, 크래시, 타임아웃, 경고를 통해 버그를 탐지합니다. 코퍼스 관리, 크래시 최소화, 코드 커버리지 보고서를 지원합니다.

저장소 보기
441187개월 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

PHP 퍼저

이 라이브러리는 PHP용 퍼저를 구현하며, 라이브러리(특히 파싱 라이브러리)에 '무작위' 입력을 제공하여 버그를 찾는 데 사용할 수 있습니다. 엣지 커버리지 계측의 피드백을 사용하여 새로운 코드 경로가 방문되도록 '무작위' 입력의 선택을 안내합니다.

설치

Phar (권장): 이 라이브러리의 phar 패키지를 릴리스 페이지에서 다운로드할 수 있습니다. phar를 사용하는 것이 권장되는 이유는 PHP-Parser를 사용하는 라이브러리와의 의존성 충돌을 피할 수 있기 때문입니다.

Composer: composer global require nikic/php-fuzzer

사용법

먼저, 대상 함수의 정의가 필요합니다. 다음은 microsoft/tolerant-php-parser에서 버그를 찾기 위한 대상 예시입니다:

root@kitploit:~
<?php // target.php

/** @var PhpFuzzer\Config $config */

require 'path/to/tolerant-php-parser/vendor/autoload.php';

// Required: The target accepts a single input string and runs it through the tested
//           library. The target is allowed to throw normal Exceptions (which are ignored),
//           but Error exceptions are considered as a found bug.
$parser = new Microsoft\PhpParser\Parser();
$config->setTarget(function(string $input) use($parser) {
    $parser->parseSourceFile($input);
});

// Optional: Many targets don't exhibit bugs on large inputs that can't also be
//           produced with small inputs. Limiting the length may improve performance.
$config->setMaxLen(1024);
// Optional: A dictionary can be used to provide useful fragments to the fuzzer,
//           such as language keywords. This is particularly important if these
//           cannot be easily discovered by the fuzzer, because they are handled
//           by a non-instrumented PHP extension function such as token_get_all().
$config->addDictionary('example/php.dict');

퍼저는 초기 '관심 있는' 입력의 코퍼스에 대해 실행되며, 예를 들어 기존 단위 테스트를 기반으로 시드될 수 있습니다. 코퍼스가 지정되지 않으면 임시 코퍼스 디렉토리가 대신 생성됩니다.

root@kitploit:~
# Run without initial corpus
php-fuzzer fuzz target.php
# Run with initial corpus (one input per file)
php-fuzzer fuzz target.php corpus/

퍼징이 중단되면, 동일한 코퍼스 디렉토리를 지정하여 나중에 다시 시작할 수 있습니다.

크래시가 발견되면 crash-HASH.txt 파일에 기록됩니다. 원래 발견된 형태로 제공되며, 불필요하게 복잡하거나 크래시와 관련 없는 조각을 포함할 수 있습니다. 따라서 먼저 크래시 입력을 축소하는 것이 좋습니다:

root@kitploit:~
php-fuzzer minimize-crash target.php crash-HASH.txt

그러면 점점 더 작아지는 minimized-HASH.txt 파일의 시퀀스가 생성됩니다. 크래시 입력에 대해 생성된 예외 추적을 빠르게 확인하려면 run-single 명령을 사용할 수 있습니다:

root@kitploit:~
php-fuzzer run-single target.php minimized-HASH.txt

마지막으로, 특정 코퍼스의 입력을 실행할 때 대상에서 어떤 코드 블록이 적중되는지 보여주는 HTML 코드 커버리지 보고서를 생성할 수 있습니다:

root@kitploit:~
php-fuzzer report-coverage target.php corpus/ coverage_dir/

추가 구성 옵션은 php-fuzzer --help로 확인할 수 있습니다.

퍼저가 실행되는 동안, 단일 출력 줄을 사용하여 지속적으로 상태를 보고합니다. 이 줄은 다음 순서로 다음 부분으로 구성됩니다:

  1. NEW 또는 REDUCED: 이 상태 줄을 트리거한 동작. NEW는 새 입력이 코퍼스에 추가되었음을 나타내고, REDUCED는 기존 코퍼스 항목이 더 짧은 입력으로 대체되었음을 나타냅니다.
  2. run: N: 퍼저가 시작된 이후 수행된 총 퍼징 반복(대상 실행) 횟수
  3. (N/s): 초당 실행 횟수로 측정된 현재 실행 속도
  4. ft: N: 지금까지 발견된 고유 특성의 총 수
  5. (N/s): 퍼저가 시작된 이후 초당 발견된 새 특성의 평균 개수
  6. corp: N: 현재 코퍼스에 저장된 관심 있는 입력의 수
  7. (%s): 코퍼스에 있는 모든 입력의 총 크기
  8. len: %d/%d: 첫 번째 숫자는 동작을 트리거한 현재 입력의 길이(바이트)이고, 두 번째 숫자는 현재 허용된 최대 입력 길이입니다.
  9. t: 퍼저가 시작된 이후 경과된 총 시간(초)
  10. mem: PHP 프로세스의 현재 메모리 사용량

버그 유형

퍼저는 기본적으로 세 가지 종류의 버그를 탐지합니다:

  • 퍼징 대상이 던진 Error 예외. Exception 예외는 잘못된 입력에 대한 정상적인 결과로 간주되는 반면, 잡히지 않은 Error 예외는 항상 프로그래밍 오류를 나타냅니다. 이는 예를 들어 null에 대해 메서드를 호출할 때 PHP 자체에서 가장 일반적으로 발생합니다.
  • 던져진 알림 및 경고(억제되지 않은 경우). 퍼저는 이를 Error 예외로 변환하는 오류 핸들러를 등록합니다.
  • 시간 초과. 대상이 지정된 시간 초과(기본값: 3초)보다 오래 실행되면 대상이 무한 루프에 빠진 것으로 간주됩니다. 이는 pcntl_alarm()과 시간 초과 시 Error를 던지는 비동기 신호 핸들러를 사용하여 구현됩니다.

특히, 이들 중 어느 것도 대상의 출력이 올바른지 확인하지 않으며, 단지 대상이 심각하게 잘못 동작하지 않음을 판단합니다. 출력 정확성을 확인하는 한 가지 방법은 동일한 결과를 생성해야 하는 두 가지 다른 구현을 비교하는 것입니다:

root@kitploit:~
$fuzzer->setTarget(function(string $input) use($parser1, $parser2) {
    $result1 = $parser1->parse($input);
    $result2 = $parser2->parse($input);
    if ($result1 != $result2) {
        throw new Error('Results do not match!');
    }
});

기술적 세부사항

이 퍼저의 많은 기술적 세부 사항은 LLVM 프로젝트의 libFuzzer를 기반으로 합니다. 다음은 몇 가지 구현 세부 사항을 설명합니다.

계측

효율적으로 작동하려면 퍼징은 특정 퍼징 입력을 테스트하는 동안 실행된 코드 경로에 대한 피드백이 필요합니다. 이 커버리지 피드백은 퍼징 대상을 "계측"하여 수집됩니다. include-interceptor 라이브러리는 포함된 모든 파일의 코드를 즉시 변환하는 데 사용됩니다. PHP-Parser 라이브러리는 코드를 구문 분석하고 추가 계측 코드를 삽입해야 하는 모든 위치를 찾는 데 사용됩니다.

모든 기본 블록 내에서 다음 코드가 삽입되며, 여기서 BLOCK_INDEX는 블록별 고유 정수입니다:

root@kitploit:~
$___key = (\PhpFuzzer\FuzzingContext::$prevBlock << 28) | BLOCK_INDEX;
\PhpFuzzer\FuzzingContext::$edges[$___key] = (\PhpFuzzer\FuzzingContext::$edges[$___key] ?? 0) + 1;
\PhpFuzzer\FuzzingContext::$prevBlock = BLOCK_INDEX;

이는 블록 인덱스가 최대 28비트라고 가정하고 실행 중에 관찰된 (prev_block, cur_block) 쌍의 수를 계산합니다. 생성된 코드는 초기화되지 않은 엣지 카운트를 처리해야 하고 정적 속성을 사용하기 때문에 상당히 비쌉니다. 향후에는 커버리지 피드백을 훨씬 더 효율적으로 수집할 수 있는 PHP 확장을 만드는 것이 가능할 것입니다.

경우에 따라 기본 블록이 표현식의 일부인 경우 추가 코드를 쉽게 삽입할 수 없습니다. 이러한 경우 대신 위 코드를 포함하는 메서드에 대한 호출을 삽입합니다:

root@kitploit:~
if ($foo && $bar) { ... }
// becomes
if ($foo && \PhpFuzzer\FuzzingContext::traceBlock(BLOCK_INDEX, $bar)) { ... }

향후에는 비교도 계측하여 $foo == "SOME_STRING"과 같은 비교에서 자동으로 사전 항목을 결정할 수 있으면 좋을 것입니다.

특징

퍼징 입력은 코퍼스에 이미 있는 다른 입력에서 관찰되지 않은 새로운 특징을 포함하는 경우 "관심 있는" 것으로 간주됩니다. 이 라이브러리는 특징으로 대략적인 엣지 적중 횟수를 사용합니다:

root@kitploit:~
ft = (approx_hits << 56) | (prev_block << 28) | cur_block

대략적인 적중 횟수는 실제 적중 횟수를 8개의 범주(AFL 기반)로 줄입니다:

root@kitploit:~
0: 0 hits
1: 1 hit
2: 2 hits
3: 3 hits
4: 4-7 hits
5: 8-15 hits
6: 16-127 hits
7: >=128 hits

따라서 각 입력은 특징을 나타내는 정수 집합과 연결됩니다. 또한 테스트 당시 다른 코퍼스 입력에서 볼 수 없었던 "고유 특징" 집합을 가집니다.

입력에 고유 특징이 있으면 코퍼스에 추가됩니다(NEW). 입력 A를 변이하여 입력 B가 생성되었지만 입력 B가 더 짧고 입력 A의 모든 고유 특징을 가지고 있으면 코퍼스에서 A가 B로 대체됩니다(REDUCE).

변이

각 반복에서 현재 코퍼스에서 무작위 입력이 선택된 다음 변이자 시퀀스를 사용하여 변이됩니다. 현재 다음 변이자(libFuzzer에서 가져옴)가 구현되어 있습니다:

  • EraseBytes: 여러 바이트를 제거합니다.
  • InsertByte: 새 무작위 바이트를 삽입합니다.
  • InsertRepeatedBytes: 여러 번 반복되는 무작위 바이트를 삽입합니다.
  • ChangeByte: 바이트를 무작위 바이트로 대체합니다.
  • ChangeBit: 단일 비트를 뒤집습니다.
  • ShuffleBytes: 작은 부분 문자열을 섞습니다.
  • ChangeASCIIInt: ASCII 정수를 증가/감소/두 배/절반으로 변경합니다.
  • ChangeBinInt: 이진 정수에 작은 무작위 양을 더하여 변경합니다.
  • CopyPart: 문자열의 일부를 덮어쓰거나 삽입하여 다른 부분에 복사합니다.
  • CrossOver: 여러 전략으로 다른 코퍼스 항목과 교차합니다.
  • AddWordFromManualDictionary: 사전의 단어를 삽입하거나 덮어씁니다(있는 경우).

변이는 최대 길이 제약을 받습니다. 대상에서 전체 최대 길이를 지정할 수 있지만(setMaxLength()), 퍼저는 자동 길이 제어(--len-control-factor)도 수행합니다. 최대 길이는 처음에 매우 낮은 값으로 설정된 다음, 마지막 len_control_factor * log(maxlen) 실행 동안 어떠한 동작(NEW 또는 REDUCE)도 수행되지 않을 때마다 log(maxlen)만큼 증가합니다.

길이 제어 계수가 높을수록 퍼저는 더 긴 입력을 허용하기 전에 짧은 입력을 더 적극적으로 탐색합니다. 이렇게 하면 생성된 코퍼스의 크기가 크게 줄어들지만 초기 탐색 속도가 느려집니다.

발견 사항

  • tolerant-php-parser: #305
  • PHP-CSS-Parser: #181 #182 #183 #184
  • league/uri: #150
  • amphp/http-client #236
  • amphp/hpack #8
  • phpmyadmin/sql-parser: #508 #510
  • club-1/sphinx-inventory-parser: #7
도구 다운로드