C 컴파일러를 처음부터 컴파일 한 다음 Unix / Linux를 처음부터 컴파일하는 방법 우리는 UNIX와 Linux 서버를 광범위하게 사용합니다. 이 기사를

미국 / 영국 이외의 지역에있는 대규모 서비스 조직에서 근무한다고 가정 해 보겠습니다. 우리는 UNIX와 Linux 서버를 광범위하게 사용합니다.

이 기사를 읽으면 백도어를 C 컴파일러에 쉽게 삽입 할 수 있다고 언급 한 다음 해당 컴파일러로 컴파일 된 코드에도 백도어가 포함됩니다. NSA / GCHQ가 모든 암호화 방법, 하드웨어 및 소프트웨어에 백도어 / 취약점을 부여해야한다는 최근의 유출로 인해 컴파일러는 이제 중요한 장애 지점이되었습니다. 잠재적으로 모든 표준 UNIX / Linix 배포판이 손상 될 수 있습니다. 우리는 우리의 시스템, 데이터 및 고객 데이터를 악의적 인 정부가 침해 할 여유가 없습니다.

이 정보가 주어지면 신뢰할 수있는 컴파일러를 처음부터 작성하고 나서 안전한 기반을 구축하여 해당 컴파일러를 사용하여 소스 코드에서 운영 체제 및 응용 프로그램을 빌드 할 수 있습니다.

질문

소스 코드에서 컴파일러를 컴파일 한 다음 (달걀 치킨 달걀 시나리오) 신뢰할 수있는 Unix / Linux 배포를 처음부터 컴파일하는 올바른 방법은 무엇입니까?

본인 또는 다른 사람이 보안 결함에 대한 소스 코드를 읽고 이해할 수 있다고 가정 할 수 있으므로 컴파일 전에 소스 코드가 먼저 검사됩니다. 내가 실제로 따르는 것은이 컴파일러를 처음부터 안전하게 생성하는 작업 안내서이며 커널, OS의 다른 부분 및 응용 프로그램을 컴파일하는 데 사용할 수 있습니다.

보안 스택은 운영 체제 또는 해당 스택에서 실행되는 응용 프로그램에 대한 확신이있는 경우 기본 수준에서 시작해야합니다. 예, 컴파일러가 빌드 될 때 마이크로 코드를 삽입 할 수있는 하드웨어 백도어가있을 수 있음을 알고 있습니다. 미국에서 설계되지 않은 칩을 사용하는 것 외에는 지금 당장 할 수있는 일이 많지 않습니다. 이 레이어를 시작으로 분류하여 백도어를 삽입하기 전에 오래된 컴퓨터에서 잠재적으로 빌드 할 수 있다고 가정하겠습니다.

브루스 슈나이어 (Bruce Schneier)는 “엔지니어들에게 이렇게 말합니다. 우리는 인터넷을 만들었고 우리 중 일부는 인터넷을 파괴하는 데 도움을주었습니다. 이제 자유를 사랑하는 사람들은 인터넷을 고쳐야합니다.”

추가 링크 :



답변

AFAIK는 보안을 완전히 확신 할 수있는 유일한 방법은 어셈블리 언어로 컴파일러를 작성하거나 디스크를 직접 수정하는 것 입니다. 그래야만 컴파일러가 백도어를 삽입하지 않을 수 있습니다. 실제로 컴파일러를 완전히 제거하기 때문에 작동합니다.

거기서부터 시작-스크래치 컴파일러를 사용하여 GNU 툴체인을 부트 스트랩 할 수 있습니다. 그런 다음 사용자 정의 툴체인을 사용하여 Linux From Scratch 시스템 을 컴파일 할 수 있습니다 .

쉽게 작업 할 수 있도록 C (또는 다른 언어)로 작성된 두 번째 중개 컴파일러를 사용할 수 있습니다. 따라서 컴파일러 A를 어셈블리로 작성한 다음 C / C ++ / Python / Brainfuck / 컴파일러 B를 가져 오려면 컴파일러 A를 사용하여 컴파일하십시오. 컴파일러 B를 사용하여 gcc와 친구를 컴파일하십시오.


답변

실제로 시간이 오래 걸리더라도 한 가지 가능한 방법은 뿌리로 돌아가는 것입니다. GNU의 개발은 1984 년에 시작되었고, 최초의 Minix 버전 (초기 리눅스 개발에서 부트 스트래핑 목적으로 사용 된)은 1987 년에 릴리스되었습니다.

이 전체 답변은 “[귀하] 또는 다른 사람이 보안 결함에 대한 소스 코드를 읽고 이해할 수 있으므로 소스 코드를 컴파일하기 전에 먼저 검사해야하며”이러한 분석의 결과를 신뢰할 수 있다는 전제를 기초로합니다. . 그것 없이는,이 답변은 아마도 무가치 한 것보다 더 나쁠 것입니다.

소스 코드가 포함 된 원본 Minix 책의 사본을 찾을 수있는 경우 책에서 입력 할 수 있습니다. 이를 컴파일 한 후 다른 시스템에서 다른 디 컴파일러를 사용하여 컴파일러가 예상 기계 언어 이진 출력을 생성하는지 확인하십시오. (코드는 너무 너무 시간이 많이 소요되지만하고, C 아마도 단지 12,000 선, 여전히 내 이유 는 이러한 프로젝트에 대해 심각한 경우.) 당신은 심지어 자신의 디스어셈블러를 작성할 수; 그렇게 어렵지 않아야합니다.

코드를 가지고 있고 외부 라이브러리에 대한 의존성이 적기 때문에 사용 가능한 GNU 유틸리티의 가장 오래된 버전을 잡고 코드를 살펴보고 Minix 용으로 빌드하십시오 (일부 작업이 필요할 수 있습니다. 절대로 피하고 싶은 것은 소스 코드를 조정하는 것입니다. 나중에 패치를 추가하면 오류가 발생하기 쉬우므로 GNU 도구에 대해 유사한 디스 어셈블 확인주기를 거치게됩니다. 이 시점에서 OS와 툴체인을 신뢰하므로 패치 세트의 소스 코드 만 수행하면되지만 (패치 세트에없는 것은 이미 신뢰할 수 있음) 도구는 여전히 사용하는 것에 비해 매우 원시적이고 조잡합니다. 오늘까지. 예를 들어 시스템 툴의 가장 기본적인 기능 이상의 기능을 기대하지 마십시오.많은 XKCD를 읽으십시오.

언젠가 리눅스가 해커들 사이에서 인기를 끌기 시작한 1990 년대 초반과 마찬가지로 초기 버전의 리눅스 커널을 컴파일하고 부트 스트랩 할 수있는 시스템을 갖게 될 것이다. 그 시점에서 Linux로 마이그레이션하는 것이 좋습니다 (리눅스에 대해 시스템 라이브러리 및 툴체인을 재구성하고, Linux 커널을 빌드하고, Linux로 부팅하고, Linux 내에서 Linux 커널 및 GNU 툴체인을 재구성 할 수 있습니다. 마지막으로 시스템이 자체 자체임을 증명합니다 호스팅), 그러나 그것은 당신에게 달려 있습니다. 패치를 확인하고 커널, 라이브러리 및 기본 GNU 도구를 패치하고 최신 버전이 될 때까지 다시 빌드하십시오.

최신 소프트웨어를 빌드하는 데 사용할 수있는 신뢰할 수있는 기본 OS 및 컴파일러가있을 때입니다. 그런 다음 Linux From Scratch 안내서를 따라 유용한 작업 을 수행 할 수있는 시스템을 구축 할 수 있습니다.

어떤 시점에서도 “컴파일러”시스템을 네트워크에 연결할 수 없습니다 (네트워크 호스트의 VM 포함). 커널을 포함한 네트워크 가능 구성 요소를 통해 침투 할 위험이 있습니다. Thompson 컴파일러 공격 이 걱정된다면 모든 VM 호스트도 손상 될 수 있습니다. sneakernet을 사용하여 컴파일하는 물리적 호스트에서 소스 코드와 바이너리를 가져옵니다. USB 대용량 저장소 지원이 구현 된 시점에 도달하기 전에 시스템에서 파일을 가져오고 꺼낼 때 문제가 발생할 수 있습니다. 당신은, 인쇄 소스 코드 목록은 정말 편집증 손으로 그들을 입력 (프린터 드라이버와 프린터에서 유사한 코드가없는 희망하는 경우 ) 또는 하나의 컴퓨터 모니터에서 코드를 읽고 실제로는 컴퓨터 옆에 있지만 연결되지 않은 다른 컴퓨터에 입력하십시오.

예, 시간 이 많이 걸립니다. 그러나이 접근법의 장점은 각 단계가 점진적으로 증가한다는 것입니다. 즉, 여러 버전의 기간에 걸쳐 서서히 도입되지 않으면 악의적 인 부분이 빠져 나가기가 훨씬 어려워집니다. 각 단계의 변경 집합이 비교적 작기 때문에 훨씬 쉽게 볼 수 있기 때문입니다. 패치 세트를 변경 로그와 비교하고 소스 코드의 모든 변경에 해당하는 변경 로그 항목을 정확하게 결정할 수 있는지 확인하십시오. 다시 말하지만, 이러한 변경 사항이 코드베이스에 몰래 들어 가지 않았는지 확인할 수있는 능력이 있다고 가정합니다 (그러나 신뢰할 수있는 사람을 통해). 그러나 소프트웨어 전용으로 신뢰할 수있는 시스템에 가깝습니다. 펌웨어 접근이 가능합니다.


답변

신뢰할 수있는 컴파일러가 필요한 경우 compcert 프로젝트 와 같은 학술 작업을 살펴볼 수 있습니다. INRIA (프랑스 IT 공공 연구소)가“인증 ”하도록 설계된 컴파일러입니다. 즉, 코드와 의미 적으로 완벽하게 동등한 실행 파일을 생성합니다 (물론 수학적으로 입증되었습니다).


답변

자신의 컴파일러를 시작점으로 수동으로 생성하는 것이 가장 안전하지만, 또 다른 옵션은 이러한 익스플로잇이 존재하기 전에 신뢰할 수있는 5 년 또는 10 년 된 설치 CD에서 시스템을 설치하는 것입니다. 그런 다음이를 새로운 감사 소스를 컴파일하기위한 기초로 사용하십시오.