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

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

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

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

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

내 질문은 :

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

최신 정보:

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



답변

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

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

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

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

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


답변

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


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

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


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

  • 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 기사 참조) .

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

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


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


답변

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

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

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

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


답변

고장 나면 고치지 마십시오

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

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

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

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

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

편집하다

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

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


답변

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

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

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

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

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


답변

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

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

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


답변

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