Merge branch '880-header-security' into 'develop'

Resolve "Improve the security via HTTP headers"

Closes #880

See merge request funkwhale/funkwhale!826
This commit is contained in:
Eliot Berriot 2019-07-18 11:11:26 +02:00
commit 5b7fad0bef
11 changed files with 126 additions and 11 deletions

View File

@ -222,14 +222,15 @@ INSTALLED_APPS = (
# MIDDLEWARE CONFIGURATION
# ------------------------------------------------------------------------------
MIDDLEWARE = (
"django.middleware.security.SecurityMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"corsheaders.middleware.CorsMiddleware",
"funkwhale_api.common.middleware.SPAFallbackMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"funkwhale_api.users.middleware.RecordActivityMiddleware",
)
@ -398,6 +399,8 @@ ASGI_APPLICATION = "config.routing.application"
# This ensures that Django will be able to detect a secure connection
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
# AUTHENTICATION CONFIGURATION
# ------------------------------------------------------------------------------

View File

@ -0,0 +1 @@
Hardened security thanks to CSP and additional HTTP headers (#880)

View File

@ -43,3 +43,58 @@ Then, edit your ``/etc/systemd/system/funkwhale-server.service`` and replace the
``ExecStart=/srv/funkwhale/virtualenv/bin/gunicorn config.asgi:application -w ${FUNKWHALE_WEB_WORKERS} -k uvicorn.workers.UvicornWorker -b ${FUNKWHALE_API_IP}:${FUNKWHALE_API_PORT}``
Then reload the configuration change with ``sudo systemctl daemon-reload`` and ``sudo systemctl restart funkwhale-server``.
Content-Security-Policy and additional security headers [manual action suggested]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To improve the security and reduce the attack surface in case of a successfull exploit, we suggest
you add the following Content-Security-Policy to your nginx configuration.
**On non-docker setups**, in ``/etc/nginx/sites-available/funkwhale.conf``::
server {
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
add_header Referrer-Policy "strict-origin-when-cross-origin";
location /front/ {
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header X-Frame-Options "SAMEORIGIN";
# … existing content here
}
# Also create a new location for the embeds to ensure external iframes work
# Simply copy-paste the /front/ location, but replace the following lines:
location /front/embed.html {
add_header X-Frame-Options "ALLOW";
alias ${FUNKWHALE_FRONTEND_PATH}/embed.html;
}
}
Then reload nginx with ``systemctl reload nginx``.
**On docker setups**, in ``/srv/funkwhalenginx/funkwhale.template``::
server {
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
add_header Referrer-Policy "strict-origin-when-cross-origin";
location /front/ {
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header X-Frame-Options "SAMEORIGIN";
# … existing content here
}
# Also create a new location for the embeds to ensure external iframes work
# Simply copy-paste the /front/ location, but replace the following lines:
location /front/embed.html {
add_header X-Frame-Options "ALLOW";
alias /frontent/embed.html;
}
}
Then reload nginx with ``docker-compose restart nginx``.

View File

@ -23,6 +23,10 @@ server {
root /frontend;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
add_header Referrer-Policy "strict-origin-when-cross-origin";
location / {
include /etc/nginx/funkwhale_proxy.conf;
# this is needed if you have file import via upload enabled
@ -31,12 +35,27 @@ server {
}
location /front/ {
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header X-Frame-Options "ALLOW";
alias /frontend/;
expires 30d;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
location /front/embed.html {
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header X-Frame-Options "ALLOW";
alias /frontend/embed.html;
expires 30d;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
location /federation/ {
include /etc/nginx/funkwhale_proxy.conf;
proxy_pass http://funkwhale-api/federation/;

View File

@ -29,6 +29,9 @@ server {
# HSTS
add_header Strict-Transport-Security "max-age=31536000";
# Security related headers
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
# compression settings
gzip on;
gzip_comp_level 5;

View File

@ -41,6 +41,9 @@ server {
# HSTS
add_header Strict-Transport-Security "max-age=31536000";
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
add_header Referrer-Policy "strict-origin-when-cross-origin";
root ${FUNKWHALE_FRONTEND_PATH};
# compression settings
@ -78,11 +81,25 @@ server {
}
location /front/ {
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header X-Frame-Options "SAMEORIGIN";
alias ${FUNKWHALE_FRONTEND_PATH}/;
expires 30d;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
location /front/embed.html {
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header X-Frame-Options "ALLOW";
alias ${FUNKWHALE_FRONTEND_PATH}/embed.html;
expires 30d;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
location /federation/ {
include /etc/nginx/funkwhale_proxy.conf;
@ -111,7 +128,7 @@ server {
internal;
alias ${MEDIA_ROOT};
}
# Comment the previous location and uncomment this one if you're storing
# media files in a S3 bucket
# location ~ /_protected/media/(.+) {

View File

@ -49,7 +49,7 @@ services:
args:
install_dev_deps: 1
entrypoint: compose/django/dev-entrypoint.sh
command: python /app/manage.py runserver 0.0.0.0:${FUNKWHALE_API_PORT-5000}
command: uvicorn --reload config.asgi:application --host 0.0.0.0 --port 5000 --reload-dir config/ --reload-dir=funkwhale_api/
volumes:
- ./api:/app
- "${MUSIC_DIRECTORY_SERVE_PATH-./data/music}:/music:ro"
@ -119,6 +119,7 @@ services:
- "${MUSIC_DIRECTORY_SERVE_PATH-./data/music}:/music:ro"
- ./deploy/funkwhale_proxy.conf:/etc/nginx/funkwhale_proxy.conf:ro
- "${MEDIA_ROOT-./api/funkwhale_api/media}:/protected/media:ro"
- "./front:/frontend:ro"
networks:
- federation
- internal

View File

@ -69,9 +69,24 @@ http {
text/x-component
text/x-cross-domain-policy;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
add_header Referrer-Policy "strict-origin-when-cross-origin";
location /front/ {
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header X-Frame-Options "SAMEORIGIN";
# uncomment the following line and comment the proxy-pass one
# to use the frontend build with "yarn build"
#alias /frontend/dist/;
proxy_pass http://funkwhale-front/front/;
}
location /front/embed.html {
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'none'; media-src 'self' data:";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header X-Frame-Options "ALLOW";
proxy_pass http://funkwhale-front/front/embed.html;
}
location /front-server/ {
proxy_pass http://funkwhale-front/;
}

View File

@ -10,6 +10,8 @@ Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
template: '<EmbedFrame/>',
render (h) {
return h('EmbedFrame')
},
components: { EmbedFrame }
})

View File

@ -122,7 +122,9 @@ store.dispatch('instance/fetchFrontSettings').finally(() => {
el: '#app',
router,
store,
template: '<App/>',
render (h) {
return h('App')
},
components: { App }
})

View File

@ -11,6 +11,7 @@ if (process.env.BUNDLE_ANALYZE === '1') {
}
module.exports = {
baseUrl: process.env.BASE_URL || '/front/',
productionSourceMap: false,
pages: {
embed: {
entry: 'src/embed.js',
@ -30,11 +31,7 @@ module.exports = {
},
configureWebpack: {
plugins: plugins,
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
devtool: false
},
devServer: {
disableHostCheck: true,