Add Secure and httpOnly Flags to Every Set-Cookie Response in Apache httpd
Asked Answered
G

6

24

I'm running Apache 2.2.26:

Server version: Apache/2.2.26 (Unix)
Server built:   Jan 17 2014 12:24:49
Cpanel::Easy::Apache v3.22.30 rev9999 +cloudlinux

I'm attempting to use mod_headers to edit Set-Cookie headers and add the secure or httpOnly flag, but its not working at all (Does nothing, doesn't give HTTP 500 error).

I can use the "modify" "append", directives of the Header command without an issue, just not the edit. I do not know why...

I've tried many combinations, but this is what I have in my .htaccess:

Header edit Set-Cookie "(.)([Hh][Tt][Tt][Pp][Oo][Nn][Ll][Yy])?(.)" "$1$2 ;HTTPOnly"
Header edit Set-Cookie "(.)([Ss][Ee][Cc][Uu][Rr][Ee])?(.)" "$1$2 ;Secure"

I'm open to any solution that will automatically add the flags to every Set-Cookie response, without requiring the editing of code within the application. I do not have access to install additional items on the web server, but the web server has the standard very long list of Apache modules found on most web hosts.

Glaze answered 9/6, 2014 at 21:16 Comment(3)
I might have found the answer, but I'm not really sure what they're talking about: apache-http-server.18135.x6.nabble.com/… A PHP file is creating the cookie, which might be configured as CGI, I'm not sure.Glaze
serverfault.com/questions/235713/… ?Ferment
I saw that, but the problem there was it was Apache 2.2.3, and the edit was added in 2.2.4. I'm running Apache 2.2.26... so unless there is a way for the edit to be taken out I would think it would be there. I suppose maybe its an old version of mod_headers rather than an old version of Apache? I'll have to poke into that.Glaze
S
56

The Header edit directive runs before your application produces a response, so if the application is producing the header you want to edit, that header won't yet exist at the time the directive runs, and there'll be nothing for it to edit.

You can fix this by using Header always edit (which runs after your application produces a response) instead:

Header always edit Set-Cookie (.*) "$1; HTTPOnly"

An example header, before applying the directive:

Set-Cookie: foo=bar; domain=.example.com; path=/

The same header after applying the directive:

Set-Cookie: foo=bar; domain=.example.com; path=/; HTTPOnly

I'm not sure what the directives in your question are meant to do exactly; what they actually result in when changed to Header always edit (assuming the same Set-Cookie header as in my example above) is e.g.

Set-Cookie: f ;HTTPOnlyo=bar; domain=.example.com; path=/

If you understand how regexes and backreferences work, it's obvious what's happening there, but presumably it's not what you want. The directive I've given at the top of this answer ought to work for you if, as you say, you want to add the flag to every Set-Cookie header; if your needs are more complex and I've misunderstood what you're trying to do with that search/replace, let me know.

EDIT: In case it isn't obvious: to add both flags, you can either modify the directive like so:

Header always edit Set-Cookie (.*) "$1; HTTPOnly; Secure"

... or use two directives:

Header always edit Set-Cookie (.*) "$1; HTTPOnly"
Header always edit Set-Cookie (.*) "$1; Secure"

The first approach seems more sensible to me, but it's largely a matter of taste.

Swingletree answered 16/6, 2014 at 14:52 Comment(7)
Hi, I'm trying this Header always edit Set-Cookie (.*) "$1; HTTPOnly; Secure" approach on Apache 2.4.6 but it doesn't seem to workLakieshalakin
@Lakieshalakin It's important to note that Secure will require HTTPS for it to work. If you use Secure on HTTP then the cookie will not work.Mclean
See if I get it right. Inside my htacess I add this line Header always edit Set-Cookie (.*) "$1; HTTPOnly; Secure"? I have this lot of error prnt.sc/pehmj8Julissa
Thanks a lot for this solution. It works perfectly. For those searching for a solution to apply site-wide but exclude specific cookies, read here: https://mcmap.net/q/581698/-edit-cookie-httponly-valueGrowing
how can I edit the header Set-Cookie for a specific cookie only, i.e I just want to add HttpOnly, Secure for the cookie name _jsessionid ?Notum
I've tried but as you can see didn't flag JessionID cookie for example. What's wrong? See at ibb.co/tPtQhJbThermoscope
If your Header always edit directive isn't being applied to a particular header, take a look at the answer I just left. You probably (also) want Header onsuccess edit.Flamethrower
F
12

Six years later, I may have solved this.

The Header directive is provided by mod_headers, and is structured as Header {condition} {action} {header name} {match} {replacement}. The key that I haven't seen anybody bring up in other answers is the first variable, condition.

condition can be always or onsuccess, per the description in the link above, but -- and this is why it took so long to crack -- always does not actually mean "always":

always is not a superset of onsuccess with respect to existing headers

More specifically, there are two tables of headers called "always" and "onsuccess" and a given module can put a value in either or both of them, and all values from both tables will be written in the response.

TL;DR: always be sure to edit headers in both tables:

Header always edit Set-Cookie (.*) "$1; HTTPOnly"
Header onsuccess edit Set-Cookie (.*) "$1; HTTPOnly"
Flamethrower answered 28/5, 2021 at 13:39 Comment(3)
Thanks for this, thought I was going crazy before I saw your answer.Medin
I would argue that whoever designed this system was the crazy one, but, you're welcome :DFlamethrower
@Coderer, In which file do we need to add the above code?Cultured
T
7

I was trying to set http, secure and samesite=strict on cookies.

This worked for me:

Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure

Samesite=strict provides protection againsts XSRF.

Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure;SameSite=strict

Hope it helps.

Trumpeter answered 20/3, 2019 at 9:24 Comment(1)
See if I get it right. Inside my htacess I add this line Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure;SameSite=strict? I have this lot of error prnt.sc/pehmj8Julissa
C
5

This will add the tag to only those cookies that need it:

Header always edit Set-Cookie "^((?!;\s?[Ss]ecure).)+$" "$0; Secure"
Chattanooga answered 6/3, 2020 at 23:5 Comment(1)
Your regex is matching any Set-Cookie header that doesn't start with ; Secure => obviously, it will also match any Set-Cookie already containing (but not starting with !) Secure, thus this will duplicate the Secure string in the resulting header.Limoli
M
0

make sure that mod_headers.so is enabled then add the following header in apache2.conf for debian based system or httpd.conf for rpm based system

 Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure

For lower than Apache 2.2.4 version use the following:

Header set Set-Cookie HttpOnly;Secure 

then Restart the server

Mcgarry answered 9/7, 2019 at 9:9 Comment(0)
L
0

Most provided answers to this problem that can be found on the web generally fail on 4 things:

  1. HttpOnly, Secure, SameSite=… should not be appended a second time to the Set-cookie header if it's already there. (how do you think the web browser should interpret something like Set-Cookie: mycookie=foo; SameSite=Lax; SameSite=Strict => is it lax or is it strict ??)
  2. Secure is a good thing if using HTTPS but it will completely break the cookie if using HTTP, therefore we should conditionally add this keyword only on HTTPS connexions.
  3. (Almost?) Nobody really knows if we should just use Header edit or Header always edit or Header onsuccess edit or may both (shame on Apache's bad documentation!)
  4. In an ideal world, it should be the responsibility of the web developers to put the appropriate security keywords whenever they create cookies in their websites. The Header set Set-Cookie trick is here only to strengthen security of your Apache web server in case the developers didn't do their job properly (but that never happens, does it? :-p). Therefore, you should not destroy the work done by a good developper (who took time to put the right SameSite=… value when creating his/her cookie) by overwriting it with a SameSite=strict which is going to break the whole web app. (I give you an example: for Single Sign-On on a CAS server, you have to set the session cookie as SameSite=lax otherwise it simply doesn't work)

Here's a working solution that addresses all those things:

Header onsuccess edit Set-Cookie ^(.*(?i:HttpOnly).*)$ ;;;HttpOnly_ALREADY_SET;;;$1
Header onsuccess edit Set-Cookie ^((?!;;;HttpOnly_ALREADY_SET;;;).*)$ $1;HttpOnly
Header onsuccess edit Set-Cookie ^(?:;;;HttpOnly_ALREADY_SET;;;)(.*)$ $1
Header always edit Set-Cookie ^(.*(?i:HttpOnly).*)$ ;;;HttpOnly_ALREADY_SET;;;$1
Header always edit Set-Cookie ^((?!;;;HttpOnly_ALREADY_SET;;;).*)$ $1;HttpOnly
Header always edit Set-Cookie ^(?:;;;HttpOnly_ALREADY_SET;;;)(.*)$ $1

Header onsuccess edit Set-Cookie ^(.*(?i:SameSite=).*)$ ;;;SameSite_ALREADY_SET;;;$1
Header onsuccess edit Set-Cookie ^((?!;;;SameSite_ALREADY_SET;;;).*)$ $1;SameSite=strict
Header onsuccess edit Set-Cookie ^(?:;;;SameSite_ALREADY_SET;;;)(.*)$ $1
Header always edit Set-Cookie ^(.*(?i:SameSite=).*)$ ;;;SameSite_ALREADY_SET;;;$1
Header always edit Set-Cookie ^((?!;;;SameSite_ALREADY_SET;;;).*)$ $1;SameSite=strict
Header always edit Set-Cookie ^(?:;;;SameSite_ALREADY_SET;;;)(.*)$ $1

<If "%{HTTPS} == 'on'">
  Header onsuccess edit Set-Cookie ^(.*(?i:Secure).*)$ ;;;Secure_ALREADY_SET;;;$1
  Header onsuccess edit Set-Cookie ^((?!;;;Secure_ALREADY_SET;;;).*)$ $1;Secure
  Header onsuccess edit Set-Cookie ^(?:;;;Secure_ALREADY_SET;;;)(.*)$ $1
  Header always edit Set-Cookie ^(.*(?i:Secure).*)$ ;;;Secure_ALREADY_SET;;;$1
  Header always edit Set-Cookie ^((?!;;;Secure_ALREADY_SET;;;).*)$ $1;Secure
  Header always edit Set-Cookie ^(?:;;;Secure_ALREADY_SET;;;)(.*)$ $1
</If>

(these lines have been tested working on Apache 2.4.56. The <If> condition requires Apache 2.4 or later. Appart from that, the rest should work with Apache 2.2.4 or later)

Limoli answered 5/7, 2023 at 18:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.