Invoke-DbaDbDecryptObject - Read the family GUID from sys.database_recovery_status instead of DBCC DBINFO - #10680
Open
howarthcd wants to merge 1 commit into
Conversation
…covery_status instead of DBCC DBINFO The DataPages method needed the database family GUID to rebuild the keystream and scraped it out of DBCC DBINFO's text dump under trace flag 3604. It now reads family_guid from the catalog view sys.database_recovery_status, a typed uniqueidentifier present since SQL Server 2005. The two sources were measured byte for byte across SQL Server 2019, 2022 and 2025, for user databases and master, and always agree, so the keystream input is unchanged while a trace flag toggle and a regex over prose are dropped. DBCC PAGE still reads the ciphertext and still needs sysadmin, so the sysadmin check stays; the catalog view needs only VIEW SERVER STATE, which a sysadmin already holds. (do Invoke-DbaDbDecryptObject) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
(do Invoke-DbaDbDecryptObject)
Reads the database family GUID from the catalog view
sys.database_recovery_statusinstead of scrapingdbi_familyGUIDout of the text thatDBCC DBINFOprints under trace flag 3604. The family GUID is one of the three inputs to the RC4 key that the-DataPagespath derives, and this changes only where that one value comes from. TheDBCC PAGEread that pulls the ciphertext is untouched, so the page reader, the seek, the scan and the chain walk are all unchanged.The two sources were measured against each other, as the sixteen bytes that actually feed the SHA1, on SQL Server 2019, 2022 and 2025, for a user database and for
master, and they agree everywhere. So the swap leaves every derived key identical while dropping a trace flag toggle and a regex over prose in favour of a typeduniqueidentifierread that a parameterisedDB_ID()selects.Type of Change
Invoke-ManualPester -Path <command> -ScriptAnalyzer -Compliance)Purpose
The
-DataPagespath rebuilds the RC4 key from public metadata, and one of its three inputs is the database family GUID. It obtained that GUID by setting trace flag 3604, runningDBCC DBINFO, and pullingdbi_familyGUIDout of the text that arrives on the connection with a regex.The catalog view
sys.database_recovery_statusexposes the same value as a typeduniqueidentifierin itsfamily_guidcolumn, and has done since SQL Server 2005, the same floor the rest of the feature already documents. Reading it there is a typed read in place of a text parse, with no trace flag toggle and no regex over prose.Approach
The failure this change has to avoid is a quiet one. Per the scheme documented on the original pull request, a wrong family GUID, or the right GUID in the wrong byte orientation, does not throw; it produces a plausible looking but wrong keystream, so an object reads as garbage of the right length rather than failing. The source therefore could not be swapped on the strength of it looking cleaner, and was measured instead.
Both paths end as a
System.Guidfed throughToByteArray, which are the sixteen bytes that seed the SHA1. Comparing those bytes on SQL Server 2019, 2022 and 2025, for a freshly created user database and formaster, they are byte identical every time, and an end to end decrypt of an encrypted object then recovers the original text exactly on all three.DBCC PAGE, which reads the ciphertext out ofsys.sysobjvalues, is unchanged and still requires sysadmin, so the up front sysadmin check stays.sys.database_recovery_statusneeds onlyVIEW SERVER STATE, which a sysadmin already holds, so the swap loosens nothing.The comment based help never named
DBCC DBINFO, so it needed no change; the inline comments and the private helper's parameter help were updated to name the catalog view.Testing
The
-DataPageshalf of the suite is the part this change touches, and all of it passed against SQL Server 2025, including the two tests that read the family GUID to build their own oracle and so exercise the swapped source directly:Every other
-DataPagescase passed with them: in row and off row definitions, a blob tree several levels deep, non ASCII text returned unchanged, a read only database snapshot, more than one database in a single call, colliding schema and object names, and the page dump parsing and multi chunk unit tests. An end to end decrypt of a freshly created encrypted procedure recovered the original text exactly, Unicode intact.The default DAC method is unchanged by this pull request and was not re-exercised here: the tests that cover it need a dedicated admin connection that the environment these tests ran in could not reach, so they are not reported above.
Commands to test