3 DreamHack Logical Bugs
Logical Bugs
프로그램의 논리적 오류
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// gcc -o logical logical.c
#include <stdio.h>
int withdraw(int balance, int money) {
return balance - money;
}
int main() {
int balance = 10000;
int amount = 0;
int result = 0;
printf("Your balance: %d\n\n", balance);
printf("Please enter the amount to withdraw: ");
scanf("%d", &amount);
result = withdraw(balance, amount);
printf("Check your balance: %d", result);
return 0;
}
해당 코드는 은행에서의 잔고 처리인데 음수에대한 처리가업다.
Command Injection
인젝션은 검증되지 않은 공격자의 입력을 셸 커맨드 또는 쿼리 일부로 처리해 정상적인 실행 흐름을 변경할 수 있는 취약점
- $ 쉘 환경변수
- && 이전 명령어 실행 후 다음 명령어 실행
- ; 명령어 구분자
-
명령어 파이핑 - ‘*’ 와일드 카드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// gcc -o cmdi cmdi.c
#include <stdlib.h>
#include <stdio.h>
int main()
{
char ip[36];
char cmd[256] = "ping -c 2 ";
printf("Alive Checker\n");
printf("IP: ");
read(0, ip, sizeof(ip)-1);
printf("IP Check: %s",ip);
strcat(cmd, ip);
system(cmd);
return 0;
}
;를 통해 의도한 명령어보다 추가적인 명령어를 악의적으로 집어넣을수있다.
ping -c 2 127.0.0.1;/bin/sh
Race Condition
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// gcc -o race1 race1.c -pthread
#include <stdio.h>
#include <pthread.h>
#include <time.h>
int count = 0;
void* counting() {
for(int i=0;i<10000000;i++) {
count += i;
}
}
int main(int argc, char* argv[]) {
pthread_t thread_id[3] = {0,};
pthread_create(&thread_id[0], NULL, counting, (void*)NULL);
pthread_create(&thread_id[1], NULL, counting, (void*)NULL);
pthread_create(&thread_id[2], NULL, counting, (void*)NULL);
sleep(1);
printf("%d\n", count);
return 0;
}
매실행마다 값이다르다.
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// gcc -o race2 race2.c -fno-stack-protector -lpthread -m32
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int len;
void giveshell() {
system("/bin/sh");
}
void * t_function() {
int i = 0;
while (i < 10000000) {
len++;
i++;
sleep(1);
}
}
int main() {
char buf[4];
int gogo;
int idx;
pthread_t p_thread;
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
while (1) {
printf("1. thread create\n");
printf("2. read buffer\n");
printf("> ");
scanf("%d", &idx);
switch (idx) {
case 1:
pthread_create( &p_thread, NULL, t_function, (void * ) NULL);
break;
case 2:
printf("len: ");
scanf("%d", &len);
if(len > sizeof(buf)) {
exit(0);
}
sleep(4);
printf("Data: ");
read(0, buf, len);
printf("Len: %d\n", len);
printf("buf: %s\n", buf);
break;
case 3:
if (gogo == 0x41414141) {
giveshell();
}
}
}
return 0;
}
Path Traversal
프로그래머가 가정한 디렉토리를 벗어나 외부에 존재하는 파일에 접근할 수 있는 취약점
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
// gcc -o path_traversal path_traversal.c
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main()
{
char path[256] = "/tmp/";
char file_buf[10240];
char filename[256] = {0,};
char cmd[256] = {0,};
int len;
FILE *fp;
printf("Filename: ");
fflush(stdout);
len = read(0, filename, sizeof(filename)-1);
filename[len-1] = '\0';
strncat(path, filename, sizeof(path)-1);
fp = fopen(path, "r");
if(!fp) {
return -1;
}
fread(file_buf, 1, sizeof(file_buf), fp);
printf("%s\n", file_buf);
fclose(fp);
return 0;
}
/ . 과 같은 상위 디렉토리로 이동하는 문자들에 대한 검증이 존재하지 않아 다른 파일을 읽을 수 있다.
Environment attack
1
2
3
4
5
6
7
8
9
10
11
// gcc -o environ1 environ1.c
#include <stdlib.h>
#include <unistd.h>
int main()
{
printf("Screen Cleaner\n");
system("clear");
return 0;
}
system에서 clear명령어를 실행해준다. /bin/sh 파일을 심볼릭 링크를 사용하여 clear 이름으로 링킹 하면 어떻게 될지 생각해보자
1
2
3
4
5
// gcc -o libc.so libc.c -fPIC -shared
#include <stdlib.h>
void read() {
execve("/bin/sh", 0, 0);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// gcc -o environ2 environ2.c
#include <unistd.h>
#include <stdio.h>
int main()
{
char buf[16];
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
write(1, "Data:", 5);
read(0, buf, sizeof(buf)-1);
write(1, "GOOD", 4);
return 0;
}
LD_PRELOAD로 직접 특정 공유라이브러리를 먼저들고와 링킹하는 방법이 있다 따라서 libc.so파일을 링킹해서 environ2.c파일의 read실행시에 직접만든 read를 실행시킬수있다.
Posted 2020-06-03