How can i add current URL to .htaccess CSP header dynamically? - apache

I'm currently working on Shopify app, one of their main requirement is to add an iframe-protection. here is more info
Currently, to resolve this I need the CSP to set should be in this format :
Content-Security-Policy: frame-ancestors https://shopify-dev.myshopify.com https://admin.shopify.com;
The https://shopify-dev.myshopify.com in above code should be the merchant/ requester domain.
What I tried?
I created .htaccess file with following, it's not adding the dynamic url.
<IfModule mod_rewrite.c>
RewriteEngine On
Header set Content-Security-Policy "frame-ancestors '%{HTTP_HOST}' 'https://admin.shopify.com';"
</IfModule>
This is what I'm getting in console:

Apache
On Apache, you would need to do it like this instead:
### Apache ###
Header set Content-Security-Policy "frame-ancestors https://%{HTTP_HOST}e https://admin.shopify.com;"
Note the e after %{HTTP_HOST}e (specific syntax for mod_headers). I've also removed the single quotes (not present in the Spotify example) and included the https:// protocol.
The <IfModule> and RewriteEngine On directives are irrelevant here.
Reference:
https://httpd.apache.org/docs/current/mod/mod_headers.html#header
UPDATE:
LiteSpeed
However, if you are using LiteSpeed (as opposed to Apache) you will instead need to first explicitly assign the Host header to an environment variable and use this in the Header directive instead. (Apache is able to access server variables directly using this syntax, but not LiteSpeed.)
For example:
### LiteSpeed ###
# Assign the "Host" header to an env var "HOSTNAME"
SetEnvIf Host "(.*)" HOSTNAME=$1
# Use "HOSTNAME" (env var) instead in the Header directive
Header set X-Content-Security-Policy "frame-ancestors https://%{HOSTNAME}e https://admin.shopify.com;"
Attempting to use the syntax %{HTTP_HOST} (as you originally had) on Apache would have resulted in a 500 Internal Server Error (with the error "Unrecognized header format %" being reported in the error logs). However, on LiteSpeed this just outputs the literal string {HTTP_HOST} and no error.

Related

Apache2 - Rewrite Response header Key

How can I rewrite response headers within the apache2 conf? Is this even possible?
We are using apache2 for legacy services which connects to a service behind an envoy proxy.
Envoy always set the response and request header to lower-case. Their solution with
preserve case format doesn't work, because they don't respect the source header.
I expect a responseheader like
"DockingStation_One: 44"
envoy does
"dockingstation_one: 44"
with their preserve case format i get
"Dockingstation_one: 44"
My idea was to rewrite the header either with mod_rewrite or mod_headers in apache2 before it send the response to the client. Sadly nothing works as expected.
My latest setting:
<Location /my/service/v2>
RewriteEngine on
# 1. Save the current value in env var (Case of header name does not matter)
SetEnvIf dockingstation_one(.*) HEADER_VALUE=$1
# 2. Delete the current header (Case of header name does not matter)
Header unset "dockingstation_one" env=HEADER_VALUE
# 3. Recreate header with the required case (Case of header name is preserved)
# env=HEADER_VALUE ensures the header is only set if it was set to begin with
Header set "DockingStation_One" %{DOCKINGSTATION_ONE}e env=HEADER_VALUE
ProxyPass "http://service.go:8090/v2"
ProxyPassReverse "http://service.go:8090/v2"
</Location>
Nevermind. My whole syntax was wrong. My fix looks like this:
Header always set "DockingStation_One" "expr=%{resp:dockingstation_one}"

Apache - Convert underscores to dashes in headers

In a project a had to run CA Webagent Siteminder which sends me legacy headers with underscores. Since Apache 2.4 underscores are deprecated and dropped silently.
I need a workaround via mod_headers which converts all underscores _ to dashes - in the request-header.
Before
legacy_header_one
legacy_header_two
legacy_header_three
After
legacy-header-one
legacy-header-two
legacy-header-three
You have two options here:
Apache Bypass
#
# The following works around a client sending a broken Accept_Encoding
# header.
#
SetEnvIfNoCase ^Accept.Encoding$ ^(.*)$ fix_accept_encoding=$1
RequestHeader set Accept-Encoding %{fix_accept_encoding}e env=fix_accept_encoding
Siteminder Bypass
#its not explicitly stated but im assuming this should be in your WebAgent.conf file
LegacyVariables="NO"
EDIT:
I know this doesn't directly answer your question of converting from _ to - but it is an answer to help mitigate the Apache 2.4 vs. CA Siteminder header issue.
In your virtualhost config:
SetEnvIfNoCase ^OAM.REMOTE.USER$ ^(.*)$ fix_accept_encoding=$1
RequestHeader set OAM-REMOTE-USER %{fix_accept_encoding}e env=fix_accept_encoding
If you are using mod_wsgi for Django or Flask, you will need to add:
WSGIPassAuthorization On

mod_rewrite: add a header if it doesn't already exist

I am attempting to add CORS handling using apache and mod_rewrite. The apache instance is front-ending multiple tomcat applications using mod_jk. Some of these applications have their own logic for adding CORS headers Access-Control-Allow-Origin, Access-Control-Max-Age, etc.
For the applications that didn't take care of the CORS logic, I would like to manage it on apache using mod rewrite.
Does anyone know if its possible to add a header to an HTTP response using mod_rewrite only if the header doesn't already exist? The browser reports an error if the CORS origin header is written twice.
mod_rewrite is to rewrite url's, not to set headers. What you want to use is mod_headers (documentation).
I don't know if mod_rewrite runs before mod_headers, but I would suggest to set environment variables using SetEnvIf instead (documentation).
You can do something like this:
SetEnvIf Request_URI "^/my/app/(.*)/?$" ADDHEADERS=1
Header set Access-Control-Max-Age 123456 env=ADDHEADERS

X-Frame-Options on Apache

I am trying to allow some particular domain to access my site via iframe
Header set X-Frame-Options ALLOW-FROM https://www.example.com
I know this could be done by add the line above to the config of Apache server.
Two questions here.
which config file should be added to? The Apache running on both Unix and windows, if not the same file
while enable the all-from, I still want to be able to run some iframe from my own domain. Can I just add the following line after the allow-from?
Header set X-Frame-Options SAMEORIGIN
Or I should just add my own domain in the all-from, ie
Header set X-Frame-Options ALLOW-FROM https://www.example.com, http://www.my-own-domain.example
You can add to .htaccess, httpd.conf or VirtualHost section
Header set X-Frame-Options SAMEORIGIN this is the best option
Allow from URI is not supported by all browsers. Reference: X-Frame-Options on MDN
See X-Frame-Options header on error response
You can simply add following line to .htaccess
Header always unset X-Frame-Options
What did it for me was the following, I've added the following directive in both the HTTP <VirtualHost *:80> and HTTPS <VirtualHost *:443> virtual host blocks:
ServerName example.com
ServerAlias www.example.com
Header always unset X-Frame-Options
Header set X-Frame-Options "SAMEORIGIN"
The reasoning behind this? Well by default if set, the server does not reset the X-Frame-Options header so we need to first always remove the default value, in my case it was DENY, and then with the next rule we set it to the desired value, in my case SAMEORIGIN. Of course you can use the Header set X-Frame-Options ALLOW-FROM ... rule as well.
This worked for me on all browsers:
Created one page with all my javascript
Created a 2nd page on the same server and embedded the first page using the object tag.
On my third party site I used the Object tag to embed the 2nd page.
Created a .htaccess file on the original server in the public_html folder and put Header unset X-Frame-Options in it.
I found that if the application within the httpd server has a rule like "if the X-Frame-Options header exists and has a value, leave it alone; otherwise add the header X-Frame-Options: SAMEORIGIN" then an httpd.conf mod_headers rule like "Header always unset X-Frame-Options" would not suffice. The SAMEORIGIN value would always reach the client.
To remedy this, I add two, not one, mod_headers rules (in the outermost httpd.conf file):
Header set X-Frame-Options ALLOW-FROM http://example.com early
Header unset X-Frame-Options
The first rule tells any internal request handler that some other agent has taken responsibility for clickjack prevention and it can skip its attempt to save the world. It runs with "early" processing. The second rule strips off the entirely unwanted X-Frame-Options header. It runs with "late" processing.
I also add the appropriate Content-Security-Policy headers so that the world remains protected yet multi-sourced JavaScript from trusted sites still gets to run.
you have to enable mod_headers first in your server
sudo a2enmod headers
sudo service apache2 restart

Rewrite authenticated Apache2.2 user for mod_proxy_ajp

I have a Tomcat connected via mod_proxy_ajp to an Apache2.2 instance. Apache does the authentication via mod_auth_kerb, and Tomcat uses request.getRemoteUser() to get the authenticated user.
This basically works, but I want to rewrite the user. However, none of the headers I set affect what is returned by request.getRemoteUser(), I only see them as additional headers, what do I have to do?
# Rewrite Magic: change REMOTE_USER to something Alfresco expects
RewriteEngine On
RewriteMap domain_map txt:/etc/apache2/rewrite-map.txt
# Grab the REMOTE_USER apache environment variable for HTTP forwarding (requires sub-request!)
RewriteCond %{LA-U:REMOTE_USER} (.*)#(.*)
# change the format and replace the domain, e.g.:
# user#some.domain ==> other.domain_user
RewriteRule . - [E=RU:${domain_map:%2|%2}_%1]
# copy processed user to HTTP headers
RequestHeader set REMOTE_USER %{RU}e
RequestHeader set HTTP_REMOTE_USER %{RU}e
RequestHeader set AJP_REMOTE_USER %{RU}e
RequestHeader set AJP_HTTP_REMOTE_USER %{RU}e
Thanks!
I suspect that the headers are not being set as you expect them to be set, and they are getting to Tomcat empty.
I have experienced some puzzling processing order issues that caused RequestHeader to ignore the environment variables set by a RewriteRule. Take a look at https://stackoverflow.com/a/9303018/239408 in case it helps
It seems the getRemoteUser() value can not be overwritten by Apache header directives, as the AJP protocol handler gets the username from some internal Apache structure. I worked around this by sending the username via http header and modifying the Java code to use that instead of using getRemoteUser().