root/blog/sqli-to-domain-admin
secure channel

// sqli-to-domain-admin.mdx

SQL Injection to Domain Admin: An External-to-Internal Compromise Chain

An authenticated web app test turned into full internal domain compromise after a SQL injection opened a path into a network segment that wasn't on the original scope.

2022-03-28[web] [network] [penetration testing]

This engagement started as a straightforward authenticated web application penetration test. The target was a production application with real user data, and the scope was limited to the application itself. I had valid credentials and was working through the standard testing methodology: input validation, authentication controls, authorization logic, business logic flaws. Nothing unusual in the setup.

The SQL injection was in a data-retrieval endpoint. The backend was MSSQL, which matters for what came next. Confirming the injection took a few minutes; the application was not particularly well-defended and the error handling was verbose enough to make blind techniques unnecessary. The finding was notable but not surprising. SQL injection against MSSQL is a well-understood attack path.

What made it interesting was where it led.

MSSQL's xp_cmdshell stored procedure, when enabled, allows executing operating system commands from within the database engine. It is disabled by default in modern MSSQL configurations, but enabling it requires only a privileged database user, which the SQL service account typically is. I enabled it and used it to get a shell on the database server running as the SQL service account.

At this point I had command execution on a server I was not supposed to have command execution on. I started mapping the network reachability from that host, and the results were more interesting than I had expected. The database server had connectivity into the client's internal corporate network, a network segment that was running a separate internal penetration test concurrently.

The two engagements were not supposed to touch. They had been scoped independently. But the network topology had not been designed with that separation in mind, and the database server sat in a position that bridged both environments.

I used the foothold on the database server as a pivot point into the internal network. From there the path to domain admin was not long. The internal assessment had already been running and I had context about what the internal environment looked like. The service account the SQL process was running under had more privilege than it needed, which gave me initial internal access, and from there lateral movement to a domain admin credential was achievable through standard techniques.

The final result was full external-to-internal compromise originating from an authenticated web application session. The attack chain was: authenticated web app user → SQL injection → xp_cmdshell on database server → pivot to internal network → domain admin.

The remediation recommendations were distinct at each layer: parameterized queries and input validation at the application layer; principle of least privilege for the SQL service account and disabling xp_cmdshell; network segmentation to prevent the database tier from having direct reachability into the internal corporate network. The concurrent internal assessment finding, that an external path into the internal network existed at all, was the highest-priority item in the report.

The client had not known about the bridge. That is the most common source of high-impact findings: not sophisticated exploitation chains, but network relationships that were allowed to exist because nobody had thought carefully about what they implied.