일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Waterfall
- Trap
- STCF
- frequency-domain spectrum analysis
- 메카님
- 배경 그림
- link layer
- protection
- 게임개발
- 유니티
- FIFO
- MAC
- 컴퓨터 네트워크
- DSP
- 유스케이스
- Security
- information hiding
- MLFQ
- SJF
- 게임 개발
- SDLC
- DP
- 운영체제
- polymorphism
- Unity #Indie Game
- unity
- stride
- OWASP
- OSI 7계층
- AINCAA
- Today
- Total
다양한 기록
Integer Overflow, Underflow / Signedness bugs / Widthness bugs 본문
아리안 5
적재된 위성을 궤도에 전달하기 위한 용도의 로켓
64비트 숫자를 16비트에 채우면서 유발
화성 기후 궤도 탐사선
록히드 마틴에서는 점화 데이터를 야드 단위로 만들었고,
나사는 미터법으로 생각했음 -> 지나치게 낮은 궤도 - 폭발
비트 크기를 제대로 맞추지 않으면 문제가 생길 수 있음
char: -128~127
unsigned char: 0~255
short: -32768~32767
unsigned short: 0~65535
Format Specifier
%d - 10진수 정수 (4바이트)
%u - 부호없는 정수
%i - 아무 정수 (10진수, 8진수, 16진수)
%hd - short (2바이트)
%hu - unsigned short
%hhd - char (1바이트)
%hhu - unsigned char
%ld - long (32비트 시스템이면 4바이트, 64비트 시스템이면 8바이트)
%lu - unsigned long
%o - 8진수 정수, 4바이트
%x - 16진수 정수, 4바이트
%p - 주소 출력, 32비트 시스템이면 4바이트, 64비트 시스템이면 8바이트 .. 인데 보통 48비트만 사용
Integer overflow / Wraparound
CWE 190
정수가 범위를 넘어선 너무 큰 값으로 증가하면 0이나 음수가 됨 (오버플로우)
CIA를 깨트릴 수 있음
가용성
- 정의되지 않을 작동으로 연결되어 크래시 발생 가능, 반복문의 인덱스에서 인티저 오버 플로우 발생 시 무한 루프에 빠져 정상 작동하지 않을 수 있음
무결성
- 문제가 되는 값들이 중요한 데이터이면 단순한 데이터 오염 발생
- 랩 어라운드가 발생하여 버퍼 오버플로우로 연결 시 메모리 오염 발생 가능
비밀성, 가용성, 접근 제어 등 ..
- 임의 코드 실행으로 연결될 수 있음
Signed Numbers
Binary | Decimal | Hexadecimal |
0111 1111 | 127 | 0x7F |
0111 1110 | 126 | 0x7E |
1111 1111 | -1 | 0xFF |
1111 1110 | -2 | 0xFE |
1000 0001 | -127 | 0x81 |
1000 0000 | -128 | 0x80 |
양수 127
2진수 - 0111 1111
1의 보수 -> 1000 0000
2의 보수 -> 1000 0001
2 +(-3) = ?
3 : 이진수로 0011
1의 보수 -> 1100
2의 보수 -> 1101
0010 + 1101 = 1111 -> -1
4비트로 제한되어 있다고 치자
+5 + 4
0101 + 0100
1001 -> 오버플로우
-7 -6
1001 + 1010
1 / 0011 -> 오버플로우
32비트의 경우
int 최고 -> 0x7FFFFFFF (2147483647)
여기다 1 더하면 -> 0x80000000
=> 언더플로우
img_t table_ptr;
int num_imgs;
num_imgs = get_num_imgs();
table_ptr = (img_t*)malloc(sizeof(img_t) * num_imgs);
malloc 내부 인자 값이 엄청 커져서 오버플로우가 발생할 수도 있음
대신 xmalloc 권장
같은 이유로 memcpy도 문제가 있음
int catvars(char *buf1, char *buf2, unsigned int len1, unsigned int len2) {
char mubuf[256];
if( (len1 + len2) > 256 ) {
return -1;
}
memcpy(mybuf, buf1, len1);
memcpy(mybuf + len1, buf2, len2);
do_some_stuff(mybuf);
return 0;
}
len1과 len2를 더해서 오버플로우 발생 시 256보다 작을 수 있음
계산 결과이후 저장된 결과와 올바른 결과가 다를 수 있음
중요한 변수에 잘못된 값을 포함하게 하는 등, 문제가 될 수 있음
어떻게 예방할 수 있는가?
에러 핸들링, 익셉션 핸들링
int sum(int a, int b) {
int c = a + b;
if( a > 0 && b > 0 && c < 0 ) {
throw new MyOverflowException(a, b);
}
return c;
}
int pord(int a, int b) {
int c = a * b;
if( a > 0 && b > 0 && c < 0 ) {
throw new MyOverflowException(a, b);
}
return c;
}
양수를 더했는데, 혹은 곱했는데 음수가 나오면 예외처리
static void update_value(char op) {
if( op == '+' ) {
if( value + 1 > value ) value++;
else printf("too big!\n");
}
else {
if( value -1 < value ) value--;
else printf("too small!\n");
}
}
int addOvf(int *result, int a, int b) {
if( a > INT_MAX - b ) return -1;
else {
*result = a + b;
return 0;
}
}
더했는데 원해 값보다 작아지거나,
원래 값이 너무 커서 남은 자리가 충분하지 않은지 검사하기
완화시키기(SDLC 단계에서 신경써야 함)
요구사항 단계
- 언어를 잘 선택해라: 파이썬같은 건 부족하면 알아서 늘림
설계 단계
- 라이브러리나 프레임워크를 잘 선택해라(SafeInt, IntegerLib)
구현 단계
- 입력 검증 하기
- 크기를 나타내는 건 unsigned 쓰기
Signedness bugs
- 부호가 없는 변수가 부호가 있는 것으로 해석되는 경우
- 부호가 있는 변수가 부호가 없는 경우로 해석되는 경우
// int.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char buf[20];
int i = atoi(argv[1]);
memcpy(buf, argv[2], i * sizeof(int));
}
// void *memcpy(void *dest, const void *src, size_t num);
1. 버퍼 오버플로우
./ 111 AAAA
i * sizeof(int) => 444
444만큼 argv[2]의 내용을 카피? -- buf는 20바이트 크기 -> 넘침
스택의 구조가 망가지고, 리턴 어드레스나 saved ebp가 망가지고, 스택 카나리가 망가짐 (스택 스매싱 detected)
2. 부호화 버그로 인한 버퍼 오버플로우
memcpy의 size_t는 unsigned integer임
그런데 ./int -1 AAAA
이런식으로 사이즈에 음수값을 주면 -1은 16진수로 0xffffffff
0xffffffff를 memcpy에서 unsigned int로 받아들이면 굉장히 큰 숫자가 되어 버퍼 오버플로우 발생
맥에서는 테스트 결과 애초에 버퍼 크기를 넘기면 안된다
우분투에선 이렇게 된다
프로세스 구조 중 스택은 위와 같다.
여기서 버퍼 오버플로우가 발생하여 argc의 값까지 망가진 것을 볼 수 있다.
무결성이 깨지는 문제
CWE-195: Signed to Unsigned Conversion Error
unsigned int readdata() {
int amount = 0;
....
if( result == ERROR ) amount = -1;
....
return amount;
}
unsigned int로 -1을 리턴하면 엄청 큰 수가 리턴 될 것
int copy_something(char *buf, int len) {
char kbuf[800];
if( len > sizeof(kbuf) ) {
return -1;
}
return memcpy(kbuf, buf, len);
}
len이 음수이면 if문은 통과하는데, memcpy에서 unsigned int로 컨버전되면서 엄청 큰 수로 바뀜
#include <stdio.h>
int main(void) {
int i;
short s;
char c;
i = 0xdeadbeef; // 0xdeadbeef
s = i; // 0xbeef
c = i; // 0xef
printf("i = 0x%x, (%d bits)\n", i, sizeof(i) * 8); // 0xdeadbeef (32bits)
printf("s = 0x%x, (%d bits)\n", d, sizeof(s) * 8); // 0xffffbeef (16bits)
printf("c = 0x%x, (%d bits)\n", c, sizeof(c) * 8); // 0xffffffef (8bits)
return 0;
}
d는 앞쪽 비트가 1 -> 사이즈 안맞추면 f로 차게 됨
%hx, %hhx를 사용하기
// width.c
#include <stdio.h>
#include <string.h>
#incldue <stdlib.h>
int main(int argc, char *argv[]) {
unsigned short s;
int i;
char buf[80];
if( argc < 3 ) return -1;
i = atoi(argv[1]);
s = i;
if( s >= 80 ) {
printf("you don't");
return -1;
}
printf("s=%d\n", s);
memcpy(buf, argv[2], i);
buf[i] = '\0';
printf("%s\n", buf);
return 0;
}
// ./width1 5 hello
// s = 5
// hello
// ./width1 80 hello
// you don't
// ./width1 65536 hello
// s = 0
// Segmentation fault (core dumped)
int에 65536 받아놓고 unsigned short로 검사 .. > 너무 커서 버퍼가 넘침
'보안개론' 카테고리의 다른 글
Byte Ordering, Simple Buffer Overflow (0) | 2024.06.04 |
---|---|
Array Operations (0) | 2024.06.04 |
Use After Free (0) | 2024.06.03 |
bin, chunk, double free (0) | 2024.06.03 |
ptr[-1], ptr[-2]가 가지는 의미 (0) | 2024.05.19 |