2

Background

I am attempting to perform a path traversal attack on a vulnerable service hosted in IIS.

The service is something like this:

GET /api/download/{file-name}

The underlying code is something like this:

return File.Read("some/directory/" + fileName);

As written, this service is clearly vulnerable.

Kestrel Attack

I can perform a path traversal attack when running locally using dotnet run, which I gather uses the Kestrel web server. My attack payload is ..\..\secret.txt, which is encoded and visible in the log:

Request starting HTTP/1.1 GET http://localhost/api/download/..%5C..%5Csecret.txt

IIS Attack

I cannot reproduce this attack on the same app when hosted in IIS. It appears that IIS somehow normalizes the URI by interpreting the ..\, which means it never hits my API. In other words, it attempts to hit the following endpoint:

GET http://localhost/secret.txt

I have tried a variety of different encodings for the ..\ character sequence, but no luck.

Question

How can I work around this IIS behavior to perform a path traversal attack on this vulnerable app, hosted in IIS?

srk
  • 1,625
  • 1
  • 10
  • 26

2 Answers2

2

There appear to be several things preventing my path traversal attack. I was able to perform a path traversal attack by (1) double-encoding the payload and (2) removing or undermining the RequestFilteringModule and UrlRoutingModule modules in IIS. I was not able to reproduce an attack if either of these modules was present and fully-enabled.

Encoding

First, I had to encode the \ character in my attack payload.

When I simply URL encode once, IIS (I assume) normalizes the URI, as I observed before:

  • Request observed in browser: http://localhost/api/download/..%5C..%5Csecret.txt
  • URI in IIS logs on server: http://localhost/secret.txt

When when I perform the encoding twice, my payload does make it through to IIS:

  • Request observed in browser: http://localhost/api/download/..%255c..%255csecret.txt
  • URI in IIS logs on server: http://localhost/api/download/..%5C..%5Csecret.txt

RequestFilteringModule

The RequestFilteringModule module responds to my attack with a 404 response:

The request filtering module is configured to deny a request that contains a double escape sequence.

We can disable this feature by removing the module or setting the allowDoubleEscaping flag in web.config or IIS:

<system.webServer>
  <security>
    <requestFiltering allowDoubleEscaping="true" />
  </security>
</system.webServer>

UrlRoutingModule

The UrlRoutingModule module responds to my attack with a 400 response:

A potentially dangerous Request.Path value was detected from the client (%).

We can disable this feature by removing the module or modifying the requestPathInvalidCharacters setting in web.config:

<system.web>
  <httpRuntime requestPathInvalidCharacters="" />
</system.web>

Conclusion

The code in question is clearly vulnerable and should be fixed. That said, it appears that using either one of the RequestFilteringModule or UrlRoutingModule modules in IIS does effectively prevent my path traversal attack, provided the module(s) are fully-enabled.

srk
  • 1,625
  • 1
  • 10
  • 26
0

This is blocked right in the IIS kernel level.

Here's the relevent text:

Unsafe:

Characters can be unsafe for a number of reasons. The space character is unsafe because significant spaces may disappear and insignificant spaces may be introduced when URLs are transcribed or typeset or subjected to the treatment of word-processing programs. The characters "<" and ">" are unsafe because they are used as the delimiters around URLs in free text; the quote mark (""") is used to delimit URLs in some systems. The character "#" is unsafe and should always be encoded because it is used in World Wide Web and in other systems to delimit a URL from a fragment/anchor identifier that might follow it. The character "%" is unsafe because it is used for encodings of other characters. Other characters are unsafe because gateways and other transport agents are known to sometimes modify such characters. These characters are "{", "}", "|","\", "^", "~", "[", "]", and "`".

All unsafe characters must always be encoded within a URL. For example, the character "#" must be encoded within URLs even in systems that do not normally deal with fragment or anchor identifiers, so that if the URL is copied into another system that does use them, it will not be necessary to change the URL encoding.

So IIS proactively blocks this up at the core level, a proactive security measure to minimize their attack surface.

There is a similar question in this link.

Ding Peng
  • 3,702
  • 1
  • 5
  • 8
  • This does not answer my question. The text you quoted says "all unsafe characters must always be encoded within a URL." But even if I encode these characters, I observe the same behavior. Also, in the future, if you directly copy-paste someone else's answer, I think you should explicitly say as much (and give them credit). – srk Jan 12 '21 at 13:58