1. 초기화되지 않은 변수 사용의 위험성
CWE-457은 변수를 선언만 하고 적절한 초기값을 할당하지 않은 채, 해당 변수를 읽거나 연산에 사용할 때 발생합니다.
-
보안 위협: 메모리 관리 방식에 따라 초기화되지 않은 변수에는 이전에 사용되었던 '쓰레기 값(Garbage Value)'이 남아있을 수 있습니다. 공격자가 메모리의 특정 영역을 조작할 수 있다면, 이 초기화되지 않은 변수를 통해 시스템의 실행 흐름을 바꾸거나 민감한 정보를 유출할 수 있습니다.
-
안정성 위협: 프로그램이 예측 불가능한 동작을 하거나, 런타임 에러가 발생하여 시스템 가용성에 영향을 줍니다.
2. 흔히 발생하는 취약한 패턴
주로 조건문이나 예외 처리 로직에서 모든 경로에 값이 할당되지 않을 때 발생합니다.
-
조건부 초기화:
if-else구문에서 특정 조건일 때만 변수를 초기화하고, 조건 밖에서 해당 변수를 참조하는 경우. -
예외 처리 시 누락:
try블록 안에서 변수를 초기화하려다 예외가 발생하여catch블록으로 넘어갔는데, 초기화되지 않은 상태의 변수를 계속 사용하는 경우. -
복잡한 루프: 루프 내부에서 처음으로 값이 할당되어야 하는데, 루프가 한 번도 실행되지 않은 상태에서 변수를 호출하는 경우.
3. 실무적 대응: 명시적 초기화와 컴파일러 활용
가장 단순하지만 확실한 방어법은 변수 선언과 동시에 의미 있는 기본값을 부여하는 것입니다.
-
선언 시 초기화: 변수를 선언할 때 항상 기본값(0, null, false 등)을 할당하는 습관을 들입니다.
-
컴파일러/정적 분석 도구 활용: Java와 같은 현대적 언어는 지역 변수가 초기화되지 않고 사용될 경우 컴파일 에러를 발생시켜 상당 부분 방어해 줍니다. 하지만 멤버 변수(필드)의 경우 기본값이 자동으로 할당되므로 로직상 의도한 값인지 확인이 필요합니다.
-
Final 키워드 사용: 값이 한 번 할당된 후 변하지 않는다면
final을 사용하여 초기화 여부를 컴파일 단계에서 강제합니다.
4. CWE-457 대응 및 안전한 변수 관리 자바 코드 예시
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class InitializationGuard {
private static final Logger logger = LoggerFactory.getLogger(InitializationGuard.class);
// [CWE-457 조치] 모든 경로에서 변수가 초기화되도록 보장
public void processDiscount(int userLevel) {
// 1. 선언 시 안전한 기본값으로 초기화
double discountRate = 0.0;
if (userLevel == 1) {
discountRate = 0.1;
} else if (userLevel == 2) {
discountRate = 0.2;
}
// else 구문이 없더라도 기본값 0.0이 할당되어 있어 안전함
logger.debug("Applying discount rate: {}", discountRate);
}
// [CWE-457 조치] 예외 상황에서도 변수 상태 보장
public void loadConfiguration() {
String configData = null; // 초기화
try {
configData = "SERVER_PORT=8080"; // 실제 데이터 로드 시도
// configData = fetchFromNetwork();
} catch (Exception e) {
logger.debug("Failed to load config, using default values.");
// catch 블록에서도 안전한 상태를 유지하거나 기본값 할당
configData = "DEFAULT_CONFIG";
}
// 초기화 여부를 명시적으로 확인 후 사용
if (configData != null) {
logger.debug("Config loaded: {}", configData);
}
}
}
코멘트: "자바는 컴파일러가 잡아주니까 괜찮아"라고 방심해서는 안 됩니다. 객체의 멤버 변수는 기본값으로 자동 초기화되지만, 그 기본값이 비즈니스 로직상 유효하지 않을 경우 심각한 논리 오류를 야기할 수 있습니다. logger.debug()를 통해 변수의 초기화 상태를 확인하되, 모든 코드 경로(Path)에서 변수가 의미 있는 값을 가지도록 설계하는 것이 시큐어 코딩의 정교함입니다.
댓글 달기