Browse Source

fix: Open Redirect Vulnerability Mitigation - CWE 601 (#1963)

* Open redirect vulnerabilty mitigation

* Refacted Open Redirect to user configurable and corrected incorrect security variable names.

Co-authored-by: danallendds <daniel.allen@friends.dds.mil>
daneallen 5 years ago
parent
commit
20e6bc1a70

+ 14 - 0
client/components/admin/admin-security.vue

@@ -20,6 +20,15 @@
                 v-card-info(color='red')
                   span Make sure to understand the implications before turning on / off a security feature.
                 v-card-text
+                  v-switch.mt-3(
+                    inset
+                    label='Block Open Redirect'
+                    color='red darken-2'
+                    v-model='config.securityOpenRedirect'
+                    persistent-hint
+                    hint='Prevents user controlled URLs from directing to websites outside of your wiki. This provides Open Redirect protection.'
+                    )
+
                   v-switch.mt-3(
                     inset
                     label='Block IFrame Embedding'
@@ -145,6 +154,7 @@ export default {
       config: {
         uploadMaxFileSize: 0,
         uploadMaxFiles: 0,
+        securityOpenRedirect: true,
         securityIframe: true,
         securityReferrerPolicy: true,
         securityTrustProxy: true,
@@ -175,6 +185,7 @@ export default {
             mutation (
               $uploadMaxFileSize: Int
               $uploadMaxFiles: Int
+              $securityOpenRedirect: Boolean
               $securityIframe: Boolean
               $securityReferrerPolicy: Boolean
               $securityTrustProxy: Boolean
@@ -188,6 +199,7 @@ export default {
                 updateConfig(
                   uploadMaxFileSize: $uploadMaxFileSize,
                   uploadMaxFiles: $uploadMaxFiles,
+                  securityOpenRedirect: $securityOpenRedirect,
                   securityIframe: $securityIframe,
                   securityReferrerPolicy: $securityReferrerPolicy,
                   securityTrustProxy: $securityTrustProxy,
@@ -210,6 +222,7 @@ export default {
           variables: {
             uploadMaxFileSize: _.toSafeInteger(_.get(this.config, 'uploadMaxFileSize', 0)),
             uploadMaxFiles: _.toSafeInteger(_.get(this.config, 'uploadMaxFiles', 0)),
+            securityOpenRedirect: _.get(this.config, 'securityOpenRedirect', false),
             securityIframe: _.get(this.config, 'securityIframe', false),
             securityReferrerPolicy: _.get(this.config, 'securityReferrerPolicy', false),
             securityTrustProxy: _.get(this.config, 'securityTrustProxy', false),
@@ -241,6 +254,7 @@ export default {
             config {
               uploadMaxFileSize
               uploadMaxFiles
+              securityOpenRedirect
               securityIframe
               securityReferrerPolicy
               securityTrustProxy

+ 1 - 0
server/app/data.yml

@@ -54,6 +54,7 @@ defaults:
       iconset: 'md'
       darkMode: false
     security:
+      securityOpenRedirect: true
       securityIframe: true
       securityReferrerPolicy: true
       securityTrustProxy: true

+ 1 - 0
server/graph/resolvers/site.js

@@ -67,6 +67,7 @@ module.exports = {
         }
 
         WIKI.config.security = {
+          securityOpenRedirect: _.get(args, 'securityOpenRedirect', WIKI.config.security.securityOpenRedirect),
           securityIframe: _.get(args, 'securityIframe', WIKI.config.security.securityIframe),
           securityReferrerPolicy: _.get(args, 'securityReferrerPolicy', WIKI.config.security.securityReferrerPolicy),
           securityTrustProxy: _.get(args, 'securityTrustProxy', WIKI.config.security.securityTrustProxy),

+ 2 - 0
server/graph/schemas/site.graphql

@@ -36,6 +36,7 @@ type SiteMutation {
     featurePageRatings: Boolean
     featurePageComments: Boolean
     featurePersonalWikis: Boolean
+    securityOpenRedirect: Boolean
     securityIframe: Boolean
     securityReferrerPolicy: Boolean
     securityTrustProxy: Boolean
@@ -67,6 +68,7 @@ type SiteConfig {
   featurePageRatings: Boolean!
   featurePageComments: Boolean!
   featurePersonalWikis: Boolean!
+  securityOpenRedirect: Boolean!
   securityIframe: Boolean!
   securityReferrerPolicy: Boolean!
   securityTrustProxy: Boolean!

+ 9 - 3
server/middlewares/security.js

@@ -13,7 +13,7 @@ module.exports = function (req, res, next) {
   req.app.disable('x-powered-by')
 
   // -> Disable Frame Embedding
-  if (WIKI.config.securityIframe) {
+  if (WIKI.config.security.securityIframe) {
     res.set('X-Frame-Options', 'deny')
   }
 
@@ -27,14 +27,20 @@ module.exports = function (req, res, next) {
   res.set('X-UA-Compatible', 'IE=edge')
 
   // -> Disables referrer header when navigating to a different origin
-  if (WIKI.config.securityReferrerPolicy) {
+  if (WIKI.config.security.securityReferrerPolicy) {
     res.set('Referrer-Policy', 'same-origin')
   }
 
   // -> Enforce HSTS
-  if (WIKI.config.securityHSTS) {
+  if (WIKI.config.security.securityHSTS) {
     res.set('Strict-Transport-Security', `max-age=${WIKI.config.securityHSTSDuration}; includeSubDomains`)
   }
 
+  // -> Prevent Open Redirect from user provided URL
+  if (WIKI.config.security.securityOpenRedirect) {
+    // Strips out all repeating / character in the provided URL
+    req.url = req.url.replace(/(\/)(?=\/*\1)/g, "")
+  }
+
   return next()
 }