용어 사전

퍼징이란: 자체 소프트웨어의 결함을 찾기 위해 예상치 못한 입력을 대량으로 넣는 기법

퍼징은 예상치 못한 입력을 소프트웨어에 자동으로 넣어 버그와 취약점을 찾습니다. 작동 방식과 자체 코드에 적용하는 방법을 설명합니다.

게시 2026-11-15 업데이트 2026-11-15 4분 읽기
이 페이지에서

퍼징은 결함을 찾기 위해 예상치 못한 입력을 소프트웨어에 자동으로 넣는 테스트 기법입니다. 이 페이지는 작동 방식과 자체 코드에 적용하는 방법을 설명합니다(타인의 시스템 테스트는 다루지 않습니다).

퍼징이란

OWASP는 퍼징을 버그, 취약점 또는 예상치 못한 동작을 식별하기 위한 소프트웨어 테스트 기법으로 설명합니다. 이는 잘못되었거나, 예상치 못했거나, 일부만 잘못된 입력을 자동으로 공급하고 프로그램이 오작동하는지 살피는 방식입니다. NIST 용어집(NIST SP 800-95 인용)도 마찬가지로, 퍼저라고 불리는 도구가 테스트 대상에 입력 조합을 제출해 그 반응을 드러내는 것을 퍼즈 테스팅으로 설명합니다.

이 기법의 강점은 시스템이 어떻게 동작해야 하는지에 대한 가정이 적다는 점입니다. 사람이 직접 작성한 테스트는 누군가 떠올린 경우만 다룹니다. 퍼저는 아무도 상상하지 못한 입력에서 깨지는 지점을 찾을 수 있습니다.

작동 방식

1. 몇 개의 시작 입력(시드)을 준비합니다
2. 퍼저가 이를 변형해 각 입력을 대상 함수에 전달합니다
↓ 실행하고, 어떤 코드가 실행되었는지와 동작 방식을 관찰합니다
3. 충돌을 일으킨 입력은 저장하고, 새로운 경로에 도달한 입력은 2단계로 되돌려 보냅니다
생성하고, 실행하고, 관찰하고, 반복합니다. 커버리지 기반 퍼저는 새로운 경로에 도달한 입력을 보관하고 이로부터 다음 입력을 만듭니다.

대부분의 최신 퍼저는 커버리지 기반입니다. 실행된 코드를 측정하고, 새 코드에 도달한 입력을 보관한 뒤 이를 변형해 다음 입력을 만듭니다. 이는 무작위 입력만 쓸 때보다 프로그램 깊숙이 도달하게 합니다. LLVM의 libFuzzer는 테스트 대상 라이브러리에 링크되어 프로세스 내부에서 동작하는, 커버리지 기반의 진화형 퍼징 엔진으로 문서화되어 있습니다.

주요 도구

도구주요 대상참고
libFuzzerC/C++ 및 기타(LLVM)대상에 링크됩니다. 문서에 따르면 원 개발진은 Centipede 엔진으로 옮겨갔고, 현재는 중요한 버그 수정만 받습니다
AFL++C/C++ 및 기타널리 쓰이는 커버리지 기반 퍼저입니다
Go 내장 퍼징Go(1.18 이상)go test -fuzz로 실행합니다. 실패한 입력은 testdata에 저장되고 일반 테스트에서 재실행됩니다
OSS-Fuzz오픈 소스 소프트웨어Google의 무료 지속 퍼징 서비스로, 여러 엔진과 새니타이저를 사용합니다

libFuzzer 퍼즈 타깃은 입력 바이트와 길이를 받는 함수(LLVMFuzzerTestOneInput)입니다. Go에서는 *testing.F를 받는 FuzzXxx라는 이름의 테스트 함수를 작성하고 f.Add로 시드 입력을 추가합니다.

자체 소프트웨어에 적용하는 방법

  1. 입력을 해석하는 함수를 고릅니다(파일 형식 파서, 설정 로더, 프로토콜 핸들러 등)
  2. 입력을 그 함수에 그대로 넘기는 작은 퍼즈 타깃을 작성합니다. 빠르고 결정적으로 동작하게 하며, 호출 사이에 상태를 유지하지 마세요
  3. 일반적인 유효 입력 몇 개를 시드로 추가합니다
  4. AddressSanitizer 같은 새니타이저를 켜고 정해진 시간 동안 실행합니다(Go에서는 -fuzztime으로 길이를 지정합니다)
  5. 실패한 각 입력을 재현 가능한 테스트로 만들고, 수정 후 회귀 테스트로 보관합니다
  6. 계속 진행하려면 CI에서 짧은 세션을 실행하고, 오픈 소스라면 OSS-Fuzz 참여를 고려하세요

Go 퍼징은 실행당 1초 제한이 있으며, 커버리지 가이드는 AMD64와 ARM64에서 동작합니다. 환경별 제한은 공식 문서에서 확인하세요.

직접 관리하는 소프트웨어만 퍼징하세요

퍼징은 잘못된 형식의 입력을 계속 대량으로 보냅니다. 테스트할 권한이 없는 서비스나 서버에 이를 수행하면 권한 없는 접근이나 서비스 방해로 간주될 수 있습니다. 직접 개발하거나 관리하는 소프트웨어, 자신의 환경에서만 수행하세요.

할 수 있는 일과 할 수 없는 일

OWASP는 퍼징이 수동 코드 리뷰와 디버깅을 대체하지 않고 보완한다고 말합니다. 또한 퍼저는 단순한 버그를 찾는 경향이 있으며, 블랙박스 테스트에서는 발견 사항의 영향을 판단하기가 더 어렵다고 설명합니다.

따라서 퍼징은 "기계가 코드가 깨지는 방법을 찾게 하는" 일에는 강하지만, 권한 누락 같은 설계 수준의 문제에는 약합니다. IDOR처럼 이런 문제는 의도한 규칙을 검사하는 테스트에 의존하세요.

이 사이트의 견해: 입력을 찾는 것은 절반의 작업이며, 회귀 테스트로 보관해야 합니다

중요한 것은 퍼저를 실행하는 것만이 아니라, 찾아낸 것을 회귀 테스트로 저장하는 것입니다. 실패한 입력을 testdata에 저장하고 일반 테스트에서 재실행하는 Go 내장 퍼징이 이 아이디어를 따릅니다. 이는 이후 변경으로 수정된 버그가 다시 나타나지 않도록 막아줍니다. 입력을 해석하는 코드를 소유하고 있다면, 현실적인 첫걸음은 함수 하나를 퍼징하는 것입니다.

출처(1차 자료)

  • OWASP Community, "Fuzzing" — owasp.org (정의, 특성, 한계)
  • NIST CSRC 용어집, "fuzz testing" — csrc.nist.gov (출처: NIST SP 800-95)
  • LLVM, "libFuzzer" — llvm.org (작동 방식, 퍼즈 타깃, 유지보수 상태)
  • Go, "Fuzzing" — go.dev (Go 1.18 이상, 실행 방법, 제한)
  • Google, "OSS-Fuzz" — google.github.io (개요, 지원 엔진). 버그 수는 시간에 따라 변하므로 여기서는 인용하지 않습니다. AFL++의 현재 사용법은 공식 문서를 확인하세요

다음으로 읽을거리

FAQ

Q퍼징이란 무엇인가요?
A

퍼징은 잘못되었거나 예상치 못한 입력을 대량으로 프로그램에 자동으로 넣고, 충돌이나 비정상 동작이 있는지 확인하는 테스트 기법입니다. OWASP는 이를 버그, 취약점 또는 예상치 못한 동작을 식별하기 위한 소프트웨어 테스트 기법으로 설명합니다. 퍼즈 테스팅이라고도 부릅니다.

Q퍼징으로 어떤 문제를 찾을 수 있나요?
A

일반적으로 충돌, 메모리 손상(범위를 벗어난 읽기 및 쓰기 등), 무한 루프, 예상치 못한 예외 등입니다. 이미지, 문서, 프로토콜 파서처럼 입력을 해석하는 코드에서 특히 효과적입니다. OWASP는 퍼저가 단순한 버그를 찾는 경향이 있으며, 발견된 문제의 영향을 판단하기는 더 어렵다고 설명합니다.

Q커버리지 기반 퍼징이란 무엇인가요?
A

퍼저는 각 입력이 어떤 코드에 도달하는지(커버리지)를 측정하고, 새로운 코드에 도달한 입력을 보관한 뒤 이를 변형해 다음 입력을 만듭니다. 이 방식은 순수한 무작위 입력보다 프로그램 깊숙한 곳까지 도달합니다. libFuzzer는 프로세스 내부에서 동작하는, 커버리지 기반의 진화형 퍼징 엔진으로 문서화되어 있습니다.

Q퍼징을 시작하려면 무엇이 필요한가요?
A

테스트할 함수에 생성된 입력을 전달하는 작은 테스트 코드, 즉 퍼즈 타깃이 필요합니다. C/C++에서는 libFuzzer나 AFL++를 사용할 수 있고, Go 1.18 이상에서는 표준 도구(go test -fuzz)를 사용합니다. 메모리 오용을 즉시 잡아내기 위해 AddressSanitizer 같은 새니타이저와 함께 쓰는 경우가 흔합니다.

Q다른 사람의 서비스를 퍼징해도 되나요?
A

아니요. 허가 없이 시스템에 잘못된 형식의 입력을 대량으로 보내면 권한 없는 접근이나 서비스 방해로 간주될 수 있습니다. 직접 개발하거나 관리하는 소프트웨어를 자신의 환경에서 퍼징하세요. 오픈 소스 프로젝트라면 OSS-Fuzz 같은 검증된 경로를 이용하세요.

QOSS-Fuzz란 무엇인가요?
A

Google이 오픈 소스 소프트웨어를 위해 제공하는 무료 퍼징 서비스입니다. 공식 페이지에 따르면 OpenSSL의 Heartbleed 취약점을 계기로 2016년에 출시되었으며, libFuzzer, AFL++, Honggfuzz, Centipede 등의 엔진을 사용하고, 발견한 버그를 개발자에게 비공개로 알립니다.