누군가 당신을 텔레그램 그룹에 초대한다. 채팅에 링크 하나가 올라온다. 무심코 클릭하는 순간, 당신의 텔레그램 계정은 더 이상 당신만의 것이 아니게 된다. 보안 연구자 Beak Sec이 공개한 텔레그램 데스크톱(Telegram Desktop) 취약점은 이처럼 단 한 번의 클릭으로 디스크의 임의 파일을 공격자에게 전송하게 만든다. 로그인 세션 파일까지 포함해서다. 문제의 핵심은 화려한 메모리 익스플로잇이 아니라, 두 개의 평범한 설계 결함이 맞물린 데 있다.
하나의 링크가 여러 명령으로 쪼개지는 이유
텔레그램 데스크톱은 단일 인스턴스로 동작한다. 운영체제는 tg:// 링크를 텔레그램에 속한 것으로 인식해 새 프로세스를 띄우지만, 이미 실행 중인 텔레그램이 있으면 새 프로세스는 로컬 소켓으로 기존 인스턴스에 접속해 링크를 넘기고 스스로 종료한다. 이때 메모리 속 URL 객체는 소켓을 건널 수 없으므로 텍스트 한 줄로 직렬화(serialization)된다. 텔레그램은 자체 포맷을 쓰는데, 각 명령은 키워드와 인자, 그리고 이를 닫는 세미콜론으로 구성된다. 받는 쪽은 이 바이트를 세미콜론마다 잘라 각 조각을 독립된 명령으로 해석한다.
바로 여기서 첫 번째 결함이 드러난다. 전달되는 값 안에 세미콜론이 들어 있어도 텔레그램은 이를 이스케이프하지 않는다. 그래서 공격자가 쿼리 문자열 안에 세미콜론을 심은 링크를 만들면, 보내는 프로세스는 이를 '하나의 URL'로 취급해 그대로 소켓에 쓰지만, 받는 인스턴스는 그 세미콜론에서 문장을 잘라 '두 개의 명령'으로 읽어낸다. 전형적인 명령 주입(injection)이다. 받아들여지는 명령은 모두 네 가지인데 셋은 사실상 무해하다. 문제는 네 번째인 OPEN:으로, 어떤 스킴(scheme)의 URL이든 필터 없이 받아들인다는 점이다.
interpret: 스킴과 빠진 권한 검사
두 번째 결함은 주입된 명령이 닿는 대상에 있다. 텔레그램 내부에는 interpret:라는 자체 URI 스킴이 존재한다. 운영체제는 이 스킴을 알지 못하지만 텔레그램 코드는 시작 URL 목록에서 이를 집어 처리한다. 원래 이 기능은 텔레그램이 새 버전을 배포할 때, 보낼 채널과 파일 경로, 설명 텍스트를 적은 텍스트 파일을 스크립트가 만들어 자동으로 채널에 올리기 위한 사내 도구였다. 명령줄에서만 호출되는 한, 이미 기기에 발판을 확보한 공격자라야 악용할 수 있으니 위협이 아니었다.
그러나 interpret:는 지정된 파일을 읽어 채팅방으로 전송하는 특권 동작을 수행하면서도, 누가 요청했는지 확인하지 않고 사용자 확인도 받지 않는다. 계정 검증에 쓰이는 from: 줄은 아예 생략하면 검사 자체가 건너뛰어진다. 이 동작이 소켓을 통해, 그리고 주입을 통해 도달 가능해지는 순간, 명령줄 전용이던 위험한 기능이 피해자가 클릭하는 링크 하나로 열린다. 빠진 권한 검사가 주입과 결합해 '임의 파일 읽기'라는 공격 원시 동작(primitive)을 완성하는 것이다.
예측 가능한 경로와 세션 탈취
남은 과제는 피해자 디스크의 예측 가능한 위치에 지시 파일을 심는 일이다. 텔레그램 데스크톱은 기본 설정에서 그룹으로 받은 8MiB 이하 파일을 자동으로 내려받는다. 파일은 보낸 사람이 정한 이름 그대로 표준 폴더에 저장되므로 경로를 특정할 수 있다. 남는 변수는 윈도 사용자 이름뿐인데, interpret:는 상대 경로도 받아들이고 이 경로는 텔레그램 데이터 폴더를 기준으로 해석되므로 사용자 이름 없이도 결정적 경로를 구성할 수 있다. 호출 한 번당 한 파일만 전송되지만, 지시 파일을 여러 개 올리고 세미콜론마다 명령을 쌓으면 여러 파일을 한꺼번에 노릴 수 있다.
훔칠 가치가 있는 것은 SSH 개인키, 브라우저 비밀번호 저장소, 클라우드 자격 증명, API 토큰 등 무엇이든 된다. 특히 텔레그램 자신의 세션 인증 파일이 위험하다. 로컬 데이터는 암호화되어 있지만, 데이터를 암호화하는 DEK는 다시 KEK로 감싸지며(key wrapping) KEK는 비밀번호에서 KDF로 파생된다. 그런데 텔레그램 데스크톱은 기본적으로 로컬 패스코드가 없다. 패스코드가 없으면 빈 문자열과 평문으로 저장된 솔트만으로 KEK를 재계산할 수 있어, 해당 파일만 읽으면 DEK가, 그와 함께 세션 인증까지 모두 복호화된다. 관련 폴더 이름은 기본 데이터 이름에서 파생되어 모든 설치본에서 동일하다. 결국 세 개의 파일을 새 데이터 폴더에 넣고 텔레그램을 실행하면 피해자의 세션이 그대로 열린다.
실무자가 기억할 점
공격은 텔레그램 바깥에서 온 클릭 한 번을 필요로 한다. 채팅 안에서 클릭한 tg:// 링크는 프로세스 내부에서 처리되어 소켓에 닿지 않기 때문에, 공격자는 평범한 https 링크를 보낸 뒤 자신의 서버에서 조작된 tg:// 링크로 리다이렉트한다. 브라우저와 이전 사용 이력에 따라 실행 전 확인 창이 뜰 수 있다는 점이 완전한 무음 공격을 일부 제약하지만, 자동 다운로드·기본 그룹 초대 허용·패스코드 미설정이라는 기본값들이 겹치면 경로는 상당히 매끄럽게 이어진다.
근본 해결책은 7.2.9 이상으로 업그레이드하는 것뿐이고 나머지는 노출을 줄일 뿐이다. 그래도 실무 관점에서 의미 있는 완화책은 분명하다. '파일마다 저장 위치 묻기'를 켜면 자동 다운로드가 일어나지 않아 지시 파일이 애초에 디스크에 안착하지 못한다. 그룹 초대를 연락처로 제한하면 훔친 파일을 전달받을 채널·슈퍼그룹을 공격자가 마련하기 어려워진다. 로컬 패스코드를 실제 비밀번호 수준으로 설정하면 파일 유출 자체는 막지 못해도 탈취된 세션을 쓸모없게 만든다. 이 사례가 주는 교훈은 단순하다. 신뢰 경계를 넘는 직렬화와 역직렬화 지점은 구분자가 구조가 아니라 문자가 되는 자리이며, 특권 동작에 권한 검사가 빠져 있으면 '명령줄에서만 쓰이니 안전하다'는 가정은 통신 채널이 하나 열리는 순간 무너진다는 것이다.