부제. atoi 함수의 정보보안상의 취약점과 그 원인.
문제
0보다 크거나 같고, 99보다 작거나 같은 정수가 주어질 때 다음과 같은 연산을 할 수 있다. 먼저 주어진 수가 10보다 작다면 앞에 0을 붙여 두 자리 수로 만들고, 각 자리의 숫자를 더한다. 그 다음, 주어진 수의 가장 오른쪽 자리 수와 앞에서 구한 합의 가장 오른쪽 자리 수를 이어 붙이면 새로운 수를 만들 수 있다. 다음 예를 보자.
26부터 시작한다. 2+6 = 8이다. 새로운 수는 68이다. 6+8 = 14이다. 새로운 수는 84이다. 8+4 = 12이다. 새로운 수는 42이다. 4+2 = 6이다. 새로운 수는 26이다.
위의 예는 4번만에 원래 수로 돌아올 수 있다. 따라서 26의 사이클의 길이는 4이다.
N이 주어졌을 때, N의 사이클의 길이를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N이 주어진다. N은 0보다 크거나 같고, 99보다 작거나 같은 정수이다.
출력
첫째 줄에 N의 사이클 길이를 출력한다.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(){
char a[3];
scanf("%s",a);
int temp;
int first = atoi(a);
int cnt = 0 ;
char one[2],two[2],min[2];
int tree,re;
if(first < 10){
one[0] = '0';
one[1] = '\0';
two[0] = a[0];
two[1] = '\0';
}
else{
one[0] = a[0];
one[1] = '\0';
two[0] = a[1];
two[1] = '\0';
}
while(1){
temp = atoi(two); // 앞으로 갈 녀석. // 6
//printf("%d\n",temp);
tree = (atoi(one) + atoi(two)) % 10; // 8
//printf("%d\n",tree);
re = temp*10+tree;
//printf("%d\n",re);
cnt++;
if(first == re)
break;
if(re < 10){
a[0] = '0';
sprintf(min,"%d",re);
a[1] = min[0];
}
else
sprintf(a,"%d",re);
one[0] = a[0];
one[1] = '\0';
two[0] = a[1];
two[1] = '\0';
}
printf("%d",cnt);
return 0;
}
문제가 간단할 줄 알았는데, 코드가 굉장히 길다.
문자열을 숫자로 변경하고 그 문자열을 숫자로 여러번 변경해가면서 사이클을 찾아내야 이 문제를 풀 수 있다.
코드를 유심히 보니 오랜만에 보는 atoi() 함수를 발견하였다.
atoi() 함수는 문자 스트링의 값을 정수형의 값으로 변환해주는 역할을 수행합니다.
입력 Sttring은 지정된 리턴 유형의 숫자 값으로 해석될 수 있는 일련의 문자를 의미합니다.
함수는 수의 일부로 인지할 수 없는 첫번째 문자에서 입력 스트링 읽기를 중지하고, 이 문자는 스트링을 종료하는 널 문자일 수도 있습니다. 최근 atoi() 함수는 거의 없어진 코드라고 할 수 있겠는데요
이유는 보안상의 문제때문입니다.
저희가 흔히 사용하는 정수는 -2,147,483,648~2,147,483,647 의 범위를 갖는데요
atoi에 그보다 큰 수를 넣으면 0 또는 음수로 인식해서 계산상에 장애를 만들어 낸다고 합니다.
이러한 경우 어떤 문제가 되냐면 여러분의 계좌를 0 원으로 만들어 버릴 수 있는 무시무시한 녀석인 것 입니다.
예를 들어 가상 화폐 자산에 정수형의 범위 값을 넘어서는 값을 임의로 집어넣게 되면 여러분의 코인이 0원이 되는 것입니다!
그렇기때문에 정보 보안, 특히 경제분야에서 문제가 될 것을 우려해 거의 사용하지 않습니다. 사용하는 분야는 대부분 공부용, 혹은 정보보안 대표 취약 코드 수준으로 이해하시면 될 것 같습니다! 이상입니다!