본문 바로가기
소프트웨어(SW) 보안약점 진단원/구현단계 보안약점 제거 기준

구현단계 보안약점 기준 - 해제된 자원 사용

by 브루노W 2025. 6. 4.
유형 코드오류
보안약점 해제된 자원 사용
개요
C언어에서 동적 메모리 관리는 보안 취약점을 유발하는 대표적인 프로그램 결함의 원인이다.
 
해제한 메모리를 참조하게 되면 예상치 못한 값 또는 코드를 실행하게 되어 의도하지 않은 결과가 발생하게 된다.
보안대책
동적으로 할당된 메모리를 해제한 후 그 메모리를 참조하고 있던 포인터를 참조 추적이나 형 변환, 수식에서의 피연산자 등으로 사용하여 해제된 메모리에 접근하도록 해서는 안 된다.
 
또한, 메모리 해제 후, 포인터에 널(Null)값을 저장하거나 다른 적절한 값을 저장하면 의도하지 않은 코드의 실행을 막을 수 있다.
진단방법
소스코드 상에 메모리나 파일과 같은 자원을 사용하는 코드를 사용하는지 확인한다.
이때, 자원을 사용하는 코드의 앞에서 자원의 해제가 발생하면 취약하다고 판단하며, 자원의 해제 후 모든 경우의 제어 흐름이 자원을 사용하는 코드로 도달하지 않을 경우 안전하다고 판단한다.
 
또한 자원을 참조하는 포인터 변수에 연산 작업을 수행하는 경우 보다 정밀하게 올바른 값을 참조하는지 검사해야 하며, 사용이 완료된 포인터 변수의 초기화가 이루어지는지 확인한다.
연관된 설계단계 기준 -

 

코드예제

 

● 안전하지 않은 코드 예 (C)

int main(int argc, const char *argv[]) {
    char *temp;
    temp = (char *)malloc(BUFFER_SIZE);
    ……
    free(temp);
    // 해제한 자원을 사용하고 있어 의도하지 않은 결과가 발생하게 된다.
    stmcpy(temp, argv[1], BUFFER_SIZE-1);
}

 

● 안전한 코드 예 (C)

int main(int argc,const char *argv[]) {
    char *temp;
    temp = (char *)malloc(BUFFER_SIZE);
    ……
    // 할당된 자원을 최종적으로 사용하고 해제하여야 한다.
    stmcpy(temp,argv[1], BUFFER_SIZE-1);
    free(temp);
}

 

 

● 안전하지 않은 코드 예 (C)

char *data;
int data_type
if (data_type==val_1) { free(data); }
……
// 이미 해제된 자원을 이중 해제하여 문제가 발생한다.
if (data_type==val_2) { free(data); }

 

● 안전한 코드 예 (C)

char *data;
int data_type
if (data_type==val_1) {
    free(data);
    // 메모리를 해제한 후 항상 포인터에 NULL을 할당하여 이중 해제하더라도 무시되게 한다.
    data = NULL;
}
……
if (data_type==val_2) {
    free(data);
    // 메모리를 해제한 후 항상 포인터에 NULL을 할당하여 이중 해제하더라도 무시되게 한다.
    data = NULL;
}

 

 

진단방법
 
소스코드 상에 메모리나 파일과 같은 자원을 사용하는 코드를 사용하는지 확인한다.
이 때, 자원을 사용하는 코드의 앞에서 자원의 해제가 발생하면 취약하다고 판단하며, 자원의 해제 후 모든 경우의 제어 흐름이 자원을 사용하는 코드로 도달하지 않을 경우 안전하다고 판단한다.
 
또한 자원을 참조하는 포인터 변수에 연산 작업을 수행하는 경우 보다 정밀하게 올바른 값을 참조하는지 검사해야 하며, 사용이 완료된 포인터 변수의 초기화가 이루어지는지 확인한다.

 

 

● 정탐코드

#define FAIL 0
#define SUCCESS 1
#define ERROR -1
#define MAX_MESSAGE_SIZE 32
int processMessage(char **message) {
    int result = SUCCESS;
    int length = getMessageLength(message[0]);
    char *messageBody;
    if ((length > 0) && (length < MAX_MESSAGE_SIZE)) {
        messageBody = (char*)malloc(length*sizeof(char));
        messageBody = &message[1][0];
        int success = processMessageBody(messageBody);
        if (success == ERROR) {
            result = ERROR;
            free(messageBody);
    	}
    } else {
        printf("Unable to process message; invalid message length");
        result = FAIL;
    }
    if (result == ERROR) {
    	logError("Error processing message", messageBody);
    }
    return result;
}

실행되는 if문에서 messageBody에 할당된 메모리를 해지하였지만, 다시 해당 변수에 접근하고 있으므로, 보안약점이 존재하는 코드라고 판단한다. 또한 사용이 완료된 변수는 반드시 널(Null) 값으로 초기화해주도록 한다.