Exploiting Blind File Reads / Path Traversal Vulnerabilities on Microsoft Windows Operating Systems
In a recent engagement I was confronted with a blind path traversal vulnerability on a server running with the Microsoft Windows operating system. That is, it was not possible to display folder contents but the complete file name and path had to be guessed. Due to the lack of a comprehensive website I was forced to gather information from various different sources.
In this blog post, I want to summarize my findings and focus on the exploitation of this kind of vulnerability.
Admittedly, vanilla path traversal vulnerabilities have become somewhat rare and Microsoft Windows as a server operating system is also more of an exception than the rule. However, in an XXE scenario, you may encounter a similar situation.
Also, this post will not shed light on the detection of this vulnerability - which is an art in itself and has already been thoroughly documented. In a nutshell, the key to the successful detection is to guess the correct path of a world-readable file (with the correct encoding).
Identifying vulnerable Applications
On Microsoft Windows, the following files are good choices since they are present in almost every version:
c:\windows\system.ini
c:\windows\win.ini
Assuming you have successfully identified a path traversal vulnerability, the only question is how further it can be escalated. The major obstacle is that you usually have to know in advance the exact location of the files you want to read. As opposed to *nix-based operating systems, the locations can differ significantly from one Windows installation to another. For instance, the main system drive letter may not be C:
or the user name may differ from the standard Administrator
.
First and foremost, we have to recall a few key characteristics of Windows operating systems:
- Files and directories are handled case-insensitive: From an attacker perspective, our life will be easier since we only have to probe one variation of a given location. For example it suffices to test for
../../windows/win.ini
instead of attempting also../../WINDOWS/win.ini
. - Forward and backward slashes can most of the times be used interchangeably; e.g.,
../..\../windows/win.ini
is a valid file path in Windows.
Determining the Privilege Level of the reading Process
In order to assess the severity of a path traversal bug, you should determine the privilege level of the process that peforms the file retrieval. From an attacker perspective, the process should ideally run with elevated privileges, i.e. by LocalSystem
(= root equivalent) or by a member of the Administrators
group.
If you can successfully retrieve one of the following files, you are at least a member of the Administrators group:
c:/documents and settings/administrator/ntuser.ini
c:/documents and settings/administrator/desktop/desktop.ini
c:/users/administrator/desktop/desktop.ini
c:/users/administrator/ntuser.ini
As already mentioned, there is a catch to this approach - there might be no such user account. In this case, you have to guess the name of an administrator account.
In contrast, the following files should be available on all modern Windows operating systems and are independent from the set up:
c:/system volume information/wpsettings.dat
C:/Windows/CSC/v2.0.6/pq
C:/Windows/CSC/v2.0.6/sm
C:/$Recycle.Bin/S-1-5-18/desktop.ini
If you can read either of these files, the file reading process has LocalSystem
privileges.
Determining the Windows Version
Moreover, you should determine the exact version of Microsoft Windows. On Linux this is again far more simple, since we can read files such as the following:
/etc/issue
/etc/*release
/proc/version
Up until Windows 10, there is a similar file also containing version information, namely at
c:/windows/system32/license.rtf
It is also present on Windows 10, but it does not contain version information (which can also be used as a blind indicator).
The best way is, however, to retrieve a Microsoft-compiled executable from the target system and analyze the included version information in the file properties
tab. Possible candidates are:
c:/windows/explorer.exe
c:/windows/notepad.exe
c:/windows/system32/ntoskrnl.exe
Afterwards, you can consulting the following table for looking up the corresponding operating system version:
10.0 = Windows 10 / Windows Server 2016
6.3 = Windows 8.1 / Windows Server 2012 R2
6.2 = Windows 8 / Windows Server 2012
6.1 = Windows 7 / Windows Server 2008 R2
6.0 = Windows Vista / Windows Server 2008
5.2 = Windows XP 64 Bit / Windows Server 2003
5.1 = Windows XP
5.0 = Windows 2000
4.0 = Windows NT 4
Instead of the file properties tab, you can also use the peinfo package for Python to analyze the version number as follows:
Finetuning
To exploit the full potential of the path traversal vulnerability, you will likely have to perform an educated brute-force or dictionary attack, as the interesting files are technology-dependent.
The following list may be helpful as a first step and I would appreciate any additions or comments to this list:
https://github.com/soffensive/windowsblindread
References and follow-up links:
Web Application Hacker’s Handbook, 2nd Edition
https://www.owasp.org/index.php/Testing_Directory_traversal/file_include_(OTG-AUTHZ-001)
https://github.com/mubix/post-exploitation-wiki/blob/master/windows/files.md
http://pwnwiki.io/#!presence/windows/blind.md
https://blog.netspi.com/smb-attacks-through-directory-traversal/
https://digi.ninja/blog/when_all_you_can_do_is_read.php
https://superuser.com/questions/363018/how-do-i-tell-what-version-and-edition-of-windows-is-on-the-filesystem
https://docs.microsoft.com/en-us/windows/desktop/sysinfo/operating-system-version
https://docs.microsoft.com/en-us/windows/desktop/api/verrsrc/ns-verrsrc-tagvs_fixedfileinfo
https://stackoverflow.com/questions/1264472/using-the-pefile-py-to-get-file-exe-version