[하루한줄] CVE-2026-107181 : Telegram Desktop의 IPC Injection으로 인한 1-Click ATO
URL
Target
- Telegram Desktop ≤ 7.2.8
Explain
CVE-2026-107181은 Telegram Desktop에서 IPC를 처리하는 과정 중 발생하는 취약점으로 복수의 내부 결함을 통해 최종적으로 1-Click Account Takeover가 가능한 버그입니다.
background
OS는 애플리케이션이 URI scheme을 등록하고 이를 통해 실행하거나 특정 동작을 구현하는 것을 허용합니다. Telegram Desktop의 경우 tg://... 형식을 사용하며 애플리케이션 실행 뿐만 아니라 인자를 전달하는 것도 가능합니다.
만약, Telegram이 실행 중이 아니라면 프로세스를 생성하고 전달된 문자열을 내부적으로 처리합니다. 반대로 이미 실행 중인 프로세스가 존재해도 운영체제는 이를 직접적으로 검증하지 않고 신규 요청으로 처리하기 때문에 중복 실행을 방지하기 위해서는 로컬 소켓에 연결을 시도하는 식의 확인이 필요합니다.
소켓 간의 통신은 객체 대신 bytes를 전달합니다. 따라서 직렬화/역직렬화와 같은 과정을 통해 송수신 데이터의 변환이 필수적입니다. 예를 들어, tg://x?a=1 URI를 클릭하는 경우 Telegram 내부에서 다음과 같은 처리가 이루어집니다:
// sandbox.cpp:295-297
for (const auto &url : cRefStartUrls()) {
commands += u"OPEN:"_q + url.toString(QUrl::FullyEncoded) + ';';
}
반대로, 직렬화된 데이터를 전달받은 프로세스는 이를 다시 객체로 변환하기 위해 역직렬화 과정을 거칩니다.
// sandbox.cpp:453-463 (abbreviated)
for (int32 to = cmds.indexOf(QChar(';'), from); to >= from; ...) {
auto cmd = base::StringViewMid(cmds, from, to - from);
...
} else if (cmd.startsWith(u"OPEN:"_q)) {
startUrls.append(cmds.mid(from + 5, to - from - 5).mid(0, 8192));
root cause
직렬화 과정을 살펴보면 변환된 데이터 마지막에 ;문자를 추가하는 것을 알 수 있습니다. 또한 역직렬화 시에는 cmds.indexOf(QChar(';')을 통해 ; 문자를 기준으로 하나의 명령으로 구분하는 것을 알 수 있습니다.
즉, 공격자가 임의로 ; 문자를 추가하여 복수의 명령을 처리하는 것 또한 가능합니다.
tg://x?a=1;CMD:quit;
위 예시는 기존 예시에 ;CMD:quit;이 추가된 것으로 내부에서 처리되는 결과는 다음과 같습니다:
OPEN:tg://x?a=1
CMD:quit
CMD:quit 명령은 프로세스를 종료하는 명령을 내리는 것으로 사용자가 해당 링크를 클릭하면 강제로 애플리케이션이 종료됩니다.
exploit
CMD: 명령은 show와 quit만 지원하므로 실질적인 공격에 활용하기 어렵습니다. 그러나 OPEN:은 별도의 URI scheme 검증 없이 전달된 URL을 처리하기 때문에, IPC Injection을 통해 내부 전용 interpret: scheme에 접근하는 것이 가능했습니다.
interpret:는 신규 버전의 빌드 파일과 변경 내역을 Telegram 채널에 게시하기 위한 자동화 기능입니다. 내부적으로 InterpretSendPath()를 호출하여 instruction 파일에 명시된 channel:과 file:을 기반으로 로컬 파일을 전송합니다. 아래는 예시 파일입니다:
from: 1234567890
channel: 1987654321
file: out/Release/deploy/6.9.3/tsetup.6.9.3.exe
caption: TDesktop at 12.06.26:
- Fixed a crash in the media viewer.
- Added a new sticker pack.
문제는 해당 기능이 파일 전송에 대한 사용자 확인이나 적절한 인가 검증 없이 실행된다는 점입니다. from:을 통한 사용자 ID 비교 또한 값을 생략하는 경우 수행되지 않았기 때문에 우회가 가능했습니다.
공격자는 다음과 같은 방식으로 이를 파일 유출에 연계할 수 있었습니다.
- Instruction 파일 배치
- Telegram Desktop은 별도의 설정을 하지 않았을 경우 그룹에 수신된 8 MiB 이하의 파일을 자동 다운로드합니다.
- 이를 통해 피해자가 그룹을 열었을 때 공격자가 작성한 Instruction 파일을 로컬 디스크에 저장하도록 유도할 수 있습니다.
- 파일 경로 예측
- 파일이 저장되는 다운로드 경로는
C:\Users\<username>\Downloads\Telegram Desktop\<filename>로 지정되어 있습니다. interpret:는../문자를 통한 상대경로를 허용하기 때문에 현재 Telegram Desktop이 설치된 위치로부터 절대경로 없이 Instruction 파일의 위치에 도달할 수 있었습니다.
- 파일이 저장되는 다운로드 경로는
- IPC Injection 트리거
tg://링크를 Telegram 메시지로 전달하는 경우 이는 IPC를 통해 처리되지 않습니다.- 따라서 공격자는 외부 링크를 전달하여 외부 브라우저로 유도한 뒤, 실제 익스플로잇을 트리거했습니다.
- 로컬 파일 유출
- 삽입된
OPEN:명령이interpret:를 호출하면 Instruction 파일에 지정된 로컬 파일이 공격자가 제어하는 그룹으로 전송됩니다. - 여러 Instruction 파일과
OPEN:명령을 조합하면 복수의 파일을 전송할 수도 있습니다.
- 삽입된
최종적으로 원문 PoC는 Telegram의 로컬 세션 데이터인 tdata 관련 파일을 유출하고, 이를 이용해 기존 인증 세션을 복원함으로써 Account Takeover가 가능함을 보였습니다. 다만 해당 시나리오는 로컬 암호가 설정되지 않은 환경을 전제로 합니다.
mitigation
Telegram Desktop은 v7.2.9에서 IPC 메시지의 직렬화 및 역직렬화 로직을 수정하고, 파일 유출에 악용된 내부 기능을 제거하여 취약점을 해결하였습니다.
기존에는 URI를 IPC 메시지로 변환하는 과정에서 레코드 구분자인 ; 문자가 별도로 이스케이프되지 않아 하나의 URI를 복수의 명령으로 처리할 수 있었습니다. 패치에서는 EscapeTo7bit()와 EscapeFrom7bit() 함수를 추가하여 IPC 메시지에 포함된 구분자를 안전하게 인코딩하고 복원하도록 변경하였습니다.
또한 공격에 활용된 interpret: scheme과 관련 파일 전송 처리 로직을 제거하였습니다. 추가적으로 동일한 IPC 요청에 OPEN: 명령과 CMD: 또는 CTRL: 명령이 혼합된 경우 후자의 처리를 제한하고, 외부 URL과 로컬 파일 경로가 함께 전달되는 경우 로컬 파일 경로를 무시하도록 변경하였습니다.
이를 통해 IPC Record Injection의 근본 원인을 해결하는 동시에, 비정상적인 명령 조합을 통한 내부 기능 접근을 제한하였습니다.
Reference
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.