If you want to remove unnecessary headers from a Web App in Azure App Services, here are some things we need to know.

App Services run on a PaaS. This means that not everything can be touched or changed.

In particular:

  • 502, 503 and 403 http statuses are returned from the front-end devices and never reach the worker, which means that we cannot influence the headers there

Removing the X-AspNet-Version header

You can do this by editing the web.config file in KUDU. If you don't have one, just create a web.config file in the wwwroot dir.

This is between the <configuration> </configuration>

<system.web>
    <httpRuntime enableVersionHeader="false" /> <!-- Removes ASP.NET version header. Not needed for Ghost running in iisnode -->
</system.web>

Removing the X-Powered-By: ASP.NET header

Again under <configuration> 

  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>

Removing the Server header

Again under <configuration>

<system.webServer>
<security>
         <requestFiltering removeServerHeader="true" /> <!-- Removes Server header in IIS10 or later and also in Azure Web Apps -->
</security>
</system.webServer>

These do not remove the Server header from 500.0 errors. You can't really do that but what you can do is rename it. More info here - https://stackoverflow.com/questions/50150160/remove-server-header-on-response-on-500-http-error

Removing the X-Powered-By: PHP/7.2.19 (or any other version) header

Now this header exists only in PHP applications and is controlled by PHP itself. What you usually need to do is go to your PHP folder and open php.ini and find this line:

expose_php = On (change it to Off to remove the header)

In Azure App Services unfortunately is a little different. The usual way of influencing php settings by placing a .user.ini file in wwwroot will not work as the expose_php setting is a Core setting and will not be affected. So the way to do it is this:

  1. Go to your Web App's Configuration blade
  2. Under Application Settings click New application setting
  3. Name: PHP_INI_SCAN_DIR
  4. Value: D:\home\site
  5. Click OK and Save

Azure Web App second php.ini

What we just did is to show PHP that we will be scanning this directoroy for additional .ini files. Now let's go and create a newphp.ini file in the site dir of your Web App. In it place expose_php = Off in a single line. Save . Restart the Web App. The X-Powered-By: PHP/7.2.19 header should be gone. You can also check if the settings have worked by using a ()phpinfo page and search for expose_php to check if the new values are Off.

The web.config so far

So if you want to do all 3 in one, here is how your web.config should look like

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
    <httpRuntime enableVersionHeader="false" /> <!-- Removes ASP.NET version header.  -->
</system.web>
  <system.webServer>
	<security>
      <requestFiltering removeServerHeader="true" /> <!-- Removes Server header in IIS10 or later and also in Azure Web Apps -->
    </security>
    <httpProtocol>
      <customHeaders>
        <clear /> <!-- Gets rid of the other unwanted headers -->
	<remove name="X-Powered-By" />
      </customHeaders>
      <redirectHeaders>
        <clear />
      </redirectHeaders>
    </httpProtocol>
  </system.webServer> 
</configuration>

Adding headers for improved security

So we were stripping down headers until now but now it's time to add some for improved security. If you run your website through a tool like https://securityheaders.com/ you will see what is it that your website is missing from the best practices. 

Here is a great blg post that explains it all. https://scotthelme.co.uk/hardening-your-http-response-headers/

Here is a sample web.config that will allow these headers. It is for a website https://www.gamerz-bg.com. It all fits between <configuration> -> <system.webServer>

<customHeaders>
        <clear /> <!-- Gets rid of the other unwanted headers -->
        <add name="X-Frame-Options" value="SAMEORIGIN" /> <!-- disables iframing the website from other than the origin -->
        <add name="X-Xss-Protection" value="1; mode=block" /> <!-- configure the built in reflective XSS protection found in Internet Explorer, Chrome and Safari (Webkit). -->
        <add name="X-Content-Type-Options" value="nosniff" /> <!-- prevents Google Chrome and Internet Explorer from trying to mime-sniff the content-type of a response away from the one being declared by the server -->
		<add name="Content-Security-Policy" value="default-src 'none'; script-src 'self' https://code.jquery.com; connect-src 'self'; img-src 'self'; style-src 'self' 'unsafe-inline'" /> <!-- https://content-security-policy.com/ - defines from where you can load scripts, styles images and so on. You use 'unsafe-inline' if you need to, although it's considered risk -->
		<add name="Referrer-Policy" value="no-referrer-when-downgrade" /> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy - Sets the referrer policy. Use for CORS -->
		<add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains" /> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security - HSTS allows you to tell a browser that you always want a user to connect using HTTPS instead of HTTP. his policy will enforce TLS on your site and all subdomains for a year. -->
		<add name="Feature-Policy" value="vibrate 'none'; usermedia *; sync-xhr 'self' https://*.google.com" /> <!-- used to disable certain features https://scotthelme.co.uk/a-new-security-header-feature-policy/ -->
		<remove name="X-Powered-By" /> <!-- removes the X-Powered-By:ASP.NET header -->
      </customHeaders>

The Complete web.config

So Removing the unnecessary headers and adding the additional ones for security. Here is how it all looks like in a single web.config

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
    <httpRuntime enableVersionHeader="false" /> <!-- Removes ASP.NET version header.  -->
</system.web>
  <system.webServer>
	<security>
      <requestFiltering removeServerHeader="true" /> <!-- Removes Server header in IIS10 or later and also in Azure Web Apps -->
    </security>
    <httpProtocol>
      <customHeaders>
        <clear /> <!-- Gets rid of the other unwanted headers -->
        <add name="X-Frame-Options" value="SAMEORIGIN" /> <!-- disables iframing the website from other than the origin -->
        <add name="X-Xss-Protection" value="1; mode=block" /> <!-- configure the built in reflective XSS protection found in Internet Explorer, Chrome and Safari (Webkit). -->
        <add name="X-Content-Type-Options" value="nosniff" /> <!-- prevents Google Chrome and Internet Explorer from trying to mime-sniff the content-type of a response away from the one being declared by the server -->
		<add name="Content-Security-Policy" value="default-src 'none'; script-src 'self' https://code.jquery.com; connect-src 'self'; img-src 'self'; style-src 'self' 'unsafe-inline'" /> <!-- https://content-security-policy.com/ - defines from where you can load scripts, styles images and so on. You use 'unsafe-inline' if you need to, although it's considered risk -->
		<add name="Referrer-Policy" value="no-referrer-when-downgrade" /> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy - Sets the referrer policy. Use for CORS -->
		<add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains" /> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security - HSTS allows you to tell a browser that you always want a user to connect using HTTPS instead of HTTP. his policy will enforce TLS on your site and all subdomains for a year. -->
		<add name="Feature-Policy" value="vibrate 'none'; usermedia *; sync-xhr 'self' https://*.google.com" /> <!-- used to disable certain features https://scotthelme.co.uk/a-new-security-header-feature-policy/ -->
		<remove name="X-Powered-By" /> <!-- removes the X-Powered-By:ASP.NET header -->
      </customHeaders>
      <redirectHeaders>
        <clear />
      </redirectHeaders>	
    </httpProtocol>
  </system.webServer> 
</configuration>

References used

http://blog.paulbouwer.com/2013/01/09/asafaweb-excessive-headers-and-windows-azure/

https://stackoverflow.com/questions/50150160/remove-server-header-on-response-on-500-http-error

https://blogs.msdn.microsoft.com/hosamshobak/2015/03/20/azure-websites-how-to-change-php-ini-settings/

https://scotthelme.co.uk/hardening-your-http-response-headers/