TT Lab
블로그 시작하기
배우기 러닝패스 코스

스캐너는 빨간 줄 마흔 개를 줬다

스캐너 하나를 진실로 믿지 않는다

TT Lab 에서 이어서 보기

목표

같은 이미지에 대한 두 스캐너(Trivy·Grype)의 리포트를 합쳐, 한 도구만으로는 놓치거나 헛걸음하는 부분을 바로잡고 '실제로 대응할 목록' 을 만듭니다.

왜 중요한가

스캐너는 서로 다른 취약점 DB 와 매칭 규칙을 씁니다. 그래서 같은 이미지를 두고도 한쪽만 잡는 CVE 가 생기고, 심각도를 다르게 매기고, 때로는 거짓 양성을 냅니다 — 배포판이 백포트로 이미 고쳤는데 상류 버전만 보고 "걸린다" 고 하는 경우입니다. 한 도구의 출력을 그대로 믿고 관문에 넣으면, 놓치거나(한쪽만 잡은 진짜) 헛걸음합니다(거짓 양성).

교차 검증의 규칙은 둘입니다 — 놓치지 않으려 합집합으로 모으고, 심각도가 갈리면 보수적으로 높은 쪽을 택합니다. 그다음 배포판 보안 추적기 같은 근거로 거짓 양성만 걸러 냅니다. 근거 없이 "이건 거짓 양성 같다" 로 빼면 진짜를 놓칩니다.

이 실습은 리포트에서 출발합니다

파드에는 스캐너도 DB 도 없어, 두 도구가 낸 것과 같은 형식의 리포트가 /opt/fixtures/vulnxcheck/ 에 준비돼 있습니다. 실제로 두 도구를 돌리는 명령은 읽기 자료에 있습니다.

단계

  1. Trivy 리포트를 공통 형태로 펴 /root/xcheck/01-trivy.json 에 저장합니다.
  2. Grype 리포트를 같은 형태로 /root/xcheck/02-grype.json 에 저장합니다.
  3. 두 결과가 갈리는 지점을 /root/xcheck/03-diff.json 에 정리합니다.
  4. 합집합으로 합치되 심각도는 높은 쪽으로 /root/xcheck/05-merged.json 에 저장합니다.
  5. 배포판 추적기로 거짓 양성을 걸러 /root/xcheck/05-actionable.json 을 만듭니다.

참고

Trivy 리포트를 공통 형태로

/opt/fixtures/vulnxcheck/trivy-report.json 을 읽어 각 취약점을 {id, pkg, installed, fixed, severity} 로 펴서 /root/xcheck/01-trivy.json 에 id 사전순 배열로 저장하세요. severity 는 대문자(HIGH 등)로 둡니다.

Trivy 는 Results[].Vulnerabilities[] 이고 필드명이 PkgName·InstalledVersion·FixedVersion·Severity 입니다. 두 도구를 비교하려면 먼저 같은 모양으로 펴야 합니다.

Grype 리포트를 같은 형태로

/opt/fixtures/vulnxcheck/grype-report.json 을 읽어 같은 {id, pkg, installed, fixed, severity} 모양으로 /root/xcheck/02-grype.json 에 id 사전순 배열로 저장하세요. Grype 의 severity(High)도 대문자(HIGH)로 맞춥니다.

Grype 는 matches[] 이고, 각 항목의 vulnerability.id·vulnerability.severity·vulnerability.fix.versions·artifact.name·artifact.version 을 씁니다. fix.versions 가 비어 있으면 fixed 는 null 입니다. 대소문자를 맞춰야 뒤에서 비교가 됩니다.

두 도구가 어디서 갈리는가

두 결과를 CVE id 로 견주어 /root/xcheck/03-diff.json 에 both(둘 다 잡은 id)·trivy_only·grype_only 를 각각 id 사전순 배열로 저장하세요.

두 배열을 id 집합으로 바꿔 교집합과 차집합을 구합니다. 한 도구만 잡은 것이 있다는 사실 자체가 '한 스캐너로는 부족하다' 의 증거입니다.

심각도가 갈리는 곳을 짚는다

두 도구가 모두 잡았지만 심각도를 다르게 매긴 CVE 를 /root/xcheck/04-severity.json 에 id 사전순 배열로 저장하세요. 각 항목은 id·trivy·grype(각 도구의 대문자 심각도)·chosen(더 높은 쪽)입니다.

03 의 both 목록에서, 두 결과의 severity 가 다른 것만 고릅니다. 같은 취약점을 CRITICAL 로도 HIGH 로도 보는 일이 흔하며, 관문에서는 보통 높은 쪽을 택합니다.

합쳐서 보수적으로

두 결과의 합집합을 /root/xcheck/05-merged.json 에 id 사전순 배열로 저장하세요. 각 항목은 id·pkg·installed·fixed·severity·sources(이 CVE 를 잡은 도구 이름 사전순 배열)이고, 심각도가 둘이 다르면 더 높은 쪽을 택합니다(CRITICAL>HIGH>MEDIUM>LOW).

합집합으로 모으되, 같은 CVE 가 두 도구에 다 있으면 심각도는 보수적으로 높은 쪽을 택합니다. 놓침을 줄이는 쪽으로 합치는 것이 교차 검증의 목적입니다.

거짓 양성을 걸러 낸다

배포판 보안 추적기 /opt/fixtures/vulnxcheck/debian-tracker.json 로 거짓 양성을 걸러, 실제 대응 목록을 /root/xcheck/05-actionable.json 에 저장하세요. 추적기에서 status 가 not-affected 인 CVE 는 excluded(id 와 이유) 로 빼고, 나머지는 actionable(id 사전순)에 둡니다. 추적기에 없는 CVE 는 그대로 actionable 입니다.

데비안은 상류 버전에 버그가 있어도 백포트로 고쳐 두는 일이 많습니다. 그러면 버전 문자열만 보는 스캐너가 '걸린다' 고 하지만 실제로는 안전합니다 — 배포판 추적기가 not-affected 로 표시합니다. 근거(추적기) 없이 거짓 양성으로 몰면 진짜를 빠뜨리게 됩니다.

결정을 요약으로 남긴다

교차 검증 결과를 /root/xcheck/07-report.json 에 요약하세요. tools(grype·trivy 이름 배열), total_merged(합집합 개수), trivy_only·grype_only(개수), severity_conflicts(개수), excluded_false_positive(개수), actionable(개수)를 담습니다.

앞 단계들의 산출물에서 숫자만 모으면 됩니다. 이 요약이 있어야 '왜 이 목록으로 정했는지' 를 다음 사람이 읽습니다.