随着大型语言模型 (LLM) 变得越来越先进,并被开发人员赋予了更多功能,安全风险也急剧增加。被操纵的 LLM 不再只是违反道德政策的风险;它们已经成为一种威胁,可能有助于破坏它们所集成的系统。这些严重威胁最近已在各种应用程序中被发现,从称为 LlamaIndex的 LLM 数据框架到称为 Vanna.AI 的 SQL 代理,甚至LLM 集成框架 LangChain。
在本文中,我们将通过研究 LLM 远程代码执行 (RCE) 漏洞的结构来揭开这一风险的神秘面纱。我们首先了解大型语言模型能够执行代码的能力,然后深入研究我们发现的一个特定漏洞。
简介
给 LLM 一些文本,它可以喋喋不休一整天;教 LLM 运行代码,它可以无休止地解决问题。
虽然这很可能是当今大多数 AI 公司的想法,但从安全角度来看,这可能是一把双刃剑。攻击者可以利用功能强大的 LLM 来对付其开发人员。
顾名思义,LLM 只是一个大型语言模型。它从用户那里获取输入,然后逐个标记地输出文本,这些文本可以创建问题的答案、幻觉(有些人可能会说是胡说八道)甚至代码。我们如何将文本输出机器变成可以执行任务和运行代码的代理?事实是我们不能。我们必须使用传统软件形式的 LLM 外部组件,而不是像 LLM 本身这样的神经网络。由于我们知道LLM 几乎 100% 的时间都可以越狱- 并且我们知道它们没有自行执行代码的能力 - 那么问题就不是 LLM 本身是否容易受到攻击,而是 LLM 与其外部组件之间的集成是否容易受到攻击。
揭秘 LLM 代码执行
为了更好地理解 LLM 与外部世界之间的这种接口,让我们来研究一下LoLLMs中存在的简单集成。LoLLMs 是“LLM(大型语言模型)和多模态智能系统的中心。该项目旨在提供一个用户友好的界面,以访问和利用各种 LLM 和其他 AI 模型来完成各种任务”。为了达到我们的目的,我们使用了 OpenAI 与gpt-4-turbo-2024-04-09的集成。
我们将研究计算功能,该功能使 LLM 能够在需要时执行算术运算。一般来说,LLM 与某种外部组件之间的这种集成中的组件如下图所示。
让我们看看这些组件如何在下图所示的 LoLLM 计算功能中体现。
首先,我们有系统提示 (1)。系统提示是给 LLM 的指示,添加到每个会话中。它旨在指导 LLM 在本会话期间的回答行为、语气、风格和范围。系统提示还可以让 LLM 了解其可用的工具。在我们的例子中,它是算术计算函数。在以下来自系统提示的片段中,我们可以看到计算器的相关部分。
!@>system:
!@>Available functions:
...
Function: calculate
Description: Whenever you need to perform mathematic computations, you can call this function with the math expression and you will get the answer.
Parameters:
- expression (string):
...
Your objective is interact with the user and if you need to call a function, then use the available functions above and call them using the following json format inside a markdown tag:```function
{
"function_name":the name of the function to be called,
"function_parameters": a list of parameter values
}
``
!@>current_language:
english
!@>discussion_messages:
在系统提示符开始时,会告知 LLM 有可用的函数,后面跟着每个函数的描述。我们的计算函数列在其中,其描述让 LLM 知道它可以在需要执行数学计算时使用它。它被告知使用数学表达式字符串调用此函数。在提示符的末尾,会告知 LLM 其目标:与用户交互并在需要时使用简单的 JSON 格式调用约定调用任何函数。在这种情况下,它需要指定函数的名称及其参数。我们对 LLM 的期望是“理解”它可以使用哪些功能,并在看到复杂的数学表达式时将其输出格式化如下:
```function
{
"function_name": "calculate",
"function_parameters": {
"expression": "
"
}
}
、、、
到目前为止,我们已经介绍了这些组件:(1) 系统提示,教 LLM 如何使用积分,(2) 用户输入的数学表达式,以及 (3) LLM 必须使用的特定格式才能执行该函数。我们如何从简单的 LLM 输出到代码执行?这就是一些简单而经典的 Python 代码发挥作用的地方。
让我们从interactwithfunctioncall()开始跟踪调用堆栈,它调用使用用户输入执行 LLM 推理的函数generate withfunctioncalls()。此函数应返回 LLM 生成的文本,以及根据用户输入需要执行的函数调用数组(图 1 中的步骤 3)。为此,它调用 extractfunctioncallsasjson ()函数。
# https://github.com/ParisNeo/lollms/blob/ccf237faba17935efd1e8ecbbf12f494c837333b/lollms/personality.py#L3870-L3871
# Extract the function calls from the generated text.
function_calls = self.extract_function_calls_as_json(generated_text)
return generated_text, function_calls
负责提取函数调用的函数只是检测 LLM 输出的代码块,检查它们的格式是否与函数调用的格式完全一致,并提取函数名称和参数,如下所示:
# https://github.com/ParisNeo/lollms/blob/ccf237faba17935efd1e8ecbbf12f494c837333b/lollms/personality.py#L4049
function_calls = []
for block in code_blocks:
if block["type"]=="function" or block["type"]=="json" or block["type"]=="":
content = block.get("content", "")
try:
# Attempt to parse the JSON content of the code block.
function_call = json.loads(content)
if type(function_call)==dict:
function_calls.append(function_call)
elif type(function_call)==list:
function_calls+=function_call
except json.JSONDecodeError:
# If the content is not valid JSON, skip it.
continue
在提取包含函数名称及其参数的函数调用对象后,interactwithfunctioncall()使用executefunctioncalls()来执行它。对于指定函数名称的执行,executefunction_calls()在可用的函数定义(每个可用工具都有一个函数定义)中搜索该名称,然后简单地调用它:
# https://github.com/ParisNeo/lollms/blob/ccf237faba17935efd1e8ecbbf12f494c837333b/lollms/personality.py#L3930-L3931
fn = functions_dict.get(function_name)
if fn:
function = fn['function']
try:
# Assuming parameters is a dictionary that maps directly to the function's arguments.
if type(parameters)==list:
f_parameters ={k:v for k,v in zip([p['name'] for p in fn['function_parameters']],parameters)}
result = function(**f_parameters)
results.append(result)
elif type(parameters)==dict:
result = function(**parameters)
results.append(result)
组件(4)的最后一步是调用计算函数:
def calculate(expression: str) -> float:
try:
# Add the math module functions to the local namespace
allowed_names = {k: v for k, v in math.__dict__.items() if not k.startswith("__")}
# Evaluate the expression safely using the allowed names
result = eval(expression, {"__builtins__": None}, allowed_names)
return result
except Exception as e:
return str(e)
calculate只是采用 LLM 提供的数学表达式,并使用eval在某种 Python 沙箱中计算它。完成所有这些之后,LLM 将获得格式化的结果,并创建最终输出,该输出将在组件(5)中返回给用户。现在,我们对用户输入到代码执行以及返回的流程有了全面的了解。
从提示到任意代码执行
站在攻击者的角度,我们将检查此集成的安全性。我们能让 LLM 运行任何我们喜欢的代码吗?
首先检查calculate()函数中的 Python 沙盒,我们发现表达式在没有任何内置函数 (“__builtins__”:None)
的情况下发送到 Python 的eval ,并且带有从数学模块k中获取的有限允许名称列表: vfork,vinmath.__dict__.items()ifnotk.startswith(“__”)
,即除通常以 __ 开头的内部函数之外的所有函数。这足以阻止我们执行任意代码吗?沙盒化 Python 代码具有挑战性,因为它的动态类型允许代码修改自身和强大的内置函数,这些函数很难在不破坏功能的情况下进行限制。演示如何执行任意代码的最简单方法是在运行 Python 沙盒的服务器上执行命令。这可以使用Python 中的os.system()函数来完成。
在我们的例子中,沙盒试图通过禁用内置函数来阻止我们导入任何外部模块。为了绕过这个问题,我们将使用一个已知的 PyJail 技巧(这里有很多技巧之一),从新的元组中获取 _frozen_importlib.BuiltinImporter
对象,并使用它来导入os模型,如下所示: ().__class__.__base__.__subclasses__()[108].load_module('os')
。导入模块后,只需调用.system()函数即可在服务器上运行我们喜欢的任何命令。
Python 沙箱逃逸
让我们尝试让 LLM 计算这个表达式,看看我们是否可以执行任意代码。我们首先请求计算一个简单的数学表达式,然后是我们的 payload。
第一次逃跑尝试
不行。我们知道如何绕过 Python 沙盒,但我们需要让 LLM 将我们的输入表达式发送到计算函数才能使其工作。看起来 GPT-4o 已经感觉到这里有些不对劲,甚至没有尝试调用这个函数。这可能是由于 OpenAI 的安全对齐。我们知道要执行任意代码,我们不仅需要使用某种越狱来绕过沙盒,还需要绕过 LLM 对齐。值得一提的是,由于 LoLLMs 与 LLM 无关并且可以与多个模型一起使用,因此所需的越狱取决于模型。有两种选择:要么我们越狱模型并让它配合攻击并在服务器上执行任意代码,要么我们诱骗它触发易受攻击的函数而没有意识到它会危及服务器。后者可能更优雅,所以我们选择后者。请记住,要使我们的外部代码执行器工作,LLM 所要做的就是输出一个格式正确的 JSON 代码块,其中包含函数名称及其参数。我们天真地要求 LLM 输出它。
第二次逃跑尝试
看来 GPT-4o 并没有那么容易上当。我们需要想出其他办法让它在不了解其真正用途的情况下输出这个 JSON。如果我们要求它帮助格式化 JSON 会怎么样?
它成功了!GPT-4o 认为它只是帮助我们处理了这个简单的 JSON,但实际上它触发了我们的任意代码执行,并且我们的文件已经创建。这就是我们如何利用 LLM 可用的工具并使其运行任意代码,从一个简单的自然语言提示开始。此漏洞已负责任地披露给 LoLLM,并且已修复。它被发布为CVE-2024-6982。
反向 shell 演示
结论
LLM 集成是一把双刃剑。我们可以获得更好的功能和更好的用户体验,但这也伴随着安全风险。归根结底,我们必须明白,任何赋予 LLM 的能力都可能被攻击者利用来攻击系统。后利用技术可能专注于 LLM 本身,例如后门、数据提取或利用进一步的集成,或者它们可能针对传统的非 LLM 组件,例如主机特权提升或横向移动。有关如何安全地将 LLM 集成到系统中以及如何实施适当的特权控制的一般信息,请查看我们之前的帖子。
如何学习大模型
现在社会上大模型越来越普及了,已经有很多人都想往这里面扎,但是却找不到适合的方法去学习。
作为一名资深码农,初入大模型时也吃了很多亏,踩了无数坑。现在我想把我的经验和知识分享给你们,帮助你们学习AI大模型,能够解决你们学习中的困难。
下面这些都是我当初辛苦整理和花钱购买的资料,现在我已将重要的AI大模型资料包括市面上AI大模型各大白皮书、AGI大模型系统学习路线、AI大模型视频教程、实战学习,等录播视频免费分享出来
,需要的小伙伴可以扫取。

一、AGI大模型系统学习路线
很多人学习大模型的时候没有方向,东学一点西学一点,像只无头苍蝇乱撞,我下面分享的这个学习路线希望能够帮助到你们学习AI大模型。
二、AI大模型视频教程
三、AI大模型各大学习书籍
四、AI大模型各大场景实战案例
五、结束语
学习AI大模型是当前科技发展的趋势,它不仅能够为我们提供更多的机会和挑战,还能够让我们更好地理解和应用人工智能技术。通过学习AI大模型,我们可以深入了解深度学习、神经网络等核心概念,并将其应用于自然语言处理、计算机视觉、语音识别等领域。同时,掌握AI大模型还能够为我们的职业发展增添竞争力,成为未来技术领域的领导者。
再者,学习AI大模型也能为我们自己创造更多的价值,提供更多的岗位以及副业创收,让自己的生活更上一层楼。
因此,学习AI大模型是一项有前景且值得投入的时间和精力的重要选择。