엔티티 인증 없는 키 교환 (Insecure Host Key Verification)
Key Exchange without Entity Authentication
설명
이 취약점은 SSH 클라이언트가 서버의 host key(서버 공개키)를 검증하지 않고 그냥 신뢰할 때 발생합니다. Go에서 ssh.InsecureIgnoreHostKey() 를 사용하면, 클라이언트는 접속하는 서버가 진짜 서버인지 확인하지 않게 됩니다. 공격자는 네트워크 중간에서 위조된 SSH 서버를 띄우고 사용자의 트래픽을 가로채는 Man-in-the-Middle(MitM) 공격을 할 수 있습니다. 사용자는 정상 서버에 접속한다고 생각하지만, 실제로는 공격자 서버에 접속하게 되고, 자격 증명(계정/비밀번호, private key 사용 세션)과 전송되는 중요 데이터를 탈취할 수 있습니다.
잠재적 영향
중간자 공격(MitM, Man-in-the-Middle): 서버의 진위를 확인하지 않아 공격자가 가짜 SSH 서버로 트래픽을 가로채서 세션 내용을 엿보거나 변조할 수 있음
자격 증명 탈취: SSH 비밀번호, 토큰, 명령 실행 결과 등의 민감 정보가 공격자에게 노출될 수 있음
원격 명령 조작: 공격자가 클라이언트와 서버 사이의 명령 또는 응답을 바꿔, 의도치 않은 명령을 실행시키거나 잘못된 데이터를 보내도록 만들 수 있음
해결 방법
ssh.InsecureIgnoreHostKey()사용 금지: 절대 프로덕션 코드에서 사용하지 않습니다.known_hosts 기반 검증 사용:
golang.org/x/crypto/ssh/knownhosts패키지의knownhosts.New를 사용해 OpenSSH 형식의known_hosts파일로 서버 host key를 검증합니다.고정된(host pinned) 공개키 사용: 제한된 환경에서는
ssh.FixedHostKey()로 미리 신뢰한 서버 공개키만 허용하는 방식으로 검증합니다.키 관리 정책 수립:
known_hosts파일 또는 pinned key를 안전하게 배포·관리하고, 서버 키가 변경될 경우 운영 절차에 따라 안전하게 업데이트합니다.개발·테스트 환경에서도 검증 습관화: 테스트 편의를 이유로
InsecureIgnoreHostKey를 남겨두지 말고, 테스트용known_hosts또는 테스트용 고정 키를 사용합니다.
취약한 코드 및 안전한 코드 예시
취약한 코드
안전한 코드
설명:
취약한 코드:
HostKeyCallback: ssh.InsecureIgnoreHostKey()설정은 SSH 서버의 host key를 전혀 검증하지 않습니다. 따라서 공격자가 네트워크 중간에 가짜 SSH 서버를 띄워도 클라이언트는 이를 정상 서버로 믿고 접속합니다. 이 과정에서 비밀번호, 명령, 결과 값 등 민감 정보가 모두 공격자에게 노출될 수 있고, 세션이 완전히 장악될 수 있습니다.안전한 코드:
knownhosts.New를 이용해 OpenSSH 형식의known_hosts파일을 읽고,HostKeyCallback으로 설정함으로써 서버 host key가 신뢰된 값인지 자동 검증합니다. 서버 키가 다를 경우 SSH 연결이 실패하므로, 중간자 공격이나 가짜 서버에 대한 접속이 차단됩니다. 이렇게 서버의 엔티티(정체)를 인증함으로써 키 교환과 통신 채널의 기밀성과 무결성을 보호할 수 있습니다.
참조
Last updated