수십 년 동안 C와 그 직계 후손 언어들은 시스템 프로그래밍에서 가장 선호되는 프로그래밍 언어였습니다. C가 개발된 1970년대 초에는 어셈블리 언어에서 크게 진일보한 언어였습니다. 50년이 지난 지금, 우리는 더 나은 선택을 할 수 있습니다.
1970년 당시에는 대부분의 사람들이 컴퓨터 보안을 염두에 두지 않았으며, 그 후로도 오랫동안 마찬가지였습니다. 인터넷에서 최초의 중대한 보안 취약점이 발생한 것은 훨씬 뒤인 1988년이었습니다. 이는 인터넷 웜으로 알려졌으며, 메모리의 배열이 범위를 벗어나 참조되는 버퍼 오버플로를 악용했습니다.
C++를 포함한 C 언어 계열에서는 배열의 범위를 검사하지 않습니다. 따라서 배열에 올바르게 접근하도록 보장하는 것은 프로그래머의 몫입니다. 이 때문에 버퍼 오버플로 오류가 흔히 발생합니다. 더 심각한 문제는 의도적으로 버퍼 오버플로를 일으켜 접근해서는 안 되는 메모리에 쉽게 접근할 수 있다는 점입니다.
버퍼 오버플로는 메모리 비안전성의 한 가지 예일 뿐입니다. 이와 관련된 다른 예로는 포인터 연산과 댕글링 포인터(해제 후 사용 버그라고도 함)가 있습니다. 오늘날에는 다양한 기법을 사용하여 해당 언어로 작성된 모든 프로그램에 메모리 안전성 문제가 없도록 보장하는 프로그래밍 언어가 많이 있습니다. C 계열 언어는 이러한 보장을 제공하지 않습니다. 메모리 안전성은 애초에 이 언어들의 설계 목표가 아니었습니다.
보안 취약점의 약 70%는 메모리 안전성 위반으로 인해 발생합니다. 이 주장은 방대한 데이터로 뒷받침됩니다. 메모리 안전성 문제가 차지하는 비율은 다음과 같습니다:
- 실제로 악용된 것으로 공개 및 탐지된 취약점의 67%(Google Project Zero 2021 추정치 기준).
- Android 취약점의 90%(Google에 따르면). 최근 Rust 사용으로 이 수치는 감소하고 있지만, 원격으로 악용 가능한 취약점의 89%는 여전히 메모리 안전성과 관련되어 있습니다.
- Microsoft 취약점의 70%(Microsoft 발표 기준).
- 최근 Apple 취약점 수정 사항의 대부분(Catalina, Big Sur, Monterey, Safari, iOS, tvOS, watchOS 전반).
2022년 7월, Chrome 103.0.5060.134에서 수정된 취약점 6개 중 5개는 메모리 안전성 문제였습니다. 분명 메모리 안전성 버그를 제거하면 엄청난 도움이 될 것입니다. 업계에서는 메모리 안전한 프로그래밍 언어를 사용하면 된다는 사실을 이미 오래전부터 알고 있었습니다. 역사적으로 문제는 항상 그에 따른 성능 비용이었습니다. 메모리 안전성이 중요하기 때문에 기존의 오버헤드 없이 이를 달성하기 위한 새로운 전략이 계속 연구되어 왔습니다. 오늘날에는 런타임 비용을 거의 또는 전혀 들이지 않고 메모리 안전성 오류를 제거하는 방법을 알고 있습니다. Rust와 같은 언어는 타입 시스템 설계의 혁신을 활용하여 비용이 많이 드는 런타임 지원 없이도 메모리 안전성을 보장합니다.
이는 피할 수 없는 결론으로 이어집니다. C/C++(더 일반적으로는 메모리 안전성이 보장되지 않는 언어)로 새로운 시스템 코드를 작성하는 일을 중단해야 합니다.
이는 기존 코드를 대규모로 무분별하게 다시 작성하자는 주장이 아닙니다. 기존 소프트웨어를 교체하려면 많은 비용이 들고 위험도 따릅니다. 그러나 업계는 기존 코드베이스에 메모리 안전성이 보장되지 않는 코드를 더 추가해 문제를 악화시키는 일을 중단해야 합니다. 기존 코드의 경우, 신뢰할 수 없는 사용자 입력을 검증하거나 처리하는 구성 요소, 권한이 부여된 컨텍스트에서 실행되는 구성 요소, 샌드박스 외부에서 실행되는 구성 요소 등 가장 민감한 구성 요소를 우선적으로 다시 작성해야 합니다.
이러한 입장은 널리 받아들여지고 있지만, 여전히 일부에게는 논란의 여지가 있습니다. 다음은 현상 유지를 지지하는 일반적인 주장과 이에 대한 우리의 답변입니다.
- 버그는 프로그래밍 언어에만 국한된 문제가 아닙니다.
- 대부분의 취약점은 메모리 안전성 버그로 인해 발생합니다. Rust와 같은 메모리 안전 언어에서는 메모리 안전성 버그가 발생할 수 없습니다. 따라서 메모리 안전 언어를 사용하면 대부분의 취약점이 애초에 생기는 것을 방지할 수 있습니다.
- 코드 검토를 통해 버그를 발견할 수 있습니다.
- 연구 결과에 따르면 코드 리뷰가 상황을 개선할 수는 있지만 많은 문제를 놓치는 경우가 많으며, 모든 문제를 찾아내는 것은 결코 아닙니다.
- 안전하지 않은 모듈이 있으면 이 모든 논의가 무의미해집니다.
- 안전하지 않은 코드는 매우 작은 코드 영역에 명확히 구분되어 있으므로, 이를 검증하는 데 리소스를 집중할 수 있습니다.
- 메모리 안전 언어의 구현에 버그가 있을 수 있습니다.
- 물론 그럴 수 있지만, 그럴 가능성은 훨씬 낮습니다. 컴파일러는 비교적 규모가 작고 엄격한 테스트를 거칩니다. 또한 단일 프로그램의 버그를 수정하는 것과 달리, 컴파일러를 수정하면 해당 컴파일러로 컴파일된 모든 프로그램이 자동으로 수정됩니다.
- 이런 실수는 초보자나 무능한 프로그래머만 저지른다.
- 오히려 위의 데이터는 Chrome 브라우저와 Windows 및 macOS 운영 체제 같은 대규모 시스템 프로젝트에서 가져온 것입니다. 이러한 프로젝트에는 업계에서 가장 유능하고 경험이 풍부한 개발자들이 참여하고 있지만, 그럼에도 여전히 메모리 안전성 문제가 발생합니다.
- 모범 사례를 따르면 이러한 문제를 방지할 수 있습니다.
- 위 내용을 참조하세요. 앞서 언급한 팀들은 매우 엄격한 모범 사례를 따르며 사용 가능한 최고의 도구를 활용합니다.
- 모든 코드를 다시 작성하는 것은 현실적으로 불가능합니다.
- 모든 코드를 완전히 다시 작성해야 한다고 주장하는 사람은 없습니다. 그보다는 핵심 요소(높은 권한, 넓은 공격 표면, 보안 보장의 핵심)를 중점적으로 개선하고, 새로운 코드는 메모리 안전 언어로 작성하는 접근 방식을 권장합니다.
- 성능이 충분하지 않다.
- Rust의 성능은 C/C++와 대체로 비슷한 수준입니다. 사소한 성능 차이 때문에 보안 위험을 감수할 이유는 없습니다. 경우에 따라서는 Rust 프로그램이 더 빠를 수도 있습니다.
- Rust와 같은 메모리 안전 시스템 프로그래밍 언어는 역사가 너무 짧다.
- Rust가 Linux 커널에 도입되고 있습니다.
- Firefox와 같은 웹 브라우저의 상당 부분은 Rust로 작성되어 있습니다.
- Google은 Android에 엄청난 양의 Rust 코드를 추가했으며, 취약점은 단 한 건도 발생하지 않았습니다.
- 정적 분석, 퍼징, 샌드박싱과 같은 다른 해결책도 있습니다.
- 보안을 위해서는 다계층적 접근 방식이 필요합니다.
- 샌드박싱에는 한계가 있습니다.
- 아무리 뛰어난 최신 C++ 관행도 쏟아지는 취약점을 막을 수는 없습니다.
위의 사항에 대한 자세한 논의는 메모리 안전성 결여의 정량화와 이에 대한 대응을 참조하세요.
반대 의견에도 불구하고 필요한 변화를 향한 움직임은 점차 탄력을 받고 있습니다. 예를 들어 오픈 소스 소프트웨어 보안 재단(리눅스 재단의 지원을 받음)에 대규모 투자가 이루어지고 있습니다. 메모리 안전성은 미국 상원 보고서와 NSA에서도 논의되었습니다. 컨슈머 리포트 역시 기업과 주 정부 기관을 위한 일련의 권고안을 제시함으로써 이러한 움직임을 가속할 수 있는 다양한 유인책을 파악하기 위해 노력하고 있습니다.
요약하면:
지난 50년 동안 사회에서 컴퓨팅의 중요성은 엄청나게 커졌습니다. 컴퓨팅 인프라를 둘러싼 위협 환경 역시 최근 수십 년 사이에 급격히 변화했습니다. 그러나 컴퓨팅 시스템을 구축하는 데 사용하는 프로그래밍 언어는 그에 맞춰 변화하지 않았습니다. 메모리 안전성의 결여는 소프트웨어 보안 취약점의 가장 큰 단일 원인입니다. 이는 특정 유형의 소프트웨어에만 국한된 문제가 아닙니다. 메모리 안전성이 보장되지 않는 언어를 사용하는 곳이라면 어디에서나 메모리 안전성 문제가 만연합니다. 수치상으로도 다른 어떤 유형의 취약점도 이에 근접하지 못합니다.
이제 우리는 점점 심각해지는 이 문제를 해결할 수단을 갖추었으며, 업계 차원에서 반드시 이를 해결해야 합니다. 다행히 이러한 상황에 대한 인식이 확산되고 있지만, 문제는 시급하며 더 이상 지체할 시간이 없습니다.
작성자 소개
관련 블로그 게시물
AI 시대의 새로운 애플리케이션 제공 원칙으로 복잡성 극복하기
보안, 일관성, 완전 자동화에 중점을 둔 애플리케이션 제공의 새로운 6가지 원칙을 도입하여 복잡성 없이 하이브리드 멀티클라우드의 유연성을 누리세요.
디지털 혁신을 가속화하는 6가지 기술 역량
오늘날의 엔터프라이즈 아키텍처에는 기술 변화를 주도하는 데 핵심적인 민첩성, 확장성, 보안 및 관찰 가능성이 부족하지만, 이 여섯 가지 핵심 역량은 기업이 디지털 혁신 전반에 걸쳐 위험과 과제를 관리하는 데 도움이 될 것입니다.
하이브리드 근무가 ID 중심 보안으로의 전환을 이끌고 있습니다
자동화와 디지털화의 폭발적인 성장에 하이브리드 근무 모델로의 전환 추세가 더해지면서, IP 기반 보안에서 벗어나 ID 기반 액세스 전략으로 전환하는 움직임이 더욱 가속화될 것입니다.
관점의 현대화: 애플리케이션에서 경험으로
그리스와 로마의 신들처럼, 여러 신화에서도 동일한 존재가 다양한 모습으로 나타나는 것을 볼 수 있습니다. 본질적으로 각각의 화신은 기존 존재가 새로운 얼굴로 드러난 것입니다. 디지털 세계에서도 이와 비슷한 양상이 나타납니다. 우리가 ‘애플리케이션’이라고 부르는 것들은 흔히 기존 기능이 새로운 형태로 구현된 것이라 볼 수 있습니다.
코로나19 이후 기업 결제의 디지털 전환
디지털 결제는 과거의 현금만큼이나 보편화되었습니다. 코로나19 팬데믹으로 인한 봉쇄 조치는 소비자의 디지털 결제 서비스 의존도를 더욱 빠르게 높였습니다. 기업의 디지털 결제 도입 역시 가속화되었습니다. 대중을 상대로 영업하든 하지 않든 기업에는 여전히 지급해야 할 대금과 받아야 할 대금이 있기 때문입니다.
공급망 해킹과 보안에서 하드웨어의 역할
수석 아키텍트 Dave Schmitt와 CTO 오피스가 최근 Bloomberg의 Super Micro 관련 기사를 계기로 하드웨어 보안 전문성의 중요성을 되짚어봅니다. 또한 이 글에서는 시스템이 안전하게 보호되고 있는지 확인하기 위해 공급업체에 물어봐야 할 질문도 소개합니다.