기본 콘텐츠로 건너뛰기

Insecure-programming-stack1

Insecure-programming-stack1 Insecure Programming by example Stack 1 # include <stdio.h> int main ( ) { int cookie ; char buf [ 80 ] ; printf ( "buf: %08x cookie: %08x\n" , & buf , & cookie ) ; gets ( buf ) ; if ( cookie == 0x41424344 ) printf ( "you win!\n" ) ; } cookie 변수 값이 0x41424344인 경우 you win! 을 출력하는 프로그램 소스 코드이다. 하지만 정상적인 프로그램 사용을 통해서 cookie 값에 값을 삽입할 수 있는 방법은 존재하지 않으므로 buf[80] 배열에 값을 넘치게 삽입하여 cookie 변수 값을 조작해야 한다. $ echo `python -c "print 'a'*80+'DCBA'" ` | ./stack1.exe buf: 0028fe6c cookie: 0028febc you win ! 위와 같이 python을 이용하여 임의의 문자 80개를 삽입한 후 cookie 변수 값에 넣을 값 지정하면 쉽게 해결할 수 있다. 주의할 점은 리틀엔디언 방식으로 문자를 역순으로 넣어주어야한다는 점이다. 추가적으로 심볼 파일을 생성하거나 gdb를 통해서 어셈블리어 구성을 살펴보자. 간단한 코드로 특이 사항은 없으므로 간단히 눈으로 읽고 지나쳐도 좋다. gcc -S -masm = intel -O3 -o stack1.s ./stack1.c Non-debugging symbols: 0x00000000 __deregister_frame_info 0x00000000 __register_frame_info 0x0040

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() 함수의 일부분이다.

힘내라 청춘. 20171221

힘내라 청춘. 20171220

힘내라 청춘. 20171219

힘내라 청춘. 20171218

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 시도 응답 정수 오