{"id":7259,"date":"2026-04-08T13:19:57","date_gmt":"2026-04-08T18:19:57","guid":{"rendered":"https:\/\/andreas-wolter.com\/?p=7259"},"modified":"2026-04-08T13:22:22","modified_gmt":"2026-04-08T18:22:22","slug":"2604_sqlserver_privilegeescalation_databasemanager-part2","status":"publish","type":"post","link":"https:\/\/andreas-wolter.com\/en\/2604_sqlserver_privilegeescalation_databasemanager-part2\/","title":{"rendered":"##MS_DatabaseManager## Privilege Escalation (Part 2): The Ownership-Based Security Model"},"content":{"rendered":"\n<style type=\"text\/css\" data-created_by=\"avia_inline_auto\" id=\"style-css-av-m0cxh8ps-51f7be1de9ac97bb552764cb50159734\">\n#top .av-special-heading.av-m0cxh8ps-51f7be1de9ac97bb552764cb50159734{\npadding-bottom:10px;\n}\nbody .av-special-heading.av-m0cxh8ps-51f7be1de9ac97bb552764cb50159734 .av-special-heading-tag .heading-char{\nfont-size:25px;\n}\n.av-special-heading.av-m0cxh8ps-51f7be1de9ac97bb552764cb50159734 .av-subheading{\nfont-size:15px;\n}\n<\/style>\n<div  class='av-special-heading av-m0cxh8ps-51f7be1de9ac97bb552764cb50159734 av-special-heading-h3 blockquote modern-quote  avia-builder-el-0  el_before_av_textblock  avia-builder-el-first '><h3 class='av-special-heading-tag'  itemprop=\"headline\"  >##MS_DatabaseManager## Privilege Escalation (Part 2): The Ownership-Based Security Model<\/h3><div class=\"special-heading-border\"><div class=\"special-heading-inner-border\"><\/div><\/div><\/div>\r\n\r\n<section  class='av_textblock_section av-m0cxgkjy-c935304b4106b45214698f40e83a9894 '   itemscope=\"itemscope\" itemtype=\"https:\/\/schema.org\/BlogPosting\" itemprop=\"blogPost\" ><div class='avia_textblock'  itemprop=\"text\" ><p>In my previous post (<a href=\"https:\/\/andreas-wolter.com\/en\/2604_sqlserver_privilegeescalation_databasemanager\/\">SQL Server Privilege Escalation via DatabaseManager-role: Newly discovered Attack Paths Explained<\/a>), I showed how a privilege escalation can be achieved by modifying a stored procedure in msdb, based on <a href=\"https:\/\/databasesecurityninja.wordpress.com\/2026\/04\/02\/microsoft-sql-server-privilege-elevation-through-ms_databasemanager-role-cve-2025-24999\/\" target=\"_blank\" rel=\"noopener\">research shared by Emad Al-Mousa<\/a>.<\/p>\n<p>When I looked into this more closely, it became clear pretty quickly:<br \/>\nIt is not just about a few specific procedures.<\/p>\n<h2>Documented behavior<\/h2>\n<p>According to the documentation, ##MS_DatabaseManager## is supposed to behave like the old <strong><em>dbcreator<\/em><\/strong> server-role:<\/p>\n<ul>\n<li>You can <strong>create<\/strong> databases<\/li>\n<li>You <strong>become the owner<\/strong><\/li>\n<li>You can fully <strong>control databases you create<\/strong><\/li>\n<li>You have <strong>no permission on other databases<\/strong><\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-7260 size-large\" src=\"https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202603_SQLServer_MS_DatabaseManager_role_doc_dbcreator-1030x458.jpg\" alt=\"\" width=\"1030\" height=\"458\" srcset=\"https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202603_SQLServer_MS_DatabaseManager_role_doc_dbcreator-1030x458.jpg 1030w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202603_SQLServer_MS_DatabaseManager_role_doc_dbcreator-300x134.jpg 300w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202603_SQLServer_MS_DatabaseManager_role_doc_dbcreator-768x342.jpg 768w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202603_SQLServer_MS_DatabaseManager_role_doc_dbcreator-705x314.jpg 705w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202603_SQLServer_MS_DatabaseManager_role_doc_dbcreator.jpg 1202w\" sizes=\"auto, (max-width: 1030px) 100vw, 1030px\" \/><\/p>\n<p>That\u2019s a simple and predictable <strong>ownership-based model<\/strong>.<\/p>\n<h2>Reality check<\/h2>\n<p>After understanding Emad\u2019s elevation paths, I took a step back to take a look at the complete picture.<\/p>\n<p>Looking at the actual server-level permissions of the role:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-7262 alignnone\" src=\"https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202604_SQLServer_MS_DatabaseManager_role_permissions_Alter_Any_Database.jpg\" alt=\"\" width=\"1015\" height=\"477\" srcset=\"https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202604_SQLServer_MS_DatabaseManager_role_permissions_Alter_Any_Database.jpg 1015w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202604_SQLServer_MS_DatabaseManager_role_permissions_Alter_Any_Database-300x141.jpg 300w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202604_SQLServer_MS_DatabaseManager_role_permissions_Alter_Any_Database-768x361.jpg 768w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202604_SQLServer_MS_DatabaseManager_role_permissions_Alter_Any_Database-705x331.jpg 705w\" sizes=\"auto, (max-width: 1015px) 100vw, 1015px\" \/><\/p>\n<p>I realized, it includes the ALTER ANY DATABASE-permission!<\/p>\n<p>With that permission, <strong>databases can be modified even without ownership<\/strong>.<\/p>\n<p>The only requirement is that the principal can access the database.<\/p>\n<h2>The built-in escalation path<\/h2>\n<p>And that\u2019s where the problem starts:<\/p>\n<p>System databases like master, msdb and tempdb are accessible for everyone by default. No user mapping required \u2013 access is granted via guest and should not be blocked.<\/p>\n<p>Here is a screenshot of the resulting permissions of a member of the ##MS_DatabaseManager##-role in msdb:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-7264 alignnone\" src=\"https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202604_SQLServer_MS_DatabaseManager_role_permissions_Alter_msdb.jpg\" alt=\"\" width=\"1015\" height=\"446\" srcset=\"https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202604_SQLServer_MS_DatabaseManager_role_permissions_Alter_msdb.jpg 1015w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202604_SQLServer_MS_DatabaseManager_role_permissions_Alter_msdb-300x132.jpg 300w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202604_SQLServer_MS_DatabaseManager_role_permissions_Alter_msdb-768x337.jpg 768w, https:\/\/andreas-wolter.com\/wp-content\/uploads\/2026\/04\/202604_SQLServer_MS_DatabaseManager_role_permissions_Alter_msdb-705x310.jpg 705w\" sizes=\"auto, (max-width: 1015px) 100vw, 1015px\" \/><\/p>\n<ol>\n<li>Access via guest<\/li>\n<li>Effective permission: ALTER on the database<\/li>\n<\/ol>\n<p>Which means:<\/p>\n<p>This is not about a few specific procedures &#8211; <strong>every executable object in msdb and master becomes part of the attack surface<\/strong>.<\/p>\n<h2>Practical attack surface<\/h2>\n<p>Once you look beyond the original exploit, multiple paths become obvious.<\/p>\n<p>In msdb, for example:<\/p>\n<ul>\n<li>SQL Agent jobs<\/li>\n<li>Alerts and schedules<\/li>\n<li>Backup and maintenance procedures<\/li>\n<li>Database Mail<\/li>\n<\/ul>\n<p>Many of those eventually run under elevated privileges.<\/p>\n<p>Emad\u2019s research showed how this can be chained into a working escalation path.<\/p>\n<h2>Intended model vs. what actual behavior<\/h2>\n<p>Looking back at the original announcement of this role (<a href=\"https:\/\/techcommunity.microsoft.com\/blog\/azuresqlblog\/new-server-roles-for-azure-sql-database-and-sql-server-2022-in-public-preview\/3428433\" target=\"_blank\" rel=\"noopener\">New server roles for Azure SQL Database and SQL Server 2022 in Public Preview<\/a>), the intent was clear:<\/p>\n<ul>\n<li>Control what you create<\/li>\n<li>Maintain strict ownership boundary<\/li>\n<\/ul>\n<p>Instead, what we have in practice is:<br \/>\nA role that can modify code in any accessible database \u2014 including system databases.<\/p>\n<h2>Background<\/h2>\n<p>I was the Program Manager at Microsoft, responsible for introducing this role.<\/p>\n<p>The goal was to:<\/p>\n<ul>\n<li>replace the special <em><a href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/relational-databases\/security\/authentication-access\/database-level-roles?view=sql-server-ver17#special-roles-for-azure-sql-database-and-azure-synapse\" target=\"_blank\" rel=\"noopener\">dbmanager<\/a> <\/em>database role in Azure SQL Database<\/li>\n<li>Introduce a proper server-level equivalent<\/li>\n<li>Preserve the ownership-based model<\/li>\n<\/ul>\n<p style=\"padding-left: 40px;\"><em>Note<\/em><br \/>\nAt the time, server roles were not available in Azure SQL Database due to architectural constraints (separation of logical and physical servers). Once those limitations were addressed, new server roles became possible.<\/p>\n<p>The intent was not to introduce broad cross-database modification capabilities.<\/p>\n<p>However, with ALTER ANY DATABASE included, the effective behavior differs significantly from that intent &#8211; something I did not catch at the time.<\/p>\n<h2>Impact on Auditing<\/h2>\n<p>This also explains why database-level auditing alone is not sufficient.<\/p>\n<p>With ALTER ANY DATABASE, it is possible to:<\/p>\n<ul>\n<li>Disable or modify database-level audits<\/li>\n<\/ul>\n<p><strong>Recommendations:<\/strong><\/p>\n<ol>\n<li>Audit to files that cannot be altered by a sysadmin<\/li>\n<li>Monitor audit start\/stop events<\/li>\n<li>Always include server-level auditing<\/li>\n<\/ol>\n<h2>The \u201climited permissions in system databases\u201d myth<\/h2>\n<p>During assessments I frequently find that application-vendors have access to master and\/or msdb so they can place objects there.<\/p>\n<p>And often this includes stored procedures.<\/p>\n<p>These elevation-examples demonstrate how quickly this opens an elevation-path.<\/p>\n<blockquote><p>If someone can modify executable objects in system databases, there is a clear path to Privilege Escalation.<\/p><\/blockquote>\n<p><strong>Recommendation:<\/strong><\/p>\n<ul>\n<li>Use a dedicated utility (code-only) database<\/li>\n<li>Do not grant permissions on system databases to non-DBA\u2019s<\/li>\n<\/ul>\n<h2>What about Azure SQL database?<\/h2>\n<p>Azure SQL Database has a different architecture when it comes to the system databases:<\/p>\n<ul>\n<li>guest is disabled in master<\/li>\n<li>msdb is not exposed<\/li>\n<\/ul>\n<p>As a result, these escalation paths are not available in Azure SQL Database.<\/p>\n<h2>My Recommendation<\/h2>\n<p>From a security perspective, this looks like a design issue rather than a documentation gap.<\/p>\n<p>A straightforward improvement would be:<\/p>\n<ul>\n<li>Remove ALTER ANY DATABASE from the role<\/li>\n<li>Preserve the ownership-based model as originally intended<\/li>\n<\/ul>\n<p>Yes, this could be called a \u201cbreaking change\u201d.<\/p>\n<p>However, in practice, I have not seen scenarios where this broader behavior is intentionally relied upon. What it does affect is the ability to safely adopt the role.<\/p>\n<p>At the moment, the documentation highlights \u201cpossible elevation under certain conditions\u201d. In real-world environments, this is not an edge case &#8211; \u00a0it is a direct and inherent possibility given default configurations.<\/p>\n<p>Addressing individual execution paths is not a sustainable solution.<br \/>\nAs long as the underlying permissions remain unchanged, new paths will continue to exist.<\/p>\n<p>From a security perspective, this puts the role much closer to <a href=\"https:\/\/andreas-wolter.com\/en\/control-server-vs-sysadmin-sa\/\">CONTROL SERVER<\/a> than its documented scope would suggest, as it provides a direct path to privilege escalation.<\/p>\n<p>Until this is addressed, I cannot recommend using this role in security-sensitive environments.<\/p>\n<p>Andreas<\/p>\n<\/div><\/section>\r\n\r\n<div  class='hr av-baku8u-c77559299fb7cb036a9bcb2d27e7c839 hr-default  avia-builder-el-2  el_after_av_textblock  el_before_av_social_share '><span class='hr-inner '><span class=\"hr-inner-style\"><\/span><\/span><\/div>\r\n\r\n<div  class='av-social-sharing-box av-5n5vpa-78ffdd9d224b4a246af65bdc00dce900 av-social-sharing-box-default  avia-builder-el-3  el_after_av_hr  el_before_av_hr  av-social-sharing-box-fullwidth'><div class=\"av-share-box\"><h5 class='av-share-link-description av-no-toc '>Share article<\/h5><ul class=\"av-share-box-list noLightbox\"><li class='av-share-link av-social-link-facebook' ><a target=\"_blank\" aria-label=\"Share on Facebook\" href=\"https:\/\/www.facebook.com\/sharer.php?u=https:\/\/andreas-wolter.com\/en\/2604_sqlserver_privilegeescalation_databasemanager-part2\/&#038;t=%23%23MS_DatabaseManager%23%23%20Privilege%20Escalation%20%28Part%202%29%3A%20The%20Ownership-Based%20Security%20Model\" aria-hidden=\"false\" data-av_icon=\"\ue8f3\" data-av_iconfont=\"entypo-fontello\" title=\"\" data-avia-related-tooltip=\"Share on Facebook\" rel=\"noopener\"><span class='avia_hidden_link_text'>Share on Facebook<\/span><\/a><\/li><li class='av-share-link av-social-link-twitter' ><a target=\"_blank\" aria-label=\"Share on Twitter\" href=\"https:\/\/twitter.com\/share?text=%23%23MS_DatabaseManager%23%23%20Privilege%20Escalation%20%28Part%202%29%3A%20The%20Ownership-Based%20Security%20Model&#038;url=https:\/\/andreas-wolter.com\/en\/?p=7259\" aria-hidden=\"false\" data-av_icon=\"\ue8f1\" data-av_iconfont=\"entypo-fontello\" title=\"\" data-avia-related-tooltip=\"Share on Twitter\" rel=\"noopener\"><span class='avia_hidden_link_text'>Share on Twitter<\/span><\/a><\/li><li class='av-share-link av-social-link-linkedin' ><a target=\"_blank\" aria-label=\"Share on LinkedIn\" href=\"https:\/\/linkedin.com\/shareArticle?mini=true&#038;title=%23%23MS_DatabaseManager%23%23%20Privilege%20Escalation%20%28Part%202%29%3A%20The%20Ownership-Based%20Security%20Model&#038;url=https:\/\/andreas-wolter.com\/en\/2604_sqlserver_privilegeescalation_databasemanager-part2\/\" aria-hidden=\"false\" data-av_icon=\"\ue8fc\" data-av_iconfont=\"entypo-fontello\" title=\"\" data-avia-related-tooltip=\"Share on LinkedIn\" rel=\"noopener\"><span class='avia_hidden_link_text'>Share on LinkedIn<\/span><\/a><\/li><\/ul><\/div><\/div>\r\n\r\n\n<style type=\"text\/css\" data-created_by=\"avia_inline_auto\" id=\"style-css-av-4ofg9q-c2108540b480aba02923089240a3a176\">\n#top .hr.hr-invisible.av-4ofg9q-c2108540b480aba02923089240a3a176{\nheight:50px;\n}\n<\/style>\n<div  class='hr av-4ofg9q-c2108540b480aba02923089240a3a176 hr-invisible  avia-builder-el-4  el_after_av_social_share  el_before_av_comments_list '><span class='hr-inner '><span class=\"hr-inner-style\"><\/span><\/span><\/div>\r\n\r\n<div  class='av-buildercomment av-284ftq-f5a1564cd6b8ffad6ce835e2d40de4b7  av-blog-meta-author-disabled av-blog-meta-html-info-disabled'><\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":4,"featured_media":7264,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[57],"tags":[206,258],"class_list":["post-7259","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security-en","tag-sql-security","tag-sysadmin-en"],"_links":{"self":[{"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/posts\/7259","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/comments?post=7259"}],"version-history":[{"count":4,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/posts\/7259\/revisions"}],"predecessor-version":[{"id":7267,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/posts\/7259\/revisions\/7267"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/media\/7264"}],"wp:attachment":[{"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/media?parent=7259"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/categories?post=7259"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/andreas-wolter.com\/en\/wp-json\/wp\/v2\/tags?post=7259"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}