Search code examples
securityhttp-headershttpresponsepenetration-testingapplication-security

Is it fine to use duplicate response header with same value?


I found a response where duplicate headers are used by the application with the same value. Could anyone tell me that, Is it a good programming practice or those are used for security perspective or anything else?

  
     HTTP/1.1 200 
     Accept-Ranges: bytes
     Cache-Control: no-cache, must-revalidate, private
     Content-Type: text/html
     Date: Mon, 20 Nov 2017 04:08:51 GMT
     Expires: 0
     Last-Modified: Thu, 16 Nov 2017 14:04:48 GMT
     Pragma: 
     Public-Key-Pins: pin-sha256="5w0XrTCAbsVO7vTngDViNHPutlvB43qYionPbpV2ky0=";  
     max-age=5184000; includeSubDomains;
     Server: Any
     Set-Cookie: ********************* httponly; secure; path=/
     Strict-Transport-Security: max-age=31536000 ; includeSubDomains
     Strict-Transport-Security: max-age=31536000; includeSubDomains
     X-Content-Type-Options: nosniff
     X-Content-Type-Options: nosniff
     X-Frame-Options: SAMEORIGIN
     X-Frame-Options: SAMEORIGIN
     X-XSS-Protection: 1; mode=block
     Content-Length: 559
     Connection: Close

This application is using duplicate X-Content-Type-Options header, Strict-Transport-Security, X-Frame-Options header with same values.


Solution

  • This is a programming/configuration error. RFC 7230 (Section 3.2.2) says:

    A sender MUST NOT generate multiple header fields with the same field name in a message unless either the entire field value for that header field is defined as a comma-separated list [i.e., #(values)] or the header field is a well-known exception (as noted below).

    So using multiple headers like this:

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

    is undefined behavior. The same section says:

    A recipient MAY combine multiple header fields with the same field name into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field value to the combined field value in order, separated by a comma.

    So one possible interpretation of the above headers is:

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

    which is not valid syntax according to https://www.rfc-editor.org/rfc/rfc6797#section-6.1 and might get rejected (and as a result, the HSTS policy is not applied).

    Note that not all implementation might follow to this specified behavior. For example, the Python http library just returns a list of headers, in the above case it might look like:

    [
        # ...
        ('Strict-Transport-Security', 'max-age=31536000 ; includeSubDomains'),
        ('Strict-Transport-Security', 'max-age=31536000; includeSubDomains')
        # ...
    ]
    

    Depending on the implementation, at least these three behaviors are possible:

    • Merging headers, separated by a comma (as specified by RFC 7230).
    • Using the first header match.
    • Using the last header match.

    A mismatch of interpretation between validation and use could lead to attacks, although this will probably not very severe for the HSTS header.