보안 공부/소스코드 보안약점 진단

소스코드 보안약점 진단 - 종료되지 않는 반복문 또는 재귀함수

H.J.World 2022. 1. 25. 10:10
728x90
반응형

소스코드 보안약점 진단 // 소프트웨어 보안약점 진단 // SW 보안약점 진단과 같이 다양한 이름으로 불리는 진단 과업 중 하나이다.

SW개발보안은 해킹 등 사이버공격의 원인인 보안약점을 SW개발단계에서 사전에 제거하고 SW 개발 생명주기의 각 단계별로 수행하는 일련의 보안활동을 통하여 안전한 SW를 개발·운영하기 위한 목적으로 적용하는 개발체계이다.

해당 내용은 KISA에서 발간하는 취약점 진단 가이드 항목을 기준으로 작성한다.

 

제 3절 보안기능

동시 또는 거의 동시 수행을 지원하는 병렬 시스템이나 하나 이상의 프로세스가 동작되는 환경에서 시간 및 상태를 부적절하게 관리하여 발생할 수 있는 보안약점이다.


2. 종료되지 않는 반복문 또는 재귀함수

가. 개요

재귀의 순환횟수를 제어하지 못하여 할당된 메모리나 프로그램 스택 등의 자원을 과다하게 사용하면 위험하다. 대부분의 경우, 귀납 조건(Base Case)이 없는 재귀함수는 무한 루프에 빠져 들게 되고 자원고갈을 유발함으로써 시스템의 정상적인 서비스를 제공할 수 없게 한다.

나. 보안대책

모든 재귀 호출시, 재귀 호출 횟수를 제한하거나, 초기값을 설정(상수)하여 재귀 호출을 제한해야 한다.

다. 코드예제

factorial 함수는 함수 내부에서 자신을 호출하는 재귀함수로, 재귀문을 빠져 나오는 조건을 정의하고 있지 않아 무한 재귀에 빠져 시스템 장애를 유발할 수 있다.

- 안전하지 않은 코드의 예 C -

1: #include <stdio.h>
2: int factorial(int i)
3: {
//재귀함수 탈출 조건을 설정하지 않아 무한루프가 된다.
4: return i * factorial(i - 1);
5: }
6: int main()
7: {
8: int num = 5;
9: int result = factorial(num);
10: printf("%d! : %d\n", num, result);
11: return 0;
12: }

 

- 안전한 코드의 예 C -

재귀 함수를 구현할 때는 아래와 같이 재귀문을 빠져 나오는 조건인 귀납조건(Base case)을 반드시 구현해야 한다.

1: #include <stdio.h>
2: int factorial(int I)
3: {
//재귀함수 사용시에는 아래와 같이 탈출 조건을 사용해야 한다.
4: if (i <= 1) {
5: return 1;
6: }
7: return i * factorial(i - 1);
8: }
9: int main()
10: {
11: int num = 5;
12: int result = factorial(num);
13: printf("%d! : %d\n", num, result);
14: return 0;
15: }

 

라. 진단방법

자신을 호출하는 재귀함수나 메소드가 존재하는지 식별하고, 해당 함수 내에 제어문을 통하여 해당 함수에서 리턴될 수 있는지 확인한다. 제어문을 통하여 재귀함수를 빠져나올 수 있으면 안전하다.

1: …
2: public int factorial(int n) {
3: return n * factorial(n - 1);---------------------①
4: }
5: …

 

- 정탐코드의 예 -

재귀함수는 함수내부에서 자신을 호출하는 경우이다. 함수명과 파라미터의 개수, 파라미터의 자료형 이 일치하는 경우 취약하다.

1: public class RecursiveCall {
2: private int a;
3:
4: public void func(int a) {
5: this.a = a;
6: }
7:
8: public void func(String a) {
9: func(a);
10: }
11: }

 

- 오탐코드의 예 -

다음의 예제와 같이 같은 이름에 파라미터가 다른 함수가 있는 경우는 취약하지 않다. 다음의 예제는 func(String a) 에서 func(int a)를 호출하고 있는데 recursive call 이 아닌 다른 함수의 호출이므로 안전하다.

1: public class RecursiveCall {
2: private int a
3:
4: public void func(int a) {
5: this.a = a;
6: }
7:
8: public void func(String a) {
9: func(Integer.parseInt(a));
10: }
11: }

 

728x90
반응형