Wednesday, July 15, 2026

SQL Server 2025 Can Call the Internet. So Can an Attacker.

Two months ago I wrote about Copilot in SSMS running as you until you fence it in. The lesson was that the security boundary is SQL Server's permission system, not the AI's intentions. Last month Brent dropped sp_BlitzUpdate, which uses SQL Server 2025's new ability to call external REST endpoints to pull code from GitHub and install it on startup. He noted you probably should not be grabbing code from the Internet and running it on your SQL Servers.

On June 10, 2026, Justin Kalnasy of SpecterOps published the other half of that sentence. If SQL Server 2025 can call the Internet, so can an attacker who owns a login on it. The full post is 'Oops, I Weaponized the Database: Abusing AI Features in SQL Server 2025'. Very good read. Here's what you need to know as a SQL Server professional.

The three features and what they actually allow

SQL Server 2025 shipped three AI-focused capabilities intended to support RAG pipeline workflows. All three are legitimate, documented, and working exactly as designed. That last part is relevant, because Microsoft has already been asked.

Feature Intended use What an attacker does with it
sp_invoke_external_rest_endpoint Call an external REST API from T-SQL POST up to 100MB of database contents per call to any HTTPS endpoint with a trusted cert
CREATE EXTERNAL MODEL Register an embedding model location Specify a UNC path to coerce NTLM authentication over SMB and capture the service account hash
AI_GENERATE_EMBEDDINGS Send text to a model and receive a vector array Disguise C2 command-and-control traffic as embedding telemetry, indistinguishable from legitimate model calls on the wire

None of these techniques give an attacker access to SQL Server. They become relevant after an attacker has already obtained a login with sufficient privileges. The concern is what those privileges now allow them to do.

The 100 MB payload limit is not much of a limitation. Kalnasy demonstrates that an attacker can split data across asynchronous requests and reconstruct it remotely, allowing very large databases to be exfiltrated in pieces.

The part that actually changes your threat model

SpecterOps built an 81-line T-SQL query that operates as a full command-and-control implant. It uses AI_GENERATE_EMBEDDINGS to check in with a C2 server, receive instructions encoded as synthetic vector arrays, XOR-decrypt them, execute commands, encode the output the same way, and send it back. Kalnasy includes a comparison of legitimate embedding traffic against C2 traffic in the original post. That image is the whole argument.

In Kalnasy's words, "Now ask yourself if an untrained analyst is really going to be able to spot the difference? Probably not".

This is the part that matters. For decades, egress web traffic from a database host was a reliable red flag. Traditionally, unexpected outbound Internet connections from a database server have always been a decent indicator that something should be investigated. SQL Server 2025 makes that signal far less reliable. As soon as an organization enables these AI features, that signal becomes much harder to trust, and any security tooling must now inspect query content and traffic payloads to verify risk. That is a much harder problem.

Kalnasy reported the NTLM coercion primitive specifically to Microsoft on April 20, 2026. On May 12, 2026, Microsoft determined the behavior did not represent a security boundary violation due to the nature of file path resolution, and it did not meet the bar for security servicing. Microsoft did not classify the reported behavior as requiring a security update. These features work as intended. The controls are yours to implement.

What the exfil actually looks like — safely

I am not reprinting a working exfil script. The SpecterOps repo is linked at the bottom if you want to lab it. What is useful here is seeing the shape so you could recognize it in an audit log.

These are descriptions of the three exfil patterns from the research so you know what to watch for:

Bulk table dump. Enable the stored procedure with sp_configure 'external rest endpoint enabled', 1, query a table with FOR JSON AUTO, store the result in a variable, and pass it as the @payload to sp_invoke_external_rest_endpoint. The entire table leaves in a single HTTPS POST. Credentials table, user table, whatever is accessible -- 100MB at a time.

File contents. Couple the same stored procedure with OPENROWSET(BULK ..., SINGLE_CLOB). Read any file the SQL Server service account can reach, including Windows hosts files, configuration files, anything on accessible shares, and POST it out the same way. The outbound connection originates from the SQL Server process, not a C2 agent.

Persistent trigger. In the SpecterOps PoC, Kalnasy demonstrates an AFTER INSERT trigger on a credentials table that calls sp_invoke_external_rest_endpoint on every write, POSTing new rows to a remote server in real time. As a proof of concept it is deliberately constructed, but the technique is sound, and a trigger is harder to evict than an agent because it lives in the database schema, not in memory. I'm including a query for you here to run now. You need to know if you have any triggers calling an external URL.

/* Detection: find triggers that call the REST endpoint.*/
SELECT
    OBJECT_SCHEMA_NAME(t.object_id) AS SchemaName,
    OBJECT_NAME(t.object_id) AS TriggerName,
    OBJECT_NAME(t.parent_id) AS ParentTable,
    m.[Definition]
FROM sys.triggers t JOIN sys.sql_modules m
  ON m.object_id = t.object_id
WHERE m.definition LIKE '%sp_invoke_external_rest_endpoint%'
   OR m.definition LIKE '%AI_GENERATE_EMBEDDINGS%';

On a clean instance it should return nothing. If it returns rows, you should look into it.

What to alert on

SpecterOps provides specific detection guidance using Splunk SPL queries against SQL Audit or Extended Events output. The full queries are in the original post and worth bookmarking. These are the four signals to capture:

Signal Why
external rest endpoint enabled = 1 The master switch. This appears in the SQL Server ERRORLOG natively, but you want it in your SIEM too.
CREATE / ALTER / DROP EXTERNAL MODEL A new model registration, possibly pointing at a UNC path or hostile URL. Should not happen without a change ticket.
CREATE ASSEMBLY / AS EXTERNAL NAME The advanced C2 variant loads a CLR implant in-memory from hex bytes. If you have CLR disabled and this fires, stop everything.
Trigger DDL on sensitive tables The persistent exfil vector. Any new trigger on a credentials, user, or financial table warrants immediate review.

The two controls that actually stop it

Alerting only tells you it happened. These two things can be used to prevent it.

Pull sysadmin off your application service accounts. Kalnasy is direct: "Too often we find web applications with database connection strings containing an account with sysadmin roles. If your app is only doing standard database queries and writes you do NOT need sysadmin privileges". Every technique in the research assumes sysadmin or near-equivalent. Remove it and you have removed the ability to flip sp_configure, create external models, and deploy CLR assemblies. This is the same principle as the CopilotExec least-privilege pattern, applied one layer out.

Block internet-bound egress from your database hosts at the firewall. This is the single highest-leverage control and the one that ends the conversation regardless of what a login can do inside the engine. If the SQL Server host cannot reach arbitrary internet endpoints, a 100MB JSON POST has nowhere to go. If you are using AI features, host your models internally and allow only those specific destinations. If you are not using AI features, there is no legitimate reason for your database host to initiate HTTPS connections to the open Internet at all. That rule was always true. SQL Server 2025 just made enforcing it urgent.

-- There is no T-SQL for this. The fix is at the network edge:
--   DENY  outbound 443 from SQL Server host subnets to 0.0.0.0/0
--   ALLOW outbound 443 from SQL Server host subnets to your internal model hosts only
--   ALERT on any denied egress from a database host -- that alert IS the canary
--
-- If your SQL Server is already making internet HTTPS calls and you
-- didn't know about it, you have a problem that needs review.

Why this is different from the usual CVE post

There is no KB number here. There is no patch to wait for. There is no 'apply update and move on.' Microsoft reviewed the NTLM coercion primitive specifically, determined it works as designed, and closed the report. The rest of the techniques are in the same category: documented features, used as intended, just by the wrong person.

That shifts the responsibility entirely to you: your service account permissions, your egress rules, your audit configuration, and your analysts' ability to distinguish legitimate embedding traffic from traffic designed to look like it. Kalnasy puts it plainly: "Behavior takes time to baseline into modern security solutions, and the burden is being put solely on the administrator to add supplementary controls. Simply telling users to implement strong access controls and to monitor without clear guidance isn't good enough."

AI isn't the vulnerability. Your security boundaries are. SQL Server 2025 simply tests them in ways previous versions never could.

More to Read

SpecterOps: Oops, I Weaponized the Database — Justin Kalnasy, June 10, 2026
GitHub: mssql2025-poc (SpecterOps PoC code)
Microsoft Learn: sp_invoke_external_rest_endpoint
Microsoft Learn: CREATE EXTERNAL MODEL
sqlfingers: Copilot in SSMS Runs As You Until You Fence It In

No comments:

Post a Comment