오래된 C 컴파일러를 사용하는 것이 보안 상 위험합니까?


139

우리는 아무도 관심을 갖지 않는 생산 시스템을 가지고 있으며 이러한 기계는 GCC 3 또는 GCC 2와 같은 고대 버전의 GCC를 실행합니다.

그리고 경영진이 더 최근으로 업그레이드하도록 설득 할 수는 없습니다. "파산하지 않으면 해결하지 마십시오"라고 말합니다.

우리는 매우 오래된 코드 기반 (80 년대로 작성 됨)을 유지하므로이 C89 코드는 이러한 컴파일러에서 잘 컴파일됩니다.

그러나 나는이 오래된 것들을 사용하는 것이 좋은 생각인지 확실하지 않습니다.

내 질문은 :

이전 C 컴파일러를 사용하면 컴파일 된 프로그램의 보안이 손상 될 수 있습니까?

최신 정보:

동일한 코드가 Windows 대상 용 Visual Studio 2008 대상에 의해 작성되었으며 MSVC는 아직 C99 또는 C11을 지원하지 않으며 (최신 MSVC가 지원하는지 알 수 없음) 최신 GCC를 사용하여 Linux 상자에서 작성할 수 있습니다. 따라서 새로운 GCC를 사용한다면 이전과 마찬가지로 잘 구축 될 것입니다.


5
흥미로운 질문 - 빠른뿐만 아니라 읽기이 될 수있는 가치 - developers.slashdot.org/story/13/10/29/2150211/... .. 그래서 새로운 컴파일러는 최적화 할 수 타협 보안 때.
Neil

6
이전 gcc 버전은 ASLR 용 PIC / PIE 로의 컴파일을 지원합니까? 스택 카나리아를 지원합니까? W ^ X (NX)? 그렇지 않은 경우 취약점에 대한 완화 조치가 부족하기 때문에 업그레이드해야합니다.
EOF

12
gcc 4.x의 경고를 살펴보면 알지 못하는 기존 보안 취약점이 즉시 드러날 수 있습니다.
OrangeDog

7
@OrangeDog : 왜 gcc 4.x인가? gcc6은 현재 릴리스 시리즈이며 gcc 5는 한동안 사용되었습니다. 그러나 -O3 -Wall -Wextra -fsanitize=undefined현대 gcc와 clang으로 식별 된 문제를 해결 하면 도움이 될 것입니다.
Peter Cordes

4
@OrangeDog GCC는 마케팅 버전 번호로 이동했습니다. GCC 5는 기본 C 및 C ++ 표준과 libstdc ++ ABI를 변경했기 때문에 큰 버전 충돌이있었습니다. GCC 6은 5.1이라고합니다.
zwol

답변:


102

사실 나는 반대를 주장 할 것입니다.

C 표준에 의해 동작이 정의되지 않은 경우가 많지만 주어진 플랫폼에서 "덤 컴파일러 (dumb compiler)"로 어떤 일이 발생하는지는 분명합니다. 부호있는 정수가 오버플로되거나 두 가지 유형의 변수를 통해 동일한 메모리에 액세스하는 것과 같은 경우.

gcc (및 clang)의 최신 버전은 이러한 경우가 "정의되지 않은 동작"조건에서 바이너리가 동작하는 방식을 변경하는 경우 신경 쓰지 않는 최적화 기회로 취급하기 시작했습니다. C를 "휴대용 어셈블러"처럼 취급 한 사람들이 작성한 코드베이스는 매우 나쁩니다. 시간이 지남에 따라 옵티마이 저는 이러한 최적화를 수행 할 때 더 큰 코드 덩어리를 찾기 시작했습니다. 바이너리는 "벙어리 컴파일러로 작성된 바이너리"가 아닌 다른 것을 수행 할 가능성이 높아집니다.

"전통적인"동작 (위에서 언급 한 두 가지에 대한 -fwrapv 및 -fno-strict-aliasing)을 복원하는 컴파일러 스위치가 있지만 먼저 알아야합니다.

원칙적으로 컴파일러 버그는 호환 코드를 보안 허점으로 바꿀 수는 있지만, 이것이 거대한 계획에서 무시할 수 있다고 생각합니다.


13
그러나이 주장은 두 가지 방식으로 작동합니다. 컴파일러가 "정의되지 않은 행동"을 예측할 수 있다면, 그것을 악의적으로 사용하는 것이 더 쉬울 수 있습니다 ...
André

18
@Andre 컴파일 된 코드 는 어쨌든 예측할 수없는 동작을 예측할 수 있습니다. 즉, 일단 코드가 컴파일되면 특정 컴파일 된 버전에서 예측할 수없는 동작을 예측할 수 있습니다.
user253751

6
people who treated C like a "portable assembler"C가 아닌가?
최대

10
@Max이 답변은 현대의 최적화 프로그램으로 인해 "휴대용 어셈블러"개념이 실제로는 구식이라는 사실에 대해 정확하게 경고합니다. 그리고 나는 그것이 개념적으로 처음에는 옳지 않다고 주장합니다.
Theodoros Chatzigiannakis

6
정의되지 않은 행동에 의존하고 나중에 뿌린 것을 거두기 시작한 사람들에게는 동정심이 없습니다. 이것은 새로운 컴파일러가 본질적으로 덜 안전하다는 것을 의미하지는 않습니다. 이는 비 호환 코드가 시한 폭탄 이었다는 것을 의미합니다. 비난은 그에 따라 분배되어야한다.
underscore_d

52

두 행동 과정 모두에 위험이 있습니다.


오래된 컴파일러는 성숙이라는 이점이 있으며, 깨진 컴파일러는 아마도 성공적으로 해결되었을 것입니다 (그러나 보장 할 수는 없습니다).

이 경우 새로운 컴파일러는 새로운 버그의 잠재적 원인입니다.


반면에 최신 컴파일러에는 추가 도구가 제공됩니다 .

  • GCC와 Clang은 이제 살균제를 사용합니다. 다양한 종류의 정의되지 않은 동작을 감지하기 위해 런타임을 계측 할 수있는 를 제공합니다 (Google Compiler 팀의 Chandler Carruth는 작년에 전체 범위에 도달 할 것이라고 주장했습니다)
  • Clang은 적어도 강화 기능을 제공 합니다. 예를 들어 Control Flow Integrity제어 흐름의 하이 잭을 탐지하는 것입니다. 스택 스매싱 공격으로부터 보호하기위한 강화 도구도 있습니다 (스택의 제어 흐름 부분을 데이터 부분에서 분리하여) ; 강화 기능은 일반적으로 오버 헤드가 낮습니다 (<1 % CPU 오버 헤드)
  • Clang / LLVM은 또한 테스트중인 함수의 입력 공간을 스마트하게 탐색하는 인스트루먼트 된 퍼징 단위 테스트를 작성하는 도구 인 libFuzzer 에서 작업 하고 있습니다 (입력을 조정하여 아직 탐색되지 않은 실행 경로를 가져옴).

살균제 (Address Sanitizer, Memory Sanitizer 또는 Undefined Behavior Sanitizer)를 사용하여 바이너리를 계측 한 다음 퍼징 ( 예 : American Fuzzy Lop 사용 )하면 여러 주요 소프트웨어의 취약점이 밝혀졌습니다 (예 : LWN.net 기사 참조) .

컴파일러를 업그레이드하지 않으면 새로운 도구와 향후의 모든 도구에 액세스 할 수 없습니다.

저전력 컴파일러를 사용하면 모래에 머리를 넣고 취약성이 발견되지 않습니다. 귀사의 제품이 고가의 목표 인 경우, 재고 할 것을 권장합니다.


참고 : 프로덕션 컴파일러를 업그레이드하지 않더라도 새로운 컴파일러를 사용하여 취약성을 점검 할 수 있습니다. 그것들은 다른 컴파일러이기 때문에 보장은 줄어 듭니다.


1
+1은 다른 답변의 'b-but my good old UB'악 대차를 사용하는 대신 새로운 컴파일러가 더 안전 할 수있는 사례를 언급하는 데 귀를 기울입니다. 이는 보안과 직접 ​​관련이 없지만 합리적이고 현대적인 동기 부여를 제공하는 다른 많은 개선 사항 중 하나입니다.
underscore_d

'모호함을 통한 보안'을 옹호하는 것처럼 느껴지지만; 오래된 컴파일러에 영향을 미치는 버그는 알려져 있으며 공개되어 있습니다. 새로운 컴파일러가 버그를 도입한다는 데 동의하지만 이러한 버그는 이전 버전의 버그와 같이 아직 공개되지 않았으므로 응용 프로그램을 자주 업데이트하는 경우 약간의 보안입니다.
The6P4C

챈들러 카루스는 너무 귀여워서 훌륭한 것들을 말합니다. 내가 할 수 있다면 나는 그와 결혼 할 것이다.
Daniel Kamil Kozar

46

컴파일 된 코드에는 악용 될 수있는 버그가 포함되어 있습니다. 버그는 소스 코드의 버그, 컴파일러 및 라이브러리의 버그 및 소스 코드의 컴파일러가 버그로 바뀌는 정의되지 않은 동작의 세 가지 소스에서 비롯됩니다. (정의되지 않은 동작은 버그이지만 아직 컴파일 된 코드의 버그는 아닙니다. 예를 들어, i = i ++; C 또는 C ++의 경우 버그이지만 컴파일 된 코드에서는 i를 1 씩 증가시키고 Ok 또는 설정할 수 있습니다. 나는 쓰레기에 버그가 있습니다).

컴파일 된 코드의 버그 비율은 테스트 및 고객 버그 보고서로 인한 버그 수정으로 인해 아마도 낮습니다. 따라서 처음에는 많은 버그가 있었을 수도 있지만 그 정도는 줄어 들었습니다.

최신 컴파일러로 업그레이드하면 컴파일러 버그로 인해 발생한 버그가 손실 될 수 있습니다. 그러나이 버그들은 모두 여러분이 아는 바도 아무도 악용하지 않은 버그 일 것입니다. 그러나 새로운 컴파일러에는 자체 버그가있을 수 있으며, 새로운 컴파일러는 정의되지 않은 동작을 컴파일 된 코드의 버그로 바꾸는 경향이 강합니다.

컴파일 된 코드에 새로운 버그가 많이 생길 것입니다. 해커가 찾아서 악용 할 수있는 모든 버그. 그리고 많은 테스트를 수행하지 않고 오랫동안 버그를 찾기 위해 고객과 코드를 남기지 않으면 덜 안전합니다.


6
다시 말해, 컴파일러가 어떤 문제를 일으키는 지 알 수있는 쉬운 방법이 없으며, 전환을 통해 알 수없는 다른 문제가 발생합니까?
제레미 카토

1
@JeremyKato : 글쎄, 당신이있는 경우가 있습니다 또한 알려진 문제의 다른 세트를 받고는. 컴파일러 자체에 알려진 보안 결함이 무엇인지 확실하지 않지만 구체적인 예제를 위해 새로운 컴파일러로 업데이트하면 최신 libc를 사용할 수도 있다고 가정합니다 (이전 버전을 사용하는 것은 불가능 함을 의미합니다) )이 작업을 수행하기 위해, 당신은 줄 아는 당신이이 결함을 수정하고 있습니다 getaddrinfo(): access.redhat.com/articles/2161461를 . 이 예제는 실제로 컴파일러 보안 결함은 아니지만 10 년 이상 동안 알려진 고정 결함이있을 수 있습니다.
Steve Jessop

2
허, 실제로 그 결함은 2008 년에 도입 된 것이므로 질문자는 안전 할 수 있습니다. 그러나 내 요점은 그 특정 예에 관한 것이 아니며, 오래된 툴 체인이 코드에 넣을 알려진 버그가 있다는 것입니다. 따라서 업데이트 할 때 새로운 미지의 세트를 도입하는 것이 사실이지만 이것이 전부는 아닙니다 . 기본적으로 최신 툴체인이 고칠 수있는 알려진 치명적인 결함을 남기거나 자신의 코드에서 정의되지 않은 모든 동작에 대해 주사위를 굴리면 알 수없는 결과를 얻는 "안전"여부를 추측해야합니다.
Steve Jessop

19

고장 나면 고치지 마십시오

그러나 상사는이 말을하는 것이 더 중요합니다. 요소는 입력, 출력, 버퍼 오버플로를 보호하는 것입니다. 그것들의 부족은 사용 된 컴파일러에 관계없이 그 관점에서 체인에서 가장 약한 링크입니다.

그러나 코드 기반이 오래되었고 형식 안전성 부족, 안전하지 않은 fgets 등과 같은 사용 된 K & R C의 약점을 완화하기위한 작업이 이루어 졌다면 " 컴파일러를보다 현대적인 C99로 업그레이드 할 것인가?" / C11 표준이 모든 것을 깨뜨 렸습니까? "

단, 부작용을 유발할 수있는 최신 C 표준으로 마이그레이션 할 명확한 경로가 있으며, 이전 코드베이스의 포크를 시도하고이를 평가하여 추가 유형 검사, 상태 검사 및 업그레이드 여부를 결정하는 것이 가장 좋습니다. 최신 컴파일러는 입 / 출력 데이터 세트에 영향을줍니다.

그런 다음 상사에게이를 보여줄 수 있습니다. " 업데이트 된 C99 / C11 표준에 따라 업데이트 된 코드베이스가 리팩토링되었습니다 ."

그것은 매우 신중하게 무게를 측정해야 할 도박입니다 . 변화에 대한 저항은 그 환경에서이 표시 될 수 있습니다 및 새로운 물건을 만져 거부 할 수 있습니다.

편집하다

그냥 몇 분 동안 앉아서,이 많은 것을 깨달았습니다 .K & R 생성 코드는 16 비트 플랫폼에서 실행될 수 있습니다. 더 현대적인 컴파일러로 업그레이드하면 실제로 코드베이스를 깨뜨릴 수 있습니다. 아키텍처 측면에서 생각하면 32 비트 코드가 생성됩니다. 이것은 다른 즉, 입력 / 출력 데이터 세트에 사용되는 구조에 재미 부작용을 가질 수있는 조심스럽게 무게하는 요인.

또한 OP는 Visual Studio 2008을 사용하여 코드베이스를 빌드하는 것에 대해 언급 했으므로 gcc를 사용하면 MinGW 또는 Cygwin으로 환경을 가져올 수 있습니다. 이는 Linux를 대상으로하지 않는 한 환경에 영향을 줄 수 있습니다. 구식 K & R 코드 기반의 노이즈를 최소화하기 위해 컴파일러에 추가 스위치를 포함시켜야 할 수도 있습니다. 다른 중요한 것은 기능이 손상되지 않도록 많은 테스트를 수행하는 것이 고통스러운 운동으로 판명 될 수 있습니다.


동일한 코드가 Visual Studio 2008 for Windows 대상에 의해 작성되었으며 MSVC는 아직 C99 또는 C11을 지원하지 않으며 (최신 MSVC가 지원하는지 알 수 없음) 최신 GCC를 사용하여 Linux 상자에서 작성할 수 있습니다. 따라서 새로운 GCC를 사용한다면 이전과 마찬가지로 잘 구축 될 것입니다.
Calmarius

@Calmarius 감사합니다. 어쩌면 의견을 포함하여 질문을 편집하는 것이 가장 좋습니다. 중요합니다 :) 그리고 거기에 있었어야합니다; D
t0mm13b

@Calmarius는 내 답변을 편집했습니다. 이것은 새로 업데이트 된 질문에 대한 나의 생각입니다.
t0mm13b

2
내가 질문을 생각하지 않는다 ", 건축의 관점에서 32 비트 코드를 생각하고, 기회는, 현대 컴파일러로 업그레이드 실제로 코드 기반을 깰 수, 16 비트 플랫폼에서 실행 될 수있는 것은"에 관한 것입니다 포팅 새로운 구현 정의에 코드를 매개 변수.
Pascal Cuoq 10

동의했다. 그것은이다 가능한 런타임 취약점이 컴파일러의 버그에 의해 생성 될 수 있음. 그러나 코드에 버퍼 및 스택 오버런과 같은 런타임 취약점이 포함되어 있을 가능성훨씬 높습니다 . 따라서이 코드 기반을보다 안전하게 만드는 데 시간을 투자 할 경우 입력 문자열 길이를 검사하여 프로그램의 한계를 초과하지 않는지 확인하는 등의 작업에 투자해야합니다. 최신 컴파일러를 얻는 것은별로 도움이되지 않습니다. 네이티브 문자열 및 배열 객체를 사용하여 언어로 코드를 처음부터 다시 작성하면 많은 도움이됩니다. 그러나 상사는 그 비용을 지불하지 않을 것입니다.
O. Jones

9

이전 C 컴파일러를 사용하면 컴파일 된 프로그램의 보안이 손상 될 수 있습니까?

물론 이전 컴파일러에 프로그램에 영향을 줄 것으로 알려진 알려진 버그가 포함되어 있다면 가능합니다.

문제는 그렇지 않습니까? 확실히 알기 위해서는 버전에서 현재 날짜까지 전체 변경 로그를 읽고 수년 동안 수정 된 모든 버그를 확인해야합니다.

프로그램에 영향을 미치는 컴파일러 버그의 증거를 찾지 못하면 GCC를 업데이트하기 위해 약간의 편집증으로 보입니다. 최신 버전에는 아직 발견되지 않은 새로운 버그가 포함되어있을 수 있습니다. 최근 GCC 5 및 C11 지원으로 많은 변경이있었습니다.

즉, 80 년대에 작성된 코드는 이미 보안 허점으로 가득 차 있으며 컴파일러에 관계없이 잘못 정의 된 동작에 의존합니다. 우리는 여기서 사전 표준 C에 대해 이야기하고 있습니다.


6
나는 그것이 편집증이라고 생각하지 않습니다. 나는 OP가 그의 상사를 설득 할 이유를 발명하려고 노력하고 있다고 생각한다. 아마도 OP는 asm을 향상시키고 (LTO를 통한 파일 간 최적화 포함)보다 유용한 진단 / 경고를 제공하며 최신 언어 기능과 구문을 허용하기 때문에 실제로 새로운 컴파일러를 원할 것입니다. (예 : C11 표준).
Peter Cordes

9

악의적 인 개발자가 컴파일러 버그를 통해 백도어를 몰래 침입 할 수있는 보안 위험이 있습니다. 사용중인 컴파일러에서 알려진 버그의 양에 따라 백도어가 다소 눈에 띄지 않게 보일 수 있습니다 (어쨌든 소스 레벨에서 코드가 복잡하더라도 코드가 정확하다는 점). 버그가없는 컴파일러는 백도어를 찾을 수 없습니다. 백도어는 이러한 조건에 존재하지 않기 때문입니다). 추가 거부 가능성을 위해 악의적 인 개발자는 이전에 알려지지 않은 컴파일러 버그를 스스로 찾을 수도 있습니다. 다시 말하지만 위장의 품질은 발견 된 컴파일러 버그의 선택에 달려 있습니다.

이 공격은 이 기사 의 프로그램 sudo에 설명되어 있습니다. bcrypt는 Javascript 축소기에 대한 훌륭한 후속 조치를 작성했습니다 .

이 외에도 우려에서, C 컴파일러의 발전은 정의되지 않은 동작을 악용하는 것이었다 성실하게 작성되었습니다 오래된 C 코드가 실제로 더 시간에서 C 컴파일러로 컴파일, 또는에서 컴파일 확보 될 수 있도록 적극적으로 -O0 (그러나 일부 새로운 프로그램 중단 UB-exploiting 최적화 는 -O0에서도 새로운 버전의 컴파일러에 도입됩니다 ).


7

오래된 컴파일러는 알려진 해킹 공격에 대한 보호 기능이 없을 수 있습니다. 예를 들어 스택 스매싱 보호 기능은 GCC 4.1까지 도입되지 않았습니다 . 따라서 오래된 컴파일러로 컴파일 된 코드는 최신 컴파일러가 보호하는 방식으로 취약 할 수 있습니다.


6

걱정해야 할 또 다른 측면 은 새로운 코드개발이다 .

구형 컴파일러는 일부 언어 기능에 대해 프로그래머가 표준화하고 기대하는 것과 다른 동작을 가질 수 있습니다. 이러한 불일치로 인해 개발 속도가 느려지고 악용 될 수있는 미묘한 버그가 발생할 수 있습니다.

오래된 컴파일러는 더 적은 기능 (언어 기능 포함)을 제공하며 최적화도하지 않습니다. 프로그래머는 누락 된 기능을 다시 구현하거나 모호하지만 더 빠르게 실행되는 영리한 코드를 작성하여 이러한 결함을 극복 할 수 있습니다.


5

아니

그 이유는 간단하고 오래된 컴파일러에는 오래된 버그와 공격이있을 수 있지만 새 컴파일러에는 새로운 버그와 공격이있을 것입니다.

새 컴파일러로 업그레이드하여 버그를 "수정"하지 않습니다. 이전 버그와 새로운 버그 및 익스플로잇에 대한 익스플로잇 전환.


3
새 컴파일러에는 약점이 있지만 이전 컴파일러보다 적을 것으로 예상되며 그 이후로 알려진 몇 가지 코드 취약성을 감지 할 수 있습니다.
PJTraill 2016 년

그러나 새로운 컴파일러에는 알려지지 않은 새로운 약점이있을 수 있습니다. 컴파일러만으로는 업데이트가 필요한 보안 위험이 아닙니다. 표면적이 줄어들지 않습니다. 알려지지 않은 세트에 대해 알려진 문제 세트를 거래합니다.
coteyr

GCC 초기부터 버그를 발견하는 데 도움이되는 도구가 개선되었으며, 이러한 도구 (정적 분석, 계측 코드 동적 분석 / 산 염증, 퍼저 등)도 컴파일러 코드에 적용되어 품질을 향상시키는 데 도움이되었습니다. GCC 2 시대에는 모든 종류의 버그를 찾기가 훨씬 어려웠습니다. 버전에 대한 컴파일러 버그 비교-7 페이지를 참조하십시오. cs.utah.edu/~regehr/papers/pldi11-preprint.pdf GCC 4.5 및 LLVM 2.8 (게시시 최신)은 퍼징에서 가장 적은 버그를 가지고 있습니다.
Jetski S-type

2

이전 컴파일러의 버그는 새로운 컴파일러를 사용하는 것과는 달리 잘 알려져 있고 문서화되어 있으므로 버그를 피하여 버그를 피하기위한 조치를 취할 수 있습니다. 따라서 업그레이드에 대한 인수로는 충분하지 않습니다. 우리는 내가 일하는 곳에서 같은 토론을하고 임베디드 소프트웨어의 코드베이스에서 GCC 4.6.1을 사용하며 문서화되지 않은 새로운 버그에 대한 두려움 때문에 최신 컴파일러로 업그레이드하기를 꺼려합니다 (관리 중).


0

귀하의 질문은 두 부분으로 나뉩니다.

  • 명시 적 : "이전 컴파일러를 사용할 경우 더 큰 위험이 있습니까?"(제목에서와 같이 더 많거나 적음)
  • 암시 적 :“관리를 업그레이드하도록 설득하는 방법”

기존 코드 기반에서 악용 가능한 결함을 찾아서 최신 컴파일러가이를 감지했음을 표시하여 두 가지 모두에 대답 할 수 있습니다. 물론 경영진은“오래된 컴파일러에서 찾은 것”이라고 말할 수도 있지만 상당한 노력이 필요하다는 점을 지적 할 수 있습니다. 또는 새로운 컴파일러를 통해 취약점을 찾아서 새로운 컴파일러로 코드를 컴파일 할 수있는 경우이를 악용하십시오. 친숙한 해커의 도움을 원할 수도 있지만, 해커를 신뢰하고 코드를 보여줄 수 있는지 (그리고 새로운 컴파일러를 사용할 수 있는지)에 달려 있습니다.

그러나 시스템이 해커에 노출되지 않은 경우 컴파일러 업그레이드가 효율성을 높일 지 여부에 더 관심을 가져야합니다. MSVS 2013 코드 분석은 MSVS 2010보다 훨씬 빨리 잠재적 인 버그를 발견하며 C99 / C11을 지원합니다. – 공식적으로는 확실하지 않지만 선언은 명령문을 따를 수 있으며 변수를 for-loops로 선언 할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.