• Administrator
  •  
    Welcome to the new PunBB.biz design forum.

    We decide to switch from Forumotion due to technical limitations.

    Information: Choosing social login option will register your account automatically without need for email confirmation.
     

[JavaScript] Protect your forum against XSS attacks in chatbox and messages

A place for codes and tutorials which will improve the functionality of your board.
Post Reply
User avatar
Shadow
Administrator
Posts: 19
Joined: Sat Jan 06, 2018 4:56 pm

Sun Jan 07, 2018 5:03 pm

Description:
This script will provide extra layer of security when someone is trying to inject xss scripting to the messages.

Version:
All forums (Forumotion)

Preview:
Image

Installation steps:
Create a new javascript.
Placement: In all pages
Name: xss_protect_js

Code: Select all

(function($) {
  'use strict';
  
  /**
    * Configuration
    */
  var config = {
      /**
      * Attributes to keep
      */
      attributes: [
        'style',
        'class',
      ],
      
      /**
      * Styles to reset
      */
      style: [
        'position',
        'margin',
        'transform',
        'top',
        'right',
        'bottom',
        'left',
      ],
  };
  
  /**
    * Elements queries by forum version
    */
  var query = {
      phpbb2: {
        postbody: '.postbody > div',
      },
      
      phpbb3: {
        postbody: '.content > div',
      },
      
      punbb: {
        postbody: '.entry-content > div > div',
      },
      
      invision: {
        postbody: '.post-entry > div',
      },
      
      modernbb: {
        postbody: '.content > div',
      },
      
      mobile: {
        postbody: '.content > div',
      },
      
      mobile_modern: {
        postbody: '.post-content',
      },
  };
  
  /**
    * Hide posts to avoid pre-render XSS
    */
  var hide = [];
  
  $.each(query, function(version, data) {
      hide.push(data.postbody);
  });
  
  hide = $.grep(hide, function(item, pos) {
      return $.inArray(item, hide) === pos;
  });
  
  var $hide = $('<style>', { html: hide.join(',') + ' { display: none; }' })
      .appendTo('head')
  ;
      
  /**
    * Clear function
    */
  var clear = function(elem) {
      var $this = $(elem);
      
      var attributes = $.map(elem.attributes, function(item) {
        return item.name;
      });
  
      $.each(attributes, function() {
        if (config.attributes.indexOf(this) === -1) {
            elem.removeAttribute(this);
        }
      });
      
      $.each(config.style, function() {
        $this.css(this, '');
      });
  };
  
  /**
    * Clear posts
    */
  $(function() {
      /**
      * Forum version detection
      */
      var version;
      
      $.each({
        phpbb2: '.bodylinewidth',
        phpbb3: '#phpbb',
        punbb: '.pun',
        invision: '#ipbwrapper',
        modernbb: '#modernbb',
        mobile: '#mpage-body',
        mobile_modern: '#mpage-body-modern',
      }, function(name, selector) {
        if ($(selector).length) {
            version = name;
            return false;
        }
      });
      
      if (!version) {
        return $hide.remove();
      }
      
      $(query[version].postbody).find('table, tr, td').each(function() {
        clear(this);
      });
      
      $hide.remove();
  });
  
  /**
    * Chatbox override
    */
  var insertChatBoxNew = window.insertChatBoxNew;
  
  window.insertChatBox = window.insertChatBoxNew = function() {
      insertChatBoxNew.apply(this, arguments);
      
      var chatbox = $('#frame_chatbox').get(0);
      
      if (chatbox.readyState === 'complete') {
        return run(event.target.contentWindow);
      }
      
      var onload = chatbox.onload;
      
      chatbox.onload = function(event) {        
        if (onload) {
            onload.apply(this, arguments);
        }
        
        run(event.target.contentWindow);
      };
  };
  
  var run = function(context) {
      /**
      * Clear chatbox
      */
      var refresh = context.Chatbox.prototype.refresh;
      
      context.Chatbox.prototype.refresh = function(data) {
        if (!data.messages || !data.messages.length) {
            return refresh.call(this, data);
        }
        
        $.each(data.messages, function() {
            this.msg = $('<div>', { html: this.msg })
              .find('table, tr, td')
                  .each(function() {
                    clear(this);
                  })
              .end()
              .html()
            ;
        });
        
        refresh.call(this, data);
      };  
      
      
      /**
      * Chatbox initial refresh
      */
      context.chatbox.refresh(context.chatbox);
  };
}(jQuery));
Closing Notes:

Post Reply
  • Information
  • Who is online

    Users browsing this forum: No registered users and 1 guest