Skip to content

Latest commit

Β 

History

History
383 lines (269 loc) Β· 35.3 KB

tab_bestpractices.md

File metadata and controls

383 lines (269 loc) Β· 35.3 KB
title displaytext layout tab order tags
bestpractices
Best Practices
true
3
headers

Best Practices

Configuration proposal

Please note the best practices below suggest methods to change web server configuration to add headers. Security headers can also be successfully added to your application at the software level as well in almost every web language. Many web frameworks add some of these headers automatically.

The following section proposes a configuration for the actively supported and working draft security headers.

πŸ’‘ Additional information about HTTP security headers on OpenCRE.

πŸ“– The headers proposed below can be applied both in the context of a classic web application and in that of a web API.

🚩 Regarding the header Content-Security-Policy, keep in mind that the policy applicability depends on the execution context. Technical details are available here. Therefore, CSP usage in a web API application implies to define the CSP in the document consuming the content of the web API.

🚩 The header Clear-Site-Data will cause the browser to take additional processing time for the HTTP response, so, set it to the logout function when possible.

πŸ”¬ For the header Permissions-Policy, as it is currently only supported by Chromium based browsers, the proposed value was generated with this site and tested against the version 128.0.6606.0 of Chromium to only specify supported features.

πŸ’‘ Content of the table below is also provided, as JSON, via this file (automatically updated).

Header name Proposed value
Strict-Transport-Security max-age=31536000; includeSubDomains
X-Frame-Options deny
X-Content-Type-Options nosniff
Content-Security-Policy default-src 'self'; form-action 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requests; block-all-mixed-content
X-Permitted-Cross-Domain-Policies none
Referrer-Policy no-referrer
Clear-Site-Data "cache","cookies","storage"
Cross-Origin-Embedder-Policy require-corp
Cross-Origin-Opener-Policy same-origin
Cross-Origin-Resource-Policy same-origin
Permissions-Policy accelerometer=(), autoplay=(), camera=(), cross-origin-isolated=(), display-capture=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(self), usb=(), web-share=(), xr-spatial-tracking=(), clipboard-read=(), clipboard-write=(), gamepad=(), hid=(), idle-detection=(), interest-cohort=(), serial=(), unload=()
Cache-Control no-store, max-age=0

Prevent information disclosure via HTTP headers

This section provides a collection of HTTP response headers to remove, when possible, from any HTTP response to prevent any disclosure of technical information about environment. The following list of headers can be used to configure a reverse proxy or a web application firewall to handle removal operation of the mentioned headers.

πŸ’‘ Additional information about technical information disclosure in HTTP header on OpenCRE.

πŸ’‘ When an HTTP response header is known by the analytics site WebTechSurvey, then, a reference link is added to its usage statistics page. Otherwise, a reference link regarding the documentation of the header is provided.

🚩 The response header Content-Type can sometimes discloses the web framework used. It is the case for the following ones:

πŸ’‘ Content of the table below is also provided, as JSON, via this file (automatically updated).

Header name Header value example Description
Server Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips Contain information about the server handling the request.
Liferay-Portal Liferay Digital Experience Platform 7.2.10 GA1 Contain the version of the Liferay software in use.
X-Turbo-Charged-By LiteSpeed/5.4.12 Enterprise Contain information about the server handling the request.
X-Powered-By PHP/5.3.3 Contain information about hosting environments or other frameworks in use.
X-Server-Powered-By Engintron Contain information about hosting environments or other frameworks in use.
X-Powered-CMS Bitrix Site Manager (DEMO) Contain the information about the CMS that generated the HTTP response.
SourceMap https://mysite.com/js/mylib.js.map Links generated code to a source map file, enabling the browser to reconstruct the original source and present the reconstructed original in the debugger.
X-SourceMap https://mysite.com/js/mylib.js.map Links generated code to a source map file, enabling the browser to reconstruct the original source and present the reconstructed original in the debugger.
X-AspNetMvc-Version 5.2 Contain the version of the ASP .Net MVC framework in use.
X-AspNet-Version 4.0.30319 Contain the version of the ASP .Net framework Common Language Runtime (CLR) in use (see here for more details).
X-SourceFiles =?UTF-8?B?QzpcVXNlcnN?= Contain information needed by the .Net SDK debugger during debugging operation on a project.
X-Redirect-By TYPO3 Shortcut/Mountpoint Specifies the component that is responsible for a particular redirect (source Wikipedia).
X-Generator Drupal 8 Contain the information about the CMS that generated the HTTP response.
X-Generated-By Smartsite version 7.11.1.3 Contain the information about the CMS that generated the HTTP response.
X-CMS Thinq CMS 1.7.0.0 Contain the information about the CMS that generated the HTTP response.
X-Powered-By-Plesk PleskLin or PleskWin Indicate that the platform is based on the Plesk software in addition to the underlying operating system.
X-Php-Version 7.4 Indicate the version of PHP technology used.
Powered-By PrestaShop Indicate the name of the framework or platform used.
X-Content-Encoded-By Joomla! 2.5 Indicate the name of the framework or platform used.
Product Z-BlogPHP 1.7.2 Indicate the name of the framework or platform used.
X-CF-Powered-By CF-Joomla 0.1.5 Indicate the name of the framework or platform used.
X-Framework JP/4.01 Indicate the name of the framework or platform used.
Host-Header owasp.org Indicate which virtual host of the web server the response is coming from.
Pega-Host srv-pega11 Indicate the internal host name of the server that handled the request in the context of usage of a software from the PEGA company.
X-Atmosphere-first-request true Indicate that the java framework Atmosphere is used.
X-Atmosphere-tracking-id 7852fcbf-f8a9-4667-9dcc-a0b5b162499c Indicate that the java framework Atmosphere is used.
X-Atmosphere-error Websocket protocol not supported Indicate that the java framework Atmosphere is used.
X-Mod-Pagespeed 1.13.35.2-0 Indicate the presence of the Apache module mod_pagespeed in the call flow.
X-Page-Speed 1.13.35.2-0 Indicate the presence of the Nginx module mod_pagespeed in the call flow.
X-Varnish-Backend pb01 Indicate the name of the backend server from which the Varnish instance will accelerate the content.
X-Varnish-Server proxy01 Indicate the name of the Varnish server instance that provided the accelerated content.
X-Envoy-Upstream-Service-Time 42 Indicate the presence of the proxy software Envoy in the call flow.
X-Envoy-Attempt-Count 1 Indicate the presence of the proxy software Envoy in the call flow.
X-Envoy-External-Address 124.128.159.165 Indicate the presence of the proxy software Envoy in the call flow.
X-Envoy-Internal true Indicate the presence of the proxy software Envoy in the call flow.
X-Envoy-Original-Dst-Host 10.195.16.237:8888 Indicate the presence of the proxy software Envoy in the call flow.
X-B3-ParentSpanId dea3f6d0324583db Indicate the presence of the software Zipkin that is a distributed tracing system.
X-B3-Sampled 0 Indicate the presence of the software Zipkin that is a distributed tracing system.
X-B3-SpanId 244753d494e83353 Indicate the presence of the software Zipkin that is a distributed tracing system.
X-B3-TraceId 11bef07b0f5c0468 Indicate the presence of the software Zipkin that is a distributed tracing system.
K-Proxy-Request activator Indicate the presence of the software Knative that is an Open-Source Enterprise-level solution to build Serverless and Event Driven Applications in Kubernetes environments.
X-Old-Content-Length 135 Indicate the presence of the software WebSEAL that is a high performance, multithreaded web server by IBM.
$wsep empty value Indicate the presence of the software WebSphere Application Server that is a JavaEE application server by IBM.
X-Nextjs-Matched-Path /blog Indicate that the web framework Next.js is used.
X-Nextjs-Page /articles Indicate that the web framework Next.js is used.
X-Nextjs-Cache REVALIDATED Indicate that the web framework Next.js is used.
X-Nextjs-Redirect /home Indicate that the web framework Next.js is used.
X-OneAgent-JS-Injection true Indicate that the Dynatrace analytics and automation platform is used.
X-ruxit-JS-Agent true Indicate that the Dynatrace analytics and automation platform is used.
X-dtHealthCheck Technical diagnostic data Indicate that the Dynatrace analytics and automation platform is used.
X-dtAgentId 95b3121c36 Indicate that the Dynatrace analytics and automation platform is used.
X-dtInjectedServlet com.company.ReportServlet Indicate that the Dynatrace analytics and automation platform is used.
X-Litespeed-Cache-Control no-cache Indicate the presence of the LiteSpeed web server.
X-LiteSpeed-Purge /phpinfo.php Indicate the presence of the LiteSpeed web server.
X-LiteSpeed-Tag pubtag1,pubtag2 Indicate the presence of the LiteSpeed web server.
X-LiteSpeed-Vary value=ismobile Indicate the presence of the LiteSpeed web server.
X-LiteSpeed-Cache hit,litemage Indicate the presence of the LiteSpeed web server.
X-Umbraco-Version 4.7 Indicate the usage of the Umbraco CMS software as well as its version.
OracleCommerceCloud-Version 23.08.01 Indicate the usage of the Oracle Commerce software as well as its version.
X-BEServer EXSRV01 Indicate the internal host name of the server that handled the request in the context of usage of the Microsoft Exchange software.
X-DiagInfo EXSRV01 Indicate the internal host name of the server that handled the request in the context of usage of the Microsoft Exchange software.
X-FEServer EXSRV01 Indicate the internal host name of the server that handled the request in the context of usage of the Microsoft Exchange software.
X-CalculatedBETarget exsrv01.mydomain.com Indicate the internal host name of the server that handled the request in the context of usage of the Microsoft Exchange software.
X-OWA-Version 15.2.1258.27 Indicate the version of the Microsoft Exchange software in use.
X-Cocoon-Version 2.1.13 Indicate that the web framework Apache Cocoon is used as well as the version used.
X-Kubernetes-PF-FlowSchema-UI cf931e2d-5a5e-4c12-892c-9bafa71f30dc Indicate that the web application issuing the HTTP response is deployed on a Kubernetes cluster.
X-Kubernetes-PF-PriorityLevel-UID 78b3face-e1cf-4fc6-a27e-08eb7f0f5b23 Indicate that the web application issuing the HTTP response is deployed on a Kubernetes cluster.
X-Jitsi-Release 5082 Indicate the version of Jitsi software in use.
X-Joomla-Version 3.9.25 Indicate that the CMS Joomla is used as well as the version used.
X-Backside-Transport OK OK Indicate the presence of the products IBM WebSphere DataPower in the call flow.

Prevent exposure to cross-site scripting when hosting uploaded files

This section describes, how the HTTP response header named Content-Disposition, can be used to prevent exposure to cross-site scripting when hosting uploaded files and opening them in the same web browsing context than the application.

It can happen a case in which an application allows a user to upload a file and then allow this file to be accessed by other users. If such feature allows uploading of HTML files (also apply for SVG file) then it can be used, as a vector, to store an HTML file containing JavaScript code. Therefore, the feature become prone to stored cross-site scripting vulnerability.

To prevent this exposure, the HTTP response header named Content-Disposition, can be used with the following value to instruct browsers to download the file instead of open it in the same web browsing context than the application:

Content-Disposition: attachment; filename="myfile.html"

Prevent CORS misconfiguration issues

πŸ“– An excellent tutorial about Cross-Origin Resource Sharing (called CORS) is provided on the Mozilla MDN. In addition, Julien Cretel provided a great blog post about CORS pitfalls.

This section proposes an approach to help preventing CORS misconfiguration issues using a simple idea: Provide the collection of CORS related HTTP response headers to use according to different contexts.

Key points to consider

  • πŸ’‘ If the web framework/web server you are using provides CORS features then always leverage them instead of implements it manually:

  • 🚩 Whatever the context, when the request is a HTTP OPTIONS (preflight request) then the value provided by the following headers must be validated against expected values. If the validation failed then return an HTTP 403 without any CORS related HTTP response headers:

  • 🚩 Validation of the Origin / Access-Control-Request-Method / Access-Control-Request-Headers request header value, against a list of allowed ones, must be performed using strict case sensitive string comparison to prevent, as much as possible, the presence of bypasses into the validation logic. If possible, does not use regular expression for the implementation of the validation, see here for an explanation of the source of this recommendation.

  • 🚩 CORS scope is the access control aspect, from a browser perspective (client side), regarding cross origins access to a resource. Thus, it does NOT replace the requirement to implements access control on the server side too. CORS and server-side access controls are complementary.

  • 🚩 Never take the value of the request header Origin to add it into the response header Access-Control-Allow-Origin (mirroring), see here for an explanation of the source of this recommendation. Indeed, always use a list of allowed origins when only a restricted collection of origins is expected to call your endpoints.

Contexts

Public without authentication

πŸ’¬ Context:

Your endpoints are expected to be consumed, by a browser, from any origins without any authentication.

πŸ’» Configuration proposal:

Access-Control-Allow-Origin: *
Access-Control-Max-Age: 3600
Access-Control-Allow-Credentials: false

Public with authentication

πŸ’¬ Context:

Your endpoints are expected to be consumed, by a browser, from any origins with authentication.

🚩 The value *, for the response header Access-Control-Allow-Origin, cannot be used when the response header Access-Control-Allow-Credentials is allowed (true). Indeed, the browser raises the following error (tested on Chrome 118.x):

The value of the 'Access-Control-Allow-Origin' header in the response must not be 
the wildcard '*' when the request's credentials mode is 'include'.

πŸ“– It is explicitly mentioned, into the Mozilla MDN documentation, as the following:

When responding to a "credentialed request" request, the server must specify an origin in the value 
of the Access-Control-Allow-Origin header, instead of specifying the "*" wildcard.

Therefore, refer to the restricted with authentication case for the configuration to use.

Restricted without authentication

πŸ’¬ Context:

Your endpoints are expected to be consumed, by a browser, from a specific collection of origins without any authentication.

πŸ’» Configuration proposal:

  • If the value of the request header Origin is present into the list of allowed Origins then:
Access-Control-Allow-Origin: [Value_Taken_From_The_List_Of_Allowed_Origins]
Access-Control-Max-Age: 10
Access-Control-Allow-Credentials: false

Restricted with authentication

πŸ’¬ Context:

Your endpoints are expected to be consumed, by a browser, from a specific collection of origins with authentication.

πŸ’» Configuration proposal:

  • If the value of the request header Origin is present into the list of allowed Origins then:
Access-Control-Allow-Origin: [Value_Taken_From_The_List_Of_Allowed_Origins]
Access-Control-Max-Age: 10
Access-Control-Allow-Credentials: true

Test CORS configuration

The tools nuclei can be used, via the template named cors-misconfig, to test a CORS configuration.

πŸ’» Command to use:

$ nuclei -silent -template-id cors-misconfig -u https://domain.com
[cors-misconfig:arbitrary-origin] [http] [info] https://domain.com [...]

References

Prevent information disclosure via the browser local cached files

This section describes why it is important to specify a caching policy, via the Cache-Control HTTP response header, when sensitive information is managed by a web-based application.

Context

πŸ’¬ The application allows a user to access to documents containing information, considered sensitive, from a confidentiality perspective.

Let's assume that the application returns the following HTTP response to a request, in which, no caching policy is defined:

HTTP/1.1 200 OK
accept-ranges: bytes
content-length: 433994
content-type: application/pdf
date: Sat, 30 Mar 2024 10:06:34 GMT
server: LiteSpeed

So, the browser will store a copy of the file (here a PDF one) into its cache storage for a certain amount of time.

🚩 Consequence: Any application running on the user's computer, will be able to access to the file (at least if executed as the user identity or an administrator one) causing an exposure of the resource to non-expected entities.

πŸ“Ί This demonstration video show an example, of such information disclosure, via a file cached by the browser.

Configuration proposal

πŸ’» To prevent such issue, the following caching policy can be specified:

Cache-Control: no-store, max-age=0

πŸ‘€ Where:

  • no-store: Is used to indicate that the response may not be stored in any cache.
  • max-age=0: Is used to force the expiration of any cached version of the resources associated to the response.

πŸ’‘ The HTTP response header Clear-Site-Data can also be leveraged, in addition, to instruct the browser to remove any cached data related to the application.

Other vulnerabilities related to caching

πŸ“– An excellent research and course content, about web cache poisoning, is provided by the PortSwigger team.

References

Prevent CSP bypasses

This section describes some points, to keep in mind, during the creation of a Content-Security-Policy (called CSP) policy to prevent introducing bypasses.

🚩 Not every directives fallback to the default-src directive when it is not specified in the CSP policy.

Directive form-action

πŸ‘€ It is the case for the form-action directive. Therefore, an html form can be used to bypass the CSP in place when the form-action is not defined.

πŸ“Ί This demonstration video show an example.

πŸ’‘ Therefore, ensure to always specify the form-action directive in a CSP policy to at least, the 'self' value, to allow forms only on the current domain.

Directive frame-ancestors

πŸ‘€ It is the case for the frame-ancestors directive. Therefore, IF it is not defined AND IF the header X-Frame-Options is not/incorrectly specified then the current domain can be embedded into a frame.

πŸ“Ί This demonstration video show an example.

πŸ’‘ Therefore, ensure to always specify the frame-ancestors directive in a CSP policy to at least, the 'none' value, to deny the current domain to be "framed".

Directive base-uri

πŸ‘€ It is the case for the base-uri directive.

πŸ“Ί This demonstration video show an example.

πŸ’‘ Therefore, ensure to always specify the base-uri directive in a CSP policy to at least, the 'self' value, to only allow the current domain to be specified as the document's base URI via a <base href="..." /> html tag.

Support for a large CSP policy

Tests were performed to identify if any limitation was in place, regarding the definition and usage of a large CSP policy. Tests were performed against the following browsers:

  • Firefox 132.0.2.
  • Chromium 131.0.6755.0.
  • Edge 131.0.2903.51.

πŸ’‘ Based on tests performed, modern browsers supports a sufficient size to specify a large CSP policy in case of need.

πŸ“Š Technical details can be found here (backup copy).