1. DNS Lookup 의존 보안 결정의 위험성
CWE-247은 시스템이 접속자의 권한을 허용하거나 차단할 때, 신뢰할 수 없는 DNS(Domain Name System) 정보에 의존하여 보안 결정을 내릴 때 발생합니다. 예를 들어, 접속자의 IP를 역조회(Reverse DNS)하여 이름이 internal.company.com이면 관리자 권한을 부여하는 방식입니다.
문제는 DNS 정보가 공격자에 의해 조작될 수 있다는 점입니다. 공격자는 DNS 스푸핑(Spoofing)이나 포이즈닝(Poisoning)을 통해 자신의 IP를 신뢰할 수 있는 호스트 이름으로 위장할 수 있습니다. 결과적으로 공격자는 아무런 인증 절차 없이 내부망 시스템에 접근하거나 제한된 자원을 탈취할 수 있게 됩니다.
2. 흔히 발생하는 취약한 패턴: "호스트 이름 기반 필터링"
주로 인프라 설정이나 접근 제어 로직에서 편의성을 위해 호스트 이름을 사용할 때 나타납니다.
-
Reverse DNS 기반 인증:
request.getRemoteHost()를 호출하여 반환된 호스트 이름이 특정 도메인에 속하는지 확인하고 접속을 허용하는 경우. -
로그인 제한 우회: 특정 내부 도메인에서 오는 요청은 패스워드 없이 로그인을 허용하도록 설정한 경우.
-
화이트리스트 오류: 방화벽이나 애플리케이션 보안 설정에 IP 주소 대신 변조 가능한 호스트 이름을 등록해 둔 경우.
3. 실무적 대응: IP 기반 통제와 강력한 인증 도입
보안 결정은 변조가 어려운 정보를 바탕으로 이루어져야 합니다.
-
IP 주소 기반 화이트리스트: 호스트 이름 대신 변동이 적고 조작이 상대적으로 어려운 고정 IP 주소를 사용하여 접근을 제어합니다.
-
다중 요소 인증(MFA): 접속 위치나 이름과 상관없이 사용자 본인임을 증명할 수 있는 추가 인증(OTP, 인증서 등)을 요구합니다.
-
상호 TLS(mTLS) 사용: 클라이언트와 서버가 서로의 인증서를 확인하는 방식을 도입하여, 네트워크 이름이 아닌 디지털 인증서로 신원을 보장받습니다.
-
DNS 정보 재검증: 만약 호스트 이름을 꼭 써야 한다면, 역조회(IP -> Host)로 얻은 이름을 다시 정조회(Host -> IP)하여 원래의 IP와 일치하는지 교차 검증(Double Reverse DNS Lookup)을 수행합니다.
4. CWE-247 대응 및 안전한 접근 제어 자바 코드 예시
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import java.util.Set;
public class AccessControlManager {
private static final Logger logger = LoggerFactory.getLogger(AccessControlManager.class);
// 신뢰할 수 있는 내부 서버 IP 대역 (예시)
private static final Set<String> ALLOWED_IPS = Set.of("192.168.10.1", "192.168.10.2");
public boolean checkAccess(HttpServletRequest request) {
// [위험한 코드] DNS 역조회 정보에 의존 (CWE-247)
// String remoteHost = request.getRemoteHost();
// if (remoteHost.endsWith(".internal.trust.com")) return true;
// [CWE-247 조치] 조작이 어려운 원격 IP 주소를 직접 확인
String remoteIp = request.getRemoteAddr();
if (ALLOWED_IPS.contains(remoteIp)) {
logger.debug("Access granted for trusted IP: {}", remoteIp);
return true;
}
logger.debug("Security Event: Unauthorized access attempt from IP: {}", remoteIp);
return false;
}
}
코멘트: 네트워크 세상에서 '이름'은 언제든 바뀔 수 있는 가면과 같습니다. 보안의 문을 열어줄 때는 가면 뒤의 진짜 주소(IP)나 위조 불가능한 신분증(인증서)을 확인해야 합니다. logger.debug()를 통해 모든 접속 시도의 IP 주소를 기록하되, 단순한 호스트 이름만으로 "아는 사람"이라 판단하여 빗장을 열어주는 실수를 범하지 않는 것이 시큐어 코딩의 기본입니다.
댓글 달기