C 컴파일러를 처음부터 컴파일 한 다음 Unix / Linux를 처음부터 컴파일하는 방법


64

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

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

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

질문

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

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

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

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

추가 링크 :


7
젠장, 이것은 매우 흥미로운 질문이며 마이그레이션하고 싶지 않지만 실제로 여기에 관한 주제는 아닙니다. 그것은 더 나은 적합 stackoverflow.com 기본적인 질문은 거의 OS 불가지론과 매우 프로그래밍 질문은 처음부터 컴파일러를 컴파일하는 방법에 대해 때문이다. 잠시 후 여기에 답변이 없으면 질문 태그 아래에있는 "플래그"링크를 사용하고 중재자에게 SO로 이동하도록 요청하십시오.
terdon

2
@terdon 특정 개발 문제보다 일반적인 프로그래밍 문제에 대한 것이기 때문에 실제로 Programmers.SE에 더 적합 할 수 있습니다. 실제로 중복 될 수 있습니다 .
CVn

2
GCC는 오픈 소스입니다. 백도어는 어떻게 삽입됩니까?
Michael Pankov

2
안정적인 Thompson 익스플로잇에는 로그인 프로그램 또는 컴파일러가 컴파일 될 때 인식 할 수있는 코드가 필요합니다. 소스를 해당 프로그램 중 하나로 컴파일러가 인식 할 수없는 형태로 수동으로 변환 할 수 있으면 백도어가 전파되지 않습니다.
Russell Borogove

2
@Constantius-첫 줄에 링크 된 Thompson 기사를 읽으십시오. 누가 컴파일러를 컴파일합니까?
Russell Borogove

답변:


30

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

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

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


13
그럼에도 불구하고 이것은 여전히 ​​악의적 인 컴파일러에 대해서만 보호합니다. 여전히 컴파일러가 실행하는 시스템을 신뢰해야합니다. 소프트웨어가 별도로 존재 하지 않습니다 .
CVn

3
자율적 인 것은 본질적으로 위험합니다. 툴체인 컴파일러 (이상한 것은 아니지만)를 효과적으로 제안하고 있는데, 이는 피하려고하는 방식으로 수정 될 수 있음을 의미합니다. 또한 MitM을 통해 전송 중에 수정 될 수 있습니다.
strugee

1
여러분은이 대답이 15 살에서 온 것임을 깨달아야합니다. 계속 투쟁하라!
mtahmed

3
미리 컴파일 된 <code> vim </ code> 또는 <code> vim </ code>을 감염된 파일 만 사용하여 감사 한 소스에서 컴파일 한 소스를 컴파일했는지 아는 사람은 처음부터 코드 편집기를 작성해야합니다. <code> vim </ code>은 신뢰할 수 있습니까?
Hagen von Eitzen

1
그 첫 번째 머신 코드 (어셈블리가 아닌 실제 머신 코드가 아님) 를 직접 작성 하지 않은 한 , 당신은 안전한 보안 허점을 인식하는 전문가가 아니며 컴파일하는 모든 코드를 읽고 확인해야합니다. 그 한 사람이 개인적으로 , 그리고 그를 신뢰는이 작업을 수행하는 .... 이 중 어느 것도 전혀 도움이되지 않습니다. 이것이 바로 킥 스타터를 시도하는 것이 요점을 망치고있는 이유입니다. 어느 것이 : 높은 신뢰도.
Evi1M4chine

22

실제로 시간이 오래 걸리더라도 한 가지 가능한 방법은 뿌리로 돌아가는 것입니다. 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 대용량 저장소 지원이 구현 된 시점에 도달하기 전에 시스템에서 파일을 가져오고 꺼낼 때 문제가 발생할 수 있습니다. 당신은, 인쇄 소스 코드 목록은 정말 편집증 손으로 그들을 입력 (프린터 드라이버와 프린터에서 유사한 코드가없는 희망하는 경우 ) 또는 하나의 컴퓨터 모니터에서 코드를 읽고 실제로는 컴퓨터 옆에 있지만 연결되지 않은 다른 컴퓨터에 입력하십시오.

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


디스 어셈블-검증 방법은 검증 기계가 완전히 신뢰할 수 있다고 여전히 큰 가정을하므로 매우 결함이 있습니다. 해당 머신과 소프트웨어를 처음부터 구축하거나 개인적으로 자신을 믿고 신뢰하는 사람을 알고 있지 않으면 이런 일이 발생하지 않습니다. 따라서 이것은 여전히 ​​안전하지 않습니다. 죄송합니다. …… 또한 이러한 문제에서“…에 가까운”은 여전히“안전하지 않은”을 의미합니다. 왜냐하면 전체 요점을 망칠 수있는 단 하나의 신뢰할 수없는 지점 만 필요하기 때문입니다.
Evi1M4chine 2016 년

9

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


1
누구나 신뢰할 수있는 컴파일러가 필요합니다. 수학이 어떻게 "신뢰할 수있는"컴파일러를 만들 수 있습니까?
David J

@DavidJ 부트 스트랩. 완벽하게 검증하고 입증 할 수있는 작은 조각을 만든 다음 더 복잡한 컴파일러를 작성하기위한 기초로 사용하십시오.
CVn

1
"" "CompCert C를 다른 프로덕션 컴파일러와 차별화하는 점은 기계 지원 수학 증명을 사용하여 컴파일 문제가 발생하지 않도록 공식적으로 검증된다는 것입니다." "" compcert.inria.fr/compcert-C.html Compilation 예전만큼 경험적이지 않습니다.
lgeorget

1
@ 아마 컴파일러에 의해 읽을 때 커널이 컴파일러 소스에 백도어를 포함하는 손상 될 수 있습니다 고려하지 않는 MichaelKjörling은
래칫 괴물

1
나는 또한 작동 할 수있는 이 링크 를 발견 했다.
David J

2

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


5
이 공격은 1984 년 이후 공개적으로 알려졌습니다. 아마도 톰슨은 그 가능성에 대해 처음으로 생각한 것은 아닙니다. 멀리 돌아가는 것은 오늘날 당연한 것으로 여겨지는 대부분의 것들이 주변에 없었 음을 의미합니다. 20 년 전의 컴퓨터 성능을 고려하여 현재 상태와 비교하십시오. 원래의 리눅스 부트 스트랩 시스템 인 Minix 조차도 87까지 출시되지 않았고 GNU 개발은 84 년에 시작되었습니다. 이론적으로 이것은 질문에 대답 할 수 있지만 실제로는 대답으로 거의 쓸모가 없습니다.
CVn

2
내가 손에 넣을 수있는 가장 빠른 컴퓨터는 286입니다. 조부모가 여전히 컴퓨터를 가지고 있는지 확인해야합니다.
David J

1
실제로 그것을 고려하는 보너스 포인트 :-). @DavidJ
11684

@ MichaelKjörling : 실제로는 아닙니다. 부트 스트랩 체인이 길어지기 때문입니다. 그러나 기계 언어로 자신의 컴파일러를 처음부터 작성하는 한 아닐 수도 있습니다.
Evi1M4chine
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.