Your Compiler Can Undo Your Security Checks
컴파일러가 보안 검사를 되돌릴 수 있다 — 최적화가 만들어내는 취약점
보안 연구가 Chris Domas가 Black Hat USA 2026에서 David Bombal과의 대담을 통해, C 언어로 모범 사례를 따라 작성한 코드도 컴파일러 최적화에 의해 보안 검사가 제거되거나 TOCTOU 취약점이 새로 생길 수 있음을 설명합니다. AI를 활용해 5억 줄의 오픈소스 코드를 분석한 결과 300개의 잠재적 위험 패턴이 발견됐으며, 개발자는 최적화된 빌드를 직접 분석하고 출시될 바이너리 그대로를 테스트해야 한다고 권고합니다.
- 주제
본문
안전한 C 코드를 작성하고 널리 인정된 모범 사례를 따르더라도 최종 바이너리는 취약할 수 있습니다. 이유는 단순합니다. CPU는 개발자가 작성한 소스 코드를 실행하는 것이 아니라 컴파일러가 생성한 결과물을 실행하기 때문입니다. David Bombal이 Black Hat USA 2026 현장에서 보안 연구가 Chris Domas를 만나, 합법적인 컴파일러 최적화가 어떻게 보안 방어를 제거하고 메모리 소거 연산을 삭제하며, 겉보기에 안전한 코드에 time-of-check to time-of-use(TOCTOU) 취약점을 주입하는지를 다룹니다.
C 추상 머신과 컴파일러의 변형 권한
Domas는 C 추상 머신(abstract machine)의 개념을 설명하며, C 스펙이 컴파일러에 코드를 극적으로 변형할 수 있는 광범위한 자유를 허용한다는 점을 짚습니다. 컴파일러는 추상 머신의 관찰 가능한 동작만 보존하면 되므로, 개발자가 의도한 부수 효과 — 예컨대 민감한 데이터를 덮어쓰는 memset 같은 메모리 소거 — 가 '죽은 코드'로 판단되어 통째로 삭제될 수 있습니다. 영상에서는 컴파일러가 메모리 소거 코드를 삭제하는 사례와, 아예 취약점을 새로 '발명'하는 사례가 별도 섹션으로 다뤄집니다.
흥미로운 점은 취약성 여부가 코드의 논리뿐 아니라 레지스터 압박(register pressure), 구조체 레이아웃, 데이터 크기 같은 우연한 요소에 좌우된다는 것입니다. 한 사례에서는 데이터 크기가 17바이트나 33바이트일 때는 안전한데 그 사이 크기에서는 취약한 코드가 생성됐습니다. 즉 같은 소스라도 최적화 결과에 따라 취약점이 나타났다 사라졌다 하는 것입니다.
Rust도, 컴파일러 교체도 답이 아니다
흔히 떠오르는 해결책들에 대해 두 사람은 신중한 입장을 보입니다. GCC에서 Clang으로, 또는 그 반대로 바꾸는 것은 근본적인 해결이 아니며, Rust 역시 이 문제를 완전히 해결해주지 않는다고 지적합니다. 문제의 본질이 특정 컴파일러 구현이 아니라 언어 스펙이 허용하는 변형의 범위에 있기 때문입니다. 그렇다고 안전한 코드 작성을 포기하라는 뜻은 아니며, 영상은 '보안 코드 작성을 포기하지 말라'는 메시지를 명확히 합니다.
AI로 5억 줄을 분석해 300개 위험 패턴 발견
연구진은 AI를 활용해 5억 줄 규모의 오픈소스 코드를 분석했고, 컴파일러 최적화에 의해 위험해질 수 있는 300개의 잠재적 패턴을 식별했습니다. 이는 이러한 문제가 이론적 가능성이 아니라 실제 코드베이스에 광범위하게 존재할 수 있음을 시사합니다. 대담은 공격자 입장에서 이 취약점을 누가 어떻게 활용할 수 있는지, 그리고 AI가 공격자의 무기가 될 수 있는지에 대한 논의로도 이어집니다.
개발자가 지금 할 수 있는 것
Domas가 제시하는 실용적 권고는 다음과 같습니다. 첫째, 컴파일러 경고를 활성화할 것. 둘째, sanitizer를 사용할 것. 셋째, 최적화가 적용된 빌드를 분석할 것. 넷째, 실제로 출시될 바이너리 그대로를 테스트할 것. 핵심은 소스 코드 수준의 검토만으로는 부족하며, 최종 산출물 수준에서 보안 속성이 유지되는지 확인해야 한다는 점입니다.
Reddit 반응
- @happyscrappy — 상수 시간(constant-time)으로 동작해야 하는 HMAC 검증 코드가 대표적인 피해 사례라고 지적합니다. null 역참조가 정의되지 않은 동작(undefined behavior)이므로 컴파일러가 null 검사를 제거할 수도 있고, '컴파일러가 bounds check를 지웠나?'는 일종의 밈이 됐다고 덧붙입니다. 이를 막는 builtin 함수가 몇 개 있다고 언급합니다.
- @PurpleOstrich97 — 중요한 보장은 언어 차원에 내장되어야 한다는 점을 보여주는 사례라고 평가합니다. C와 Rust 모두 inline 힌트가 있지만 Rust에는 no_mangle, repr(C) 같은 추가 보장 장치가 있으며, 컴파일러 플래그만 바꿔도 보안이 깨지고 손쓸 방법이 없다면 그것은 언어에 무언가가 부족하다는 뜻이라고 주장합니다.
- @ryan017 — 여기서 새로운 소식은 TOCTOU 취약점을 피하려 작성한 소스 코드에서 컴파일러가 TOCTOU 취약점을 만들어낼 수 있다는 점이라고 정리합니다. 소스에서 가변 상태를 지역 변수에 명시적으로 스냅샷해도 컴파일러가 그 복사를 '최적화'해서 제거하고 가변 상태를 두 번 읽는 코드를 만들 수 있다는 것입니다.
- @esiy0676 — 이 링크가 영상/팟캐스트 형태임을 알리며 시놉시스를 공유합니다.
- @TheWheez — Chris Domas의 Black Hat, DEFCON 발표는 지금까지 본 콘퍼런스 토크 중 가장 흥미롭고 독특한 편이며, x86을 누구보다 잘 아는 인물이라고 추천합니다.
원문: David Bombal / 번역·요약: Trawling