共用方式為


IIS 6 prefixing paths with \?

One of the most fundamental security changes in IIS6 appends \\?\ to all filesystem access by IIS. This is supposed to be fairly transparent, but...

Question:

Dear comrades:

I have a cgi executable program that has worked just fine under W2000 Server. It also works fine when tested with Windows XP Pro.

Under W2003, the cgi executable works except when the cgi attempts to read a file from disk, please see the message reported below:

Cannot open file \\?\C:\Web\\Templates\DefaultTemplate.htm

Previously, the file path was not prefixed with \\?\ and everything worked as expected. The cgi found the path and loaded the template above. Can someone please shed some light as to what is now different under IIS 6?

Thank you,

Answer:

This looks like a bug in the CGI executable program exposed by IIS6.

\\?\ is a documented and existing syntax accepted by File IO API calls on Windows. Look up CreateFile and fopen on MSDN for more details.

For security reasons, IIS 6.0 uses \\?\ on all file system accesses (this includes serving of static files and loading of ISAPI DLLs and CreateProcess of CGI EXEs). \\?\ disables namespace canonicalization by the file system, which prevents a whole class of security issues related to canonicalization.

Since \\?\ is accepted by all File IO API calls on Windows, this change should transparently work downstream for any ISAPI DLL and CGI EXE.

A common failure pattern that I have seen happens when the custom ISAPI DLL or CGI EXE tries to interpret a filename and does so incorrectly ( for example, code that assumes that leading \\ means UNC share - this code will think that the UNC share server name is "?", which causes problems). This failure is basically a bug in the custom binary.

Now, please realize that this change in IIS 6 to append  \\?\ is by-design and cannot be changed/turned-off. The reason IIS 6 insists on this change is because of security. We knew that there will be a hit to application compatibility (i.e. exposing bugs in existing code, even if righteous, is not good compatibility), but the security gained from eliminating this canonicalization risk is worth the change.

See this other post for related possibilities.

//David

Comments

  • Anonymous
    July 13, 2005
    Thank you very much for the detailed explanation.

    Best regards,

    Alex

  • Anonymous
    July 15, 2005
    If ? is valid synthax, why the following .net 2.0 code does not work:

    System.IO.File.ReadAllText(@"?c:boot.ini");

  • Anonymous
    July 15, 2005
    Very good question.

    You must realize that ? is a Windows concept while .Net Framework and System.IO namespace are OS agnostic. This means that you cannot assume that .Net code on Windows allows ? .

    Two reasons:
    1. The .Net Framework is not tied to Windows nor Win32 API and its File IO namespace should be agnostic of the underlying platform. Since other file systems may not support ? , the .Net File IO API should not do anything "special" to make ? work.
    2. The .Net Framework runs on older Win9x OS which do not support ? syntax

    All of this means that if you want to write platform independent .Net code, you cannot explicitly use ? . The .Net Framework itself my internally use ? on appropriate Windows platforms for its own reasons, but from a conceptual standpoint for users of .Net, ? is not a valid concept.

    //David

  • Anonymous
    July 19, 2005
    The Windows INI-File API calls seems to have problems with ? filenames too. In my CGI exe I did use some INI files which don't anymore work under IIS6. Removing the ? from the Path does solve the problem.

  • Anonymous
    July 19, 2005
    Please give:
    1. an example of your exact INI file API call
    2. the exact strings you are using on the API call
    3. what makes you think the GetPrivate* API has problems with ?

    I believe the problem is that your code depends on file system canonicalization to function, and it should not.

    //David

  • Anonymous
    June 29, 2006
    The comment has been removed

  • Anonymous
    June 29, 2006
    Bert - Your error references a missing permission of the Internet Zone to read from the local Environment, so it looks like a problem in the configuration of your CGI within the .Net Framework on the new server. I suggest looking up documentation for CAS Policy on .Net.

    //David

  • Anonymous
    August 23, 2006
    Thanks for the article, I think it explains a problem I'm having with a cgi executable that doesn't run when moved from IIS 5 to IIS 6. It returns an error to the browser
    "Cannot find  ?C:Inetpubwwwrootappnamecgi-binapp.ini". Would I be right in thinking that I'd have to get an updated version of the application from the original vendor (purchased application, no source code available), or is there anything I might be able to do to get it to work on IIS 6?

  • Anonymous
    April 18, 2007
    Does this submission form work?

  • Anonymous
    April 18, 2007
    If a CGI .EXE program invokes a COM visible .NET DLL which executes, for example: ConnectionStringSettingsCollection conStrings = ConfigurationManager.ConnectionStrings; Then the following exception occurs: System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize ---> System.ArgumentException: Illegal characters in path. This appears to stem from the .NET (2.0) Framework’s failure to determine if the application has a configuration file using a path containing the prefix '?'. Please is there any way around this?

  • Anonymous
    April 18, 2007
    If a CGI .EXE program invokes a COM visible .NET DLL which executes, for example: ConnectionStringSettingsCollection conStrings = ConfigurationManager.ConnectionStrings; Then the following exception occurs: System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize ---> System.ArgumentException: Illegal characters in path. This appears to stem from the .NET (2.0) Framework’s failure to determine if the application has a configuration file using a path containing the prefix '?'. Please is there any way around this?

  • Anonymous
    June 26, 2007
    In my application I have the same problem exposed... I have a CGI that invokes a COM .NET DLL which make a connection to a database. A soon as the COM make the Connection.Open it generates an exception: Configuration system failed to initialize ---> System.ArgumentException: Illegal characters in path. I use IIS 6.0 as the Web Server. Is there any work around to solve this? It's urgent i need absolutely help.

  • Anonymous
    June 27, 2007
    I have solved the issue adding the CGI exe in the allowed ISAPI extension, under the properties of the Web Site.

  • Anonymous
    July 01, 2007
    mikey123, Daniele - hmm, weird resolution. I see no reason why Web Service Extensions in IIS has any interaction with Managed code parsing of a path string, but if it works for you, great! //David

  • Anonymous
    July 31, 2007
    I have the same issue as Daniele but in IIS 7 after calling sqlconnection. Not good for interoperability.

  • Anonymous
    August 02, 2007
    The comment has been removed