What are Permissions?File permissions are a method for helping to prevent unauthorized access to files and folders on a computer. The file system keeps track of the permissions on a given file by maintaining Access Control Lists (ACLs). There are two popular types of access controls that apply to file systems (and sometimes to resources on the file system as well):
- Discretionary Access Controls (DAC): The discretionary in discretionary access controls means that the permissions on a file or folder are set by the individuals or groups that own it (or have sufficient access to the file or folder). For example, if you create a text document, you can control who can modify it or read it.
- Mandatory Access Controls (MAC): Mandatory access controls are set by the administrator of a system and are enforced by the operating system. As opposed to discretionary access controls, users and groups cannot change the permissions on a resource like a file. Instead, each file is assigned a security label, and your level of access depends on the access your user or group has to objects holding that security label. A popular example of MAC is SELinux.
- Role-Based Access Controls (RBAC / RoBAC): Users on systems enforcing role-based access controls are assigned roles typically based on their function in the organization. For example, there might be an Engineer role. Your access to a file depends on your role in the organization. With this system, all individuals or groups in a role have the same permissions. Eve the Engineer has the same permissions as Bob the Engineer because they both have the Engineer role. This makes things less complicated, but can be problematic if you need granular access controls.
- Rule-Based Access Controls (RBAC / RuBAC): Rule based access control is similar to MAC. When a user wants to access a given resource, the operating system checks if that user should be granted access by looking at the rules defined in the access control lists for that resource. Users cannot change these ACLs. An example of rule based access control is restricting access to the Internet during certain hours.
Permissions in NTFSNTFS uses discretionary access controls. On your local Windows system using a drive formatted with NTFS, there are five basic permissions you can set on a file:
- Read: A user with Read permissions can read the contents and metadata (properties) of the file.
- Read and Execute: A user with Read and Execute permissions can read the file and its metadata as well as execute (run) the file. Execution can happen on executables and scripts.
- Write: A user can write to a file, but they cannot take control of it or change its properties.
- Modify: A user can view and modify the properties of a file, but not change its contents or permissions.
- Full Control: A user can do anything to the file including take ownership of it.
- Another permission: List Folder Contents - Exactly what it sounds like :).
- Modify: A user can remove and add files to the directory.
In the top half of the pane, you see the users and groups that have access (or are denied access) to the file. The check marks indicate the permissions that the user or group have on the file. You can see here that Users on the local system can Read and Read and Execute notepad.exe. What would happen if the check mark next to Write, Modify, or Full Control was checked for notepad.exe?
When File System Permissions Are Not Set Correctly
If a user could make changes to something like notepad.exe, that could be problematic because the user could replace notepad.exe with another executable that looks and acts like notepad.exe but contains a key logger or something else. What would be worse is if the executable with incorrect permissions was executed as SYSTEM. That could allow a malicious user to execute arbitrary code as SYSTEM (the highest user on a Windows system). This is an example of privilege escalation.
That is the gist of the article I linked to at the bottom of this post. Essentially, a common application had the correct file permissions for its service executable, but one of the components (a second executable) that the service executable ran had permissions such that any authenticated user on the machine could write to it. This means that if a malicious user overwrote the second executable, the code that the malicious user substituted would be run as SYSTEM. That is not good.
So What Can We Do?
I thought about the issue, and I thought it would be good to have a script that you could run on any folder on your system and it will tell you if there are any executable files that have Write or Full Control allowed for a user that is not SYSTEM, an Administrator, or TrustedInstaller. If someone has SYSTEM or administrative access to your system, they have already escalated privileges, and this problem is moot. TrustedInstaller is a mechanism that Microsoft introduced with Windows Vista that helps to maintain the integrity of key system files (listed here). If an attacker is able to use this to control your system, they have already escalated privileges as well, and they do not need to escalate them via the method we have been talking about.
When I thought about writing the script, I had to think about what language to write it in. I am most familiar with Python, and Python has the tools to accomplish this task. However, Python is not installed on every Windows machine, so I did not want to make that a dependency. There is one tool that is available on every Windows box from Windows 7 on (and each corresponding server edition): Powershell. Powershell is also available to download for Windows XP, Server 2003, Vista, and Server 2008. So, in order to make this tool as useful as possible, I decided to try to code it in Powershell (which I have never coded in before). While you are looking at the code, keep in mind that there may be better ways to do this, and if there are, please let me know. I think Powershell is an interesting tool, and I would like to get better at it.
The code is available on GitLab, but we will talk through how it works in general. The source code contains full comments.
Essentially, the script does five things:
- Given a directory (or directories) to search, the script gets all of the files and folders recursively for each directory (Get-ChildItem).
- For each item, it looks to see if it is a file or a folder (checks if the file type is a Container (folder)).
- If it is an executable file, the script will get the access control lists for the file using Get-Acl. For us, an executable is an exe (Windows executable file), DLL (dynamically linked library), COM (DOS executable - they still exist), BAT (Windows batch file), PS1 (Powershell script), CMD (Windows batch file), VBS (Visual Basic Script), VBE (Encoded VisualBasic script), WSF (Windows Script File), and WSH (Windows Script Host - a fancy batch file). If hijacked, these files may be run by another user and become a vector for privilege escalation. This is not guaranteed, of course, but this script helps you find potential issues that you can investigate further.
- Get-Acl returns a System.Security.AccessControl object. Within that object, there is a property called Access, which is a FileSystemAccessRule object. That Access object has two properties we are interested in:
- FileSystemRights: FileSystemRights tells us permissions on the file (analogous to the checkboxes in the dialog box above).
- IdentityReference: IdentityReference tells us who has those permissions on the file.
- The script checks to see if any user except Administrator, SYSTEM, and TrustedInstaller has Write or Full Control access to the object. We talked about this above. The names of these files are printed to the screen. You can then investigate them to see if they might be a problem.
What should the permissions be?To answer this question, we need to talk about the principle of least privilege. The principle of least privilege says that a user in a system should have everything he needs to do his job and nothing more. What exactly that entails depends on the user, their role, and the rules in place in the organization. As a rule of thumb, it is good to give SYSTEM and Administrators Full Control (if this makes sense in your organization). TrustedInstaller only concerns Windows system files, and there is no need for you to manage it since Windows takes care of that. Also, the CREATOR OWNER of the file should also have Full Control.
We have not talked about CREATOR OWNER yet because it is a bit abstract. It is a sort of alias for whoever happens to own the file when it is accessed. You cannot say who is in the group, but you can restrict its access.
Authenticated users should have read and execute permissions (if executing the file is allowed for them), and nothing for everyone else.
Final ThoughtsNTFS allows you to have granular control over file permissions. We only talked about local file permissions in this article, but this is a good start. If you have suggestions to make the script better or more useful, please let me know. If we can help pick this low hanging fruit, our collective defensive posture will be just a bit better.
Thanks for reading!