Security problem of mapping file structure of Azure Web App and other IIS APP – part 1.
If you deploy sample ASP.NET 4.x pure, out of the box web app (https://portal.azure.com/#create/Microsoft.WebSite) the behaviors is like:
https://pure.azurewebsites.net/yfgrueygfuyrgfrf – 404 error – what is ok…
https://pure.azurewebsites.net/a/a.txt – 200 OK (of course you need first put a.txt file to this directory)
https://pure.azurewebsites.net/a/ – 403 forbidden – so it means that hacker can search for something here. Expected secure behavior is to return here 404 also…
I tried to test UMBRACO CMS deployed from Azure marketplace (https://portal.azure.com/#create/umbracoorg.UmbracoCMS) what seems to be written to avoid mapping file structure – just see:
https://umbrecomf.azurewebsites.net/wruihfgweihgufr – 404 error
https://umbrecomf.azurewebsites.net/a/a.txt – 200 – OK (of course you need first put a.txt file to this directory)
https://umbrecomf.azurewebsites.net/a/ – Also 404… – What is OK…. We need this behavior…
This behavior is because the UMBRACO CMS is routing all requests into the Umbraco app (<modules runAllManagedModulesForAllRequests=”true”>) – and when the CMS encounters a path that hasn’t been configured in their system, it returns a 404. So it is addressed programmatically.
UMBRACO CMS web.config:
<?xml version=”1.0″ encoding=”utf-8″?>
<configuration>
<!–
Define the Web.config template, which is used when creating the initial Web.config,
and then transforms from web.Template.[Debug|Release].config are applied.
Documentation for Web.config at: https://our.umbraco.com/documentation/Reference/Config/webconfig/
–>
<configSections>
<section name=”clientDependency” type=”ClientDependency.Core.Config.ClientDependencySection, ClientDependency.Core” requirePermission=”false” />
<sectionGroup name=”umbracoConfiguration”>
<section name=”settings” type=”Umbraco.Core.Configuration.UmbracoSettings.UmbracoSettingsSection, Umbraco.Core” requirePermission=”false” />
<section name=”HealthChecks” type=”Umbraco.Core.Configuration.HealthChecks.HealthChecksSection, Umbraco.Core” requirePermission=”false” />
</sectionGroup>
<sectionGroup name=”imageProcessor”>
<section name=”security” requirePermission=”false” type=”ImageProcessor.Web.Configuration.ImageSecuritySection, ImageProcessor.Web” />
<section name=”processing” requirePermission=”false” type=”ImageProcessor.Web.Configuration.ImageProcessingSection, ImageProcessor.Web” />
<section name=”caching” requirePermission=”false” type=”ImageProcessor.Web.Configuration.ImageCacheSection, ImageProcessor.Web” />
</sectionGroup>
</configSections>
<umbracoConfiguration>
<settings configSource=”config\umbracoSettings.config” />
<HealthChecks configSource=”config\HealthChecks.config” />
</umbracoConfiguration>
<clientDependency configSource=”config\ClientDependency.config” />
<appSettings>
<add key=”Umbraco.Core.ConfigurationStatus” value=”8.13.0″ />
<add key=”Umbraco.Core.ReservedUrls” value=”” />
<add key=”Umbraco.Core.ReservedPaths” value=”” />
<add key=”Umbraco.Core.Path” value=”~/umbraco” />
<add key=”Umbraco.Core.HideTopLevelNodeFromPath” value=”true” />
<add key=”Umbraco.Core.TimeOutInMinutes” value=”20″ />
<add key=”Umbraco.Core.DefaultUILanguage” value=”en-US” />
<add key=”Umbraco.Core.UseHttps” value=”false” />
<add key=”Umbraco.Core.AllowContentDashboardAccessToAllUsers” value=”true” />
<add key=”ValidationSettings:UnobtrusiveValidationMode” value=”None” />
<add key=”webpages:Enabled” value=”false” />
<add key=”enableSimpleMembership” value=”false” />
<add key=”autoFormsAuthentication” value=”false” />
<add key=”dataAnnotations:dataTypeAttribute:disableRegEx” value=”false” />
<add key=”owin:appStartup” value=”UmbracoDefaultOwinStartup” />
<add key=”Umbraco.ModelsBuilder.Enable” value=”true” />
<add key=”Umbraco.ModelsBuilder.ModelsMode” value=”PureLive” />
</appSettings>
<!–
Important: if you’re upgrading Umbraco, do not clear the connectionString/providerName during your Web.config merge.
–>
<connectionStrings>
<remove name=”umbracoDbDSN” />
<add name=”umbracoDbDSN” connectionString=”Data Source=|DataDirectory|\Umbraco.sdf;Flush Interval=1;” providerName=”System.Data.SqlServerCe.4.0″ />
</connectionStrings>
<system.data>
<DbProviderFactories>
<remove invariant=”System.Data.SqlServerCe.4.0″ />
<add name=”Microsoft SQL Server Compact Data Provider 4.0″ invariant=”System.Data.SqlServerCe.4.0″ description=”.NET Framework Data Provider for Microsoft SQL Server Compact” type=”System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe” />
</DbProviderFactories>
</system.data>
<system.net>
<mailSettings>
<!–
If you need Umbraco to send out system mails (like reset password and invite user),
you must configure your SMTP settings here – for example:
–>
<!–
<smtp from=”noreply@example.com” deliveryMethod=”Network”>
<network host=”localhost” port=”25″ enableSsl=”false” userName=”” password=”” />
</smtp>
–>
</mailSettings>
</system.net>
<system.web>
<customErrors mode=”RemoteOnly” />
<trace enabled=”false” requestLimit=”10″ pageOutput=”false” traceMode=”SortByTime” localOnly=”true” />
<httpRuntime requestValidationMode=”2.0″ enableVersionHeader=”false” targetFramework=”4.7.2″ maxRequestLength=”51200″ fcnMode=”Single” />
<httpModules>
<add name=”ScriptModule” type=”System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ />
<add name=”UmbracoModule” type=”Umbraco.Web.UmbracoModule,Umbraco.Web” />
<add name=”ClientDependencyModule” type=”ClientDependency.Core.Module.ClientDependencyModule, ClientDependency.Core” />
<add name=”ImageProcessorModule” type=”ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web” />
</httpModules>
<httpHandlers>
<remove verb=”*” path=”*.asmx” />
<add verb=”*” path=”*.asmx” type=”System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ validate=”false” />
<add verb=”*” path=”*_AppService.axd” type=”System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ validate=”false” />
<add verb=”GET,HEAD” path=”ScriptResource.axd” type=”System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ validate=”false” />
<add verb=”*” path=”DependencyHandler.axd” type=”ClientDependency.Core.CompositeFiles.CompositeDependencyHandler, ClientDependency.Core ” />
</httpHandlers>
<compilation defaultLanguage=”c#” debug=”false” batch=”true” targetFramework=”4.7.2″ numRecompilesBeforeAppRestart=”50″ />
<authentication mode=”Forms”>
<forms name=”yourAuthCookie” loginUrl=”login.aspx” protection=”All” path=”/” />
</authentication>
<authorization>
<allow users=”?” />
</authorization>
<!– Membership Provider –>
<membership defaultProvider=”UmbracoMembershipProvider” userIsOnlineTimeWindow=”15″>
<providers>
<clear />
<add name=”UmbracoMembershipProvider” type=”Umbraco.Web.Security.Providers.MembersMembershipProvider, Umbraco.Web” minRequiredNonalphanumericCharacters=”0″ minRequiredPasswordLength=”10″ useLegacyEncoding=”false” enablePasswordRetrieval=”false” enablePasswordReset=”false” requiresQuestionAndAnswer=”false” defaultMemberTypeAlias=”Member” passwordFormat=”Hashed” allowManuallyChangingPassword=”false” />
<add name=”UsersMembershipProvider” type=”Umbraco.Web.Security.Providers.UsersMembershipProvider, Umbraco.Web” />
</providers>
</membership>
<!– Role Provider –>
<roleManager enabled=”true” defaultProvider=”UmbracoRoleProvider”>
<providers>
<clear />
<add name=”UmbracoRoleProvider” type=”Umbraco.Web.Security.Providers.MembersRoleProvider” />
</providers>
</roleManager>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration=”false” />
<modules runAllManagedModulesForAllRequests=”true”>
<remove name=”WebDAVModule” />
<remove name=”UmbracoModule” />
<remove name=”ScriptModule” />
<remove name=”ClientDependencyModule” />
<remove name=”FormsAuthentication” />
<remove name=”ImageProcessorModule” />
<add name=”UmbracoModule” type=”Umbraco.Web.UmbracoModule,Umbraco.Web” />
<add name=”ScriptModule” preCondition=”managedHandler” type=”System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ />
<add name=”ClientDependencyModule” type=”ClientDependency.Core.Module.ClientDependencyModule, ClientDependency.Core” />
<!– FormsAuthentication is needed for login/membership to work on homepage (as per http://stackoverflow.com/questions/218057/httpcontext-current-session-is-null-when-routing-requests) –>
<add name=”FormsAuthentication” type=”System.Web.Security.FormsAuthenticationModule” />
<add name=”ImageProcessorModule” type=”ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web” />
</modules>
<handlers accessPolicy=”Read, Write, Script, Execute”>
<remove name=”WebServiceHandlerFactory-Integrated” />
<remove name=”ScriptHandlerFactory” />
<remove name=”ScriptHandlerFactoryAppServices” />
<remove name=”ScriptResource” />
<remove name=”ClientDependency” />
<remove name=”MiniProfiler” />
<remove name=”ExtensionlessUrlHandler-Integrated-4.0″ />
<remove name=”OPTIONSVerbHandler” />
<remove name=”TRACEVerbHandler” />
<add name=”ScriptHandlerFactory” verb=”*” path=”*.asmx” preCondition=”integratedMode” type=”System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ />
<add name=”ScriptHandlerFactoryAppServices” verb=”*” path=”*_AppService.axd” preCondition=”integratedMode” type=”System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ />
<add name=”ScriptResource” verb=”GET,HEAD” path=”ScriptResource.axd” preCondition=”integratedMode” type=”System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ />
<add verb=”*” name=”ClientDependency” preCondition=”integratedMode” path=”DependencyHandler.axd” type=”ClientDependency.Core.CompositeFiles.CompositeDependencyHandler, ClientDependency.Core” />
<add name=”MiniProfiler” path=”mini-profiler-resources/*” verb=”*” type=”System.Web.Routing.UrlRoutingModule” resourceType=”Unspecified” preCondition=”integratedMode” />
<add name=”ExtensionlessUrlHandler-Integrated-4.0″ path=”*.” verb=”*” type=”System.Web.Handlers.TransferRequestHandler” preCondition=”integratedMode,runtimeVersionv4.0″ />
</handlers>
<staticContent>
<remove fileExtension=”.air” />
<mimeMap fileExtension=”.air” mimeType=”application/vnd.adobe.air-application-installer-package+zip” />
<remove fileExtension=”.svg” />
<mimeMap fileExtension=”.svg” mimeType=”image/svg+xml” />
<remove fileExtension=”.woff” />
<mimeMap fileExtension=”.woff” mimeType=”font/woff” />
<remove fileExtension=”.woff2″ />
<mimeMap fileExtension=”.woff2″ mimeType=”font/woff2″ />
<remove fileExtension=”.less” />
<mimeMap fileExtension=”.less” mimeType=”text/css” />
<remove fileExtension=”.mp4″ />
<mimeMap fileExtension=”.mp4″ mimeType=”video/mp4″ />
<remove fileExtension=”.json” />
<mimeMap fileExtension=”.json” mimeType=”application/json” />
</staticContent>
<!– Ensure the powered by header is not returned –>
<httpProtocol>
<customHeaders>
<remove name=”X-Powered-By” />
</customHeaders>
</httpProtocol>
<!– Increase the default upload file size limit –>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength=”52428800″ />
</requestFiltering>
</security>
<!–
If you wish to use IIS rewrite rules, see the documentation here: https://our.umbraco.com/documentation/Reference/Routing/IISRewriteRules
–>
<!–
<rewrite>
<rules></rules>
</rewrite>
–>
</system.webServer>
<runtime>
<assemblyBinding xmlns=”urn:schemas-microsoft-com:asm.v1″>
<dependentAssembly>
<assemblyIdentity name=”Microsoft.Owin” publicKeyToken=”31bf3856ad364e35″ culture=”neutral” />
<bindingRedirect oldVersion=”0.0.0.0-4.0.1.0″ newVersion=”4.0.1.0″ />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name=”Microsoft.Owin.Security” publicKeyToken=”31bf3856ad364e35″ culture=”neutral” />
<bindingRedirect oldVersion=”0.0.0.0-4.0.1.0″ newVersion=”4.0.1.0″ />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name=”Microsoft.Owin.Security.Cookies” publicKeyToken=”31bf3856ad364e35″ culture=”neutral” />
<bindingRedirect oldVersion=”0.0.0.0-4.0.1.0″ newVersion=”4.0.1.0″ />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name=”Microsoft.Owin.Security.OAuth” publicKeyToken=”31bf3856ad364e35″ culture=”neutral” />
<bindingRedirect oldVersion=”0.0.0.0-4.0.1.0″ newVersion=”4.0.1.0″ />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name=”Newtonsoft.Json” publicKeyToken=”30ad4fe6b2a6aeed” culture=”neutral” />
<bindingRedirect oldVersion=”0.0.0.0-12.0.0.0″ newVersion=”12.0.0.0″ />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name=”System.Collections.Immutable” publicKeyToken=”b03f5f7f11d50a3a” culture=”neutral” />
<bindingRedirect oldVersion=”0.0.0.0-1.2.3.0″ newVersion=”1.2.3.0″ />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name=”System.Web.Http” publicKeyToken=”31bf3856ad364e35″ culture=”neutral” />
<bindingRedirect oldVersion=”0.0.0.0-5.2.7.0″ newVersion=”5.2.7.0″ />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name=”System.Web.Mvc” publicKeyToken=”31bf3856ad364e35″ culture=”neutral” />
<bindingRedirect oldVersion=”0.0.0.0-5.2.7.0″ newVersion=”5.2.7.0″ />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name=”System.ValueTuple” publicKeyToken=”cc7b13ffcd2ddd51″ culture=”neutral” />
<bindingRedirect oldVersion=”0.0.0.0-4.0.3.0″ newVersion=”4.0.3.0″ />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name=”System.Net.Http.Formatting” publicKeyToken=”31bf3856ad364e35″ />
<bindingRedirect oldVersion=”0.0.0.0-5.2.7.0″ newVersion=”5.2.7.0″ />
</dependentAssembly>
</assemblyBinding>
</runtime>
<location path=”umbraco”>
<system.webServer>
<urlCompression doStaticCompression=”false” doDynamicCompression=”false” dynamicCompressionBeforeCache=”false” />
</system.webServer>
</location>
<location path=”App_Plugins”>
<system.webServer>
<urlCompression doStaticCompression=”false” doDynamicCompression=”false” dynamicCompressionBeforeCache=”false” />
</system.webServer>
</location>
<imageProcessor>
<security configSource=”config\imageprocessor\security.config” />
<caching configSource=”config\imageprocessor\cache.config” />
<processing configSource=”config\imageprocessor\processing.config” />
</imageProcessor>
<system.codedom>
<compilers>
<compiler language=”c#;cs;csharp” extension=”.cs” type=”Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ warningLevel=”4″ compilerOptions=”/langversion:7 /nowarn:1659;1699;1701″ />
<compiler language=”vb;vbs;visualbasic;vbscript” extension=”.vb” type=”Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ warningLevel=”4″ compilerOptions=”/langversion:14 /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+” />
</compilers>
</system.codedom>
</configuration>