퍼징

퍼즈 테스팅(Fuzz testing) 또는 퍼징 (fuzzing)은 (종종 자동화 또는 반자동화된) 소프트웨어 테스트 기법으로서, 컴퓨터 프로그램에 유효한, 예상치 않은 또는 무작위 데이터를 입력하는 것이다. 이후 프로그램은 충돌이나 빌트인 코드 검증의 실패, 잠재적인 메모리 누수 발견 등 같은 예외에 대한 감시가 이루어진다. 퍼징은 주로 소프트웨어나 컴퓨터 시스템들의 보안 문제를 테스트하기 위해 사용된다. 이것은 하드웨어나 소프트웨어 테스트를 위한 무작위 테스팅 형식이다.
퍼징이라는 분야는 1988년 위스콘신 대학교 매디슨의 바턴 밀러에 의해 생겨났다. 초창기의 연구는 무작위의 구조화되지 않은 테스트 뿐만 아니라, 이런 종류의 테스팅으로 인해 공개되는 오류들을 체계적으로 분석하는 것과 함께 여러 다양한 플랫폼에서의 다양한 소프트웨어 유틸리티들을 평가하기 위한 체계적인 툴들의 집합을 포함하였다. 게다가, 그들은 그들의 툴 소스코드, 테스트 절차 그리고 원자료 결과에 대한 접근도 공개하였다.
퍼징 프로그램의 형태로 변이 기반과 생성 기반 두 종류가 있으며, 화이트, 그레이, 또는 블랙박스 검사에 사용된다. 파일 형식과 통신 프로토콜들은 테스트의 가장 흔한 목표이지만, 어떤 종류의 프로그램 입력도 퍼즈될 수 있다. 흥미로운 입력들로는 환경 변수, 키보드와 마우스 이벤트, 그리고 API 호출의 순서 등이 있다. 입력으로 간주되지 않는 이벤트 항목들도 퍼즈될 수 있는데, 데이터베이스, 공유 메모리의 내용 또는 스레드들의 정확한 인터리빙 등이 있다.
보편적인 면에서, 신뢰 범위를 가로지르는 입력이 가장 흥미로운 주제이다. 예를 들면, 모든 유저에게 허용된 파일 업로드를 다루는 코드를 퍼즈하는 것이 오직 권한을 가진 사용자만 접근할 수 있는 설정 파일을 분석하는 코드를 퍼즈하는 것보다 중요하다.
사용.
퍼즈 테스팅은 종종 테스트 툴 개발을 위한 예산이 존재하는 큰 소프트웨어 프로젝트에서 블랙박스 검사 방법론으로서 사용된다.
이 기법은 단지 시스템 행동의 랜덤한 샘플만을 제공하며, 많은 경우에 정확히 동작하는 것보다는 소프트웨어가 충돌 없이 예외 처리를 할 수 있는가만을 입증한다. 이것은 퍼즈 테스팅이 버그 찾는 툴로서 보다는 전체적 질을 보장하는 툴이며, 정형 기법이나 철저한 테스팅을 대체할 수는 없다는 것을 의미한다.
신뢰도의 중대한 측정으로서, 퍼징은 (코드 감사, 정적 코드 분석 또는 부분적 재작성의 형태로) 프로그램의 어떤 부분이 특별한 관심을 받아야 하는지를 제안할 수 있다.
버그의 종류.
눈에 띄는 충돌 테스팅처럼, 퍼징은 실패 검증이나 메모리 누수 같은 버그를 찾는데 사용되기도 한다. 이 방법론은 메모리 보안에 영향을 미치는 어떤 버그도 심각한 취약점이 될 수 있는 큰 애플리케이션에 유용하다.
퍼징이 종종 유효하지 않은 입력을 생성하기 때문에, 오류 처리 루틴의 테스트에 사용된다. 이것은 입력을 제어하지 않는 소프트웨어에 중요하다. 간단한 퍼징은 네거티브 테스트 자동화 방식으로 여겨질 수 있다.
퍼징은 또한 몇몇 "정확한" 버그들의 종류를 찾을 수 있다. 예를 들면, 이것은 프로그램의 직렬변환기가 같은 프로그램의 파서가 거부한 것을 방출할 때마다 불평함으로써 부정확한 직렬화 버그를 찾을 수 있다. 이것은 또한 두 프로그램 버전 사이의, 또는 같은 명세의 두 구현들 사이에서의 의도하지 않은 차이점을 찾을 수 있다.
기법.
퍼징 프로그램은 두 다른 카테고리로 나뉜다. 변이 기반 퍼저는 생성 기반 퍼저가 입력의 모델에 기반해서 새로운 테스트 데이터를 정의하는 반면, 존재하는 데이터 샘플을 테스트 데이터로 변형한다.
퍼징 기법의 가장 간단한 형태는 명령 줄 옵션이나 무작위하게 변이된 프로토콜 패킷 또는 이벤트로서 소프트웨어에 무작위 비트들의 스트림을 보내는 것이다. 이 무작위 입력 기법은 명령 줄 애플리케이션, 네트워크 프로토콜, GDI 기반 애플리케이션과 서비스 등에서 버그를 찾는 강력한 툴이 된다. 다른 구현하기 쉬운 흔한 기법으로 무작위하게 비트를 플립하거나 파일 주변의 블록들을 이동시킴으로써, (시험조 (test suite)에서의 파일들 같이) 존재하는 입력을 변형하는 것이 있다. 그러나 가장 성공적인 퍼저는 테스트되는 것의 포맷이나 프로토콜에 대한 상세한 이해를 가지고 있는 것이다.
퍼징은 시방서를 기반으로 이해할 수 있다. 명세 기반 퍼저는 명세들의 전체 배열들을 툴에 쓰고, 모델 기반 테스트 생성 기법을 사용하는 것과 관련된다. 이 "똑똑한 퍼징" 기법은 또한 억센 테스팅, 문법 테스팅 그리고 결함 인젝션으로 알려져 있다. 프로토콜 인식은 또한 세퀴투르(Sequitur) 같은 툴을 사용하는 예시들로부터 휴리스틱적으로 생성될 수 있다. 이러한 퍼저들은 자국에서 테스트 케이스를 생성할 수 있거나, 시험조나 실제 생활에서 예시들을 변형할 수 있다. 이것들은 거의 유효한 입력이 가장 깊은 오류를 유발할 수 있다는 생각으로, 유효한 또는 유효하지 않은 입력에 집중한다.
공개된 명세들의 프로토콜 구현에 기반한 프토토콜 기반 퍼징은 두 한계가 있다. 1) 테스팅은 명세가 상대적으로 끝나갈 때까지 진행될 수 없다. 명세가 퍼저를 작성하기 위한 전제조건이기 때문이다. 2) 많은 유용한 프로토콜들은 공개되지 않아 있다. 만약 퍼징이 단지 공개된 명세에만 기반한다면, 검사 방법은 제한되거나 존재하지 않게된다.
퍼즈 테스팅은 다른 테스팅 기법들과 결합될 수 있다. 화이트박스 퍼징은 기호 실행과 제약 충족 문제를 사용한다. 점진적인 퍼징 영향력은 효과적으로 탐색 시험의 접근을 자동화하는 휴리스틱(예를 들면 그레이박스 활용에서의 코드 커버리지 또는 블랙박스 활용에서의 모델화된 공격자 행동에서 피드백된다.
재생과 고립.
테스트 케이스 축소는 초기 테스트 케이스에서 최소한의 테스트 케이스를 추출하는 과정이다. 테스트 케이스 축소는 수작업이나 소프트웨어 툴의 사용 그리고 분할 정복 알고리즘과 관련하여 수행될 수 있다.
오류들을 재생하기 위해서, 퍼징 소프트웨어는 종종 소프트웨어에 적용하기 전에 자신이 만들어낸 입력 데이터를 기록한다. 만약 컴퓨터가 충돌된다고 해도, 테스트 데이터는 보존된다. 만약 퍼즈 스트림이 의사난수로 생성되었다면, 시드값은 퍼즈 시도를 재생하기 위해 저장될 수 있다. 버그가 발견되면, 몇몇 퍼징 소프트웨어는 디버깅에 사용되는 테스트 케이스 빌드를 도와준다.
장점과 단점.
퍼징을 프로그램의 결함을 찾을 때 사용할 시에 가장 큰 문제점은 이것이 단지 매우 간단한 결함만 찾는다는 것이다. 소프트웨어 테스팅 문제의 컴퓨터적인 복잡함은 점근 표기법 (formula_1, formula_2)이며, 모든 퍼저들은 한 기간 동안 사람이 관심있어하는 흥미로운 것을 찾기 위한 지름길을 찾는다. 원시적인 퍼저는 형편없는 코드 커버리지를 갖는다.; 예를 들면, 입력이 다른 랜덤 변화와 일치하게 적절하게 업데이트되지 않은 체크섬을 포함하면, 단지 체크섬 확인 코드만 확인될 것이다. 코드 커버리지 툴들은 종종 퍼저가 얼마나 잘 하느냐를 측정하기 위해 사용되지만, 단지 퍼저의 질에 대한 가이드라인일 뿐이다. 모든 퍼저들은 다른 버그들의 집합을 찾을 수 있다.
한편, 퍼즈 테스팅을 사용해 찾은 버그들은 가끔은 심각하고 익스플로잇 가능한 버그들로서 실제 공격자들에 의해 사용될 수 있다. 퍼즈 테스팅이 더 많이 알려질수록 발견은 더 흔해졌지만, 같은 기법들과 툴들이 공격자들에 의해 소프트웨어를 익스플로잇하기 위해 사용되고 있다. 이것은 바이너리나 소스 감사 또는 결함 제거에서 큰 장점을 갖는다.
퍼징에서 사용되는 임의적인 입력은 종종 단점으로 보이는데, 임의적인 입력을 사용해서 경곗값 조건을 찾는 것이 매우 힘들기 때문이다. 그러나 현재 대부분의 퍼저들은 결정론적 알고리즘을 기반한 사용자 입력을 사용함으로써 이 문제를 푼다.
퍼즈 테스팅은 간과한 실수나 테스트하는 사람이 찾기 힘든 결함을 찾아주므로 애플리케이션 보안을 강화시켜 준다.