public function onRespond(FilterResponseEvent $event) {
$response = $event->getResponse();
// ...
// Prevent browsers from sniffing a response and picking a MIME type
// different from the declared content-type, since that can lead to
// XSS and other vulnerabilities.
// https://www.owasp.org/index.php/List_of_useful_HTTP_headers
$response->headers->set('X-Content-Type-Options', 'nosniff', FALSE);
// ...
}
# Various header fixes.
<IfModule mod_headers.c>
# Disable content sniffing, since it's an attack vector.
Header always set X-Content-Type-Options nosniff
# Disable Proxy header, since it's an attack vector.
RequestHeader unset Proxy
</IfModule>
public function onRespond(FilterResponseEvent $event) {
$response = $event->getResponse();
// ...
$response->headers->set('X-Frame-Options', 'SAMEORIGIN', FALSE);
// ...
}
Source | Destination | Referrer |
---|---|---|
https://example.com/page-one | https://example.com/page-two | https://example.com/page-one |
https://example.com/page-one | https://google.com/ | https://example.com |
https://example.com/page-one | http://example.com/page-two | NULL |
https://example.com/page-one | http://google.com/ | NULL |
services:
my_module.response_listener:
class: Drupal\my_module\EventSubscriber\ResponseSubscriber
arguments: ['@config.factory']
tags:
- { name: event_subscriber }
namespace Drupal\my_module\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
class ResponseSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
$events[KernelEvents::RESPONSE] = ['onKernelResponse'];
return $events;
}
public function onKernelResponse(FilterResponseEvent $event) {
if (!$event->isMasterRequest()) {
return;
}
$response = $event->getResponse();
$response->headers->set('HeaderName', 'header-value');
}
}
SSLEngine On
SSLCertificateFile example.crt
SSLCertificateKeyFile example.key
# Set HSTS header for six months
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=15552000"
</IfModule>
![]()
Fascinating thread from a leader in HTTPS ecosystem — providing HPKP capability to unvetted web developers was a mistake, in retrospect. https://t.co/qUjaXym7uT
— SwiftOnSecurity (@SwiftOnSecurity) 24 Aug 2017
![]()
tl;dr the people who standardized HPKP say don't use it, it sounds like a cool hedge, but the risk incredible long-term for theoretical gain
— SwiftOnSecurity (@SwiftOnSecurity) 24 Aug 2017
![]()
But pinning is terrible - and harms the ecosystem more than helps, as we've seen. It was a bad thing to standardize 😔
— Ryan Sleevi (@sleevi_) 24 Aug 2017
![]()
Interesting. I should buy you some scotch so I can learn more.
— Mark Nottingham (@mnot) 24 Aug 2017
![]()
No scotch needed to get me to apologize for my sins and the painful lessons learned. I actively discourage it now, even w/ ecosystem risk
— Ryan Sleevi (@sleevi_) 24 Aug 2017
![]()
But pinning your own key is a still a footgun. I know of several who pinned to keys they couldn't legit get certs for when needed
— Ryan Sleevi (@sleevi_) 24 Aug 2017
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' code.jquery.com www.google.com www.google-analytics.com;
style-src 'self' 'unsafe-inline' netdna.bootstrapcdn.com www.google.com ajax.googleapis.com;
img-src 'self' s3.amazonaws.com www.google-analytics.com stats.g.doubleclick.net;
connect-src 'self' www.drupal.org www.google-analytics.com;
report-uri https://gapple.report-uri.io/r/default/csp/enforce;
Content-Security-Policy:
default-src *;
script-src * 'unsafe-inline';
style-src * 'unsafe-inline';
report-uri https://gapple.report-uri.io/r/default/csp/enforce;
Content-Security-Policy-Report-Only:
default-src 'self';
report-uri https://gapple.report-uri.io/r/default/csp/reportOnly;
Content-Security-Policy:
default-src 'self';
script-src assets.example.com;
style-src assets.example.com;
img-src assets.example.com files.example.com;
connect-src 'self';
testlib:
version: "1.x"
css:
theme:
https://example.com/css/testlib.css: {}
js:
http://example.com/js/testlib.js: {}
<!-- Google Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<!-- End Google Analytics -->
<!-- Google Analytics -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
<!-- End Google Analytics -->
Locate this session at the DrupalCon Vienna website
https://events.drupal.org/vienna2017/sessions/using-your-headers-better-security
Take the survey!
https://www.surveymonkey.com/r/drupalconvienna