1. 부적절한 전자서명 확인의 위험성
전자서명은 데이터의 발신자가 누구인지 증명(인증)하고, 데이터가 전송 과정에서 수정되지 않았음(무결성)을 보장하기 위해 사용됩니다. CWE-347은 시스템이 전자서명을 확인하는 과정에서 검증 결과값을 무시하거나, 잘못된 키로 검증하거나, 혹은 서명 유무 자체를 확인하지 않고 데이터를 신뢰할 때 발생합니다. 공격자는 서명을 위조하거나 제거하여 변조된 데이터를 보낼 수 있으며, 시스템은 이를 정상적인 데이터로 판단하여 처리하게 됩니다. 이는 소프트웨어 업데이트 위조, 잘못된 라이선스 활성화, 결제 정보 변조 등으로 이어질 수 있습니다.
2. 흔히 발생하는 취약한 패턴
주로 외부 라이브러리나 API를 연동할 때 검증 단계를 생략하거나 로직을 오해하여 발생합니다.
• 검증 결과값 무시: 서명 확인 함수(verify())를 호출만 하고, 반환된 boolean 결과값이 false임에도 다음 로직을 진행하는 경우.
• 잘못된 공개키 사용: 서명을 검증할 때 신뢰할 수 있는 루트 인증서나 공개키가 아닌, 공격자가 전달한 가짜 공개키를 사용하여 검증하는 경우.
• 서명 누락 허용: 서명이 있는 경우에만 검증하고, 서명이 아예 없는 데이터에 대해서는 검증 없이 신뢰하는 경우.
• 알고리즘 강도 약화: 취약한 해시 알고리즘(MD5, SHA-1)을 기반으로 한 서명을 수용하는 경우.
3. 실무적 대응: 철저한 결과 검증과 신뢰 체계 구축
데이터를 처리하기 전, 서명의 유효성을 명시적으로 확인하는 단계가 반드시 선행되어야 합니다.
• 반환값의 엄격한 확인: Signature.verify() 메서드의 결과가 반드시 true일 때만 후속 로직을 수행하도록 조건문을 구성합니다.
• 신뢰된 키 저장소(Truststore) 활용: 검증에 사용하는 공개키는 외부에서 입력받지 않고, 서버 내부의 안전한 키 저장소에 보관된 것을 사용합니다.
• 서명 의무화: 서명이 없는 데이터는 비정상적인 데이터로 간주하여 즉시 거부(Fail-safe)합니다.
• 표준 라이브러리 준수: Java의 java.security.Signature 클래스 등을 활용하여 표준화된 방식으로 구현합니다.
4. CWE-347 대응 및 안전한 전자서명 검증 자바 코드 예시
코멘트: 전자서명 코드를 작성했다는 것만으로는 충분하지 않습니다. "검증을 시도했는가"가 아니라 "검증에 성공했는가"를 확인하는 것이 시큐어 코딩의 핵심입니다. 특히 하위 호환성을 이유로 서명이 없는 데이터를 허용하는 사각지대를 조심하십시오. logger.debug()를 통해 검증 실패 내역을 기록하되, 공격자가 변조한 데이터가 우리 시스템의 논리 흐름에 단 한 발자국도 들여놓지 못하도록 빗장을 걸어 잠그는 습관이 필요합니다.
댓글 달기