Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ampersand in folder name when browsing physical directory #306

Open
sborkman opened this issue Sep 5, 2019 · 2 comments
Open

Ampersand in folder name when browsing physical directory #306

sborkman opened this issue Sep 5, 2019 · 2 comments

Comments

@sborkman
Copy link

sborkman commented Sep 5, 2019

I have a website that utilizes physical directory browsing. Here's my code:

    public void Configuration(IAppBuilder app)
    {   
                
        AreaRegistration.RegisterAllAreas();

        HttpConfiguration config = GlobalConfiguration.Configuration;
		//config.MessageHandlers.Add(new CustomHeaderHandler()); // Added this for no caching
		//System.Web.Http.GlobalConfiguration.Configure(Startup.Register);
		config.MessageHandlers.Add(new CancelledTaskBugWorkaroundMessageHandler());
		config.EnsureInitialized();
		//app.UseWebApi(config);


        AutofacConfig.RegisterAutoFac(config);

        RegisterRoutes(RouteTable.Routes);
        GlobalFilters.Filters.Add(new HandleErrorAttribute());                        
       
        app.UseStaticFiles();
        ConfigureStaticFiles(app);
    }

    private void ConfigureStaticFiles(IAppBuilder app)
    {

		

		//app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
		//app.Use(typeof(ToolDirectory.Web.Middleware));

		app.UseStageMarker(PipelineStage.MapHandler);
        var wwwroot = BuildFileServerOptions(string.Empty, "wwwroot");
        app.UseFileServer(wwwroot);

		// http://stackoverflow.com/questions/37035175/net-owin-self-host-with-with-no-caching

		var downloads = BuildFileServerOptions("/Downloads", Properties.Settings.Default.DownloadDirectory);
        downloads.StaticFileOptions.ServeUnknownFileTypes = true;
        downloads.EnableDirectoryBrowsing = true;
        app.UseFileServer(downloads);
		


		var attachments = BuildFileServerOptions("/Attachments", Properties.Settings.Default.AttachmentDirectory);
        attachments.StaticFileOptions.ServeUnknownFileTypes = true;
        attachments.EnableDirectoryBrowsing = true;
		app.UseFileServer(attachments);
		
    }

    private static FileServerOptions BuildFileServerOptions(string requestPath, string physicalPath)
    {
        var options = new FileServerOptions
        {
            RequestPath = new PathString(requestPath),
            FileSystem = new PhysicalFileSystem(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, physicalPath)),
            EnableDefaultFiles = true
        };

        return options;
    }

Everything's been working fine, until a user created a folder with an ampersand. The URL in the OWIN-generated directory-browsing page doesn't properly escape the ampersand (although it DOES appear to escape spaces, which is interesting). When a user clicks on the link, it results in an error.

Here's what the URL on the OWIN-generated directory-browsing page might look like:
http://localhost:1234/downloads/Phast/Phast%20&%20Safeti%208.11/

Notice the ampersand is NOT escaped.

The error in IIS is:
System.Web.HttpException:
A potentially dangerous Request.Path value was detected from the client (&).

My project targets .Net Framework 4.6.1
I'm using Microsoft.Owin Nuget packages with version 4.0.1

I suspect the fix for this will be to use System.Web.HttpUtility.UrlEncode for URLs, rather than ONLY escaping spaces.

@Tratcher
Copy link
Member

Tratcher commented Sep 5, 2019

That code is here:

foreach (var subdir in contents.Where(info => info.IsDirectory))
{
builder.AppendFormat(@"
<tr class=""directory"">
<td class=""name""><a href=""{0}/"">{0}/</a></td>
<td></td>
<td class=""modified"">{1}</td>
</tr>",
HtmlEncode(subdir.Name),
HtmlEncode(subdir.LastModified.ToString(CultureInfo.CurrentCulture)));
}
foreach (var file in contents.Where(info => !info.IsDirectory))
{
builder.AppendFormat(@"
<tr class=""file"">
<td class=""name""><a href=""{0}"">{0}</a></td>
<td class=""length"">{1}</td>
<td class=""modified"">{2}</td>
</tr>",
HtmlEncode(file.Name),
HtmlEncode(file.Length.ToString("n0", CultureInfo.CurrentCulture)),
HtmlEncode(file.LastModified.ToString(CultureInfo.CurrentCulture)));
}

It is HtmlEncoding the folder name via WebUtility:

private static string HtmlEncode(string body)
{
return WebUtility.HtmlEncode(body);
}

Hmm, maybe that should be url encoded before html encoding it. Or the href portion and the display portion need to be encoded differently.

Note this code also exists in Core.
https://github.com/aspnet/AspNetCore/blob/7317bb16a9cd5a834c0468a74113055031262217/src/Middleware/StaticFiles/src/HtmlDirectoryFormatter.cs#L134-L213

@Tratcher
Copy link
Member

Tratcher commented Sep 5, 2019

That said, '&' is a valid url path character. I wonder why it's being filtered. Looks like a common complaint:
https://www.hanselman.com/blog/ExperimentsInWackinessAllowingPercentsAnglebracketsAndOtherNaughtyThingsInTheASPNETIISRequestURL.aspx

@Tratcher Tratcher added this to the Discussions milestone Sep 18, 2019
@Tratcher Tratcher modified the milestones: Discussions, Backlog Sep 3, 2020
@Tratcher Tratcher self-assigned this Sep 3, 2020
@Tratcher Tratcher modified the milestones: Backlog, 4.1.1 Sep 3, 2020
@Tratcher Tratcher removed their assignment Sep 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants