source

Secure C 및 Secure C 관용구 쓰기

ittop 2023. 9. 19. 21:25
반응형

Secure C 및 Secure C 관용구 쓰기

"평범한 사람들은 자유로워지고 싶어하지 않습니다.그는 그저 안전하기를 원할 뿐입니다." - H.L. 멘켄

나는 매우 안전한 C를 쓰려고 시도하고 있습니다.아래에는 제가 사용하는 몇 가지 기술이 나열되어 있으며 제가 생각하는 것만큼 안전한지 물어봅니다.부디 주저하지 마시고 제 코드/선개념을 갈기갈기 찢어버리세요.가장 사소한 취약점이라도 찾아내거나 새로운 아이디어를 알려주는 답변은 높은 평가를 받을 것입니다.

스트림에서 읽기:

GNUC 프로그래밍 튜토리얼 getline에 따르면:

getline 기능은 reloc 기능을 통해 필요에 따라 메모리 블록을 자동으로 확장하므로 공간이 부족하지 않습니다. getline이 안전한 이유 중 하나입니다.[..] 입력 라인이 아무리 길어도 안전하게 처리할 수 있습니다.

getline은 모든 입력 하에서 스트림에서 읽을 때 버퍼 오버플로가 발생하지 않도록 해야 한다고 생각합니다.

  • 제 추측이 맞습니까?이것이 악용으로 이어질 수 있는 입력 및/또는 할당 체계가 있습니까?예를 들어 스트림의 첫 번째 문자가 특이한 제어 문자인 경우 0x08 BACKSPACE(ctl-H)일 수 있습니다.
  • getline을 수학적으로 안전하다고 증명하는 작업이 이루어졌습니까?

실패 시 Malloc이 Null을 반환합니다.

malloc에서 오류가 발생하면 malloc에서 NULL 포인터를 반환합니다.이는 NULL (0x0) 포인터에 포인터 산술을 적용할 수 있기 때문에 보안 위험을 나타냅니다. 따라서 위키피디아는 권장합니다.

/* Allocate space for an array with ten elements of type int. */
int *ptr = (int*)malloc(10 * sizeof (int));
if (ptr == NULL) {
    /* Memory could not be allocated, the program should handle 
       the error here as appropriate. */
} 

보안 검색:

sscanf를 사용할 때 저는 추출할 문자열의 크기를 입력 문자열의 크기에 할당하는 습관이 생겼습니다. 오버런의 가능성을 피하기를 바랍니다.예를 들어,

const char *inputStr = "a01234b4567c";
const char *formatStr = "a%[0-9]b%[0-9]c":
char *str1[strlen(inputStr)];
char *str2[strlen(inputStr)];

sscanf(inputStr, formatStr, str1, str2);

str1과 str2는 inputStr의 크기이고 inputStr에서 strlen(inputStr) 이상의 문자를 읽을 수 없기 때문에 inputStr에서 버퍼 오버플로가 발생할 가능성이 있는 모든 값을 고려할 때 불가능해 보입니다.

  • 내가 맞나요?제가 미처 생각하지 못한 이상한 코너 케이스가 있나요?
  • 이 글을 쓰는 더 좋은 방법이 있습니까?이미 해결한 라이브러리?

일반 질문:

제가 많은 질문을 올렸지만 아무도 그 질문에 모두 답하지는 않을 것으로 예상합니다.그 질문들은 제가 찾고 있는 답변의 종류에 대한 가이드라인에 가깝습니다.저는 안전한 C 사고방식을 꼭 배우고 싶습니다.

  • 또 다른 안전한 C 관용구는?
  • 항상 확인해야 하는 코너 케이스는 무엇입니까?
  • 이 규칙을 적용하기 위해 단위 테스트를 작성하려면 어떻게 해야 합니까?
  • 테스트 가능성 또는 올바른 방법으로 제약 조건을 적용하려면 어떻게 해야 합니까?
  • C에 권장되는 정적/동적 분석 기술이나 도구가 있습니까?
  • 귀하는 어떤 보안 C 관행을 따르고 있으며, 귀하와 다른 사람들에게 어떻게 이를 정당화합니까?

리소스:

많은 자료들이 답변들로부터 빌려왔습니다.

나는 당신의 스캔 예시가 틀렸다고 생각합니다.그렇게 사용해도 여전히 넘칠 수 있습니다.

읽어 볼 최대 바이트 수를 지정하는 시도:

void main(int argc, char **argv)
{
  char buf[256];
  sscanf(argv[0], "%255s", &buf);
}

버퍼 오버플로를 방지하는 방법에 대한 IBM 개발 기사를 살펴보십시오.

테스트 측면에서, 저는 무작위 길이의 문자열을 생성하여 당신의 프로그램에 공급하는 프로그램을 작성하고, 그것들이 적절하게 처리되는지 확인할 것입니다.

  1. 스트림에서 읽기

    그 은.getline()"필요에 따라 메모리 블록을 자동으로 확대합니다."는 프로세스(또는 시스템)에 사용 가능한 메모리를 소진할 정도로 긴 입력을 생성하는 것은 사소한 일이므로 서비스 거부 공격으로 사용될 수 있음을 의미합니다.메모리 부족 상태가 발생하면 다른 취약성도 작동할 수 있습니다.메모리 부족/무메모리에서 코드의 동작은 거의 양호하지 않으며 예측하기 매우 어렵습니다.IMHO는 특히 보안에 민감한 애플리케이션에서 모든 것에 합리적인 상한을 설정하는 것이 더 안전합니다.

    와 같이 ()getline()는 버퍼만 제공하고 버퍼의 내용에 대해서는 보장하지 않습니다(안전성은 애플리케이션에 전적으로 의존하기 때문에).따라서 입력을 검사하는 것은 사용자 데이터를 처리하고 검증하는 데 여전히 필수적인 부분입니다.

  2. 스스캔프

    는 를 보다 정규 사용하고 표현식 라이브러리를 합니다.sscanf. 이렇게 하면 입력 시 많은 유효성 검사를 수행할 수 있습니다.

  3. 일반댓글

    • 입력 처리를 테스트하는 데 사용할 수 있는 임의 입력(유효 및 무효)을 생성하는 퍼징 도구를 사용할 수 있습니다.
    • 버퍼 오버플로, 언더플로, 메모리 부족 등 버퍼 관리가 중요합니다.
    • 레이스 상태를 보안 코드로 이용할 수 있음
    • 이진 파일을 조작하여 잘못된 값 또는 오버사이즈 값을 헤더에 주입할 수 있으므로 파일 형식 코드는 rock-solid여야 하며 이진 데이터가 유효하다고 가정하지 않아야 함
    • 임시 파일은 종종 보안 문제의 원인이 될 수 있으므로 신중하게 관리해야 합니다.
    • 코드 주입은 시스템 또는 런타임 라이브러리 호출을 악성 버전으로 대체하는 데 사용될 수 있습니다.
    • 플러그인은 공격을 위한 거대한 벡터를 제공합니다.
    • 일반적인 원칙으로, 사용자 데이터(또는 애플리케이션 외부의 데이터)가 처리, 소독 및 검증될 때까지 유효하지 않고 적대적인 것으로 간주되고 사용자 데이터가 애플리케이션에 진입할 수 있는 유일한 방법인 명확하게 정의된 인터페이스를 제안합니다.

이것을 살펴보기에 좋은 곳은 David Wheeler의 훌륭한 보안 코딩 사이트입니다.

그의 무료 온라인 책 "리눅스유닉스 HOWTO용 안전한 프로그래밍"은 정기적으로 업데이트되는 훌륭한 자료입니다.

또한 그의 뛰어난 정적 분석기인 FlakeFinder를 통해 몇 가지 힌트를 얻을 수 있습니다.하지만 경험이 풍부한 두 눈을 위한 자동화된 도구는 없다는 것을 기억하시기 바랍니다. 또는 David가 그렇게 다채롭게 표현한 것처럼 말이죠.

Flakefinder와 같은 모든 정적 분석 도구는 도구에 불과합니다.어떤 도구도 인간의 생각을 대체할 수 없습니다!간단히 말해서, "도구를 가진 바보는 여전히 바보입니다."분석 도구(예: 결함 탐지기)가 보안 교육 및 지식의 대체물이라고 생각하는 것은 잘못된 것입니다.

저는 몇 년 동안 David의 자원을 개인적으로 사용해 왔고 그것들이 훌륭하다는 것을 알게 되었습니다.

예제에 의한 안전하지 않은 프로그래밍
답이 몇 개 있는 블로그

야닉 모이(Yannick Moy)는 박사과정 중 C를 위한 Hoare/Floyd 최약체 전제조건 시스템을 개발하여 CERT 관리 스트링 라이브러리에 적용했습니다.그는 많은 버그를 발견했습니다. (그의 회고록 197쪽 참조)좋은 소식은 도서관이 그의 일에 더 안전하다는 것입니다.

여기 Les Hatton의 웹사이트와 아마존에서 얻을 수 있는 그의 책 Safer C도 볼 수 있습니다.

사용하지않습니다.gets()용,fgets(). 사용방법fgets() "(, "에"), 합니다 합니다.

char buf[N];
...
if (fgets(buf, sizeof buf, fp) != NULL)

합니다의 에도 계속 합니다.buf 이 양식은 다음과 같습니다.

#define N whatever
char buf[N];
if (fgets(buf, N, fp) != NULL)

는 을 사용하기 입니다.buf두 번째 인수를 결정합니다. 그리고 더 명확합니다.


fclose().


언급URL : https://stackoverflow.com/questions/2008173/writing-secure-c-and-secure-c-idioms

반응형