icacls: rewriting NTFS permissions to read a file
icacls is the Windows utility to view and modify the access control lists (ACLs) of NTFS files and folders. In post-exploitation it solves a concrete, common problem: having a privileged session but being unable to read a file because its ACL does not include your identity. If you can change the ACL, you grant yourself access and read it.
Why SYSTEM cannot always read everything. It is a common mistake to think NT AUTHORITY\SYSTEM opens everything. Access to a file is decided by its ACL, not by the account's "rank": if root.txt's ACL only grants Administrator and the user who created it, a SYSTEM shell gets Access is denied. What does give SYSTEM/Administrator power is the ability to take ownership and rewrite the ACL.
The move. Grant full control to your identity over the file and read it:
icacls root.txt # see the current ACL (who can read)
takeown /f root.txt # take ownership if you are not the owner
icacls root.txt /grant "nt authority\system":F # grant yourself full control
type root.txt
accesschk.exe -quv "%username%" C:\path # find objects where you can rewrite the ACL/grant <user>:F adds a full-control ACE (F); if ownership is needed first, use takeown /f <file>. After the change, the read is no longer denied.
When it shows up. It is the typical finish on boxes where you reach SYSTEM via a service (e.g. psexec.py after reusing a password) but the flag has a restrictive ACL excluding SYSTEM. It also serves to open protected config or credential files.
Hint vs proof. Access is denied does not mean "impossible": it means that identity is not in the ACL. The proof you can bypass it is being able to run the /grant successfully (Successfully processed 1 files), confirming you hold WRITE_DAC/ownership over the object.
How to detect it. With object-access auditing enabled, an ACL change raises Event ID 4670 ("permissions on an object were changed") and taking ownership raises 4674/use of SeTakeOwnershipPrivilege; running icacls /grant or takeown lands in 4688 (process creation) and, with Sysmon, in Event ID 1 with the full command line. The signature is a /grant on a sensitive file (root.txt, web.config, a .kdbx) by an account that just gained privilege, followed by reading it (4663 read on the same object). A takeown followed by icacls /grant over files the account didn't create is the unmistakable pattern.
Defence. Keeping minimal ACLs does not stop SYSTEM/Administrator (they can rewrite them), so the real mitigation is not letting an attacker reach those identities; audit ACL changes (takeown/icacls, events 4670/4674) with event logging. Related to SeImpersonatePrivilege abuse and credential reuse.
Machines where it's used
- ChatterboxHackTheBox