The Much Misunderstood SeRelabelPrivilege
2021-06-03 06:49:00 Author: www.blogger.com(查看原文) 阅读量:143 收藏

tag:blogger.com,1999:blog-4304739697716191998.post-21529945357938691922021-06-02T14:49:00.000-07:002021-06-02T14:49:12.646-07:00The Much Misunderstood SeRelabelPrivilege<p>Based on my <a href="https://www.tiraniddo.dev/2021/05/dumping-stored-credentials-with.html">previous blog post</a> I recently had a conversation with a friend and well-known Windows security researcher about token privileges. Specifically, I was musing on how <i>SeTrustedCredmanAccessPrivilege</i> is not a "God" privilege. After some back and forth it seemed we were talking at cross purposes. My concept of a "God" privilege is one which the kernel considers to make a token elevated (see&nbsp;<a href="https://www.tiraniddo.dev/2017/05/reading-your-way-around-uac-part-3.html">Reading Your Way Around UAC (Part 3)</a>) and so doesn't make it available to any token with an integrity level less than <i>High</i>. They on the other hand consider such a privilege to be one where you can directly compromise a resource or the OS as a whole by having the privilege enabled, this might include privileges which aren't strictly a "God" from the kernel's perspective but can still allow system compromise.</p><p>After realizing the misunderstanding I was still surprised that one of the privileges in their list wasn't considering a "God", specifically&nbsp;<i>SeRelabelPrivilege</i>. It seems that there's perhaps some confusion as to what this privilege actually allows you to do, so I thought it'd be worth clearing it up.</p><p><i>Point of pedantry: I don't believe it's correct to say that a resource has an integrity level. It instead has a mandatory label, which is stored in an ACE in the SACL. That ACE contains a SID which maps to an integrity level and an mandatory policy which is stored in the access mask. The combination of integrity level and policy is what determines what access is granted (although you can't grant write up through the policy). The token on the other hand does have an integrity level and a separate mandatory policy, which isn't the same as the one in the ACE. Oddly you specify the value when calling <a href="https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-settokeninformation">SetTokenInformation</a> using a <a href="https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-token_mandatory_label">TOKEN_MANDATORY_LABEL</a> structure, confusing I know.</i></p><p>As with a lot of privileges which don't get used very often the official documentation is not great. You can find the MSDN documentation&nbsp;<a href="https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/modify-an-object-label">here</a>. The page is worse than usual as it seems to have been written at a time in the Vista/Longhorn development when the <a href="https://docs.microsoft.com/en-us/windows/win32/secauthz/mandatory-integrity-control">Mandatory Integrity Control (MIC)</a> (or as it calls it <i>Windows Integrity Control (WIC)</i>) feature was still in flux. For example, it mentions an integrity level above <i>System</i>, called <i>Installer</i>. Presumably&nbsp;<i>Installer</i>&nbsp;was the initial idea to block administrators modifying system files, which was replaced by the&nbsp;<i>TrustedInstaller&nbsp;</i>SID as the owner (see previous blog posts). There is a level above <i>System</i> in Vista, called <i>Protected Process</i>, which is not usable as protected processes was implementing using a different mechanism.&nbsp;</p><p>Distilling what the documentation says the privilege does, it allows for two operations. First it allows you to set the integrity level in a mandatory label ACE to be above the caller's token integrity level. Normally as long as you've been granted <i>WRITE_OWNER</i> access to a resource you can set the label's integrity level to any value less than or equal to the caller's integrity level.</p><p>For example, if you try to set the resource's label to <i>System</i>, but the caller is only at <i>High </i>then the operation fails with the&nbsp;<i>STATUS_INVALID_LABEL</i> error. If you enable <i>SeRelabelPrivilege </i>then you can set this operation will succeed.&nbsp;</p><p><i>Note, the privilege doesn't allow you to raise the integrity level of a token, you need SeTcbPrivilege for that. You can't even raise the integrity level to be less than or equal to the caller's integrity level, the operation can only decrease the level in the token without SeTcbPrivilege.</i></p><p>The second operation is that you can decrease the label. In general you can always decrease the label without the privilege, unless the resource's label is above the callers. For example you can set the label to&nbsp;<i>Low</i> without any special privilege, as long as you have <i>WRITE_OWNER</i> access on the handle and the current label is less than or equal to the caller's. However, if the label is <i>System </i>and the caller is <i>High </i>then they can't decrease the label and the privilege is required.</p><p>The documentation has this to say (emphasis mine):</p><p><i>"If malicious software is set with an elevated integrity level such as Trusted Installer or System, administrator accounts do not have sufficient integrity levels to delete the program from the system. In that case, use of the Modify an object label right is mandated so that the object can be relabeled. However, <b>the relabeling must occur by using a process that is at the same or a higher level of integrity than the object that you are attempting to relabel</b>."</i></p><p>This is a very confused paragraph. First it indicates that an administrator can't delete resource with <i>Trusted Installer</i> or <i>System</i> integrity labels and so requires the privilege to relabel. And then it says that the process doing the relabeling must be at a greater or equal integrity level to do the relabeling. Which if that is the case you don't need the privilege. Perhaps the original design on mandatory labels was more sticky, as in maybe you always needed <i>SeRelabelPrivilege </i>to reduce the label regardless of its current value?</p><p>At any rate the only user that gets <i>SeRelabelPrivilege</i> by default is SYSTEM, which defaults to the <i>System </i>integrity level which is already the maximum allowed level so this behavior of the privilege seems pretty much moot. At any rate as it's a "God" privilege it will be disabled if the token has an integrity level less than <i>High</i>, so this lowering operation is going to be rarely useful.</p><p>This leads in to the most misunderstood part which if you squint you might be able to grasp from the privilege's documentation. The ability to lower the label of a resource is mostly dependent on whether the caller can get <i>WRITE_OWNER</i> access to the resource. However, the <i>WRITE_OWNER</i> access right is typically part of <i>GENERIC_ALL</i> in the generic mapping,&nbsp;which means it will never be granted to a caller with a lower integrity level regardless of the DACL or whether they're the owner.&nbsp;</p><p>This is the interesting thing the privilege brings to the lowering operation, it allows the caller to circumvent the MIC check for <i>WRITE_OWNER</i>. This then allows the caller to open for <i>WRITE_OWNER</i> a higher labeled resource and then change the label to any level it likes. This works the same way as <i>SeTakeOwnershipPrivilege</i>, in that it grants <i>WRITE_OWNER</i> without ever checking the DACL. However, if you use&nbsp;<i>SeTakeOwnershipPrivilege </i>it'll still be subject to the MIC check and will not grant access if the label is above the caller's integrity level.</p><p>The problem with this privilege is down to the design of MIC, specifically that <i>WRITE_OWNER</i> is overloaded to allow setting the resource's mandatory label but also its traditional use of setting the owner. There's no way for the kernel to distinguish between the two operations once the access has been granted (or at least it doesn't try to distinguish).&nbsp;</p><p>Surely, there is some limitation on what type of resource can be granted <i>WRITE_OWNER</i> access? Nope, it seems that even if the caller does not have any access rights to the resource it will still be granted&nbsp;<i>WRITE_OWNER</i>&nbsp;access. This makes the <i>SeRelabelPrivilege </i>exactly like&nbsp;<i>SeTakeOwnershipPrivilege</i> but with the adding feature of circumventing the MIC check. Summarizing, a token with <i>SeRelabelPrivilege</i> enabled&nbsp;can take ownership of any resource it likes, even one which has a higher label than the caller.</p><p>You can of course verify this yourself, here's some PowerShell script using <i>NtObjectManager</i> which you should run as an administrator. The script creates a security descriptor which doesn't grant SYSTEM any access, then tries to request <i>WRITE_OWNER</i> without and with <i>SeRelabelPrivilege</i>.</p><div style="text-align: left;"><span style="font-family: courier;">PS&gt; $sd = New-NtSecurityDescriptor "O:ANG:AND:(A;;GA;;;AN)" -Type Directory<br />PS&gt;&nbsp;Invoke-NtToken -System {</span></div><div><span style="font-family: courier;">&nbsp; &nbsp;Get-NtGrantedAccess -SecurityDescriptor $sd -Access WriteOwner -PassResult</span></div><div><span style="font-family: courier;">}</span></div><div><div><span style="font-family: courier;">Status&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Granted Access Privileges</span></div><div><span style="font-family: courier;">------&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-------------- ----------</span></div><div><span style="font-family: courier;">STATUS_ACCESS_DENIED 0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NONE</span></div></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">PS&gt; Invoke-NtToken -System {</span></div><div><span style="font-family: courier;">&nbsp; &nbsp;Enable-NtTokenPrivilege SeRelabelPrivilege</span></div><div><span style="font-family: courier;">&nbsp; &nbsp;Get-NtGrantedAccess -SecurityDescriptor $sd -Access WriteOwner -PassResult</span></div><div><span style="font-family: courier;">}</span></div><div><span style="font-family: courier;">Status&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Granted Access Privileges</span></div><div><span style="font-family: courier;">------&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-------------- ----------</span></div><div><span style="font-family: courier;">STATUS_SUCCESS WriteOwner&nbsp; &nbsp; &nbsp;SeRelabelPrivilege</span></div><p>The fact that this behavior is never made explicit is probably why my friend didn't realize its behavior before. This coupled with the privilege's rare usage, only being granted by default to SYSTEM means it's not really a problem in any meaningful sense. It would be interesting to know the design choices which led to the privilege being created, it seems like its role was significantly more important at some point and became almost vestigial during the Vista development process.&nbsp;</p><p>If you've read this far is there any actual useful scenario for this privilege? The only resources which typically have elevated labels are processes and threads. You can already circumvent the MIC check using <i>SeDebugPrivilege</i>. Of course usage of that privilege is probably watched like a hawk, so you could abuse this privilege to get full access to an elevated process, by accessing changing the owner to the caller and lowering the label. Once you're the owner with a low label you can then modify the DACL to grant full access directly without <i>SeDebugPrivilege</i>.</p><p>However, as only SYSTEM gets the privilege by default you'd need to impersonate the token, which would probably just allow you to access the process anyway. So mostly it's mostly a useless quirk unless the system you're looking at has granted it to the service accounts which might then open the door slightly to escaping to SYSTEM.</p>tiraniddo[email protected]

文章来源: https://www.blogger.com/feeds/4304739697716191998/posts/default/2152994535793869192
如有侵权请联系:admin#unsafe.sh