⭐️

Fundamentals Of HTTP Headers And Web Application Security

one of the top cyber security pentesting companies

Table of Contents

Fundamentals of HTTP Headers and Web Application Security

The notorious targets for all sorts of cyber attacks can be zeroed down to the web applications. The increasing pattern of cyber attacks has led us, to not just inculcate cyber security as a luxury, rather as a necessity for all the web developers and above all for those developers who are responsible for building the consumer-facing applications. In hand with the above fact, it is also true enough that as and when the world is becoming more and more interconnected, along with rise of online services there is also rise in personal and sensitive data being created in tones. All such changes give in to more vulnerabilities and risks which the cyber criminals easily exploit through techniques such as, cross-site scripting, man-in-the-middle attacks, cross-site request forgery, clickjacking, etc.

There are many things to consider while thinking about securing our web applications or sites, but a rather good place would be to start with the exploration and implementation of HTTP security headers that put in an extra layer of security. So, in order to tighten up the security of web applications, the HTTP headers can be put to leverage by just incorporating few lines of code which help in balancing both usability as well as security. These HTTP headers help prevent the modern browsers from encountering all sorts of vulnerabilities. Speaking in technical terms, the HTTP headers are just simple fields which are encoded in clear text and are said to be part of the request as well as response message headers in HTTP. Their design is such that they cause enablement of both HTTP server as well as client in order to have exchange of metadata based on parameters such as, connection that has to be established, resource that is being requested and resource that is being returned.

At times when a user wants to access a certain specific page from a server, the server in turn provides the response by giving the required content along with the response headers of HTTP which carry metadata such as status error codes, cache-control, etc. Now, a huge part of such headers are termed as security headers that provide instructions to the browsers about how it should behave while handling our website’s data as well as content. They play a major part in protecting us from threats and attacks such as, clickjacking, XSS, compromised website resources, drive-by-downloads, passive eavesdropping, compromised certificates, information disclosure to name a few. To wrap it all up it can be rightly put that these security centric headers help in empowering our browsers in making smarter decisions for the users.

X-XSS-Protection

It is a HTTP response header. This is characteristic of Internet Explorer, Chrome and Safari. Whenever there seems to be a chance of reflected XSS attacks or detection of such attacks, the browsers stop the loading of pages. This header provides a means of protection to the users who still use old browsers what lack privileges of having CSP (Content-Security-Policy) header.

Syntax:

X-XSS-Protection: 0
X-XSS-Protection: 1
X-XSS-Protection: 1; mode=block
X-XSS-Protection: 1; report=

Directives:

  • 0 – Disables XSS filtering.
  • 1 – Enables XSS filtering (default in some browsers). Browser sanitizes the page if an attack is detected.
  • 1; mode=block – Enables filtering and blocks page load on detection.
  • 1; report= – Enables filtering and reports detected attacks.

Example:

X-XSS-Protection: 1; mode=block

In PHP:

header("X-XSS-Protection: 1; mode=block");

In Nginx:

add_header "X-XSS-Protection" "1; mode=block";

WWW-Authenticate

It is a HTTP response header that helps in defining the authentication method which must be used so as to gain access to a resource. This header is sent along with a 401 Unauthorized response status code.

Syntax:

WWW-Authenticate: realm=
  • The most common authentication type is Basic. Other authentication schemes maintained by IANA are: Bearer, Digest, HOBA, Mutual, Negotiate, OAuth, SCRAM-SHA-1, SCRAM-SHA-256 and vapid.
  • realm= – Description of the protected area.
  • charset= – Server’s preferred encoding for username/password. Only allowed value is UTF-8 (case-insensitive). Not related to the realm string encoding.

Examples:

WWW-Authenticate: Basic
WWW-Authenticate: Basic realm="Access to the staging site", charset="UTF-8"

Authorization

This is a HTTP request header that contains the credentials in order to authenticate a user with a server. It usually happens after the server has responded with 401 Unauthorized status and the WWW-Authenticate header.

Syntax:

Authorization:
  • Common scheme is Basic. Others include: Bearer, Digest, HOBA, Mutual, Negotiate, OAuth, SCRAM-SHA-1, SCRAM-SHA-256, vapid.
  • For Basic, credentials are Username:Password (e.g., root:toor), Base64-encoded.

Example:

Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l

Proxy-Authenticate

It is a HTTP response header that defines the authentication method which should be employed so as to gain access to a resource behind a proxy server. It helps authenticate the request to the proxy server, thereby allowing it to transmit the request further. This header is sent along with a 407 Proxy Authentication Required status code.

Syntax:

Proxy-Authenticate: realm=
  • Common type: Basic. Others: Bearer, Digest, HOBA, Mutual, Negotiate, OAuth, SCRAM-SHA-1, SCRAM-SHA-256, vapid.
  • realm= – Describes the protected area.

Examples:

Proxy-Authenticate: Basic
Proxy-Authenticate: Basic realm="Access to the internal site"

Proxy-Authorization

It is a HTTP request header that contains the credentials so as to authenticate a user to a proxy server. It happens usually after the server has responded with a 407 Proxy Authentication Required status and the Proxy-Authenticate header.

Syntax:

Proxy-Authorization:
  • Common scheme: Basic. Others include Bearer, Digest, HOBA, Mutual, Negotiate, OAuth, SCRAM-SHA-1, SCRAM-SHA-256, vapid.
  • For Basic, credentials are Username:Password (e.g., root:toor), Base64-encoded.

Example:

Proxy-Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l

Content-Security-Policy (CSP)

It is a response header that allows all the website administrators to control resources that the user is allowed to load for a given page. With a very few exceptions, policies in most cases involve specifying the server origins and the script endpoints, which helps guard against XSS attacks.

Syntax:

Content-Security-Policy: <directives>
  • Fetch directives – control locations from which resource types may be loaded (e.g., connect-src, default-src, font-src, frame-src, img-src, manifest-src, media-src, object-src, script-src, style-src, worker-src).
  • Document directives – govern document/worker environment (e.g., base-uri, plugin-types, sandbox).
  • Navigation directives – govern allowed navigation/submit targets (e.g., form-action, frame-ancestors).
  • Other directives: block-all-mixed-content, require-sri-for, upgrade-insecure-requests.

Examples:

// header
Content-Security-Policy: default-src https:

// meta tag

Not implementing the above policy yet; rather reporting violations that would have occurred:

Content-Security-Policy-Report-Only: default-src https:; report-uri /csp-violation-report-endpoint/

Content-Security-Policy-Report-Only

This is a response header which allows web developers to experiment with policies by monitoring (and not enforcing) their effects. These violation reports consist of JSON documents sent through a HTTP POST request to the specified URI.

Syntax:

Content-Security-Policy-Report-Only: <directives>

Use the same directives as CSP. The report-uri directive of CSP should be used here so as make it functional.

Examples:

Content-Security-Policy-Report-Only: default-src https:; report-uri /csp-violation-report-endpoint/
Content-Security-Policy: default-src https:; report-uri /csp-violation-report-endpoint/

Violation Report Syntax:

The report JSON object constitutes the following data such as; blocked-uri, disposition, document-uri, effective-directive, original-policy, referrer, script-sample, status-code and violated-directive.

Public-Key-Pins

This is a response header that associates a specific kind of cryptographic public key with a certain web server so as to decrease the risk of MITM attacks by implementing forged certificates. If for example, one or several keys are pinned and none of them are used by the server, the browser will not by any means accept the response as legitimate, and will thereby not display it.

Syntax:

Public-Key-Pins: pin-sha256=""; 
  max-age=<seconds>; 
  includeSubDomains; 
  report-uri=""
  • pin-sha256=”” – Base64 encoded SPKI fingerprint. Multiple pins can be specified.
  • max-age= – Time in seconds to remember the site must be accessed using one of the defined keys.
  • includeSubDomains (Optional) – Apply rule to subdomains.
  • report-uri=”” (Optional) – Where to report pin validation failures.

Example:

Public-Key-Pins:
  pin-sha256="cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=";
  pin-sha256="M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE=";
  max-age=5184000; includeSubDomains;
  report-uri="https://www.example.org/hpkp-report"

Strict-Transport-Security (HSTS)

It is a HTTP response header that allows a website inform browsers that it should only be accessed using HTTPS rather than using HTTP.

Syntax:

Strict-Transport-Security: max-age=<seconds>
Strict-Transport-Security: max-age=<seconds>; includeSubDomains
Strict-Transport-Security: max-age=<seconds>; preload
  • max-age= – Time (in seconds) the browser should remember HTTPS-only.
  • includeSubDomains (Optional) – Apply to subdomains.
  • preload (Optional) – Not part of the HSTS specification.

Description:

When a website accepts a connection with the use of HTTP and redirects to HTTPS, users may initially communicate with the non-encrypted version before being redirected. This creates a chance for a man-in-the-middle attack (e.g., redirecting to a malicious site). The HSTS header informs the browser it should never load a site using HTTP and automatically convert attempts to HTTPS.

Example Case:

Using free WiFi, a malicious access point could intercept HTTP requests and redirect to a lookalike banking site, exposing private data. With HSTS, once the banking site is accessed via HTTPS and the browser records the header, future attempts will automatically use HTTPS, preventing the MITM.

How the browser handles it:

  • On first HTTPS visit, browser records the HSTS policy.
  • Until expiration, HTTP attempts are upgraded to HTTPS automatically.
  • Receiving the header again updates/extends expiration.
  • Setting max-age=0 disables HSTS immediately.

Example:

Strict-Transport-Security: max-age=31536000; includeSubDomains

X-Content-Type-Options

This is a response HTTP header used as a marker by the server to indicate that the MIME types advertised in the Content-Type headers should not be changed. This header allows opt-out of MIME type sniffing. Introduced by Microsoft in IE 8 and later adopted by other browsers. Testers often expect this header to be set.

Syntax:

X-Content-Type-Options: nosniff
  • nosniff – Blocks a request if the requested type is:
    • style and the MIME type is not text/css, or
    • script and the MIME type is not a JavaScript MIME type.

X-Frame-Options

It is a HTTP response header. It indicates whether a web browser should be allowed to render a page in a frame, <iframe> or <object>. Using this, sites can avoid clickjacking by ensuring their content is not embedded into other sites.

  • X-Frame-Options: DENY – The page cannot be displayed in a frame, regardless of the site attempting to do so.
  • X-Frame-Options: SAMEORIGIN – The page can only be displayed in a frame on the same origin as the page itself.
  • X-Frame-Options: ALLOW-FROM https://example.com/ (or ALLOW-FROM uri) – The page is only displayed in a frame on the explicitly mentioned origin. (In Firefox, this suffers from ancestor-checking limitations similar to SAMEORIGIN.)

Examples (Configuring Apache):

# Send SAMEORIGIN for all pages
Header always set X-Frame-Options SAMEORIGIN

# Set DENY
Header set X-Frame-Options DENY

# Allow from a specific host
Header set X-Frame-Options "ALLOW-FROM https://example.com/"

Configuring Nginx:

add_header X-Frame-Options SAMEORIGIN;

Upgrade-Insecure-Requests

This is a request header that sends a signal to the server expressing the client’s preference for an encrypted and authenticated response and that it can handle the upgrade-insecure-requests CSP directive successfully.

Syntax:

Upgrade-Insecure-Requests: 1

Example:

GET / HTTP/1.1
Host: example.com
Upgrade-Insecure-Requests: 1

The server can now redirect to a secure version. A Vary header can be used so caches don’t serve to clients that don’t support the upgrade mechanism.

Location: https://example.com/
Vary: Upgrade-Insecure-Request

X-Permitted-Cross-Domain-Policies

Cross-domain policy files are XML documents that grant a web client (e.g., Adobe Flash Player or Adobe Acrobat) permission to handle data across domains. When content from a source domain makes requests to another domain, the remote domain needs to host a cross-domain policy file granting access. A meta-policy can also be declared using the X-Permitted-Cross-Domain-Policies HTTP response header.

Syntax:

X-Permitted-Cross-Domain-Policies: none
  • none – No policy files allowed anywhere on the target server.
  • master-only – Only the master policy file is allowed.
  • by-content-type – Only policy files served with Content-Type: text/x-cross-domain-policy are allowed (HTTP/HTTPS only).
  • by-ftp-filename – Only policy files whose file names are crossdomain.xml are allowed (FTP only).
  • all – All policy files on this target domain are allowed.

Referrer-Policy

This HTTP header governs which referrer information is sent in the Referer header with requests.

Syntax:

Referrer-Policy: no-referrer
Referrer-Policy: no-referrer-when-downgrade
Referrer-Policy: origin
Referrer-Policy: origin-when-cross-origin
Referrer-Policy: same-origin
Referrer-Policy: strict-origin
Referrer-Policy: strict-origin-when-cross-origin
Referrer-Policy: unsafe-url
  • no-referrer – Omits the Referer header entirely.
  • no-referrer-when-downgrade – Default if no policy specified. Sends origin to equally secure destinations (HTTPS→HTTPS), not to less secure (HTTPS→HTTP).
  • origin – Sends only the origin (e.g., https://example.com/).
  • origin-when-cross-origin – Full URL for same-origin; only origin for cross-origin.
  • same-origin – Sends referrer for same-site; none for cross-origin.
  • strict-origin – Sends origin to equally secure destinations only.
  • strict-origin-when-cross-origin – Full URL for same-origin; origin to equally secure cross-origin; none to less secure.
  • unsafe-url – Sends full URL (stripped of parameters) for same-origin or cross-origin.

Expect-CT

The Expect-CT header is used by a server to indicate that browsers should evaluate connections to the host emitting the header for Certificate Transparency compliance.

Syntax:

Expect-CT: report-uri="<uri>", enforce, max-age=<age>
  • max-age – Number of seconds to regard the host as a Known Expect-CT Host.
  • enforce – Optional; enforce CT policy (not report-only).
  • report-uri – Optional; URL to which the browser should report Expect-CT failures.

Example:

Expect-CT: max-age=86400, enforce, report-uri="https://foo.example/report"

Access-Control-Allow-Origin

This response header indicates whether the response can be shared with resources from the given origin.

Syntax:

Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: <origin>
  • * – For requests without credentials, allows any origin.
  • <origin> – Specific URI allowed to access the resource.

Examples:

Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: https://developer.mozilla.org

Set-Cookie

This HTTP response header is used so that cookies can be sent from the server to the user agent.

Syntax:

Set-Cookie: <cookie-name>=<cookie-value>
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax

Multiple directives can be combined, for example:

Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly
  • <cookie-name> – US-ASCII (no CTLs/spaces/tabs/separators).
  • <cookie-value> – US-ASCII; may be quoted; excludes CTLs, whitespace, double quote, comma, semicolon, backslash.
  • Expires=<date> (Optional) – Max lifetime as HTTP-date; otherwise session cookie.
  • Max-Age=<number> (Optional) – Seconds until expiration; 0 or negative expires immediately.
  • Domain=<domain-value> (Optional) – Hosts to which the cookie will be sent; default is current host (excluding subdomains).
  • Path=<path-value> (Optional) – URL path that must exist before sending the cookie.
  • Secure (Optional) – Send only over HTTPS.
  • HttpOnly (Optional) – Not accessible via JavaScript document.cookie.

Example:

Set-Cookie: sessionid=38afes7a8; HttpOnly; Path=/
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly

Cache-Control

A general header used to specify directives for caching in both requests and responses. Directives are unidirectional and case-insensitive; multiple directives are comma-separated.

Request Directives:

Cache-Control: max-age=<seconds>
Cache-Control: max-stale[=<seconds>]
Cache-Control: min-fresh=<seconds>
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: no-transform
Cache-Control: only-if-cached

Response Directives:

Cache-Control: must-revalidate
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: no-transform
Cache-Control: public
Cache-Control: private
Cache-Control: proxy-revalidate
Cache-Control: max-age=<seconds>
Cache-Control: s-maxage=<seconds>
  • public – Response may be cached by any cache.
  • private – Intended for a single user; not stored by shared caches.
  • no-cache – Caches must revalidate with origin before release.
  • only-if-cached – Do not retrieve new data; serve only cached copy.
  • max-age=<seconds> – Time a resource is fresh (relative to request time).
  • s-maxage=<seconds> – Overrides max-age/Expires for shared caches only.
  • max-stale[=<seconds>] – Client accepts expired responses.
  • min-fresh=<seconds> – Needs response fresh for at least given seconds.
  • must-revalidate – Must verify stale resources before using.
  • proxy-revalidate – Like must-revalidate but only for shared caches.
  • no-store – Cache must not store request or response.
  • no-transform – No transformations on the resource.

Examples:

Cache-Control: no-cache, no-store, must-revalidate
Cache-Control: public, max-age=31536000

Access-Control-Allow-Credentials

A response header that indicates whether the response to the request can be exposed to the page. When the value is true, credentials (cookies, Authorization header, or TLS client certificates) are exposed.

Syntax:

Access-Control-Allow-Credentials: true
  • true – The only valid value (case-sensitive). If credentials are not needed, omit the header rather than setting false.

Example:

Access-Control-Allow-Credentials: true

ETag

This HTTP response header is an identifier for a specific version of a resource. It allows caches to be more efficient and saves bandwidth. If the resource changes, a new ETag value must be generated. ETags can also be used for tracking by some servers.

Syntax:

ETag: W/"<etag_value>"
ETag: "<etag_value>"
  • W/ (Optional) – Weak validator used; easier to generate but less useful for byte-for-byte comparison.
  • “<etag_value>” – ASCII string in quotes uniquely representing the resource (e.g., hash, timestamp, or revision number).

Examples:

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
ETag: W/"0815"

Vary

A HTTP response header that signifies how to match a future request header to decide whether a cached response can be used instead of requesting from the origin server. Should be set on 304 Not Modified the same as on an equivalent 200 OK.

Syntax:

Vary: *
Vary: <header-name>, <header-name>, ...
  • * – Treat each URL request as unique and uncacheable.
  • <header-name> – Comma-separated list of headers considered when deciding cache reuse.

Example:

Vary: User-Agent

Using Vary: User-Agent ensures caches consider the user agent (e.g., serving different content to mobile vs desktop).

Pragma

A HTTP/1.0 general header, implementation-specific, used for backwards compatibility with HTTP/1.0 caches when the Cache-Control header is not present.

Syntax:

Pragma: no-cache
  • no-cache – Same as Cache-Control: no-cache; forces revalidation before releasing a cached copy.

Example:

Pragma: no-cache

Expires

This header encompasses the date/time after which the response is considered stale. Invalid dates (e.g., 0) indicate a past date, meaning the resource is already expired. If Cache-Control with max-age or s-maxage is present, Expires is ignored. A past expiration (or 0) prevents caching.

Syntax:

Expires: <http-date>
  • <http-date> – HTTP-date timestamp.

Example:

Expires: Wed, 21 Oct 2015 07:28:00 GMT

Access-Control-Allow-Headers

A response header used in reply to a preflight request, indicating which HTTP headers can be used during the actual request. Required if the request has an Access-Control-Request-Headers header.

Syntax:

Access-Control-Allow-Headers: <header-name>, <header-name>, ...
  • <header-name> – Comma-delimited list of supported request headers.

Example:

Access-Control-Allow-Headers: X-Custom-Header

Access-Control-Allow-Methods

A response header specifying the HTTP method(s) allowed when accessing the resource, in response to a preflight request.

Syntax:

Access-Control-Allow-Methods: <method>, <method>, ...
  • <method> – Comma-delimited list of allowed HTTP request methods.

Example:

Access-Control-Allow-Methods: POST, GET, OPTIONS

Access-Control-Expose-Headers

A response header indicating which headers can be exposed as part of the response. By default, the six simple response headers are exposed: Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, and Pragma.

Syntax:

Access-Control-Expose-Headers: <header-name>, <header-name>, ...
  • <header-name> – List of exposed headers beyond the simple response headers.

Examples:

Access-Control-Expose-Headers: Content-Length
Access-Control-Expose-Headers: Content-Length, X-Kuma-Revision

Access-Control-Max-Age

A response header indicating how long the results of a preflight request can be cached.

Syntax:

Access-Control-Max-Age: <delta-seconds>
  • <delta-seconds> – Number of seconds results can be cached. (Firefox caps at 86400; Chromium caps at 600 and defaults to 5. -1 disables caching.)

Example:

Access-Control-Max-Age: 600

Access-Control-Request-Headers

A request header used when issuing a preflight request to let the server know which HTTP headers will be used in the actual request.

Syntax:

Access-Control-Request-Headers: <header-name>, <header-name>, ...
  • <header-name> – Comma-delimited list of HTTP headers included in the request.

Example:

Access-Control-Request-Headers: X-PINGOTHER, Content-Type

Access-Control-Request-Method

A request header used in a preflight request to indicate which HTTP method will be used in the actual request. The preflight is always OPTIONS.

Syntax:

Access-Control-Request-Method: <method>
  • <method> – One of the HTTP request methods, e.g., GET, POST, DELETE.

Example:

Access-Control-Request-Method: POST

Allow

This header lists the set of methods supported by a resource. It should be sent when the server responds with 405 Method Not Allowed to indicate which methods can be used. An empty Allow header signifies that the resource allows no request methods (may occur temporarily).

Syntax:

Allow: <http-methods>
  • <http-methods> – List of allowed HTTP request methods.

Example:

Allow: GET, POST, HEAD

Content-Type

This header indicates the media type of the resource. In requests like POST or PUT, the client tells the server what type of data is being sent.

Syntax:

Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=something
  • media-type – MIME type of the resource or data.
  • charset – Character encoding.
  • boundary – Required for multipart entities; 1–70 robust characters; encapsulates message part boundaries.

Prashant Phatak

Founder & CEO, Valency Networks

Prashant Phatak is an accomplished leader in the field of IT and Cyber Security. He is Founder and C-level executive of his own firm Valency Networks. Prashant specializes in Vulnerability assessment and penetration testing (VAPT) of Web, Networks, Mobile Apps, Cloud apps, IoT and OT networks. He is also a certified lead auditor for ISO27001 and ISO22301 compliance.As an proven problem solver, Prashant's expertise is in the field of end to end IT and Cyber security consultancy to various industry sectors.

Related Blogs

Difference Between Privilege Escalation Attack and IDOR Attack

⭐️

Wireshark Tutorial -10 | Creating Wireshark Profiles

⭐️

Wireshark Tutorial -9 | Exporting and Sharing PCAP Files

⭐️

Wireshark Tutorial -8 | Detecting ICMP Floods or DoS Attempts

⭐️

Wireshark Tutorial -7 | Expose passwords sent in plain text

⭐️

Wireshark Tutorial -6 | Analyze HTTP, HTTPS, and DNS traffic