* 부호버그
부호가 없는 정수를 부호가 있는 정수로 바꾸거나
부호가 있는 정수를 부호가 없는 정수로 바꾸려할 때 발생한다.
예시)
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char buf[20];
int i = atoi(argv[1]);
//atoi는 아스키를 int로 바꾸어준다.
memcpy (buf, argv[2], i*sizeof(int));
printf("the number is:%d=%d\n",i, i*sizeof(int));
printf("the buffer is: %s\n",buf);
}
-----------------------------------------------------------------------------------------
changmin@ubuntu:~/Documents$ ./test3 1 AAAA
the number is:1=4
the buffer is: AAAA�vbV
=> 1 AAAA를 입력하면,
i는 1이되고 i*sizeof(int)는 4가된다.
"�vbV"는 memcpy가 null을 추가하지 않고 복사하기때문에 그런것같다.
-----------------------------------------------------------------------------------------
changmin@ubuntu:~/Documents$ ./test3 111 AAAA
the number is:111=444
the buffer is: AAAA
*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)
111 AAAA를 입력하면
i는 111이되고 i*sizeof(int)는 444가된다.
따라서 argv[2]에서 444만큼 가져와 buf 에 copy하려한다.
---------------------------------------------------------------------------------------
changmin@ubuntu:~/Documents$ ./test3 -1 AAAA
Segmentation fault (core dumped)
-1 AAAA를 입력하면
i는 -1이되고 i*sizeof(int)는 -4가된다.
memcpy 원형을 보면
#include <string.h>
void *memcpy(void *dest, const void *src, size_t num);
인데 size_t는 unsigned int 타입이다.
따라서 -4가 아니라 언더플로우가 일어나 엄청나게 큰 수로 바뀌게 된다.
따라서 버퍼 오버플로우가 발생한다.
gdb를 사용하여 테스트해보면
(위와 같은 코드이다.)
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char buf[20];
int i = atoi(argv[1]);
//atoi는 아스키를 int로 바꾸어준다.
memcpy (buf, argv[2], i*sizeof(int));
printf("the number is:%d=%d\n",i, i*sizeof(int));
printf("the buffer is: %s\n",buf);
}
(파이썬을 설치하지 않아 A 44번 B 4번을 일일이 입력했다...)
(gdb) r 12 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
Starting program: /home/changmin/Documents/test3gdb 12 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
the number is:12=48
the buffer is: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
*** stack smashing detected ***: <unknown> terminated
Program received signal SIGABRT, Aborted.
0xf7fd5059 in __kernel_vsyscall ()
=> argv[0]에 12, argv[1]에 A*44+B*4를 입력하였다.
=>buf의 크기는 20인데 memcpy에서 12*4(i*sizeof(int))를 하여 48크기만큼 memcpy하려하여 버퍼가 넘치는 버퍼 오버플로우가 발생한다.
이번엔 argv[0]에 -1073741810을 입력하였다.
(gdb) r -1073741810 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/changmin/Documents/test3gdb -1073741810 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
the number is:-1073741810=56
the buffer is: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
*** stack smashing detected ***: <unknown> terminated
Program received signal SIGABRT, Aborted.
0xf7fd5059 in __kernel_vsyscall ()
=> -1073741810 * 4 (i*sizeof(int))값이 memcpy의 인자로 들어가는데 usigned int로 바뀌면서 값이 56으로 변환이 된다. 따라서 버퍼의 크기 20을 넘게된다.
* CWE-195의 부호변환 에러
=> readdata함수는 unsigend int형을 반환한다.
=> 함수 안에서 if문을 보면, 조건 만족시 amount에 -1을 넣고 그 값을 반환한다.
=> usigned int 형으로 바뀌어 반환되므로 언더플로우가 발생한다.
=> 이 경우 또한 usigned int형을 반환하는데 amount가 음수값이 된다면 언더플로우가 발생할 것이다.
=> if문에서 numHeaders가 100보다 큰지 체크한다.
=> 하지만 int형이 numHeaders가 INT_MAX보다 큰값이 된다면 오버플로우로 음수가 될 것이다.
=> 따라서 ExitError를 실행하지 않고 malloc을 한다.
=> 하지만 malloc에서 unsigned int형으로 바뀌면서 언더 플로우가 발생된다.
int copy_something(char *buf, int len){
char kbuf[800];
if(len > sizeof(kbuf)){ /* [1] */
return -1;
}
return memcpy (kbuf, buf, len); /* [2] */
}
=> if문에서 len의 값이 음수라면 return의 memcpy에서 언더플로우가 발생된다.
=> short형으로 선언된 len이 음수라면 if문을 만족하여 memcpy시 언더플로우를 일으키게된다.
=>(len이 SHORT_MAX보다 크면 오버플로우로 음수가 될 것이다.)
int table[800];
int insert_in_table (int val, int pos) {
if ( pos > sizeof(table) / sizeof(int) ) {
return -1;
}
table[pos] = val;
return 0;
}
일이 벌어
만약 pos값이 0x8000 0000(0x8 = 1000(2))이거나 0x9000 0000(1001(2))이면
최상위 비트가 1이므로 음수가 된다.
따라서 table[음수값] =val; 이 되어버린다.
=> 위와 같은 일이 벌어지면 무결성이 깨지게 된다.
'공부 > 보안' 카테고리의 다른 글
MyEtherWallet 해킹사건 분석 (0) | 2021.04.18 |
---|---|
보안개론 정리(2) - software 취약점 (0) | 2021.04.16 |
Int Overflow/Underflow(1) - 예시, 예방법 (0) | 2021.04.15 |
보안개론 정리(1) (0) | 2021.04.13 |
Role-Based Access Control (RBAC) (0) | 2020.12.08 |