기본 콘텐츠로 건너뛰기

라벨이 소프트웨어 보안 평가인 게시물 표시

typos

typos 오탈자 도전 1 whlie ( * src && left ) { * dst ++ = * src ++ ; if ( left = 0 ) die ( "badlen" ) ; left -- ; } if 조건에 관계 연산자 == 대신 대입 연산자 = 가 설정되어 있다. 이로 인해 left 이 0으로 설정되어도 while 구문을 벗어나지 못하고 left 값을 감소시키며 반복 수행한다. 수정 코드 if ( left == 0 ) 도전 2 int f ; f = get_security_flags ( username ) ; if ( f = FLAG_AUTHENTICATED ) { return LOGIN_OK ; } return LOGIN_FAILED ; if 조건에 관계 연산자 == 대신 대입 연산자 = 가 설정되어 있어 get_security_flags 결과와 무관하게 로그인 성공을 반환하고 있다. 수정 코드 if ( f == FLAG_AUTHENTICATED ) 도전 3 for ( i == 5 ; src [ i ] && i < 10 ; i ++ ) { dst [ i -5 ] = src [ i ] ; } for 조건에 대입 연산자 = 대신에 관계 연산자 == 가 설정되어 있어 i 가 10보다 작은 값일 때, 버퍼를 벗어날 위험이 있다. 수정 코드 for ( i = 5 ; src [ i ] && i < 10 ; i ++ ) 도전 4 if ( get_string ( src ) && check_for_overflow ( src ) & copy_string ( dst , src ) ) printf ( "string safely copied\n" ) ; 논리 연산자

Signed-Numeric-overflow

Signed-Numeric-overflow 부호 있는 정수 경계 오버플로우 부호 있는 정수 취약점 예 char * read_data ( int sockfd ) { char * buf ; int length = network_get_int ( sockfd ) ; if ( ! ( buf = ( char * ) malloc ( MAXCHARS ) ) ) die ( "malloc: %m" ) ; if ( length < 0 || length + 1 >= MAXCHARS ) { free ( buf ) ; die ( "bad length: %d" , value ) ; } if ( read ( sockfd , buf , length ) <= 0 ) { free ( buf ) ; die ( "read: %m" ) ; } buf [ value ] = '\0' ; return buf ; } 먼저 length 가 MAXCHARS 보다 작은지 검사한다. 그리고 2 번째 length 검사에서 length 값에 1을 더한다. 이것이 공격 벡터가 된다. 값이 0x7FFFFFFF라면 이 값은 0보다 크기 때문에 첫 번째 검사를 통과하며, 두 번째 length 검사를 통과한다. (0x7FFFFFFF + 1은 0x80000000이 되고 이는 음수 값이다.) 결과적으로 read() 는 경게가 없는, 즉 음수 값을 가진 length 인자로 호출되고, 이는 잠재적으로 버퍼 오버플로우 상황을 만든다. OpenSSL 0.9.6I에서 정부 부호 경계 취약점 예 BIO(buffered IO) 스트림으로부터 ASN.1 객체를 읽어 들이는 crypto/asn1/a_d2i_fp.c - ASN1_d2i_fp() 함수의 일부분이다.

Unsigned-Numeric-overflow

Unsigned-Numeric-overflow 부호 없는 정수 경계 오버플로우 정수 오버플로우 예 u_char * make_table ( unsigned int width , unsigned int height , u_char * init_row ) { unsigned int n ; int i ; u_char * buf ; n = width * height ; buf = ( char * ) malloc ( n ) ; if ( ! buf ) return ( NULL ) ; for ( i = 0 ; i < height ; i ++ ) memcpy ( & buf [ i * width ] , init_row , width ) ; return buf ; } make_table() 함수의 목적은 너비와 높이, 초기 배열을 받아들여 각 행이 init_row 값과 동일한 값으로 초기화된 테이블을 메모리에 생성하는 것이다. 만약 사용자에게 width 와 height 에 대한 제어권을 갖고 있다면 오버플로우 공격을 일으킬 가능성이 있다. 너비가 1,000,000이고 높이가 3,000 같은 큰 값을 지정한다면 malloc() 함수를 호출하여 3,000,000,000 바이트를 할당하는 과정에서 에러를 감지하고 실패할 확률이 높다. 하지만 결과 값에서 1 비트만 큰 산술 오버플로우를 유도한다면 성공할 가능성이 높다. 실제 초기화는 for 루프에서 이루어지기 때문이다. 사용자가 width 를 0x400으로, height 를 0x1000001로 할당한다면 곱셈 결과 0x400000400이며, 이 값의 모듈로 0x100000000은 0x00000400 또는 1024가 된다. 그러므로 1024바이트가 할당되고 for 루프에서 init_row 를 약 천육백만 번 정도 더 많이 복사하게 된다. OpenSSH 시도 응답 정수 오

memory-corruption-impact

memory-corruption-impact 메모리 오염 영향 평가 취약점의 심각도를 가장 정확하게 파악할 수 있는 방법은 POC 공격을 작성하는 것이지만, 이는 너무 많은 시간을 필요로 한다. 따라서 몇 가지 질문에 대한 답을 찾는 것으로 영향 평가를 수행할 수 있다. 메모리에서 버퍼의 위치 변수는 주로 스택, 힙, 지속 데이터(정적 변수, 전역 변수 포함) 이렇게 세 개의 메모리 영역에 저장되지만 종종 이 세 위치를 분할하거나 새로운 영역을 나누기도 한다. 때로는 초기화된 전역 변수와 초기화 되지 않은 전역 변수를 나누기도 하고, 특별할 위치에 TLS를 두기도 한다. 또한 공유 라이브러리는 라이브러리 코드 바로 다음에 위치하는 프로세스 메모리에 초기화되거나 비초기화된 상태에서 매핑된다. 어디서 메모리 오염이 일어나고 어떤 특별한 고려 사항이 적용되는지 파악할 필요성이 있으며, 운영체제 별 고유 메모리 배치에 대한 이해가 필요하다. 다른 데이터로 덮어쓰기 되는 것 메모리 오염은 공격자가 목표하는 변수에만 국한되지 않을 수 있으며, 다른 변수에 까지 값을 덮어 쓸 수 있다. 예제에서 보는 바와 같이 프로그램 카운터를 덮어쓰기전 지역 변수 값을 같이 덮어쓸 수 잇다. 지역 변수로의 오버플로우 int dostuff ( char * login ) { char * ptr = ( char * ) malloc ( 1024 ) ; char buf [ 1024 ] ; . . . strcpy ( buf , login ) ; . . . free ( ptr ) ; return 0 ; } 여기서 공격자는 프로그램 카운터를 덮어쓸 때 ptr 변수도 같이 덮어쓰게 되는데, ptr 변수는 프로그램이 리턴되기 바로 전에 해제되는 값이다. 이로 인해 유효하지 않은 주소 값으로 ptr 변수를 덮어 쓰게 되면 free() 함수 호출 시 프로그램 크래시가 발생할 수 있다. 이로