66. Telnet과 평문 프로토콜의 위험

changseop lee·5일 전

📚 네트워크 · 패킷 분석 › 02. 포트 · 프로토콜 분석 — 66편
이전 글: 65. SSH · 다음 글: 67. SMTP
참고(리눅스 시스템 기초): SSH 구조 이해 — Telnet을 대체하는 암호화 원격 접속

1. 왜 알아야 하는가

Telnet은 오래된 원격 접속 프로토콜이지만 아직도 관제에서 자주 등장합니다.

  • 오래된 네트워크 장비·산업용 장비·프린터가 관리용으로 Telnet을 기본 활성화해 둔 경우가 있습니다.
  • IoT 기기의 기본 계정을 노리는 악성코드가 23번(및 2323번) 포트를 대량 스캔한 사례가 널리 알려져 있습니다(Mirai 계열).
  • 무엇보다 Telnet은 아이디·비밀번호·입력 명령이 모두 평문입니다. 같은 경로에서 패킷을 볼 수 있는 누구든 내용을 읽을 수 있습니다.

이 글의 목표는 "Telnet은 위험하다"를 외우는 것이 아니라, 직접 캡처해서 평문이 어떻게 보이는지 확인하고, 같은 문제를 가진 다른 평문 프로토콜까지 한 번에 정리하는 것입니다.


2. 핵심 개념

Telnet과 SSH 비교
그림 1. 같은 원격 접속이라도 평문 프로토콜은 도청 시 모든 내용이 드러납니다

2-1. Telnet 기본 정보

항목내용
포트TCP 23
암호화없음 (인증 정보·명령·출력 모두 평문)
인증서버의 login 프로그램이 계정/비밀번호를 받음 (시스템 PAM 사용)
전송 단위구현·모드에 따라 한 글자씩 전송되는 경우가 많음
제어 방식IAC(0xFF)로 시작하는 옵션 협상(DO / DON'T / WILL / WON'T)
대체SSH (TCP 22)

2-2. 옵션 협상(Negotiation)

Telnet 연결 직후에는 사람이 입력한 데이터가 아니라 양쪽 터미널 설정을 맞추는 제어 명령이 먼저 오갑니다. 예를 들어 "에코는 서버가 하겠다(WILL ECHO)", "터미널 종류를 알려 달라(DO TERMINAL-TYPE)" 같은 내용입니다. 캡처 초반에 보이는 알아보기 힘든 바이트들이 이것입니다. 필드 단위 해석은 (03 Wireshark 시리즈에서 다룸)

2-3. 평문 프로토콜과 대체 프로토콜

Telnet만의 문제가 아닙니다. 아래 프로토콜은 기본 형태로는 암호화가 없습니다.

평문 프로토콜포트노출되는 것암호화 대체
TelnetTCP 23계정·비밀번호·명령SSH (22)
FTPTCP 21 (+데이터 포트)계정·비밀번호·파일 내용SFTP(22), FTPS(21 명시적 / 990 암묵적)
HTTPTCP 80쿠키·폼 입력·Basic 인증HTTPS (443)
SMTPTCP 25메일 본문(STARTTLS 미사용 시)STARTTLS, 587(제출) / 465
POP3TCP 110계정·비밀번호·메일POP3S (995)
IMAPTCP 143계정·비밀번호·메일IMAPS (993)
SNMP v1/v2cUDP 161Community 문자열·장비 정보SNMPv3 (authPriv)
LDAPTCP 389Simple Bind 비밀번호LDAPS (636), StartTLS
rlogin / rshTCP 513 / 514명령, 호스트 기반 신뢰SSH

FTP, 메일, SNMP는 이어지는 12·13·16편에서 각각 다룹니다.


3. 동작 원리

3-1. Telnet 세션 흐름

 클라이언트 (192.168.10.20:51514)                 서버 (192.168.10.10:23)
      │                                                  │
      │── SYN / SYN-ACK / ACK (3-Way Handshake) ─────────│
      │                                                  │
      │←─ IAC DO TERMINAL-TYPE, IAC WILL ECHO ... ───────│  옵션 협상
      │── IAC WILL TERMINAL-TYPE ... ───────────────────→│
      │                                                  │
      │←─ "login: " ─────────────────────────────────────│
      │── "t" → "e" → "s" → "t" ... (한 글자씩) ────────→│  ← 평문
      │←─ "t" → "e" → "s" → "t" (서버 에코) ──────────────│
      │←─ "Password: " ──────────────────────────────────│
      │── "P" → "a" → "s" → "s" ... ───────────────────→│  ← 비밀번호도 평문 (에코만 없음)
      │                                                  │
      │←─ 셸 프롬프트 ───────────────────────────────────│
      │── "i" "d" "\r\n" ──────────────────────────────→│  ← 명령 평문
      │←─ "uid=1001(testuser) ..." ──────────────────────│  ← 결과 평문
      ↓
 경로상의 누구나(미러 포트, 감염된 중간 장비, 같은 무선망) 읽을 수 있음

비밀번호 입력 시 화면에 글자가 안 보이는 것은 서버가 에코를 보내지 않을 뿐이고, 클라이언트 → 서버 방향으로는 그대로 전송됩니다. "화면에 안 보인다 = 암호화되었다"가 아닙니다.

3-2. SSH와의 차이

구분TelnetSSH
연결 직후옵션 협상 후 바로 로그인 프롬프트버전 문자열 교환 → 키 교환 → 암호화 채널
서버 신원 확인없음호스트 키 지문 확인
캡처 시 보이는 것계정·비밀번호·명령·출력 전부버전 문자열(SSH-2.0-...) 이후 암호문
인증 방식비밀번호비밀번호, 공개키 등

SSH의 인증·설정 보안은 기존 글에서 정리했습니다: 12. SSH 인증 방식, 13. SSH 보안 설정


4. 실제 명령어 / 실습

실습 환경: 본인 소유 Linux VM (Rocky Linux 또는 Ubuntu), 인터페이스는 ens33을 예시로 사용합니다. 평문 노출 위험이 있으므로 루프백(127.0.0.1)에서만 접속하고, 실습 전용 테스트 계정을 쓰며, 실습 후 Telnet 서버를 반드시 제거합니다.

4-1. 테스트 계정과 Telnet 서버 준비

# 실습 전용 계정 (실제 쓰는 비밀번호와 다른 값 사용)
sudo useradd -m testuser
sudo passwd testuser
# Rocky Linux: telnet 서버는 systemd 소켓 활성화 방식
sudo dnf install -y telnet-server telnet
sudo systemctl start telnet.socket
# Ubuntu: inetd 방식으로 동작 (버전에 따라 telnetd 또는 inetutils-telnetd 패키지)
sudo apt install -y telnetd telnet
# 23번 포트 대기 확인
sudo ss -tlnp | grep ':23 '

방화벽은 열지 않습니다. 루프백 접속만 하므로 외부에 노출할 필요가 없습니다.

4-2. 평문 캡처

# 터미널 1: 루프백의 23번 포트를 ASCII로 출력
sudo tcpdump -i lo -nn -A 'tcp port 23'
# 터미널 2: 로컬 접속 후 testuser로 로그인, id 명령 실행 후 exit
telnet 127.0.0.1

📷 [실습 화면 삽입] tcpdump -A 출력에서 login:, 입력한 계정 문자, Password: 이후 비밀번호 글자가 한 글자씩 보이는 부분 (비밀번호 부분은 캡처 이미지에서 가림 처리)

4-3. 인증 로그 확인

# Rocky
sudo tail -n 20 /var/log/secure
# Ubuntu
sudo tail -n 20 /var/log/auth.log

4-4. 실습 정리 (필수)

# Rocky
sudo systemctl stop telnet.socket
sudo dnf remove -y telnet-server

# Ubuntu (버전에 맞는 패키지명 사용)
sudo apt remove --purge -y telnetd

# 23번 포트가 사라졌는지 확인
sudo ss -tlnp | grep ':23 ' || echo "23/tcp not listening"

# 테스트 계정 제거
sudo userdel -r testuser

📷 [실습 화면 삽입] 정리 후 ss -tlnp에서 23번 포트가 없는 화면


5. 결과 확인

tcpdump -A 출력 (형식 예시(값은 환경마다 다름))

10:30:01.201 IP 127.0.0.1.23 > 127.0.0.1.51514: Flags [P.], ... length 7
E..;..@.@.............login:
10:30:03.410 IP 127.0.0.1.51514 > 127.0.0.1.23: Flags [P.], ... length 1
E..5..@.@.............t
10:30:03.411 IP 127.0.0.1.23 > 127.0.0.1.51514: Flags [P.], ... length 1
E..5..@.@.............t
...
10:30:05.020 IP 127.0.0.1.23 > 127.0.0.1.51514: Flags [P.], ... length 10
E..>..@.@.............Password:
10:30:06.115 IP 127.0.0.1.51514 > 127.0.0.1.23: Flags [P.], ... length 1
E..5..@.@.............P        ← 비밀번호 첫 글자 (서버 에코 없음)

인증 로그 (형식 예시(값은 환경마다 다름)) — PAM 서비스 이름(login, remote 등)은 배포판 설정에 따라 다릅니다.

login[5123]: pam_unix(remote:session): session opened for user testuser(uid=1001) by (uid=0)
login[5123]: LOGIN ON pts/1 BY testuser FROM localhost

점검 체크리스트

  • 실습 전용 테스트 계정을 사용했다
  • 접속을 루프백(127.0.0.1)으로만 했고 방화벽 포트를 열지 않았다
  • tcpdump에서 계정·비밀번호·명령 문자열이 평문으로 보이는 것을 확인했다
  • 비밀번호는 서버 에코가 없어도 클라이언트 → 서버 방향으로 전송됨을 확인했다
  • 인증 로그에 Telnet 로그인 기록이 남은 것을 확인했다
  • 실습 후 Telnet 서버 제거, 23번 포트 미사용, 테스트 계정 삭제를 확인했다

6. 패킷 / 로그 분석

6-1. 23번 포트 트래픽 판단 기준

관찰정상일 수 있는 경우의심해야 하는 경우
내부 → 네트워크 장비 23번레거시 장비 관리(개선 필요 대상)관리자 대역이 아닌 일반 PC에서 접속
외부 → 내부 23번거의 없음인터넷에서 직접 도달 = 노출 자체가 문제
짧은 연결 다수, 여러 목적지없음23/2323 포트 대량 접속 시도 = 스캔·감염 확산 징후 (05 스캔 시리즈에서 다룸)
로그인 실패 반복관리자 비밀번호 오입력기본 계정명(admin, root 등) 순차 시도
내부 서버가 외부 23번으로 접속거의 없음감염된 내부 단말이 외부를 스캔하는 중일 수 있음
서버에 23번 LISTEN정책상 허용된 예외(문서화 필요)관리자도 모르는 Telnet 서비스

6-2. 확인 명령

# 서버에 Telnet이 떠 있는지 (리슨 포트 점검)
sudo ss -tlnp | grep ':23 '

# 현재 23번 포트로 맺어진 연결
sudo ss -tnp state established '( sport = :23 or dport = :23 )'

# 캡처: 23번 포트 SYN만 (접속 시도 규모 파악)
sudo tcpdump -i ens33 -nn 'tcp port 23 and tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'

# 인증 실패 확인
sudo grep -i "fail" /var/log/secure      # Rocky
sudo grep -i "fail" /var/log/auth.log    # Ubuntu

리슨 포트 점검 방법은 37. Listening Port 보안 점검에서 자세히 다뤘습니다.


7. 보안관제 관점

흔적이 남는 곳

위치남는 정보
방화벽23번 포트 허용/차단 세션 로그, 출발지 국가·IP
IDS/IPSTelnet 로그인 시도, 알려진 기본 계정 사용 시그니처 (06 방화벽·IDS 시리즈에서 다룸)
서버 인증 로그/var/log/secure, /var/log/auth.log의 login/PAM 기록
네트워크 장비 로그vty 접속 로그(장비가 syslog를 중앙으로 보낼 때)
패킷 캡처계정·명령·출력 전체 (평문이므로 사후 재구성 가능)

관제 시 핵심 포인트

  • Telnet 서비스의 존재 자체가 취약점입니다. 트래픽 분석보다 먼저 "누가 23번을 열어 두었는가"를 자산 점검으로 찾는 것이 효과적입니다.
  • 평문이라는 점은 양날의 검입니다. 공격자에게도 보이지만, 관제 입장에서도 캡처만 있으면 공격자가 입력한 명령을 그대로 재구성할 수 있습니다. 증거 확보 관점에서 pcap 보존이 의미가 있습니다(pcap 증거 보존은 03 Wireshark 시리즈에서 다룸).
  • Telnet 대량 접속 시도는 대부분 자동화된 인터넷 스캔입니다. 외부 → 23번 차단 로그 자체는 흔한 "소음"이므로, 허용(Accept)된 세션과 내부 → 외부 23번 발신에 더 무게를 둡니다.

한계와 오탐 주의

  • 포트 번호만으로 Telnet이라고 단정할 수 없습니다. 23번에서 다른 서비스가, 다른 포트에서 Telnet이 동작할 수 있습니다(02. 서비스와 포트 매핑).
  • 한 글자씩 전송되는 특성 때문에 IDS의 단순 문자열 매칭은 명령어를 놓칠 수 있습니다. 세션 재조립 기능이 필요합니다.
  • 반대로 "Telnet 클라이언트"는 포트 연결 테스트 용도로도 쓰입니다(telnet host 80). 23번이 아닌 포트로 telnet 명령을 쓴 흔적은 Telnet 프로토콜 사용과 다릅니다.

8. 핵심 정리

  • Telnet은 TCP 23을 쓰며 계정·비밀번호·명령·출력을 모두 평문으로 주고받습니다.
  • 비밀번호가 화면에 안 보이는 것은 서버 에코가 없을 뿐이며, 전송 자체는 평문입니다.
  • FTP·HTTP·POP3·IMAP·SNMPv1/v2c·LDAP 등도 기본 형태는 평문이므로, 각각 SSH·HTTPS·POP3S·IMAPS·SNMPv3·LDAPS 등으로 대체합니다.
  • 관제에서는 23번 LISTEN 서비스 존재, 외부에서의 허용 세션, 내부 → 외부 23번 발신을 우선 확인합니다.
  • 평문 캡처는 공격자 행위를 재구성하는 증거가 되지만, 포트만으로 프로토콜을 단정해서는 안 됩니다.

다음 글: 12. FTP Active·Passive 모드와 보안

profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글