올해 초, 저희 팀은 PCI-DSS 및 SOC-2 규정 준수를 위해 기존 보안 도구와 소프트웨어 개발+테스트 관행을 강화해 달라는 요청을 받았습니다. 우리가 보강해야 했던 핵심 영역 중 하나는 K8s 기반 마이크로서비스와 몇 가지 모놀리식 서비스에 대한 취약성 스캐닝이었습니다. 결과적으로, 당사의 DevOps 팀은 소프트웨어의 취약성 스캐닝을 구현하기 위해 몇 가지 상용 도구와 오픈소스 솔루션 중에서 선택해야 했습니다. 이러한 모든 도구는 매우 유사한 작업을 수행합니다. 종속성(프로젝트 라이브러리 또는 OS 패키지)을 스캔하고 취약성 데이터베이스(NIST의 NVD 및 기타)와 비교합니다.
취약성 스캐닝 솔루션을 직접 구축하는 데 사용할 수 있는 오픈소스 도구가 몇 가지 있고, 기본 스캐닝에 추가 기능을 추가하여 삶을 더욱 편리하게 만들어 주는 상용 제품을 사용할 수도 있습니다. 다음은 그 예입니다.
대부분의 상용 솔루션은 공개된 취약성 데이터베이스에 자체 취약성 데이터베이스를 추가하여 거짓 긍정/부정을 제거하고 더욱 관련성 있는 결과를 제공합니다. 그러나 개발자 수가 늘어날수록 이러한 모든 상업용 도구는 정말 비싸집니다. 따라서 기존 오픈 소스 툴링을 사용하여 솔루션을 구매하는 것이 "더 나은지" 또는 자체 솔루션을 구축하는 것이 "더 나은지" 고려해야 합니다.
처음에 우리는 시간적 제약을 고려해 볼 때 상용 툴이 우리의 필요에 가장 적합하다고 결정했습니다. 하지만 업계를 선도하는 상용 제품을 배포하고 테스트하는 데 3개월을 보낸 후, 우리는 많은 어려움에 직면했습니다. 예를 들어, golang에 대한 지원이 제한적이고, 잘못된 종속성을 선택하여 정상적으로 종료되지 않으며, 처음부터 빌드한 컨테이너와 기본 이미지로 빌드한 컨테이너 간의 문제 등이 있었습니다. 결국, 우리는 이를 포기하고, 사용 가능한 오픈 소스 기술을 사용하여 우리만의 도구를 만드는 방향으로 전환하기로 결정했습니다.
이 글에서는 오픈 소스를 선택하려는 분들을 위해 튼튼한 기초를 제공해 드리겠습니다. 게다가, 게시물의 마지막에는 여러분이 시작할 수 있도록 오픈소스 리포지토리에 대한 링크가 포함되어 있습니다!
기본적으로 취약점을 스캔하려는 것은 두 가지입니다.
나중에 라이선스 확인이나 정적 코드 분석과 같은 더 많은 기능을 추가할 수 있지만 이는 이 게시물의 범위를 벗어납니다.
우선, 코드나 Docker 이미지 변경으로 인해 새로운 취약점이 발생하지 않는지 확인해야 하므로 병합하기 전에 모든 병합 요청을 검사하는 것이 좋습니다.
하지만 시간이 지남에 따라 새로운 취약점이 나타날 수 있으므로 주기적으로 검사해야 합니다. 또한 심각도가 변경될 수 있습니다. 처음에 무시했던 낮은 심각도가 시간이 지나면서 새로운 공격 벡터나 익스플로잇이 발견되면서 심각해질 수 있습니다. 상용 도구는 마지막 검사를 기억하고 새로운 취약점이 발견되면 알려주지만, 오픈소스 솔루션에서는 프로젝트의 마스터 브랜치 위에서 간단히 검사를 반복합니다.
사용 가능한 오픈소스 도구는 많지만 우리가 선택한 것은 Trivy였습니다. 사용하기 간편하고, 활발하게 개발 중이며, 여러 프로젝트와 OS 유형을 스캔할 수 있기 때문입니다.
Trivy는 컨테이너 및 기타 아티팩트를 위한 간단하고 포괄적인 취약성 스캐너입니다. 소프트웨어 취약점이란 소프트웨어나 운영 체제에 존재하는 결함, 오류 또는 약점을 말합니다. Trivy는 OS 패키지(Alpine, RHEL, CentOS 등)와 애플리케이션 종속성(Bundler, Composer, npm, yarn 등)의 취약성을 감지합니다. Trivy는 사용하기 쉽습니다. 바이너리를 설치하기만 하면 스캔할 준비가 끝납니다! 스캐닝을 위해 해야 할 일은 컨테이너의 이미지 이름 등의 대상을 지정하는 것뿐입니다.
빌드된 Docker 이미지나 프로젝트 루트에 대해 로컬로 쉽게 설치하고 실행할 수 있습니다. 또한 JSON 및 테이블 출력을 포함한 여러 출력을 지원합니다.
불행히도 Trivy가 스캔할 수 없는 프로젝트(예: Golang)가 있기 때문에 많은 코드가 Golang으로 되어 있으므로 OWASP Dependency-Check 에 의존해야 했습니다.
Dependency-Check는 프로젝트의 종속성에 포함된 공개적으로 공개된 취약점을 감지하려는 소프트웨어 구성 분석(SCA) 도구입니다. 이는 주어진 종속성에 대한 CPE(Common Platform Enumeration) 식별자가 있는지 여부를 확인하여 수행됩니다. 발견되면 관련 CVE 항목을 링크하는 보고서가 생성됩니다.
보고서, JUnit, JSON 출력(및 기타)을 포함하는 HTML 페이지를 생성할 수 있습니다.
이제 우리는 더 흥미로운 것에 점점 가까워지고 있습니다 😊
DevOps 및 SRE 팀에서 이미 Elasticsearch + Kibana + Fluentd를 사용하고 있으므로 보안 검사의 JSON 출력을 분석하기 위해 기존 인프라를 사용하는 것은 자연스러운 일이었습니다.
신뢰할 수 없는 인프라(CI 실행자)에서 안전한 Elasticsearch로 데이터를 전송할 수 있는 방법만 찾으면 되었습니다. 이러한 목적을 위해 우리는 중간에 메시지 큐를 두기로 결정했습니다. Fluentd에는 Amazon SQS에서 메시지를 읽기 위한 in_sqs 플러그인이 있으며 사용하기도 간단하므로 최종 아키텍처는 다음과 같습니다.
데이터가 Elasticsearch에 도달하면 Kibana를 사용하여 몇 가지 대시보드를 간단하게 만들거나 Discover를 사용하여 필요에 따라 모든 세부 정보로 취약성을 쿼리할 수 있습니다.
이제 스캔 결과와 멋진 대시보드가 생겼습니다. 다음은 무엇일까요? 개발자들이 이러한 대시보드를 정기적으로 확인할 것이라고 기대할 수는 없습니다. 대신 우리는 심각도가 높거나 그 이상의 문제가 발견되고 해결책이 있는 경우 CI를 실패시키기로 결정했습니다. 이런 방식으로 책임이 개발자와 프로젝트 소유자에게 전가됩니다.
당연히 CVE를 허용 목록에 추가하거나 프로젝트별로 이 기본 동작을 재정의할 수 있는 옵션이 필요했습니다. 그래서 우리는 Trivy 실행을 래핑하고 그 동작과 출력을 처리하는 스캐닝 도구에서 사용되는 보안 스캐닝 프로필이 있는 저장소를 만들었습니다.
이제 모든 개발자는 이 저장소에 병합 요청을 제출하고 예외를 요청할 수 있습니다. Kibana 프로젝트에 대한 예시 프로필:
보안 스캐닝을 구현한 방식은 초기 사용 사례를 넘어 확장 가능한 견고한 기반입니다. 예를 들어:
Dockerfile과 도구는 공개 Gitlab 저장소에서 찾을 수 있습니다: https://gitlab.com/volterra.io/security-scanning
Jakub Pavlík 에게 감사드립니다.