Welcome to the prologue article for a three-part series where I try to infiltrate the OS layer of Azure SQL Managed Instance and uncover a few surprises Microsoft didn’t expect me to find.
Before we dive into the rabbit holes, let’s zoom out.
In the cloud world, everything runs as a certain Service Model. From IaaS (where you manage almost everything yourself) to SaaS (where you just consume what's handed to you). PaaS sits in the middle, offering convenience while promising control over the essentials: code, data, and maybe a few knobs via a portal or CLI.

So, where does Azure SQL Managed Instance (MI) sit on this spectrum? It’s not quite the full freedom of a SQL Server VM, and it’s definitely not as hands-off as Azure SQL Database. Microsoft pitches it as a “best of both worlds” solution: near-full SQL Server compatibility, with the operational benefits of PaaS.
This series is for the “what really runs this thing?” crowd, the DBAs, DevSecOps engineers, and platform tinkerers who live to understand what’s under the hood. I’m one of you, and I didn’t just explore MI, I pushed boundaries, found cracks, and shared everything with Microsoft. After reviewing the findings, they did not object to me publishing this triptych of stories.
What follows here is just a taster of what's to come.
Part 1 – “Why Clone Fails: Discovering the Hardware Beneath Azure SQL MI”
Microsoft markets Azure SQL MI as offering near-full SQL Server compatibility and more control than typical PaaS. But just how much control can a curious developer really get?
I originally set out to see whether Azure SQL MI could support fast, lightweight database cloning, armed with the same DIY tricks I’d used on VMs and IaaS. The idea was simple: if Azure SQL MI was basically just “SQL Server in a VM” with some extra orchestration, maybe I could make it work. If it was still a tightly locked-down PaaS black box, then probably not.
Part one of this series will reveal what I learned from my first real exploration of Azure SQL MI’s architecture. I uncovered just enough about the underlying virtual hardware to get a clearer picture of how it’s built, what it is, and what it isn’t.
A quick dig around the filesystem delivered my first big surprise. I was met with an extremely minimal list of installed programs:
Program Name | Version |
Microsoft OLE DB Driver for SQL Server | 18.7.4.0 |
Microsoft OLE DB Driver 19 for SQL Server | 19.3.0.0 |
Microsoft Visual C++ 2022 X64 Minimum Runtime | 14.40.33816 |
Microsoft Visual C++ 2022 X86 Minimum Runtime | 14.40.33816 |
Microsoft Visual C++ 2022 X64 Additional Runtime | 14.40.33816 |
Microsoft Visual C++ 2022 X86 Additional Runtime | 14.40.33816 |
Yes, you're reading that right: no SQL Server installation in sight. That, along with a clutter of cryptic Fabric_ environment variables, made it immediately clear to me that this was not just a general-purpose Windows VM with SQL Server installed.
It was a specialized runtime in a containerized environment, tightly orchestrated by the Azure platform. I realized quickly that my cloning approach wasn’t just unsupported; it was fundamentally misaligned with how MI was architected.
That should’ve been the end of the story, but something told me to keep digging. A PowerShell task I assumed would quietly fail…executed successfully. Was I starting to see cracks in the walls of this PaaS fortress?
Those walls are supposed to guarantee security and isolation; surely, they would prevent me from digging around in the container OS? I certainly shouldn’t be able to find and kill the sqlservr process. And there’s no way it would let me inject custom binaries, or extract platform files… right?
Part 2 – “Getting In: Running External Code in a Locked-Down PaaS”
In Part 1, I started to sense that Azure SQL MI isn’t quite the fully a locked-down black box I expected it to be. I could explore the container OS and even kill the sqlservr process, only to watch it respawn automatically.
In Part 2, I will describe what happened when I set out to do something more provocative: to see whether I could run external code inside the MI environment. After all, if I could observe and interrupt internal processes, maybe I could also introduce my own!
This wasn’t a hacking exercise. No SQLCLR, no shell exploits, no sounds of breaking glass. I stayed within the lines, using only documented features and some strategic file placement. My idea was simple: could I insert a binary file into a user database, sync it across to MI, and somehow coax the system into executing it from the container OS?
To test the theory, I chose one of the most recognizable utilities in the Windows world: a Sysinternals tool. I read the binary into a local table …
INSERT INTO dbo.binaries (FileName, FileExtension, FileData) SELECT 'psloglist64.exe', BulkColumn FROM OPENROWSET(BULK N'D:\tools\PSTools\psloglist64.exe', SINGLE_BLOB) AS FileData;
Then I synced the database content to Azure SQL Managed Instance, transferring the binary along with it. And finally… I executed it.
With no special privileges and no external shell, I successfully injected a binary into the MI container and ran it, just by using SQL Server’s own data movement features.
And that raised my next question. If I could smuggle code in…could I also smuggle it out?
Part 3 – “Getting Out: Smuggling Binaries (and PDBs) from Azure SQL MI”
Finally, I flipped the funnel. If I could inject binaries into Azure SQL MI and run them, the next question was obvious: what could I extract? Part 3 will focus on exfiltration. Using only supported techniques, what sort of data could be pulled from the OS of the MI environment? This is about more than just developer curiosity. It's a lesson in what you need to do to secure your deployment pipeline and prevent data leakage from your production environment.
While poking around the Azure MI's OS container, I came across several directories that immediately grabbed my attention: assemblies, support files, and, most surprisingly, .pdb files. Just sitting there. Not obscured. Not encrypted.
They were clearly part of the deployed runtime environment, timestamped, structured, and, as it turns out, easily retrieved! Using the same techniques, I’d used to inject binaries in Part 2, but in reverse, I was able to pull these files straight from the container, byte for byte!
If these had been build-time artifacts that somehow made it into production containers, it would be a DevOps red flag. When a CI/CD pipeline doesn’t fully separate build outputs by environment, debug configurations can creep into production. Assuming instead that the .pdb files are there intentionally, for debugging release builds, it still raises the question: why were they so easily accessible to me, from within a running Managed Instance?
I started this series wondering how far down the rabbit hole my "developer's curiosity" could take me. I ended up learning how important it is to know, and control, what’s actually running in your production environment. Your containers need to be isolated. Your builds need to be clean. And your DevOps pipeline shouldn't be letting debug artifacts, or anything else, slip through the cracks.
Conclusion & Invitation
Azure SQL Managed Instance promises the convenience of PaaS with the power of SQL Server, but as you’ll see throughout this series, that combination comes with quirks, edge cases, and a few surprises Microsoft might not advertise up front.
This isn’t just about curiosity or clever tricks. It’s about understanding the boundaries of the platform you trust with mission-critical data. Whether you’re building on MI, operating it, or securing it, these stories will help you ask sharper questions and make better decisions.
Each article includes hands-on proof, reproducible steps, and actionable takeaways. But let me be clear: just because you can doesn’t mean you should, especially not in production.
This series was much fun to create, and I hope it informs, provokes, and entertains in equal measure.
Try it yourself — for free!
Feeling inspired (or skeptical)? You can spin up your own Azure SQL MI and explore safely. Microsoft now offers 720 vCore hours on a General Purpose SQL Managed Instance, with up to 100 databases per instance, free for the first 12 months.
And yes… I let Suno make a song about it. When a cloud platform surprises you this much, sometimes the only rational response is music, just give it a listen.