bunkerity / bunkerweb

🛡️ Open-source and next-generation Web Application Firewall (WAF)
https://www.bunkerweb.io
GNU Affero General Public License v3.0
6.12k stars 339 forks source link

[BUG] content-security-policy set statically, cannot open "_blank" , cannot set (X-)Content-Security-Policy from Webserver #221

Closed benchonaut closed 1 year ago

benchonaut commented 2 years ago

Description

Content-Security-Policy is not set via map , also x-content-security-policy etc. are missing Also one cannot set it from the webserver behing bunkerized nginx.

How to reproduce

start it with a site that has Content-Security-Policy / X-Content-Security-Policy you cannot open target="_blank" pages due to sandbox in CSP even when sending correct headers from upstream

Example image of Firefox

Firefox will fetch the contents due to browser console of your _blank target but not show it , instead "Blocked Page"(here in german "Blockierte Seite") will appear

firefox blocked_page

Logs

(none, your browser will e.g. show blocked page or misbehave when you expect to have content-security-policy from your backend )

Fix

(

To fix it

( be careful , this one has a very open default CSP since you should send these headers from your framework ) you would need a map setup similiar to the one here: https://gitlab.com/the-foundation/flying-docker-compose-letsencrypt-nginx-proxy-companion/-/blob/master/nginx.tmpl.behindproxy#L406 https://gitlab.com/the-foundation/flying-docker-compose-letsencrypt-nginx-proxy-companion/-/blob/master/nginx.conf#L49

put in nginx.conf

map $upstream_http_strict_transport_security $sts {
  '' "max-age=15552123 ; includeSubDomains; preload";
}
map $upstream_http_x_xss_protection $xssprot {
  '' "1";
}
map $upstream_http_referrer_policy $refpolicy {
  '' "no-referrer-when-downgrade";
}
map $upstream_http_x_content_type_options $contoptions {
  '' "nosniff";
}
map $upstream_http_x_frame_options $xframeoptions {
  '' "SAMEORIGIN";
}
map $upstream_http_access_control_allow_origin $alloworigin {
  '' "*";
}
map $upstream_http_permissions_policy $permpolicy {
  '' "accelerometer=(), autoplay=(self), battery=(), camera=(), cross-origin-isolated=(self), display-capture=(), document-domain=(self), encrypted-media=(self), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=*, geolocation=(self), gyroscope=(), magnetometer=(), microphone=(), midi=(), navigation-override=(self), payment=(), picture-in-picture=*, publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(self), usb=(), web-share=(self), xr-spatial-tracking=(self), clipboard-read=(), clipboard-write=(self), gamepad=(self), speaker-selection=(self), conversion-measurement=(), focus-without-user-activation=(), hid=(), idle-detection=(self), serial=(), sync-script=(), trust-token-redemption=(), vertical-scroll=(self)" ;
}

map $upstream_http_content_security_policy  $csp {
  '' "default-src 'self' https: ; script-src * 'unsafe-inline' 'unsafe-eval'; script-src-elem * 'unsafe-inline' 'unsafe-eval' ; script-src-attr * 'unsafe-inline' 'unsafe-eval'; style-src * data: 'unsafe-inline'; img-src * data: ; font-src * data: ; connect-src *; media-src *; object-src *; prefetch-src *; child-src *; frame-src *; worker-src *; frame-ancestors *; form-action 'self'; upgrade-insecure-requests; base-uri *; manifest-src *";
}
map $upstream_http_content_security_policy  $cspstrict {
  '' "default-src 'self' 'unsafe-inline' 'unsafe-hashes'; script-src 'self' data: 'unsafe-inline' 'unsafe-hashes'; script-src-elem *; script-src-attr *; style-src 'self' data: 'unsafe-inline'; style-src-elem 'self' data: 'unsafe-inline'; style-src-attr 'self' data: 'unsafe-inline'; img-src *; font-src 'self' data:; connect-src 'self'; media-src 'self'; object-src 'self'; prefetch-src 'self'; child-src 'self'; frame-src 'self'; worker-src 'self'; frame-ancestors 'self'; form-action 'self'; upgrade-insecure-requests; base-uri *; manifest-src *";
}

and then in your server or location context:

  add_header Strict-Transport-Security "$sts";

    #add_header Access-Control-Max-Age 7200;
  #add_header Access-Control-Expose-Headers Content-Length;
  #add_header Access-Control-Allow-Headers Range;
    add_header X-XSS-Protection $xssprot;
  add_header Referrer-Policy $refpolicy;
  add_header X-Content-Type-Options $contoptions ;
  add_header Content-Security-Policy $csp;
  add_header X-Content-Security-Policy $csp;
  add_header X-WebKit-CSP $csp;
  add_header Permissions-Policy $permpolicy;
  add_header X-Frame-Options $xframeoptions;
  add_header Access-Control-Allow-Origin $alloworigin;

)

fl0ppy-d1sk commented 1 year ago

Hello @benchonaut,

With 1.5.1 release, you can now use the KEEP_UPSTREAM_HEADERS setting to list headers coming from upstream that you want to keep. Default value is set to Content-Security-Policy Permissions-Policy Feature-Policy X-Frame-Options.

Thanks for your issue.