430 likes | 764 Views
16 장 . 네트워크 보안 프로그래밍 소프트웨어공학연구실 최 상 수. 목차. 보안에 대한 정의 보안 문제점들 적과 아군의 식별 Inetd 서버의 보호 래퍼 및 서버 프로그램의 설치 클라이언트 프로그램의 소개 래퍼의 설치 및 테스트 데이터그램 취약성. 보안에 대한 정의. The Merriam Webster ’ s Collegiate Dictionary 위협으로부터의 자유와 같은 안전한 특성 또는 상태 스파이행위 또는 사보타주 , 범죄 , 공격 , 누출에 대항하여 이루어지는 보호의 측정 네트워크 보안
E N D
16장.네트워크 보안 프로그래밍소프트웨어공학연구실최 상 수
목차 • 보안에 대한 정의 • 보안 문제점들 • 적과 아군의 식별 • Inetd 서버의 보호 • 래퍼 및 서버 프로그램의 설치 • 클라이언트 프로그램의 소개 • 래퍼의 설치 및 테스트 • 데이터그램 취약성
보안에 대한 정의 • The Merriam Webster’s Collegiate Dictionary • 위협으로부터의 자유와 같은 안전한 특성 또는 상태 • 스파이행위 또는 사보타주, 범죄, 공격, 누출에 대항하여 이루어지는 보호의 측정 • 네트워크 보안 • 인지된 위협으로부터의 자유 • 무단 조사, 사보타주, 도난 또는 기타 공격으로부터 시스템 자원들의 보호
보안 문제점들 • Lock의 형태 • 무장 경비원의 고용 • 키-기반과 카드-기반 Lock : 물리적 토큰 • Lock과 패스워드, PIN 번호의 조합 : 비밀 지식 • 망막, 지문과 성문(voice print) 스캔 : 유일한 특징 • 보안 방법들의 약점 • 물리적 토큰 → 복사 • 비밀 지식 → 공유, 기록, 추측 • 유일한 특징 → 무력
보안 문제점들 • 보안에 대한 기본적인 진리 • 한 명의 사용자에게 접근 권한을 허가한 시스템은, 잠재적으로 다른 사용자들에게도 마찬가지로 접근을 허용할 수 있다. • 어느 누구도 접근 권한을 얻지 못하는 시스템만이, 오직 완벽하게 안전한 시스템이다. • 결론 • 자원에 대한 타당하고 안전한 접근이 허용되는지, 항상 보안에 대하여 고려해야만 한다.
적과 아군의 식별 • IP 번호 →호스트네임과 도메인네임 분석(적용 가능한 접근정책) • 특정 호스트 네임들에 대한 접근 허가 • 특정 도메인들에 대한 접근 허가 • 특정 호스트 네임들에 대한 접근 거부 • 특정 도메인들에 대한 접근 거부 • 어떤 이름으로 분석되지 않은 IP 번호들에 대한 접근 거부
Accept(2) Recvfrom(2) Gethostbyaddr(3) 적과 아군의 식별 • 호스트네임 또는 도메인네임에 의한 보호
적과 아군의 식별 • Accept(2) 예제 Struct sockaddr_in adr_clnt; Int len_inet; Int c; …… Len_inet = sizeof adr_clnt; c = accpt(s, (struct sockaddr *)&adr_clnt, &len_inet);
적과 아군의 식별 • Recvfrom(2) 예제 Int z; Struct sockaddr_in adr_clnt; Int len_inet; Int s; char dgram[512]; len_inet = sizeof adr_clnt; z = recvfrom(s, dgram, sizeof dgram, 0, (struct sockaddr *)&adr_clnt, &len_inet);
적과 아군의 식별 • Gethostbyaddr(3) 예제 Struct sockaddr_in adr_clnt; Struct hostent *hp; hp = gethostbyaddr( (char *)&adr_clnt.sin_addr, sizeof adr_clnt.sin_addr, adr_clnt.sin_family); If(!hp) fprintf(logf, “ERROR: %s\n”, hstrerror(h_errno)); else printf(logf, “ %s\n”, hp->h_name);
적과 아군의 식별 • IP 번호에 의한 식별 • 보안 문제 : IP 번호를 받을때 또다른 네트워크 프로세스를 사용하여 그 번호를 호스트네임으로 분석해야만 함 • IP 번호를 단독으로 사용 • IP 번호 갱신 • 자신들의 IP 번호를 모르는 사용자 처리 • 로그 파일에 기록 • 네트워크 ID 단계에서의 접근 제한
Inetd 서버의 보호 • 중앙 집중화된 정책 • Inetd 데몬 • 클라이언트 요청을 위한 listen에 필요한 모든 코드 제공 • 필요시에만 서버를 구동 • 중앙 집중화된 네트워크 보안 모델의 설치 가능 • TCP 래퍼 프로그램 • Wietse Venema의 TCP 래퍼 프로그램 (레드헷 6.0) • Tcpd 프로그램이 inetd와 서버 사이에 자신을 삽입 • 투명한 방법으로 이루어짐
tcpd fork(2)&exec(2) Remote Client1 exec(2) inetd In.telnetd Inetd 서버의 보호 • TCP 래퍼 개념의 이해
3.새로운 프로세스 fork(2) / 부모 프로세스는 listen 5.접속허가여부 결정 4.자식 프로세스는 exec(2) 호출하여 usr/sbin/tcpd 실행 tcpd fork(2)&exec(2) 6.거부:종료 7.허가:경로 명시 /usr/sbin/in.telnetd Remote Client1 exec(2) inetd 8.입출력 수행 In.telnetd 1.연결요청 2.요청수락 Inetd 서버의 보호 • 원격 클라이언트가 in.telnetd 서버에 접속하는 프로세스
tcpd fork(2)&exec(2) Remote Client1 exec(2) inetd In.telnetd Inetd 서버의 보호 • 번호를 사용 PID 1243 자식 PID 1243 서버 프로세스가 부모 inetd의 직접적인 자식 프로세스일 때에만 정확하게 수행한다! PID 1243 Wait(2) 호출 PID 124 종료시 SIGCHLD
Inetd 서버의 보호 • 접근 결정 • 서비스 결정 • Getsoketname(2) 함수 : 소켓 주소, 서비스 포트 번호 • 클라이언트의 신분 결정 • Getpeername(2) 함수 : 클라이언트의 주소, 포트 번호 • 데이터그램 클라이언트의 신분 결정 • 데이터그램은 accept(2) 함수를 사용하지 않음 • MSG_PEEK 플래그 옵션 + recvfrom(2) 함수 • MSG_PEEK : 클라이언트의 주소를 리턴
Inetd 서버의 보호 • MSG_PEEK 플래그 옵션 + recvfrom(2) 함수 Int z; Struct sockaddr_in adr_clnt; Int len_inet; Int s; Char dgram[512]; Len_inet = sizeof adr_clnt; z = recvfrom(s, dgram, sizeof dgram, MSG_PEEK, (struct sockaddr *)&adr_clnt, &len_inet);
래퍼 및 서버 프로그램의 설치 • 서버와 래퍼 로깅 코드의 시험 • 리스트 16.1 : log.c • 로그 파일 open : log_open() 21: Int 22: Log_open(const char *pathname) { 23: 24: logf = fopen(pathname, “a”); 25: return logf ? 0 : -1; 26: }
래퍼 및 서버 프로그램의 설치 • Printf(3) 스타일의 로깅 함수 : log() 31: Void 32: Log(const char *format,…) { 33: va_list ap; 34: 35: if(!logf) 36: return; 37: 38: fprintf(logf, “[PID %ld] “, (long)getpid()); 39: 40: Va_start(ap, format); 41: vfprintf(log, format, ap); 42: va_end(ap); 43: fflush(logf); 44: }
래퍼 및 서버 프로그램의 설치 • 로그 파일 close : Log_close() 49: Void 50: Log_close(void) { 51: 52: if(logf) 53: fclose(logf); 54: logf = NULL; 55: }
래퍼 및 서버 프로그램의 설치 • 로그 파일에 출력 내용 기록 : bail() 61: Void 62: Bail(const char *on_what) { 63: 64: if(logf) { 65: if(errno) 66: log(“%s: “, strerror(errno)); 67: log(“%s\n”, on_what); 68: log_close(); 69: } 70: exit(1); 71: }
래퍼 및 서버 프로그램의 설치 • 리스트 16.2 : log.h 1: /* log.h 2: * 3: * log.c externs: 4: */ 5: extern int log_open(const char *pathname); 6: extern void log(const char *format,…); 7: extern void log_close(void); 8: extern void bail(const char *on_what);
로그파일 open Date/time 요청 처리 Server Loop 시작(for) Client에 결과 응답 데이터그램 read 다른 데이터그램 wait 데이터그램 도착 Error/timeout 데이터그램 종료 에러/타임아웃 기록 래퍼 및 서버 프로그램의 설치 • 데이터그램 서버 코드의 시험 • 리스트 16.3 : dgramisrvr.c
래퍼 및 서버 프로그램의 설치 • 로그 파일 open if(log_open(LOGPATH) == -1) exit(1); log(“dgramisrvr started.\n”); S = 0; FD_ZERO(&rx_set); FD_SET(s, &rx_set);
래퍼 및 서버 프로그램의 설치 • 데이터그램 read alen = sizeof adr_clnt; z = recvfrom(s, dgram, sizeof dgram, 0, (struct sockaddr *)&adr_clnt, &alen); If(z < 0) bail(“recvfrom(2)”);
래퍼 및 서버 프로그램의 설치 • 데이터그램 종료 dgram[z] = 0; • Date/time 요청 처리 time(&td); dtv = *localtime(&td); strftime(dtfmt, sizeof dtfmt, dgram, &dtv);
래퍼 및 서버 프로그램의 설치 • 클라이언트에 결과 응답 Z = sendto(s, dtfmt, strlen(dtfmt, 0, (struct sockaddr *)&adr_clnt, alen); if(z < 0) bail(“sendto(2)”);
래퍼 및 서버 프로그램의 설치 • 다른 데이터그램 wait do { tmout.tv_sec = 8; tmout.tv_usec = 0; z = select(s+1, &rx_set, NULL, NULL, &tmout); } while(z == -1 && errno = EINTR); • Select(2) 호출의 리턴값 • 데이터그램 도착 : 1 • Timeout : 0 • Error : -1
래퍼 및 서버 프로그램의 설치 • Error/timeout 발생시 for loop 종료 if(z <= 0) break; • Error/timeout 메시지 기록 if(z == -1) log(“%s: select(2)\n”, strerror(errno)); else log(“Timed out: server exiting.\n”);
로그파일 open 요청 거부 데이터그램 주소 결정 요청 허가 주소→스트링 변환 클라이언트 주소 Test 래퍼 및 서버 프로그램의 설치 • 간단한 TCP 래퍼 프로그램의 시험 • 리스트 16.4 : wrapper.c
래퍼 및 서버 프로그램의 설치 • 간단한 보안 정책 구현 • 클라이언트 주소 = 127.7.7.7 → 요청 허가 • 그 이외의 주소 → 요청 거부 • 클라이언트 주소 Test …… str_addr = inet_ntoa(adr_clnt.sin_addr); If(strcmp(str_addr, “127.7.7.7”) != 0) { …… ……
래퍼 및 서버 프로그램의 설치 • 요청 거부 log(“Address %s port %d rejected.\n”, str_addr, ntohs(adr_clnt.sin_port)); // 요청 기록 z = recvfrom(0, // 데이터그램 discard dgram, sizeof dgram, 0, (struct sockaddr *)&adr_clnt, &alen); if(z < 0) // 에러 기록 및 종료 bail(“recvfrom(2), eating dgram”); exit(1);
래퍼 및 서버 프로그램의 설치 • 요청 허가 log(“Address %s port %d accepted.\n”, str_addr, ntohs(adr_clnt.sin_port)); // 요청 기록 log(“Starting ‘%s’\n”, argv[0]); // 시작상태 기록 log_close(); // 로그 close z = execve(argv[0], argv, envp); // 래퍼 교체
클라이언트 프로그램의 소개 • 리스트 16.5 : dgramcln2.c • 6장의 리스트 6.2 dgramclnt.c와 비슷함 • 두개의 command-line argument 요구 If(argc != 3) { fputs(“Usage: dgramclnt <server_ipaddr>” “<client_ipaddr>\n”, stderr); return 1; }
클라이언트 프로그램의 소개 • 로컬 소켓의 IP 주소 한정 memset(&adr_clnt, 0, sizeof adr_clnt); adr_clnt.sin_family = AF_INET; adr_clnt.sin_port = 0; adr_clnt.sin_addr.s_addr = inet_addr(clnt_addr); if(adr_clnt.sin_addr.s_addr == INADDR_NONE) bail(“bad client address.”); z = bind(s, (struct sockaddr *)&adr_clnt, sizeof adr_clnt); if(z == -1) bail(“bind(2) of client address”);
래퍼의 설치 및 테스트 • Inetd 데몬의 실행 $ /usr/sbin/inetd /tmp/inetd.conf $ $ ps –ef | grep inetd Root 313 1 0 Feb15 ? 00:00:00 inetd Studnt 12763 1 0 23:04 ? 00:00:00 /usr/sbin/inetd /tmp/inetd.conf Studnt 12765 11739 0 23:04 ? 00:00:00 grep inetd
래퍼의 설치 및 테스트 • 래퍼 프로그램의 테스트 $ ./dgramcln2 127.0.0.1 127.7.7.7 Enter format string: %A %B %D Result from 127.7.7.7 port 9090 : ‘Tuesday November 11/09/99’ Enter format string:
래퍼의 설치 및 테스트 • Wrapper log $ tail –f /tmp/wrapper.log [PID 1279] wrapper started. [PID 1279] Address 127.7.7.7 port 1027 accepted. [PID 1279] Starting ‘/tmp/dgramisrvr’ • Server log $ tail –f /tmp/dgramisrvr.log [PID 1279] dgramisrvr started. [PID 1279] Got request ‘%A %B %D’ from 127.7.7.7 port 1027 [PID 1279] Timed out: server exiting.
래퍼의 설치 및 테스트 • 서버 timeout 테스트 $ ./dgramcln2 127.0.0.1 127.7.7.7 Enter format string: %x Result from 127.7.7.7 port 9090 : ‘11/09/99’ Enter format string: %x %X Result from 127.7.7.7 port 9090 : ‘11/09/99 19:11:32’ Enter format string: CTRL+D $
래퍼의 설치 및 테스트 • 8초 이내에 처리했을 경우 단일 프로세스로 처리됨 $ tail –f /tmp/dgramisrvr.log [PID 1279] dgramisrvr started. [PID 1279] Got request ‘%A %B %D’ from 127.7.7.7 port 1027 [PID 1279] Timed out: server exiting. [PID 1294] dgramisrvr started. [PID 1294] Got request ‘%x’ from 127.7.7.7 port 1027 [PID 1294] Got request ‘%x %X’ from 127.7.7.7 port 1027 [PID 1294] Timed out: server exiting.
데이터그램 취약성 • 데이터그램 서버를 위한 래퍼 설계시 취약성 • 서버 루핑 • 데이터그램 도착, inetd에게 통보 • Inetd 데몬은 래퍼 프로그램 시작 • 래퍼 프로그램은 exec(2) 호출 • 데이터그램 서버는 데이터그램을 읽고 처리 • 서버는 다른 데이터그램을 위해 wait • 데이터그램 도착하면, 4부터 반복 • 그렇지 않다면, 서버는 timeout되고 종료됨 • 1부터 반복
데이터그램 취약성 • 단계 3 → 보안 점검 • 서버가 계속 실행중인 동안 프로세스는 단계 4부터 반복 → 보안 점검 생략 • 선택 가능한 옵션 • 오직 nowait 스타일의 데이터그램을 사용 • 처리 전에 각 데이터그램 테스트 위해, 데이터그램 서버 내에 custom 코드 사용