소프트웨어 테스트
- 소프트웨어의 결함을 최대한 찾아내 줄이고, 소프트웨어의 품질을 높인다.
테스트의 필요성과 특징
소트프웨어 테스트의 정의
- IEEE : 테스트는 시스템이 명시된 요구를 잘 만족하는지, 즉 예상된 결과와 실제 결과가 어떤 차이를 보이는지 수동이나 자동으로 검사하고 이를 평가하는 작업을 의미한다.
- 조하 만나 : 테스트는 시스템의 명세까지 완벽하게 옳다고 확신할 수 없고, 테스트 시스템 그 자체가 맞다고 증명할 수 없기 때문에 프로그램을 완전히 테스트할 수 없다.
- 달, 다익스트라, 호어 : 테스트는 결함이 있음을 보여줄 뿐, 결함이 없음을 증명할 수는 없다.
결국 소프트웨어 테스트는 **’소프트웨어 내에 존재하지만 드러나지 않고 숨어 있는 오류를 발견할 목적으로 개발 과정에서 생성되는 문서나 프로그램에 있는 오류를 여러 기술을 이용해 검출하는 작업’**이다.
- 작은 의미 : 원시 코드 속에 남아 있는 오류를 발견하는 것
- 큰 의미 : 개발된 소프트웨어가 고객의 요구를 만족하는지 확인해주는 것
테스트의 어려움
- 테스트 케이스가 적어 효과에 한계가 있다.
- 완벽한 테스트 케이스를 도출하기 어렵다.
- 테스트를 위한 실제 사용 환경을 구축하기 어렵다.
- 완벽한 테스트는 불가능하다. (오류가 없음을 보장할 수 없다.)
- 테스트 내성 문제 해결을 위해 테스트 케이스 업데이트가 필요하다.
테스트 케이스
테스트 케이스란 명세 기반 테스트의 설계 산출물로 설계된 입력값, 실행조건, 기대 결과로 구성되어 있는 테스트 항목의 명세서를 의미한다.
테스트 누락 방지와 테스트 투명화를 위해 사용한다.
오류 : 소프트웨어 개발자에 의해 생기는 실수로 결함의 원인이 됨.
결함 : 오류에 의해 프로그램이 완전하지 못한 것으로, 고장의 원인이 됨.
- 프로그램이 실행 중에 멈추거나, 예외 처리 모듈이 작동할 수 있다. 시스템이 작동 불능상태에 빠질 수 있다.
고장 : 시스템이 요구사항대로 작동하지 않는 것을 말한다.
- 모든 결함은 반드시 실패를 유발하지는 않는다.
테스트의 분류
확인 테스트
- 개발자가 개발한 프로그램이 제대로 돌아가는지 확인하는 테스트.
- 사용자가 1
10까지 곱하는 프로그램을 주문했는데, 개발자가 110까지 더하는 프로그램을 만들었다. - 확인 테스트를 수행한다면, 1~10까지 더하는 과정이 정확하고, 결과가 맞는지만 테스트 한다.
- 하지만 실제 사용자가 원하는 것은 덧셈이 아닌 곱셈으로, 확인 테스트만으로는 사용자가 원하는 것을 개발했는지 알 수 없다.
검증 테스트
- 사용자의 요구사항대로 만들었는지를 테스트.
- 검증 테스트를 통해 소프트웨어가 사용자의 목적에 맞게 구현되었는지를 알 수 있다.
성능 테스트
- 소프트웨어의 효율성을 진단하는 테스트.
- 사용자의 요구사항 중에서 성능과 관련된 요구사항을 시스템이 얼마나 준수하는지 테스트.
스트레스 테스트
- 평소보다 많은 비정상적인 값, 양, 빈도, 부피 등으로 부하를 발생시켜 부하가 최고치인 상황에서시스템의 반응을 살피고 이때 발생하는 오류를 찾는 것이다.
보안 테스트
- 보안 시스템이 불법적인 침투를 잘 막아내는지 테스트 한다.
안정성 테스트
- 소프트웨어는 한 번 설치되면 오랫동안 운영된다.
- 일주일 동안 시스템에 부하를 주어 관찰한다.
- 자원을 사용한 후에 정상적으로 반납하는지 관찰.
복원 가능성 테스트
- 소프트웨어에 문제가 생겼을 경우, 이를 복원 가능한지 테스트.
black-box 테스트
- 프로그램 내부의 구조나 알고리즘을 보지 않고, 요구분석명세서나 설계서에서 테스트 케이스를 추출해 테스트한다.
- 어떻게 수행하는가보다는 사용자가 원하는 기능을 수행하는가에 대해 테스트 한다.
- 신택스 기법 : 문법에 기반을 둔 테스트, 문법을 정해놓고 적합/부적합 입력에 따라 결과를 확인.
- 경계 값 분석 기법 : 경계 값을 테스트 데이터로 쓴다. 경계 값, 경계 이전 값, 경계 이후 값 결과 확인.
white-box 테스트
- 프로그램 내부에서 사용되는 변수나 서브루틴 등의 오류를 찾기 위해 프로그램 코드의 내부 구조를 테스트.
- 어떻게 수행하는 지를 테스트.
- statement, branch, condition, path를 실행 테스트.
퍼즈 테스팅
퍼징
- 퍼즈 테스팅(Fuzz testing)은 fuzzing을 이용하는 소프트웨어 테스팅 기술의 한 형태라고 볼 수 있다.
- 다른 테스팅 분야와 차별화되는 가장 큰 목적성은 프로그램의 충돌(Crash) 현상을 비롯한 ‘보안 관련 버그’를 찾는 것이다.
- 간단한 퍼징을 통해 오류 처리 루틴의 테스트에 사용되기도 한다.
퍼징을 하는 이유
- 어떤 제품에 대하여 테스트 케이스가 정의되어 있다면, 이는 ‘어떻게 작동하도록 설계되어있는지’, ‘어떻게 하면 안되는지’ 에 대한 명세가 정해져있다는 뜻이다.
- 이러한 기준이 있다하더라도, 프로그래머 또는 테스터는 사람이므로, 생각해보지 못한 초월 영역이 존재할 수 있다.
- 이러한 빈틈을 매우는 것이 퍼징이며, 그러한 정의되지 않은 영역을 테스트하는 일종의 탐험가 역할을 한다.
퍼징의 주요 목적은 제품/프로그램의 올바른 기능을 테스트하는 것이 아니라, 정의되지 않은 영역을 검증하고 확인하는 작업이다.
Black-box 퍼징
- PUT의 내부를 들여다 보지 않고, input과 output만을 관찰한다.
- valid한 input을 mutate하는 방식으로 사용.
- 커버리지를 측정하지 못해 Corpus가 자라나지 않음.
- 커스텀 펌웨어의 추출과 에뮬레이션이 어려운 IoT에 대부분 블랙박스 방식을 사용.
White-box 퍼징
- PUT의 내부구조와 실행 중에 발생하는 정보들을 기반으로 하여 테스트 케이스를 생성한다.
- 블랙 박스보다 오버헤드가 크다.
- 커버리지를 측정할 수 있다.
- Corpus는 퍼징에 사용되는 샘플 셋이며, 코드 커버리지가 최대한 겹치지 않는 최소한의 샘플 셋을 만들어 퍼징 효율을 높일 수 있다.
사용 관점
개발자는 프로그램 내 잠재된 보안 관련 버그를 찾아 패치하여 SW 품질을 높인다.
공격자는 프로그램 내 잠재된 보안 관련 버그를 찾아 공격에 사용한다.
결론
- 퍼즈 테스팅은 소프트웨어 테스팅 기법 중 하나로, 보안 관련 버그를 찾기 위해 사용된다.
- 테스트 기준을 만들고, 이 기준을 목표로 테스팅을 했지만, 무수히 많은 가능성이 존재하기에 오류는 남아 있을 것이며, 이를 위한 자동화된 동적 테스팅 기법이 퍼즈 테스팅이다.
- 버퍼 오버 플로우, 메모리 릭 과 같은 취약점을 미리 방지해 기밀성과 무결성을 유지할 수 있다.