회원가입을 하면 원하는 문장을
저장할 수 있어요!
다음
AWS 이용 중이라면 최대 700만 원 지원받으세요
지난 두 편의 글을 통해 데브섹옵스(DevSecOps)와 정적 보안 테스팅(SAST)에 대해 알아봤습니다. 이번 글에서는 정적 보안 테스팅을 상호 보완할 수 있는 ‘동적 보안 테스팅(DAST)’ 도구를 실습 사례와 함께 살펴보겠습니다.
회원가입을 하면 원하는 문장을
저장할 수 있어요!
다음
회원가입을 하면
성장에 도움이 되는 콘텐츠를
스크랩할 수 있어요!
확인
지난 두 편의 글을 통해 데브섹옵스(DevSecOps)와 정적 보안 테스팅(SAST)에 대해 알아봤습니다. 이번 글에서는 정적 보안 테스팅을 상호 보완할 수 있는 ‘동적 보안 테스팅(DAST)’ 도구를 실습 사례와 함께 살펴보겠습니다.
동적 보안 테스팅은 실행 중인 애플리케이션을 대상으로, 보안 취약점을 식별하는 보안 테스트 방법입니다. SQL 인젝션, 크로스 사이트 스크립팅(XSS), 인증 및 세션 관리 취약점, 서버 구성 오류 등의 실제 운영 환경에서 발생할 수 있는 보안 문제를 탐지합니다. 동적(dynamic)이라는 용어는 실제 프로그램을 실행하면서 테스트를 수행하기 때문에 사용됩니다. 이는 소스 코드만을 분석하여 보안 취약점을 검사하는 정적 보안 테스팅과 대조됩니다.
동적 보안 테스팅의 주요 장점은 다음과 같습니다.
동적 보안 테스팅은 실제 운영 환경과 유사한 조건에서 애플리케이션을 테스트하므로, 실제 공격 시나리오를 시뮬레이션할 수 있습니다. 이를 통해 정적 분석으로는 발견하기 어려운 런타임(운영 중) 취약점이나 설정상 오류를 식별할 수 있습니다.
동적 보안 테스팅은 실제로 취약점을 공격해 보는 방식으로 진행되어, 정적 분석에 비해 오탐율(False Positive)이 낮습니다. 또한 대부분의 동적 보안 테스팅 도구가 취약점 발견 시 실제 요청과 응답 메시지를 증거로써 같이 제공합니다. 따라서 개발자들이 상대적으로 실제 문제를 쉽게 파악할 수 있습니다.
동적 보안 테스팅은 일반적으로 애플리케이션의 전체 스택을 대상으로 테스트를 수행하므로, 외부 데이터베이스, 웹 서버 구성, API 연동 등과 관련된 보안 문제도 식별할 수 있습니다. 그러나 이러한 동적 보안 테스팅에도 몇 가지 단점이 있습니다.
동적 보안 테스팅은 애플리케이션이 실행 가능한 상태여야 하므로, 정적 보안 테스팅과는 달리 개발 주기의 후반부에 수행됩니다. 이는 취약점을 발견하고 수정하는 데 더 큰 비용과 시간이 소요될 수 있음을 의미합니다.
동적 보안 테스팅은 실제 실행 가능한 경로만을 테스트하므로, 모든 코드 경로를 커버하기 어렵습니다. 특히 복잡한 조건문이나 예외 처리 로직의 경우 테스트하기 어려울 수 있습니다.
이러한 단점에도 불구하고, 동적 보안 테스팅은 실제 운영 환경에서 발생할 수 있는 취약점을 효과적으로 식별할 수 있는 중요한 보안 테스팅 방법입니다. 가장 효과적인 보안 테스팅을 위해서는 정적 보안 테스팅과 동적 보안 테스팅을 함께 사용하는 통합적인 접근 방식이 권장됩니다.
최근 웹 서비스들이 마이크로 서비스로 개발되고 있습니다. 마이크로 서비스 아키텍처는 여러 서비스가 별도로 구현되고 서로 통신하는 구조이기에, 상호 간의 통신을 위해 API를 활용합니다. 계속해서 더 많은 서비스가 API로 구현됨에 따라, API 보안 역시 점점 더 중요해지고 있습니다. DAST를 개발 과정에 적용할 때, API 보안 역시 고려해야 합니다.
기존의 웹 스캐닝을 활용한 동적 보안 테스팅 사례는 이미 알려진 내용이 많습니다. 그래서 이 글에서는 최근 개발 트렌드인 API를 대상으로, 동적 보안 테스팅을 자동화하는 방법을 알아보겠습니다.
여러 상용 도구를 활용할 수도 있지만, 개발자들이 무료로 사용할 수 있는 오픈소스 도구 ‘RapiDAST’로 실습 과정을 살펴보겠습니다. 필자가 사내 데브섹옵스 실현을 위해 동료들과 개발하여 깃허브에 공개한 오픈소스 프로젝트로 계속 발전하고 있습니다. RapiDAST는 특히 API 보안 검사 자동화에 유용하게 활용할 수 있습니다.
만약 API 서비스를 개발 중인 분이 있다면, 직접 개발하고 있는 서비스의 테스트 환경에서 실습해 보는 것을 추천합니다. 이 글에서는 필자의 팀 동료가 개발한 간단한 실습용 웹 서비스를 사용했습니다.
실습용 웹 서비스를 구동하려면 다음과 같은 도커 명령어를 사용합니다.
$ docker pull ghcr.io/jeremychoi/vapi:latest $ docker run -it --rm -p 3000:3000 -p 5000:5000 -e API_HOST=192.168.1.100:5000 ghcr.io/jeremychoi/vapi |
192.168.1.100은 각자의 테스트 환경에 맞추어 변경해야 합니다.
이 서비스는 보안 테스트용 프로젝트로 SQL 인젝션 취약점을 포함하고 있습니다. 프론트엔드는 Next.js(리액트 기반)로, 백엔드는 파이썬 Flask로 개발되었습니다. 소스코드는 깃허브를 참고하세요.
명령어 실행 후 서비스가 구동된 후, (포트 3000번의 프론트엔드 서비스의 경우 시스템 환경에 따라 수십 초 정도 걸릴 수 있음), 192.168.1.100:3000으로 접속하면 위 그림과 같은 프론트엔드 화면을 볼 수 있습니다. 그리고 포트 5000번의 백엔드 API 서비스는 API의 OpenAPI(예전 Swagger) 문서를 제공합니다.
실습용 웹 서비스와 같은 요즘 주로 사용되는 자바스크립트 프레임워크와 API 아키텍처 기반의 웹 서비스를 기존의 전통적인 크롤링 기반 웹 스캐닝 도구로 검사하려면, 실제 API 엔드 포인트를 확인하는 데 어려움이 많습니다. 이러한 경우, OpenAPI 문서를 활용하면 쉽게 전체 API를 검사할 수 있습니다. OpenAPI 문서에는 API 엔드 포인트에 대한 경로, 파라미터 등 정보가 기술되어 있기 때문입니다.
RapiDAST를 활용하면 테스트 대상 API 서비스의 URL, 해당 API를 기술하는 OpenAPI 문서 URL만 알면, 아래와 같은 설정 파일을 생성(코드 저장소에 예제 파일 포함)하여 검사를 자동화할 수 있습니다.
config: configVersion: 5 # 디폴트 설정값 application: shortName: "yozmit-demo" # 서비스 이름. 임의 입력 url: "http://192.168.50.143:5000" # 서비스 URL. 입력 필요 scanners: zap: # ZAP 도구 사용 apiScan: apis: apiUrl: "http://192.168.50.143:5000/docs/openapi.json" # OpenAPI 문서 URL. 입력 필요 passiveScan: disabledRules: "2,10015,10027,10096,10024,10098,10023,10105" # 패시브 검사 룰 설정 - 오탐/중복 이슈 해결 activeScan: policy: API-scan-minimal # 스캔 룰 설정. RapiDAST 저장소 기본 제공 report: format: ["json","html"] # 보고서 형식 지정 container: parameters: executable: "/Applications/ZAP.app/Contents/Java/zap.sh" # Mac OS 기준 ZAP 설치 경로 |
여러 설정값이 보이지만, 대부분은 RapiDAST 코드 저장소에 있는 예제 파일의 기본값을 사용할 수 있어, 설정 파일을 준비하는 것은 어렵지 않습니다. 설정 파일을 생성했다면, 다음과 같이 검사 명령어를 실행합니다.
$ ./rapidast.py --config v5-yozm-demo.yaml |
검사 중에는 로그를 확인할 수 있으며, 검사가 끝나면 결과 파일이 results 디렉토리에 생성됩니다.
검사 결과 파일을 확인하여, SQL 인젝션 취약점이 발견된 것을 알 수 있습니다.
추가로 위 검사 실행 과정을 젠킨스(Jenkins)나 깃허브 액션 등을 이용해, CI/CD 파이프라인에 통합하여 DAST를 자동화하고 개발 프로세스에 포함시킬 수 있습니다.
이렇게 RapiDAST를 통해 보안 검사 자동화를 구현하는 과정을 살펴봤습니다. 모든 검사 과정이 CLI를 통해 진행되기에 쉽게 자동화할 수 있습니다.
가장 간단한 예제를 보여드렸지만, 경우에 따라서는 생성되는 검사 결과들을 구글 클라우드 스토리지, 다른 취약점 관리 도구로 연동하는 등 다양한 활용법이 있습니다. (RapiDAST 깃허브에서 설치 방법과 추가 설정 예제 및 방법을 참고해 보세요.) 참고로 RapiDAST는 오픈소스 프로젝트로 누구나 언제든 깃허브 프로젝트에 풀리퀘스트(pull request)로 기여할 수 있으며, 사용 중 문제가 있을 때 깃허브 이슈 등록(영어로 리포트 추천)하면 지원도 받을 수 있습니다.
이전 글에서 정적 보안 테스팅(SAST) 자동화 시 고려 사항에 대해서 살펴봤습니다. 이 중 많은 부분이 동적 보안 테스팅(DAST)에도 공통적으로 적용될 수 있습니다. 그래서 이번 글에서는 DAST와 SAST의 차이점을 위주로 살펴보려고 합니다.
SAST와 마찬가지로 DAST도 체계적인 계획이 필요합니다. 그러나 DAST는 실행 중인 애플리케이션을 대상으로 해, 테스트 시나리오 개발과 실제 사용 환경을 모방한 테스트 데이터 준비가 더욱 중요합니다. 서버 구성, 네트워크 설정 등 인프라 요소도 고려해야 합니다. 이 점은 SAST 자동화 시에는 고려하지 않았던 새로운 요소입니다.
주의할 점은 DAST 과정에서는 데이터를 추가로 생성하거나, 변조하는 테스트가 포함되어 있기 때문에 절대로 실제 운영 중의 서비스를 대상으로 테스트해서는 안 된다는 점입니다. 실제 운영 환경의 검증은 모의해킹/침투 테스트 전문가에게 맡겨두고, DAST는 별도의 테스트 환경을 구성해서 구현해야 합니다.
DAST도 CI/CD 파이프라인에 통합되어야, 소프트웨어 개발 주기상에서의 보안 검사 자동화를 구현할 수 있습니다. DAST는 실행 가능한 애플리케이션이 필요하므로, 일반적으로 빌드가 완료된 후 테스트 단계(또는 테스트 파이프라인)에서 수행됩니다.
이 점은 SAST가 코드 커밋 단계에서 수행될 수 있는 것과는 차이가 있습니다. DAST를 위한 가장 좋은 시점은 통합(integration test) 테스트를 하는 시점입니다. 따라서 QA 팀의 역할이 중요합니다. 개발팀과 QA 팀이 분리되어 있는 경우, 상호 간 협업 계획을 세우면 좋습니다. API 서비스의 경우, OpenAPI를 활용한 전반적인 개발/테스트 프로세스를 구축한다면 훨씬 수월하게 자동화를 구현할 수 있습니다.
SAST와는 달리, 실제 환경을 가정하고 테스트하는 DAST에서는 인증 및 세션 관리에 대해 고려해야 합니다. DAST는 미인증된 상태에서의 테스트와 더불어, 인증된 상태에서의 테스트도 별도로 수행해야 합니다. 따라서 자동화 과정에서 다양한 사용자 역할로 로그인하고 세션을 유지하는 메커니즘을 구현해야 합니다.
SAST와 마찬가지로 DAST도 지속적인 업데이트와 개선이 필요합니다. 그러나 DAST는 실제로 공격이 시연될 수 있는 상황을 마주하므로, 새로운 공격 기법과 취약점 유형에 더 민감하게 대응해야 합니다. 따라서 보안 커뮤니티의 동향을 주시하고, 새로운 공격 패턴을 신속하게 테스트 시나리오에 반영하는 체계가 필요합니다. 모의해킹과 같은 실제 웹 공격 사례에 대한 교육을 담당자에게 제공하고, 지속적인 관심을 갖게 하는 것이 중요합니다.
지금까지 실습 예제와 함께 동적 보안 테스팅에 대해 살펴봤는데요. 동적 보안 테스팅 도구를 자동화하여 활용한다면, 소스 코드 검사에서 놓친 보안 취약점을 개발 프로세스 초기 단계에서 발견하고 해결할 수 있습니다. 또한 애플리케이션의 보안성을 높이고 잠재적인 위험과 비용을 크게 줄일 수 있습니다.
결론적으로 DAST 자동화는 SAST와 여러 공통점을 가지고 있지만, 실행 중인 애플리케이션을 대상으로 한다는 특성으로 추가적인 고려 사항이 있습니다. SAST와 DAST를 상호 보완적으로 활용하면, 더욱 효과적인 데브섹옵스 구현을 이루어낼 수 있을 것입니다.
요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.