CERT C 프로그래밍 2/e [버그 없는 안전한 소프트웨어]
- 원서명The CERT C Coding Standard, Second Edition: 98 Rules for Developing Safe, Reliable, and Secure Systems (ISBN 9780321984043)
- 지은이로버트 C. 시코드(Robert C. Seacord)
- 옮긴이노영찬
- ISBN : 9791161756769
- 43,000원
- 2022년 08월 31일 펴냄
- 페이퍼백 | 612쪽 | 188*235mm
- 시리즈 : 프로그래밍 언어, 해킹과 보안
책 소개
요약
코딩 과정에서 오류 및 취약성을 유발하는 불안전한 프로그램 코드를 제거해 안전성, 신뢰성, 보안성을 갖춘 C 프로그램을 개발할 수 있는 효과적인 방법을 제공한다. 관련 규칙은 제목과 설명, 부적절한 코드 예제, 규칙에 부합하는 해결 방법을 코드 예제로 설명한다. 맞춤형 소프트웨어 개발을 위한 이해관계자들의 요구사항을 정의하기 위해 사용할 수 있으며, 안전성과 신뢰성이 요구되는 시스템 개발에서 지켜야 할 사항을 위험 평가 항목과 우선순위에 따라 정리하고 있다.
추천의 글
“시스코에서는 보안 코딩 표준으로 CERT C 코딩 표준을 채택했다. 보안 프로그램의 라이프사이클에 핵심적인 컴포넌트이며, 이 책에서 설명하는 코딩 표준은 복잡한 소프트웨어의 보안 관련 문제들을 실제 사례와 함께 적용하기 쉽도록 세부적으로 나눠 설명하고 있다. C와 C++ 프로그래밍 언어로 보안성과 각종 위험에 회복력이 강한 소프트웨어를 작성하고 싶은 개발자에게 필수적인 참고서다.”
— 에드워드 D. 파라다이스(Edward D. Paradise)/ 시스코 시스템즈의 엔지니어링, 위험관리, 정보 및 개발 관련 부사장
초판에 쏟아진 찬사
“나는 CERT 안전한 코딩 이니셔티브(CERT Secure Coding Initiative)의 열렬한 지지자다. 프로그래머는 정확성, 명확성, 유지보수성, 성능, 심지어 안정성에 관해서도 여러 방법으로 조언을 구할 수 있다. 하지만 특정 언어의 특징이 보안에 미치는 영향은 다루고 있지 않다. 이 책이야말로 바로 이러한 요구를 충족시켜주는 책이다.”
— 랜디 마이어스/ ANSIC 회장
“수년간 우리는 CERT/CC를 통해 수없이 많은 보안 문제에 대한 조언을 문서로 등록할 수 있었다. 이제 CERT는 최고 기술 전문가들의 제언을 책에 수록해 새로운 애플리케이션에서 발생할 수 있는 문제를 예방하고 기존 시스템을 안전하게 유지하도록 프로그래머와 매니저에게 실용적 길잡이 역할을 해준다.”
— Dr. 토머스 플럼/ 플럼홀사 창시자
“연결성(connectivity)으로 인해 해커로부터 안전한 애플리케이션이 필요하게 됐다. 이 책의 CERT 표준과 안정성 가이드라인을 통해 완전한 보호와 무결함 등의 소프트웨어 목표를 달성할 수 있을 것이다.”
— 크리스 탭/ LDRA Ltd. 필드 애플리케이션 엔지니어
“이 책은 오늘날의 소프트웨어 시스템이 실제 상황에서 어떻게 실패하게 되는지를 정확히 보여주며, 우리에게 꼭 필요한 전문 정보를 모아놓았다. 내부적으로 안전한 코딩 가이드라인을 구축하기 위한 시작 단계로 먼저 이 책을 읽어보자. 소프트웨어 보안 영역에서는 무지했던 부분이 종종 우리를 괴롭히게 될 것이다. 다른 어떤 곳에서도 얻을 수 없었던 이 정보를 펼쳐보길 바란다.”
— 존 맥도널드/ 『소프트웨어 보안 평가(The Art of Software Security Assessment)』의 공저자
이 책에서 다루는 내용
◆ 전처리기
◆ 선언과 초기화
◆ 표현식
◆ 정수
◆ 부동소수점
◆ 배열
◆ 문자와 문자열
◆ 메모리 관리
◆ 입력/출력
◆ 환경변수
◆ 시그널
◆ 에러 처리
◆ 동시성 제어
◆ 기타 이슈
이 책의 대상 독자
C 언어 개발자를 우선 대상으로 하며 맞춤형 소프트웨어(bespoke software)를 위한 이해관계자의 요구 사항을 정의하는 데 사용한다. 신뢰성과 견고성이 있고 보안 공격에 잘 견디는 고성능 시스템 개발에 관심 있는 개발자라면 더욱 흥미롭게 읽을 것이다.
C++ 개발자를 대상으로 하지는 않지만 C 언어 프로그램에서 발생하는 대다수의 문제가 C++ 프로그램에서도 공통적으로 나타나기 때문에 C++ 개발자도 참고하기 좋다.
이 책의 구성
총 14장으로 구성됐으며 특정 주제에 대한 표준과 규칙, 세 파트로 구성된 부록과 참고 문헌, 색인을 포함한다. 부록의 첫 부분은 이 책에서 사용된 용어 사전이다. 두 번째 부분은 Annex J, J.2 [ISO/IEC 9899:2011] 표준 C에 정의되지 않은 가이드라인을 쉽게 참조하도록 번호를 붙여 주제별로 분류했다. 세 번째 부분은 Annex J, J.1 [ISO/IEC 9899:2011] 표준 C에 정의되지 않은 가이드라인을 포함했으며 필요 시 표준 규칙으로 쉽게 참조할 수 있다.
이 책은 C11을 사용해 개발됐으나 C99를 포함, C 언어의 하위 버전과 호환해서 사용할 수 있다. 표준 규칙을 적용하는 데 영향을 미칠 수 있는 표준 C 버전 간의 차이를 주의해야 한다.
목차
목차
- 1장. 전처리기
- PRE30-C. 유니버설 문자 이름을 여러 문자열에 붙여서 만들지 마라
- PRE31-C. 불안전한 매크로에 매개 변수로 인한 부수 효과를 피하라
- PRE32-C. 함수형 매크로 호출에 전처리 지시자를 사용하지 마라
- 2장. 선언과 초기화
- DCL30-C. 객체를 선언할 때 적절한 지속 공간을 지정하라
- DCL31-C. 식별자를 사용하기 전에 먼저 선언하라
- DCL36-C. 연결(링크) 분류에서 충돌하는 식별자를 선언하지 마라
- DCL37-C. 예약어를 식별자로 선언하거나 정의하지 마라
- DCL38-C. 유연한 배열의 멤버를 선언할 때 정확한 문법을 사용하라
- DCL39-C. 구조체 패딩에서 정보의 누출을 피하라
- DCL40-C. 동일한 함수나 객체에 호환되지 않는 선언을 생성하지 마라
- DCL41-C. switch구문에 첫 번째 case 절 앞에 변수를 선언하지 마라
- 3장. 표현식
- EXP30-C. 부수 효과로 인한 평가 순서에 의존하지 마라
- EXP32-C. volatile이 아닌 참조자로 volatile 객체에 접근하지 마라
- EXP33-C. 초기화되지 않은 메모리를 읽지 마라
- EXP34-C. 널 포인터를 역참조하지 마라
- EXP35-C. 임시 존속 기간을 가진 객체를 수정하지 마라
- EXP36-C. 포인터를 더 엄격하게 할당된 포인터 타입으로 변환하지 마라
- EXP37-C. 인자의 정확한 개수와 타입으로 함수를 호출하라
- EXP39-C. 호환되지 않는 타입의 포인터 변수에 접근하지 마라
- EXP40-C. 상수 객체를 수정하지 마라
- EXP42-C. 패딩 데이터를 비교하지 마라
- EXP43-C. restrict로 지정된 포인터를 사용할 때 정의되지 않은 동작을 피하라
- EXP44-C. sizeof, Alignof, Generic에서 피연산자의 부수 효과에 의존하지 마라
- EXP45-C. 선택문에서 할당을 하지 마라
- 4장. 정수
- INT30-C. unsigned 정수 연산이 래핑되지 않도록 주의하라
- INT31-C. 정수 변환으로 데이터가 손실되거나 잘못 처리되지 않도록 주의하라
- INT32-C. signed 정수의 연산이 오버플로되지 않도록 보장하라
- INT33-C. 나눗셈이나 나머지 연산에서0으로 나누는 에러가 발생하지 않게 하라
- INT34-C. 음수나 피연산자의 비트보다 더 많은 비트를 시프트하지 마라
- INT35-C. 정확한 정수 정밀도를 사용하라
- INT36-C. 포인터를 정수로 또는 정수를 포인터로 변환할 때 주의하라
- 5장. 부동소수점
- FLP30-C. 부동소수점 변수를 반복문의 카운터로 사용하지 마라
- FLP32-C. 수학 함수에서 도메인 에러나 영역 에러를 찾고 예방하라
- FLP34-C. 부동소수점 변환이 새로운 타입의 범위 안에 들어가는지 확인하라
- FLP36-C. 정숫값을 부동소수점으로 변환할 때 정밀도를 보존하라
- 6장. 배열
- ARR30-C. 경계를 초과한 포인터나 배열 첨자를 만들거나 사용하지 마라
- ARR32-C. 가변 배열에서 크기를 나타내는 인자가 유효한 범위에 있음을 보장하라
- ARR36-C. 같은 배열을 참조하지 않으면 2개의 포인터를 빼거나 비교하지 마라
- ARR37-C. 배열이 아닌 객체에 대한 포인터에 정수를 더하거나 빼지 마라
- ARR38-C. 라이브러리 함수가 유효하지 않은 포인터를 만들지 않도록 보장하라
- ARR39-C. 포인터에 스케일링된 정수를 더하거나 빼지 마라
- 7장. 문자와 문자열
- STR30-C. 문자열 리터럴을 수정하려고 하지 마라
- STR31-C. 문자열을 위한 공간이 문자 데이터와 널 종료 문자를 담기에 충분함을 보장하라
- STR32-C. 문자열을 처리하는 라이브러리 함수에 널 종료 문자가 없는 문자열을 전달하지 마라
- STR34-C. 문자열을 더 큰 타입인 정수로 변환하기 전에 unsigned 타입으로 캐스팅하라
- STR37-C. 문자를 처리하는 함수로 전달되는 인자는 반드시 unsigned char로 표현 가능해야 한다
- STR38-C. 와이드와 내로 타입의 문자열과 함수를 혼동하지 마라
- 8장. 메모리 관리(MEM)
- MEM30-C. 해제된 메모리에 접근하지 마라
- MEM31-C. 동적으로 할당된 메모리는 더 이상 필요 없을 때 해제하라
- MEM33-C. 유연한 배열 원소를 포함하는 동적인 구조체를 할당하고 복사하라
- MEM34-C. 동적으로 할당된 메모리만 해제하라
- MEM35-C. 객체에 충분한 메모리를 할당하라
- MEM36-C. realloc() 호출로 객체의 정렬을 수정하지 마라
- 9장. 입력과 출력(FIO)
- FIO30-C. 포맷 문자열에서 사용자 입력을 배제하라
- FIO31-C. 이미 열려 있는 파일을 다시 열지 마라
- FIO32-C. 파일에만 적용 가능한 연산을 장치에 대해 수행하지 마라
- FIO34-C. 파일에서 읽어야 할 문자와 EOF또는 WEOF를 구별하라
- FIO37-C. fgets() 또는 fgetws()가 성공 시 비어 있지 않은 문자열을 반환한다고 가정하지 마라
- FIO38-C. 입출력 FILE객체를 복사하지 마라
- FIO39-C. 플러시나 위치 조정 함수 호출 없이 스트림으로부터 입출력을 교대로 수행하지 마라
- FIO40-C. fgets() 또는 fgetws() 실패 시 문자열을 리셋하라
- FIO41-C. 부수 효과가 있는 스트림 인자로 getc()나 putc(), getws(), putwc()를 호출하지 마라
- FIO42-C. 더 이상 필요 없어진 파일이 적절히 닫혔는지 확인하라
- FIO44-C. fsetpos()에는 fgetpos()에서 반환된 값만 사용하라
- FIO45-C. 파일에 접근하는 동안 TOCTOU 경쟁 상태를 피하라
- FIO46-C. 닫혀 있는 파일에 접근하지 마라
- FIO47-C. 유효한 포맷 문자열을 사용하라
- 10장. 환경(ENV)
- ENV30-C. 함수에서 반환하는 값을 참조하는 객체를 수정하지 마라
- ENV31-C. 환경 변수의 값을 무효화할 수 있는 연산을 수행했다면 더 이상 그 값에 의존하지 마라
- ENV32-C. 모든 exit 핸들러는 반드시 반환에 의해 종료해야 한다
- ENV33-C. system()을 호출하지 마라
- ENV34-C. 함수에서 반환하는 포인터를 저장하지 마라
- 11장. 시그널(SIG)
- SIG30-C. 시그널 핸들러에서는 비동기적으로 안전한 함수만 호출하라
- SIG31-C. 시그널 핸들러에서 공유 객체에 접근하거나 수정하지 마라
- SIG34-C. 인터럽트 가능한 시그널 핸들러 안에서 signal()을 호출하지 마라
- SIG35-C. 연산의 예외 시그널 핸들러에서 반환을 하지 마라
- 12장. 에러 처리(ERR)
- ERR30-C. errno를 사용하는 라이브러리 함수를 호출하기 전에 errno 값을 0으로 설정하고, 함수가 에러를 의미하는 값을 반환했을 때는 errno 값을 체크하라
- ERR32-C. 애매한 errno 값에 의존하지 마라
- ERR33-C. 표준 라이브러리 에러를 발견하고 처리하라
- 13장. 동시(CON)
- CON30-C. 스레드 지정 공간을 클린업하라
- CON31-C. 뮤텍스가 잠금 상태일 경우에 없애지 마라
- CON32-C. 멀티스레드에서 비트 필드에 접근할 때에 데이터 경쟁을 예방하라
- CON33-C. 라이브러리 함수를 사용할 때 경쟁 상태를 피하라
- CON34-C. 적합한 저장 존속 기간을 가진 스레드 사이에서 공유되는 객체를 선언하라
- CON35-C. 미리 정의된 순서에서 잠금으로 인한 교착 상태를 피하라
- CON36-C. 반복문에서 부정하게 동작할 수 있는 함수를 래핑하라
- CON37-C. 멀티스레드 프로그램에서 signal() 함수를 호출하지 마라
- CON38-C. 조건 변수를 사용할 때 스레드의 안전성과 생존상태를 보존하라
- CON39-C. 이미 병합되거나 분리됐던 스레드를 다시 사용하지 마라
- CON40-C. 표현식에서 아토믹 변수를 두 번 참조하지 마라
- CON41-C. 반복문에서 부정하게 실패할 수 있는 함수를 래핑하라
- 14장. 기타(MSC)
- MSC30-C. 의사 난수를 만들려고 rand() 함수를 사용하지 마라
- MSC32-C. 의사 난수 생성기를 적합하게 시드하라
- MSC33-C. 표준 라이브러리 에러를 발견하고 처리하라
- MSC37-C. 제어식이 void가 아닌 함수의 끝에 도달하지 않도록 보장하라
- MSC38-C. 매크로로 구현되는 객체를 이미 정의된 식별자로 취급하지 마라
- MSC39-C. 지정되지 않은 값을 가진 valist에서 vaarg() 함수를 호출하지 마라
- MSC40-C. 제한 사항을 위반하지 마라
- 부록 A. 용어 설명
- 부록 B. 정의되지 않은 동작
- 부록 C. 지정되지 않은 동작