Giter Site home page Giter Site logo

Comments (13)

itm4n avatar itm4n commented on July 22, 2024 2

I think I solved the issue globally with a few changes in Get-ModifiablePath.

As you know, this function is in two parts. First, it creates a candidate path list and then it iterates this list and checks the ACL of each file/folder. To do so, it invokes Get-Acl on each candidate path and then it iterates the list of ACEs.

So, first things first, I transformed the original ForEach-Object loop into a "proper" ForEach ($i in $array) { ... } loop. I did that because this allows the use of the break and continue keywords. You probably don't care but I found it interesting to mention. πŸ˜„

Here is the key part. I spent some time reading the documentation and experimenting on a few Virtual Machines. You were totally on the right track with the InheritanceFlags and PropagationFlags values. These are key values that determine how ACEs are applied to an object and its children.

  • The value of InheritanceFlags determines how the ACE is inherited by child objects, so it is of no use for us.
  • The value of PropagationFlags determines how the ACE propagates to the child objects and the object itself. This second value is really interesting.

To summarize, PropagationFlags can have the following values:

  • None (0): no propagation rule is defined, therefore the ACE applies to the object and its children.
  • NoPropagateInherit (1): the ACE is not propagated to child objects, therefore the ACE only applies to the object itself.
  • InheritOnly (2): the ACE is propagated only to child objects, therefore it does not apply to the object itself.

At first, I had quite a hard time getting my head around the PropagationFlags value because it should be considered "in reverse". For example, if the value is None, it does not mean that the ACE does not propagate. It's the opposite, it means that it applies to the object and its children.

Conclusion: I added a simple test case to check whether the value InheritOnly is set. If so, I simply ignore the ACE and I go to the next one.

if ($Ace.PropagationFlags -band ([System.Security.AccessControl.PropagationFlags]"InheritOnly").value__) {
    continue
}

It should be noted that, in the case of a file, these two values seem to always be set to 0, which makes sense.

Hopefully, the issue is fixed now. It would be really great if you could test on your VMs as well though. πŸ™‚

from privesccheck.

itm4n avatar itm4n commented on July 22, 2024 1

Yup, exactly. But this particular privesc has always been more or less unlikely anyway, even on older versions of Windows.

If you find other bugs, you know what to do. πŸ™‚
Your feedback is really great. With all the information you provide each time, fixing the issues is a lot easier.

In the meantime, I close this issue (again).

from privesccheck.

itm4n avatar itm4n commented on July 22, 2024

I did take this into account in a previous commit but my solution actually worked only on Windows 10.
I made sure that the user had the AddFile permission and it was ok because the ACL of the system drive's root folder on Windows 10 doesn't contain such ACE.

Though, on older versions of Windows, the ACL is different and users have the AddFile permission (although they can't actually create files).

So yeah, basically I have to manually exclude C:\ from the list when it's returned as a vulnerable path. :/

from privesccheck.

itm4n avatar itm4n commented on July 22, 2024

I added a check to make sure the reported path is not the root of the system drive (usually C:\).
From now on, these false positives should always be filtered out.
I tested it on Windows Server 2012 and Windows Server 2008R2, it seems to work. :)

from privesccheck.

SAERXCIT avatar SAERXCIT commented on July 22, 2024

Hi!

While this solution filters out possible false positives, it would also (if I understand correctly) not report an actually writable C:\ directory (in the admittedly rare case where permissive ACLs have been set manually), which is a bigger problem than outputting false positives.

I'm guessing the issue is due to ACL propagation rules, where ACLs can be applied to only sub-items of the target directory and not on the directory itself (for instance the CreateFile entry for Users below):
Screenshot from 2021-02-18 11-40-53

Same info with icacls, which shows the related inheritance flags (relevant line is BUILTIN\Users:(CI)(IO)(WD), the pair (CI)(IO) limits the ACL to the child/grandchild folders):
Screenshot from 2021-02-18 11-41-34

The correct solution would be, in my opinion, to somehow retrieve the inheritance information/flags with PowerShell, and compare them with this joyous mess of possible pairings in order to determine whether they actually apply to the target folder.

I might have missed something making this irrelevant, if so please let me know πŸ™‚

from privesccheck.

itm4n avatar itm4n commented on July 22, 2024

This fix was implemented to handle a very particular case. On Windows < 10, users had the AddFile right in C:\ but they could not really create files. As far as I know, it's because of a mitigation that was actually implemented to circumvent unquoted path exploits (such as C:\Program Files\blah.exe). I still don't know how this really works.
So, the script would report C:\ as being writable whereas it was not. PowerUp had the exact same issue by the way.

On Windows 10, this mitigation is probably still present although users no longer have the AddFile right as you pointed out.
This means, that even if the ACL would allow users to create files in C:\, they would not really be able to do so.

If you have a Windows 10 VM, you could create a snapshot and test this scenario. I'm actually quite curious about the result. πŸ™‚

from privesccheck.

SAERXCIT avatar SAERXCIT commented on July 22, 2024

Hmm, I'm not seeing this behaviour on my test VM (up-to-date 20H2 installed in version 20H2) where I manually set the CreateFile privilege on C:\ for Users:
Screenshot from 2021-02-18 18-46-16

(Non-privileged user, the ACLs on the C:\ directory allow Users to Read and Execute (RX) and Add File (WD) on the target directory, subdirectories, and files ((OI)(CI)), the non-privileged user still managed to copy C:\Windows\System32\cmd.exe to C:\Program.exe).

However I did have for some reason default ACLs granting Authenticated Users Modify access on the C:\ directory, I had to manually remove this ACL in order to test this. I don't know where that one came from. Moreover, once I actually tried to transform this into a privesc, I could not start the service (Error 1053: The Service did not Respond to the Start or Control Request in a Timely Fashion) with C:\Program.exe.

This is still pretty blurry to me because of the variables in play (is it Windows version-specific? Have I installed software that set this Modify ACL for Authenticated Users? Why didn't the service start after creating C:\Program.exe?), but based on this single observation it looks like this setup could result in a false negative by PrivescCheck.

from privesccheck.

SAERXCIT avatar SAERXCIT commented on July 22, 2024

So after further investigation and new Windows installations I was able to shed some light on these questions:

  • The ACLs of the C:\ directory seem to be edition-specific:

    • Windows 10 20H2 Pro N: An ACL allows Authenticated Users to Modify C:\ itself: Privesc possible by default
    • Windows 10 20H2 Enterprise: ACLs allow Authenticated Users to Modify subdirectories and files of C:\, and to CreateFolder on C:\ itself: Privesc not possible by default
    • Windows Server from 2012 R2 to 2019 1809: ACLs allow Users to CreateFile on subdirectories of C:\ only, and CreateFolder on C:\ itself and its subdirectories: Privesc not possible by default
  • Even though an error is shown, the illegitimate C:\program.exe is still being executed (on an up-to-date 10 20H2 Pro N), so it does not look like a mitigation is in place.

So from these test cases, enterprise-oriented editions seem to have restrictive default ACLs, while consumer-oriented editions do not? Interesting observation. Most importantly, PrivescCheck does not detect possible unquoted path privescs when non-privileged users are allowed to CreateFile in C:\ πŸ™‚

from privesccheck.

itm4n avatar itm4n commented on July 22, 2024

Wow! Thank you for your work! 😲
Conclusion: it's a mess. πŸ˜„
As I won't check every possible version of Windows, I will probably revert back to the original implementation.
Another thing I could do is try to create a random file such as C:\foo.txt and see if an error is triggered.
Although I'm not a big fan of this kind of solution, it would be really effective in this scenario.
What do you think?

from privesccheck.

SAERXCIT avatar SAERXCIT commented on July 22, 2024

To be honest I'm not really a fan of writing a file to disk either, I like the idea of being able to run PrivescCheck in-memory and it leaving (as far as I know ?) no trace on the FS (apart from potential PS logging I guess).

The Get-Acl command does include InheritanceFlags and PropagationFlags in each entry of its Access attribute. It surely is possible to use this info to retrieve whether the ACL applies to the directory itself. I'll try on my end, but you're welcome to try too/improve on it as I don't have a lot of PS experience. πŸ™ƒ

In the meantime, I agree that the original implementation does look better for now. Maybe if you feel like it with a disclaimer/warning in the banner, hopefully temporarily until we find a correct solution. πŸ™‚

from privesccheck.

itm4n avatar itm4n commented on July 22, 2024

OMG, I just had a "Eureka" moment. My assumption was based on something that someone told me a long time ago. But this was not correct and I never verified it by myself.
You're completely right. The PropagationFlags and InheritanceFlags values hold the information we need in order to handle such case properly. And actually, this is a broader issue as the same problem could also occur on other directories (although it's not that common).
This should be fixed directly in the Get-ModifiablePath function. I should make sure that, in the case of a Directory object, the ACE applies to the current folder by checking the value of PropagationFlags. If the ACE applies only to subdirectories I should just discard it.
I think that's it, that's the solution! πŸ™‚
I need to work on that this weekend, I'll keep you posted.

from privesccheck.

SAERXCIT avatar SAERXCIT commented on July 22, 2024

That was fast, well done! Your solution is way more elegant than what I would have come up with. πŸ™‚

Thank you for your work and for your detailled explanation, that is much appreciated. That issue was a good opportunity to learn about NTFS permissions.

I've tried on two VMs and it does work as expected, perfect!
Capture d’écran 2021-02-20 211719
(Left is actually vulnerable, Right is not as the only allowed action is CreateFolder.)

Cheers !

from privesccheck.

SAERXCIT avatar SAERXCIT commented on July 22, 2024

For information, update on this statement:

The ACLs of the C:\ directory seem to be edition-specific:

* Windows 10 20H2 **Pro N**: An ACL allows `Authenticated Users` to `Modify` `C:\` itself: Privesc **possible** by default
* Windows 10 20H2 **Enterprise**: ACLs allow `Authenticated Users` to `Modify` subdirectories and files of `C:\`, and to `CreateFolder` on `C:\` itself: Privesc **not possible** by default
* Windows Server from 2012 R2 to 2019 1809: ACLs allow `Users` to `CreateFile` on subdirectories of `C:\` only, and `CreateFolder` on `C:\` itself and its subdirectories: Privesc **not possible** by default

It turns out this issue seems to be specific to the first release of 20H2. 2004 did not have permissive ACLs, and a new version of the 20H2 iso has been released (Win10_20H2_v2_Language_x64.iso) which does not suffer from this issue (ACLs are the same as in 2004).

So I guess finding this specific privesc will be even more unlikely. πŸ™‚

from privesccheck.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.