원문 보기: https://dawoum.duckdns.org/wiki/Debian/HardeningWalkthrough
데비안 패키지 제작은 데비안 패키지 관리자가 아닐지라도 몇 가지 지식이 필요할 수 있습니다.
직접 패키지를 제작하지 않다라도, 기존의 패키지에서 성능 향상을 위해 컴파일 옵션을 변경하여 재 패키징을 시도할 수 있습니다.
보통, 성능 향상을 위해 특정 컴파일 옵션을 시스템 전역에 걸쳐 추가하는 것이 쉽지만, 해당 옵션과 부딪히는 패키지는 이로 인해 컴파일 오류로 이어질 수 있습니다.
결국 일반 사용자의 입장에서는 해당 패키지를 컴파일해 보기 전에는 해당 옵션이 컴파일하려는 프로그램에서 안전한지 여부를 확인하기 힘들기 때문에, 다른 경로, 예를 들어, 아치 리눅스의 패키징 정보로부터 이에 대한 정보를 얻을 수도 있습니다.
어쨌든, 그런 정보를 시스템 전역으로 설정할 경우에 상당히 많은 패키지에서 컴파일 오류가 발생할 수 있기 때문에, 이를 데비안 rules 파일에서 조작하는 것이 바람직해 보입니다.
이 문서를 패키지 강화에 대한 얘기를 다루지만, 그런 사용처에 대한 지식을 얻을 수도 있습니다.
What is all this about?
dpkg-buildflags는 C 및 C++로 작성된 코드에 대한 기본 빌드 플래그의 균등한 설정을 허용합니다. 만약 패키지가 Java, pure Python, pure Perl 또는 shell로 작성되었으면, 아무것도 할 필요가 없습니다. 좋아요, 그렇지 않나요?
기본 빌드 플래그에는 여러 가지 이점이 있습니다:
- 이들 빌드 플래그는 (편집 중 잠재적 보안 문제를 감지하고 회귀를 발견하는 데 도움이 되는) 컴파일 시간에 더 엄격한 점검을 시행하고 아직 감지되지 않은 보안 문제를 활성화/무효화합니다. 다음 섹션을 참조하십시오.
- dpkg-buildflags는 새로운/수정된 플래그로 Debian을 다시 빌드할 수 있습니다. 예를 들어 누군가는`-O2` 대신 `-Os`를 갖는 임베디드 시스템에 대한 Debian을 다시 빌드하기를 원하며, 필요한 것은 수천 개의 소스 패키지 대신 dpkg-buildflags를 패치하는 것입니다.
- dpkg-buildflags는 DEB_BUILD_OPTIONS=noopt (policy 4.9.1)를 지원합니다. 현재는 몇 가지 패키지만 지원하고, 반면에 dpkg-buildflags는 noopt가 설정되면 직접 -O0를 방출합니다.
패키지에서 dpkg-buildflags를 활성화하는 것은 두 가지입니다. 한편으로는 debian/rules 파일에서 플래그를 활성화해야 하고, 다른 한편 코드의 빌드-시스템이 필요한 플래그를 준수하는 것을 보장해야 합니다.
Selecting security hardening options
데비안 7 ("wheezy")에 대해 표준 빌드 플래그는 다음을 포함합니다:
- Format string checks
- D_FORTIFY_SOURCE
- Stack protector
- Read-only relocations
이러한 강화 기능은 여기에서 더 깊이 설명됩니다.
추가적으로 기본적으로 활성화되어 있지는 않은 두 가지 기능이 있습니다:
- Position independent executables (not enabled by default due to potential build failures)
- -z now (not enabled by default due to potential application startup slowdown)
이들 두 가지 옵션이 패키지와 함께 작동하는지 여부를 테스트하고 모든 것이 제대로 작동하면 활성화하는 것이 좋습니다. 패키지의 rules 파일에 다음을 추가함으로써 그것들을 활성화할 수 있습니다:
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
Enabling dpkg-buildflags in your debian/rules files
rules files based on debhelper and minimised dh(1)
debhelper 9
만약 debhelper dh(1) v9 이상을 사용하면 (debian/compat에서 값 9 이상), 강화된 빌드 플래그를 살펴 보십시오:
- `buildflags.mk`에 포함시키고 `dpkg-buildflags`에 대한 호출은 `debian/rules`에서 불필요합니다.
- export CFLAGS 및 LDFLAGS 등이 필요 없는데 왜냐하면 `dh_auto_*` 프로그램으로 호출하는 동안 자동으로 전달되기 때문입니다.
기본값에 더 많은 플래그를 추가하기를 원하는 경우에서, `debian/rules`의 꼭대기에 다음과 같은 것을 사용하십시오:
# To enable all, uncomment following line
# export DEB_BUILD_MAINT_OPTIONS = hardening=+all
export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
GNU/* 시스템에서와 같이 이 플래그는 이제 기본적으로 gcc에 의해 링커에 전달되기 때문에, 데비안 11 (Bullseye) 이후 "Wl,--as-needed" 줄은 더 이상 필요하지 않습니다.
*_SET을 사용하지 마십시오 또는 그것이 기본 강화 플래그를 덮어 씁니다.
이것은 buildflags.mk와도 잘 작동합니다.
Older debhelper
이전의 compat드 레벨을 유지하기를 원하면, 그것들을 dh_auto_configure로 전달함으로써 여전히 빌드 플래그를 주입할 수 있습니다. 예를 들어,
override_dh_auto_configure:
dh_auto_configure -- $(shell dpkg-buildflags --export=configure)
rules files based on standard debhelper or hand-written rules files
빌드 파일이 표준 debhelper 형식을 사용하면, 플래그를 주입하는 방법은 빌드 시스템에 따라 다릅니다. 만약 그것이 autotools를 기반으로 하면, 내보낸 형태의 dpkg-buildflags를 구성 스크립트로 전달하는 것이 보통 필요합니다. 예를 들어,
../configure --prefix=/usr $(shell dpkg-buildflags --export=configure)
빌드 시스템이 CFLAGS, CXXFLAGS, CPPFLAGS, 또는 LDFLAGS와 같은 표준 환경 변수의 값을 읽어 들이면, 종종 rules 파일의 시작 부분에서 이들 값을 export할 종종 있습니다. 이를 달성하는 가장 간단한 방법은 모든 필요한 플래그를 export하기 위해 rules 파일 시작 부분에 dpkg로부터 다음 스니펫을 포함하는 것입니다:
DPKG_EXPORT_BUILDFLAGS = 1
include /usr/share/dpkg/buildflags.mk
rules files based on cdbs
cdbs는 이미 모든 dpkg-buildflags를 내보내고 있습니다. 패키지가 cdbs를 사용하면, 보통 업스트림 빌드 시스템이 이들 플래그를 올바르게 따르는지 여부를 확인할 필요만 있습니다. 누락된 CPPFLAGS 및 LDFLAGS에 대한 cdbs 버그 bug 651964는 수정되었습니다.)
cdbs는 DEB_*_MAINT_APPEND 및 DEB_BUILD_MAINT_OPTIONS를 직접 지원합니다 (CDBS 0.4.127 이후) - CDBS 스니펫을 포함하기 전에 선언하십시오.
Handling dpkg-buildflags in your upstream build system
업스트림 빌드 시스템에서 모든 강화된 빌드 플래그를 완전히 지원하기 위해, 다음 플래그가 지원되는지 확인하십시오:
- C로 작성된 코드에 대해 CFLAGS, CPPFLAGS, 및 LDFLAGS
- C++로 작성된 코드에 대해 CXXFLAGS, CPPFLAGS, 및 LDFLAGS
buildsystems based on the autotools
빌드-시스템이 autotools를 기반으로 하면, 보통 더 이상 수정할 필요가 없습니다. 어쨌든, 발생할 수 있다면, 일부 변수는 Makefile.in 파일 중 하나에서 하드-코딩된 것에서 발생할 것입니다. 이에 대한 예제는 bug 655870에서 찾을 수 있습니다.
Handwritten Makefiles
패키지가 개인이 만든 시스템을 사용하면, 위에서 언급된 플래그를 준수하는지 확인해야 합니다. 그렇지 않으면, 데비안-지정 수정의 일부로 dpkg-buildflags 호출을 직접 추가할 수 있습니다. 또 다른 해결책은 이미 존재하는 환경 변수를 공급하기 위해 Makefiles를 수정하는 것입니다.
많은 개인이 만든 Makefiles는 이미 CFLAG 및 LDFLAG를 지원하지만, CPPFlags는 지원하지 않습니다. 대부분의 경우에서, CPPFLAGS를 CFLAGS에 덧붙일 수 있습니다, 예를 들어,
CFLAGS = `dpkg-buildflags --get CFLAGS`
CFLAGS += `dpkg-buildflags --get CPPFLAGS`
buildsystems for Perl modules
Debhelper는 강화된 빌드 플래그가 ExtUtils::MakeMaker 및 ExtUtils::CBuilder,로 전달되도록 수정해 왔으며, 대부분의 Perl 모듈은 debhelper 수준 9에 부딪친 강화된 빌드 플래그를 받아야 하도록 수정되어 왔습니다. 이것이 debhelper (>= 9.20120312)와 빌드를 요구함을 주목하십시오. dh_auto* 최소 rules 파일이 이것의 사용하도록 사용되어야 함에 주목하십시오.
bug 662666에서 더 많은 토론을 참조하십시오
buildsystems using cmake
cmake는 CPPFLAG를 따르지 않습니다. 수정은 sid에서 잠시 사용할 수 있었지만, 업스트림이 패치를 거부한 이후로 취소되어 왔습니다. 자세한 내용에 대해 bug 653916을 참조하십시오. CPPFLAGS를 CFLAGS와 CXXFLAG에 덧붙이는 해결 방법은 대부분의 경우에서 작동해야 합니다. Debhelper (0.9.20120417 이후, compat=9 및 dh_auto* 명령과 함께!) 및 cdbs (0.4.110 이후)가 이것을 자동으로 처리하므로 그것들이 사용 가능하다면 그 해결 방법이 더 이상 필요하지 않습니다.
Testing your packages after conversion
이전에는 "hardening-includes" 패키지로부터 "hardening-check"은 강화 옵션이 제대로 활성화되었는지 여부를 확인하기 위해 바이너리를 테스트를 허용했지만, "hardening-includes"가 이제는 불안정 버전에서 제거되었으므로 이것 역시 더 이상 이용할 수 없으며, 대체를 위해, lintian은 hardening-check로부터 코드를 기반으로 한 hardening-no-* tags를 구현합니다. 강화하지 않은 태그를 구현합니다.
그것을 여전히 사용할 수 있는 경우에서, hardening-check에 대한 오래된 정보는 다음과 같습니다:
만약 dpkg-buildflags에서 방출된 기본 플래그만 사용하면, "Stack protected", "Fortify Source functions", 및 "Read-only relocations"를 "Yes"로 표시한 것을 보아야 합니다: 예를 들어,
jmm@pisco:~$ hardening-check /usr/bin/emacs23
/usr/bin/emacs23:
Position Independent Executable: no, normal executable!
Stack protected: yes
Fortify Source functions: yes (some protected functions found)
Read-only relocations: yes
Immediate binding: no not found!
일부 경우에서, "Stack protected"와 "Fortify Source functions"이 잘못된 양성을 방출하고, hardening-check의 맨 페이지에서 이들 메모를 참조하십시오.
- Stack Protected: 임의의 문자 배열이 스택에 할당되지 않고 실행 파일을 빌드했을 때, 이 점검은 잘못된 경보로 이어질 것입니다 (올바른 옵션으로 컴파일되었음에도 불구하고 stack_chk_fail을 사용하지 않기 때문입니다).
- Fortify Source functions: glibc 함수의 강화된 버전이 유용하지 않음을 만족하는 실행 파일이 빌드되었을 때 (예를 들어, 컴파일 시간에 안전한 것으로 확인되거나, 실행 시간에 사용을 확인할 수 없음), 이 점검은 잘못된 경보로 이어질 것입니다. 이를 완화하기 위한 노력으로, 임의의 강화된 함수가 발견되면 점검이 통과할 것이고, 강화되지 않은 함수만 발견되면 실패할 것입니다. 확인할 수 없는 조건도 통과합니다 (예를 들어, 강화될 수 있는 함수가 발견되거나, glibc와 링크되지 않음).
패키지가 모든 플래그를 활성화했으면, 출력은 다음과 같게 보여야 합니다:
jmm@pisco:~$ hardening-check /usr/sbin/sshd
/usr/sbin/sshd:
Position Independent Executable: yes
Stack protected: yes
Fortify Source functions: yes (some protected functions found)
Read-only relocations: yes
Immediate binding: yes
hardening-check은 결과 바이너리만 확인할 수 있고 따라서 그것들이 몇 곳에서만 누락되면 누락된 강화 플래그를 잡지 못할 수 있습니다. [[1]]는 Perl에 작성된 작은 파서이며, 이는 누락된 강화 플래그에 대한 빌드 로그를 확인합니다. 그것은 dpkg-buildpackage 또는 buildd에 의해 생성된 빌드 로그에 사용될 수 있습니다.
예제 사용법:
$ blhc /path/to/log/file
Common questions / problems
My package already uses hardening-wrapper or hardening-includes. Should I switch to dpkg-buildflags?
예. 이들 패키지는 이제 불안정에서 제거되어 왔습니다. 대신 dpkg-buildflags를 사용해야 하는데, 왜냐하면 그것이 문제에 대한 보다 일반화된 해결책이고 보안 강화를 넘어서도 유용하기 때문입니다.
My package builds with optimisation flags other than -O2, e.g. -Os
dpkg-buildflags를 호출하기 전에 rules에 다음을 추가할 수 있습니다:
DEB_CFLAGS_MAINT_APPEND=-Os
How can I use additional flags?
추가 플래그, 예를 들어, LDFLAGS에 대해 `-Wl,--as--needed`를 설정하기 위해, 새로운 DEB_*_MAINT_APPEND 변수를 사용하십시오 (자세한 정보에 man dpkg-buildflags). DEB_*_MAINT_SET를 사용하지 마십시오. 왜냐하면 그것은 기본 강화 플래그를 덮어쓰기 때문입니다. DEB_*_APPEND ( _MAINT 없음)는 debian/rules을 위한 것이 아니며, 항상 *_MAINT_*를 사용하십시오.
debhelper 9/buildflags.mk
export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
`export LDFLAGS += -Wl,--as-needed`과 같은 것을 사용하지 마십시오. `export`는 기본 LDFLAGS 강화 플래그를 덮어쓸 것이기 때문입니다.
dpkg-buildflags
make의 $(shell)은 지역 변수를 사용하지 않고, 따라서 사용자 정의 명령을 정의해야 합니다:
dpkg_buildflags = DEB_LDFLAGS_MAINT_APPEND="-Wl,--as-needed" dpkg-buildflags
...
./configure $(shell $(dpkg_buildflags) --export=configure)
Are there example patches?
[강화 플래그 Wheezy 릴리스 목표에 대해 제출된 다수의 파일에 ] 첨부된 패치가 있습니다.
더 강화된 세부 사항은 Hardening에서 설명됩니다.
How can I use this and keep my packages backportable to Squeeze?
squeeze-backports에는 1.16.1.1의 백포트가 포함되어 있으므로. 모두 것이 괜찮아야 합니다.
추가적으로, dpkg-buildflags는 이미 일반 Squeeze에 존재했습니다 (플래그 w/o hardening만 방출합니다):
$ dpkg-buildflags --get CFLAGS
-g -O2
$ dpkg-buildflags --get CPPFLAGS
$ dpkg-buildflags --get LDFLAGS
$ dpkg-buildflags --get CXXFLAGS
-g -O2
대부분의 편의 함수 (/usr/share/dpkg/buildflags.mk 및 dpkg-buildflags --export=configure)은 아직 존재하지 않습니다. 이를테면, 다음과 같이 플래그를 export해야 합니다:
CFLAGS:=$(shell dpkg-buildflags --get CFLAGS)
CPPFLAGS:=$(shell dpkg-buildflags --get CPPFLAGS)
LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS)
Is there a lintian test?
이 버그에 따라 lintian 테스트가 버전 2.5.7에서 사용할 수 있게 되었습니다. Lintian 태그 hardening-no-bindnow가 보고됩니다.
My package isn't security-sensitive, should I still convert it?
예. dpkg-buildflags는 데비안을 수정된 빌드 플래그로 다시 빌딩을 쉽게 하고 패키지에서 오랜 버그를 발견하는 데 유용합니다. 예제에 대해 [Planet Debian의 블로그 게시]를 참조하십시오.
My package is (partly) written in OCaml
OCAML 런타임 자체가 먼저 강화되어야 합니다. 당분간 다른 곳에서는, 아무것도 하지 않습니다 (특히 Lintian 태그를 덮어쓰지 마십시오).
See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=702349#19