반응형

https://gun-ny.tistory.com/15

전에 scanf와 gets 함수의 버퍼 오버플로우 취약점에 대해 얘기한 적이 있었다.

 

나는 주로 Visual Studio Code(VS Code)를 쓰지만 Visual Studio IDE(VS IDE)를 쓰면 VS IDE에서 기본적으로 제공하는 scanf_s 함수로 scanf의 버퍼 오버플로우를 해결할 수 있다.

 

gets도 똑같은 취약점을 가지고 있고 gets_s 함수를 제공하길래 써봤는데 내가 못 쓰는 건지 해결이 안 된다.

그래서 scanf와 scanf_s 기준으로 글을 작성해 보려고 한다. (전에도 gets는 뒷전이었지만..)

 

전에 썼던 코드를 그대로 컴파일 해보았다.

응..? 그런데 컴파일 에러가 뜬다.

 

'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

 

번역하면

'scanf': 이 함수 또는 변수는 안전하지 않을 수 있습니다. 대신 scanf_s를 사용하는 것을 고려해 보십시오. 더 이상 사용하지 않도록 설정하려면 _CRT_SECURE_NO_WARNINGS를 사용하십시오. 자세한 내용은 온라인 도움말을 참조하십시오.

 

요약하면

scanf는 안전하지 않다.

scanf_s를 써라

그래도 쓸거면 _CRT_SECURE_NO_WARNINGS를 사용하라고 한다.

 

마이크로소프트에서는 scanf의 취약점을 인지하고 2010년대 초반부터 VS IDE에서 scanf를 사용하지 못하도록 하였다.

 

scanf_s? 쓰면 되지

C11 표준에 scanf_s가 수록되었다곤 하는데 10년이 지난 지금도 VS IDE의 컴파일러 cl 이외 컴파일러에서 scanf_s를 지원하지 않는 컴파일러들이 있다.

모두 다 VS IDE를 쓰면 상관이 없지만 개개인마다 다른 컴파일러를 쓰는 경우가 있어서 VS IDE에서 잘 컴파일 됐던 파일을 다른 팀원이 받아서 컴파일 했는데 안되는 경우가 생길 수 있다.

나 같은 경우도 GCC, G++ 컴파일러를 사용하는데 GCC 컴파일러를 사용하는 C 파일에서 작성된 scanf_s는 잘 컴파일 됐는데 G++ 컴파일러를 사용하는 CPP 파일에서 컴파일 하니 안된 기억이 있다.

이런 경우들 때문에 그들을 위해 scanf를 사용하는 일이 생긴다.

 

scanf 한번 써보자

경고 메시지에서는 _CRT_SECURE_NO_WARNINGS를 사용하라고 한다.

#define _CRT_SECURE_NO_WARNINGS

코드 상단에 복붙해주면 VS IDE에서도 scanf를 사용할 수 있다.

 

컴파일 되었다.

이왕 여기까지 온 거 VS IDE에서 디버깅도 한번 해보자

 

그때처럼 다른 str 메모리 영역을 침범해 덮어씌우지 않고 다른쪽 메모리를 손상시켜 VS IDE는 런타임 에러를 띄운다.

 

Run-Time Check Failure #2 - Stack around the variable 'str_1' was corrupted.

런타임 검사 실패 #2 - 변수 'str_1' 주변 스택이 손상되었습니다.

 

이번엔 scanf_s를 써보자

scanf_s("%s", str, sizeof(str) / sizeof(str[0]));

기존 scanf 인수에서 버퍼 사이즈를 추가로 지정해주면 된다.

 

디버깅을 해보면 입력 자체를 안 받은 걸 확인할 수 있다.

이렇게 입력 자체를 안 받아버리면 테스트 중 문제점을 발견하기도 쉽고 메모리 침범도 없어 디버깅이 쉬워지는데......

왜 printf("Hello World"); 마냥 킹표준이 되지 못하는 걸까 하는 생각이다.

반응형

+ Recent posts