'How to disable Apache HTTP Header info in AWS Load Balancer Response?
I have a node.js environment deployed using AWS Elastic Beanstalk on an Apache server. I have run a PCI scan on the environment and I'm getting 2 failures:
- Apache ServerTokens Information Disclosure
- Web Server HTTP Header Information Disclosure
Naturally I'm thinking I need to update the httpd.conf file with the following:
ServerSignature Off
ServerTokens Prod
However, given the nature of Elastic Beanstalk and Elastic Load Balancers, as soon as the environment scales, adds new servers, reboots etc the instance config will be overwritten.
I have also tried putting the following into an .htaccess file:
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule .* https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]
# Security hardening for PCI
Options -Indexes
ServerSignature Off
# Dissallow iFrame usage outside of loylap.com for PCI Security Scan
Header set X-Frame-Options SAMEORIGIN
On the node js side I use the "helmet" package to apply some security measures, I also use the "express-force-https" package to ensure the application is enforcing https. However, these only seem to be taking effect after the Express application is initiated and after the redirect.
I have Elastic Load Balancer listeners set up for both HTTP (port 80) and HTTPS (port 443), however the HTTP requests are immediately routed to HTTPS.
When I run the following curl command:
curl -I https://myenvironment.com --head
I get an acceptable response with the following line:
Server: Apache
However when I run the same request on the http endpoint (i.e. before redirects etc):
curl -I http://myenvironment.com --head
I get a response that discloses more information about my server than it should, and hence the PCI failure:
Server: Apache/2.4.34 (Amazon)
How can I force my environment to restrict the http header response on HTTP as well as HTTPS?
Solution 1:[1]
Credit to @stdunbar for leading me to the correct solution here using ebextensions.
The solution worked for me as follows:
- Create a file in the project root called
.ebextensions/01_server_hardening.config
- Add the following content to the file:
files:
"/etc/httpd/conf.d/03_server_hardening.conf":
mode: "000644"
owner: root
group: root
content: |
ServerSignature Off
ServerTokens Prod
container_commands:
01_reload_httpd:
command: "sudo service httpd reload"
(Note: the indentation is important in this YAML file - 2 spaces rather than tabs in the above code).
During elastic beanstalk deployment, that will create a new conf file in /etc/httpd/conf.d folder which is set up to extend the httpd.conf settings in ELB by default.
The content manually turns off the ServerSignature and sets the ServerTokens to Prod, achieving the PCI standard.
Running the container command forces a httpd reboot (for this particular version of Amazon linux - ubuntu and other versions would require their own standard reload
).
After deploying the new commands to my EB environment, my curl commands run as expected on HTTP and HTTPS.
Solution 2:[2]
An easier and better solution exists now.
The folder /etc/httpd/conf.d/elasticbeanstalk
is deleted when the built-in application server is restarted (e.g. when using EB with built-in Tomcat). Since .ebextensions are not re-run the above solution stop working.
This is only the case when the application server is restarted (through e.g. Lambda or the Elastic Beanstalk web-console). If the EC2 instance is restarted this is not an issue.
The solution is to place a .conf file in a sub-folder in the .ebextensions.
- .ebextensions
- httpd
- conf.d
- name_of_your_choosing.conf
- conf.d
- httpd
Content of the file is the same as the output of the .ebextensions above, e.g.
ServerSignature Off
ServerTokens Prod
This solution will survive a restart of the application server and is much easier to create and manage.
Solution 3:[3]
You will ultimately need to implement some ebextensions to have this change applied to each of your Beanstalk instances. This is a mechanism that allows you to create one or more files that are run during the initialization of the beanstalk. I have an older one that I have not tested in your exact situation but it does the HTTP->HTTPS rewrite like you're showing. It was used in the Tomcat Elastic Beanstalk type - different environments may use different configurations. Mine looks like:
files:
"/tmp/00_application.conf":
mode: "000644"
owner: root
group: root
content: |
<VirtualHost *:80>
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R,L]
</VirtualHost>
container_commands:
01_enable_rewrite:
command: "echo 'LoadModule rewrite_module modules/mod_rewrite.so' >> /etc/httpd/conf/httpd.conf"
02_cp_application_conf:
command: "cp /tmp/00_application.conf /etc/httpd/conf.d/elasticbeanstalk/00_application.conf"
Again, this is a bit older and has not been tested for your exact use case but hopefully it can get you started.
This will need to be packaged with your deployment - i.e. in Java a .jar
or .war
or a .zip
in other environments. Take a look at the documentation link to learn more about deployments.
Solution 4:[4]
There is a little change in configuration file path as AWS has introduced Amazon Linux 2
.ebextentions
.platform
httpd
conf.d
whateverFilenameyouwant.conf
in .platform/httpd/conf.d/whatever-File-NameYouWant.conf
add below two line
ServerSignature Off
ServerTokens Prod
Above is for Apache Since AWS by default uses nginx for reverse proxy replace httpd to nginx it should work
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | contool |
Solution 2 | Martin Verner |
Solution 3 | stdunbar |
Solution 4 | cigien |