From addb666a235872cf11ebe0ade20d5dd48c6d5ec6 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Tue, 9 Aug 2016 14:46:32 +0200 Subject: [PATCH] introducing CSP header to mitigate XSS attacks, closes #10 --- CHANGELOG.md | 3 ++- cfg/conf.ini.sample | 7 ++++++ js/privatebin.js | 49 ++++++++++++++++++++++++++++++++++++- lib/Configuration.php | 1 + lib/PrivateBin.php | 1 + tpl/bootstrap-compact.php | 6 ++--- tpl/bootstrap-dark-page.php | 6 ++--- tpl/bootstrap-dark.php | 6 ++--- tpl/bootstrap-page.php | 6 ++--- tpl/bootstrap.php | 6 ++--- tpl/page.php | 2 +- 11 files changed, 75 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1fe6fbc..8b2c0bdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,12 @@ * ADDED: Option to disable vizhashs in discussions (will only affect newly created pastes) * ADDED: Composer support * CHANGED: Renamed the ZeroBin fork to PrivateBin - * CHANGED: Removed unmaintained RainTPL template engine, replacing the templates with straight forward PHP file + * CHANGED: Removed unmaintained RainTPL template engine, replacing the templates with straight forward PHP files * CHANGED: New favicon * CHANGED: Upgrading SJCL library to 1.0.4 * CHANGED: Switched to GCM instead CCM mode for AES encryption for newly created pastes * CHANGED: Switched to a SHA256 HMAC of the IP in traffic limiter instead of storing it in plain text on the server + * CHANGED: Introduced content security policy header to reduce cross site scripting (XSS) risks * CHANGED: Refactored PHP code to conform to PSR-4 and PSR-2 standards. * FIXED: Content-type negociation for HTML in certain uncommon browser configurations * FIXED: JavaScript error displayed before page is loaded or during attachment load diff --git a/cfg/conf.ini.sample b/cfg/conf.ini.sample index 10fd56d2..96062647 100644 --- a/cfg/conf.ini.sample +++ b/cfg/conf.ini.sample @@ -59,6 +59,13 @@ languageselection = false ; and a rainbow table is generated for all IPs. Enabled by default. ; vizhash = false +; Content Security Policy headers allow a website to restrict what sources are +; allowed to be accessed in its context. You need to change this if you added +; custom scripts from third-party domains to your templates, e.g. tracking +; scripts or run your site behind certain DDoS-protection services. +; Check the documentation at https://content-security-policy.com/ +cspheader = "default-src 'none'; connect-src *; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self';" + ; stay compatible with PrivateBin Alpha 0.19, less secure ; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of ; sha256 in HMAC for the deletion token diff --git a/js/privatebin.js b/js/privatebin.js index 5b851389..8244c138 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -281,7 +281,7 @@ $(function() { getCookie: function(cname) { var name = cname + '='; var ca = document.cookie.split(';'); - for(var i = 0; i < ca.length; ++i) { + for (var i = 0; i < ca.length; ++i) { var c = ca[i]; while (c.charAt(0) === ' ') c = c.substring(1); if (c.indexOf(name) === 0) @@ -1249,6 +1249,45 @@ $(function() { $('.navbar-toggle').click(); }, + /** + * Set the expiration on bootstrap templates. + * + * @param Event event + */ + setExpiration: function(event) + { + event.preventDefault(); + var target = $(event.target); + $('#pasteExpiration').val(target.data('expiration')); + $('#pasteExpirationDisplay').text(target.text()); + }, + + /** + * Set the format on bootstrap templates. + * + * @param Event event + */ + setFormat: function(event) + { + event.preventDefault(); + var target = $(event.target); + $('#pasteFormatter').val(target.data('format')); + $('#pasteFormatterDisplay').text(target.text()); + }, + + /** + * Set the language on bootstrap templates. + * + * Sets the language cookie and reloads the page. + * + * @param Event event + */ + setLanguage: function(event) + { + document.cookie = 'lang=' + $(event.target).data('lang'); + this.reloadPage(event); + }, + /** * Support input of tab character. * @@ -1388,6 +1427,14 @@ $(function() { this.message.keydown(this.supportTabs); this.messageEdit.click($.proxy(this.viewEditor, this)); this.messagePreview.click($.proxy(this.viewPreview, this)); + + // bootstrap template drop downs + $('ul.dropdown-menu li a', $('#expiration').parent()).click($.proxy(this.setExpiration, this)); + $('ul.dropdown-menu li a', $('#formatter').parent()).click($.proxy(this.setFormat, this)); + $('#language ul.dropdown-menu li a').click($.proxy(this.setLanguage, this)); + + // page template drop down + $('#language select option').click($.proxy(this.setLanguage, this)); }, /** diff --git a/lib/Configuration.php b/lib/Configuration.php index 15c35a15..44a35d63 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -51,6 +51,7 @@ class Configuration 'languagedefault' => '', 'urlshortener' => '', 'vizhash' => true, + 'cspheader' => 'default-src \'none\'; connect-src *; script-src \'self\'; style-src \'self\'; font-src \'self\'; img-src \'self\';', 'zerobincompatibility' => false, ), 'expire' => array( diff --git a/lib/PrivateBin.php b/lib/PrivateBin.php index e4d91e87..5985bba7 100644 --- a/lib/PrivateBin.php +++ b/lib/PrivateBin.php @@ -402,6 +402,7 @@ class PrivateBin header('Expires: ' . $time); header('Last-Modified: ' . $time); header('Vary: Accept'); + header('Content-Security-Policy: ' . $this->_conf->getKey('cspheader')); // label all the expiration options $expire = array(); diff --git a/tpl/bootstrap-compact.php b/tpl/bootstrap-compact.php index 9c895bc9..95e0e864 100644 --- a/tpl/bootstrap-compact.php +++ b/tpl/bootstrap-compact.php @@ -107,7 +107,7 @@ endforeach; foreach ($EXPIRE as $key => $value): ?>
  • - +
  • @@ -155,7 +155,7 @@ endif; foreach ($FORMATTER as $key => $value): ?>
  • - +
  • @@ -219,7 +219,7 @@ if (strlen($LANGUAGESELECTION)): foreach ($LANGUAGES as $key => $value): ?>
  • - + ()
  • diff --git a/tpl/bootstrap-dark-page.php b/tpl/bootstrap-dark-page.php index f567321f..86f2d05b 100644 --- a/tpl/bootstrap-dark-page.php +++ b/tpl/bootstrap-dark-page.php @@ -106,7 +106,7 @@ endforeach; foreach ($EXPIRE as $key => $value): ?>
  • - +
  • @@ -193,7 +193,7 @@ endforeach; foreach ($FORMATTER as $key => $value): ?>
  • - +
  • @@ -214,7 +214,7 @@ if (strlen($LANGUAGESELECTION)): foreach ($LANGUAGES as $key => $value): ?>
  • - + ()
  • diff --git a/tpl/bootstrap-dark.php b/tpl/bootstrap-dark.php index 94bfd921..3f71b405 100644 --- a/tpl/bootstrap-dark.php +++ b/tpl/bootstrap-dark.php @@ -106,7 +106,7 @@ endforeach; foreach ($EXPIRE as $key => $value): ?>
  • - +
  • @@ -193,7 +193,7 @@ endforeach; foreach ($FORMATTER as $key => $value): ?>
  • - +
  • @@ -214,7 +214,7 @@ if (strlen($LANGUAGESELECTION)): foreach ($LANGUAGES as $key => $value): ?>
  • - + ()
  • diff --git a/tpl/bootstrap-page.php b/tpl/bootstrap-page.php index 15ad551f..c97a61da 100644 --- a/tpl/bootstrap-page.php +++ b/tpl/bootstrap-page.php @@ -106,7 +106,7 @@ endforeach; foreach ($EXPIRE as $key => $value): ?>
  • - +
  • @@ -193,7 +193,7 @@ endforeach; foreach ($FORMATTER as $key => $value): ?>
  • - +
  • @@ -214,7 +214,7 @@ if (strlen($LANGUAGESELECTION)): foreach ($LANGUAGES as $key => $value): ?>
  • - + ()
  • diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 38faf431..20f60a75 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -106,7 +106,7 @@ endforeach; foreach ($EXPIRE as $key => $value): ?>
  • - +
  • @@ -193,7 +193,7 @@ endforeach; foreach ($FORMATTER as $key => $value): ?>
  • - +
  • @@ -214,7 +214,7 @@ if (strlen($LANGUAGESELECTION)): foreach ($LANGUAGES as $key => $value): ?>
  • - + ()
  • diff --git a/tpl/page.php b/tpl/page.php index d94b1b7b..b62b0e1c 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -159,7 +159,7 @@ if (strlen($LANGUAGESELECTION)): $value): ?> -