HTTP/1.1 200 OK
Content-Length: 88
Content-Type: text/html
X-Frame-Options: deny
<html> ...
X-Frame-Options
header. This prevents clickjacking attacks against your page. In case you really need to be framed by certain sites, you can explicitly allow them by replacing deny
with the according origin of the page you would like to be framed by. By explicitly allowing origins the risk of being framed by an attacker-controlled origin is minimized.HTTP Header | Secure-by-default | Description |
---|---|---|
X-Frame-Options | deny | Prevents other sites from framing yours and running Clickjacking attacks (deprecated) |
Content-Security-Policy | frame-ancestors none; | Prevents other sites from framing yours and running Clickjacking attacks |
X-XXS-Protection | 1; mode=block | Activates browsers' XSS filter when available; Blocks rendering when XSS detected |
X-Content-Type-Options | nosniff | Disables content-type sniffing of the browser |
Referrer-Policy | no-referrer | Disables automatic sending the referrer header when links are followed |
X-Download-Options | noopen | Disables automatic opening of downloads in older IE versions |
X-DNS-Prefetch-Control | off | Disables speculative DNS resolving for external links on your page |
Server | envoy | Automatically set by Istio's ingress gateway |
X-Powered-By | Removed to hide name and version of potentially vulnerable application servers | |
Feature-Policy | camera 'none'; microphone 'none'; geolocation 'none'; encrypted-media 'none'; payment 'none'; speaker 'none'; usb 'none'; | Restricts access to interfaces of the host machine for own page and all frames |
Content-Security-Policy
or Feature-Policiy
settings. But for now, this is our baseline setting.(Source: https://istio.io/docs/concepts/traffic-management/#ingress-and-egress)
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: security-by-default-header-filter
spec:
filters:
- listenerMatch:
listenerType: GATEWAY
filterType: HTTP
filterName: envoy.lua
filterConfig:
inlineCode: |
function envoy_on_response(response_handle)
function hasFrameAncestors(rh)
s = rh:headers():get("Content-Security-Policy");
delimiter = ";";
defined = false;
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
match = match:gsub("%s+", "");
if match:sub(1, 15)=="frame-ancestors" then
return true;
end
end
return false;
end
if not response_handle:headers():get("Content-Security-Policy") then
csp = "frame-ancestors none;";
response_handle:headers():add("Content-Security-Policy", csp);
elseif response_handle:headers():get("Content-Security-Policy") then
if not hasFrameAncestors(response_handle) then
csp = response_handle:headers():get("Content-Security-Policy");
csp = csp .. ";frame-ancestors none;";
response_handle:headers():replace("Content-Security-Policy", csp);
end
end
if not response_handle:headers():get("X-Frame-Options") then
response_handle:headers():add("X-Frame-Options", "deny");
end
if not response_handle:headers():get("X-XSS-Protection") then
response_handle:headers():add("X-XSS-Protection", "1; mode=block");
end
if not response_handle:headers():get("X-Content-Type-Options") then
response_handle:headers():add("X-Content-Type-Options", "nosniff");
end
if not response_handle:headers():get("Referrer-Policy") then
response_handle:headers():add("Referrer-Policy", "no-referrer");
end
if not response_handle:headers():get("X-Download-Options") then
response_handle:headers():add("X-Download-Options", "noopen");
end
if not response_handle:headers():get("X-DNS-Prefetch-Control") then
response_handle:headers():add("X-DNS-Prefetch-Control", "off");
end
if not response_handle:headers():get("Feature-Policy") then
response_handle:headers():add("Feature-Policy",
"camera 'none';"..
"microphone 'none';"..
"geolocation 'none';"..
"encrypted-media 'none';"..
"payment 'none';"..
"speaker 'none';"..
"usb 'none';");
end
if response_handle:headers():get("X-Powered-By") then
response_handle:headers():remove("X-Powered-By");
end
end
GATEWAY
listener - the Ingress gateway. Further, the type indicates that a Lua script defines the behavior of the filter. The Lua script itself registers itself onto the envoy_on_response
event which means the filter is only invoked for outgoing traffic and not incoming requests. The logic of the Lua code is quite simple: When a security header is already defined by the application do nothing. Otherwise, add the security header with a strict setting. Take into account that only parts of the Content-Security-Policy
and Feature-Policy
are set by the filter.secure-http-headers.yaml
) to an Istio cluster and the secure-by-default headers are ready to go.$ kubectl apply -f secure-http-headers.yaml
$ kubectl get envoyfilter
NAME AGE
security-by-default-header-filter 1m
kubectl apply
. The secure-by-default headers can be overruled by setting them explicitly within your application.You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
21 | |
14 | |
11 | |
9 | |
8 | |
8 | |
7 | |
6 | |
6 | |
6 |