상세 컨텐츠

본문 제목

취약점 심각도를 정직하게 매기기 — RCE라고 부풀리지 않으려고 한 일들

보안

by 코드스키 2026. 7. 28. 11:00

본문

퍼징으로 크래시를 찾으면 잠깐 “이거 RCE 아닐까?”라는 생각이 든다. 하지만 크래시와 코드 실행 사이에는 큰 간격이 있다. 네트워크 파서 버그들을 제보하면서 실제로 확인한 영향만 남기고 심각도를 계속 낮춰 잡았던 과정을 정리한다. 공개가 끝난 사례의 평가 방법만 다루고, 미공개 취약점과 재현 입력은 싣지 않는다.

RCE로 부풀리지 않는 취약점 영향도와 CVSS 평가 대표 이미지
RCE로 부풀리지 않는 취약점 영향도와 CVSS 평가 대표 이미지

Out-of-bounds read를 RCE라고 부르지 않았다

찾은 버그의 중심은 버퍼 경계 밖을 읽는 OOB read였다. 비정상 종료가 재현되면 가용성 영향은 설명할 수 있다. 인접 메모리가 외부 응답이나 로그로 실제 노출되는 경로가 확인되면 기밀성 영향도 논의할 수 있다. 하지만 “읽기 범위를 벗어났다”는 사실만으로 공격자가 값을 쓰거나 명령 포인터를 제어했다고 말할 수는 없다.

MITRE CWE-125 Out-of-bounds Read 정의
MITRE CWE-125 Out-of-bounds Read 정의

그래서 보고서에는 확인된 것을 짧게 썼다. “OOB read가 발생하고 프로세스가 종료된다. 코드 실행과 외부 정보 노출은 확인하지 못했다.” 가능성을 크게 쓰는 대신 증거가 생기면 그때 영향 범위를 넓히는 방식이다.

ASan 빌드와 일반 최적화 빌드를 같이 봤다

Clang AddressSanitizer 공식 문서
Clang AddressSanitizer 공식 문서

AddressSanitizer는 경계 밖 접근 위치와 호출 스택을 찾는 데 강하다. 반면 실제 배포 바이너리와 메모리 배치가 달라질 수 있다. 같은 입력을 ASan 디버그 빌드와 일반 -O2 빌드에 넣었다.

결과 해석
두 빌드 모두 결정적으로 크래시 가용성 영향 근거가 강함
ASan만 abort, 일반 빌드는 정상 종료 버그는 맞지만 배포 영향은 추가 검증 필요
일반 빌드에서 출력만 달라짐 데이터 무결성·논리 영향으로 별도 평가

Sanitizer 리포트 한 장만으로 “원격 DoS가 확정됐다”고 쓰지 않았다. 실제 입력 경로가 네트워크에서 도달하는지, 데몬이 죽는지, supervisor가 즉시 복구하는지도 같이 봤다.

CVSS 벡터를 숫자보다 먼저 적었다

FIRST CVSS v3.1 공식 계산기
FIRST CVSS v3.1 공식 계산기

점수를 먼저 정하고 벡터를 맞추면 원하는 숫자 쪽으로 해석이 끌린다. 공격 벡터, 복잡도, 필요한 권한과 사용자 상호작용, 범위 변화, C/I/A 영향을 문장으로 정한 뒤 계산기에 넣었다. 특히 네트워크 패킷으로 도달한다는 사실과 아무 인증 없이 도달한다는 사실은 다른 지표다.

  • C: 외부로 실제 데이터가 노출됐는가
  • I: 파싱 결과나 저장 상태를 공격자가 바꿀 수 있는가
  • A: 단일 요청이 프로세스·서비스 가용성을 얼마나 깨는가

버전 대조와 중복 검색을 붙였다

취약 버전과 이전 릴리스, 최신 브랜치에 같은 최소 입력을 적용했다. 특정 커밋 이후에만 재현되면 도입 범위를 좁힐 수 있고, 옛 CVE와 함수·입력 형식이 다르다면 그 근거를 적을 수 있다. 공개 이슈, 커밋, NVD, GitHub Security Advisory를 검색했지만 비공개 중복까지 알 수는 없다는 한계도 명시했다.

패치의 성공 기준은 “안 죽음” 하나가 아니다

경계 값을 clamp하거나 길이를 확인하는 패치를 넣은 뒤 같은 PoC가 ASan·일반 빌드에서 모두 살아남는지 확인했다. 정상 입력 회귀 테스트와 기존 출력도 비교했다. 크래시만 막고 정상 레코드를 버리거나 카운트를 바꾸면 안전한 수정이라고 하기 어렵다.

제보에 남긴 증거

  • 대상 버전·커밋·빌드 옵션
  • 최소 입력의 크기와 해시
  • ASan 스택과 일반 빌드 결과
  • 버전별 재현 표
  • 패치 전후·정상 입력 회귀 결과
  • 중복 검색 범위와 확인하지 못한 부분

퍼징 자체보다 이 평가 과정이 더 오래 걸렸다. 크래시를 크게 부르는 건 쉽지만, 어디까지 확인했고 어디부터 모르는지 정확히 쓰는 쪽이 결국 메인테이너와 CNA의 신뢰를 얻었다.

공식 자료

같은 크래시도 배치 방식에 따라 벡터가 달라진다

예를 들어 인증 없이 외부 네트워크에서 한 패킷으로 데몬을 매번 종료할 수 있고 서비스가 자동 복구되지 않는다면 AV:N/AC:L/PR:N/UI:N과 높은 가용성 영향을 검토할 수 있다. 반대로 로컬 파일을 관리자가 직접 열어야 재현되고 프로세스가 즉시 재시작된다면 공격 벡터·권한·가용성 평가는 달라진다. “네트워크 파서에서 발견했다”만으로 AV:N을 고정하면 안 된다.

보고서 문장을 이렇게 나눴다

구분 문장 예시
관찰 ASan이 함수 X의 OOB read를 보고하고 프로세스가 abort했다.
재현 최신 커밋에서 동일 입력으로 5회 모두 재현됐다.
영향 해당 입력이 실제 서비스 경로에 도달할 때 가용성 저하가 가능하다.
미확인 메모리 내용의 외부 노출과 코드 실행은 확인하지 못했다.

관찰과 영향을 한 문장에 섞지 않으면 과장이 줄어든다. 특히 sanitizer의 진단명은 버그 종류이지 곧바로 원격 공격 결과가 아니다.

제보 전 마지막 질문

  1. PoC가 최신 기본 브랜치에서도 재현되는가
  2. 외부 입력이 해당 코드까지 실제로 도달하는가
  3. 프로세스·서비스·시스템 중 어디까지 영향이 가는가
  4. 정보 노출과 코드 실행을 직접 관찰했는가
  5. 패치가 정상 입력을 깨뜨리지 않는가

같이 읽기

이 기준으로 정리한 실제 공개 제보 흐름은 AFL++ 퍼징과 GHSA 10건 제보 기록, 메인테이너와 비공개로 협업한 과정은 GitHub 책임 제보와 PVR이 없을 때의 대응에 적었다.

관련글 더보기