JavaScript anti HTTP hijacking and XSS for front end security

Time:2021-7-3
catalogue
  • HTTP hijacking, DNS hijacking and XSS
    • HTTP hijacking
    • DNS hijacking
    • XSS cross site scripting
  • The page is embedded in the iframe and the iframe is redirected
    • Use white list to release normal iframe nesting
    • Change URL parameters to bypass operator logo
  • Inline event and inline script interception
    • Browser event model
  • Static script interception
    • Using white list to match and filter SRC
  • Dynamic script interception
    • Mutation events and domnodeinserted
  • Rewrite setAttribute and document. Write
    • Override the native element. Prototype. SetAttribute method
    • Override element.prototype.setattribute in nested iframes
    • Rewrite document.write
  • Lock up apply and call
    • Establish interception Report
      • HTTPS and CSP
        • CSP
        • HTTPS

      HTTP hijacking, DNS hijacking and XSS

      Let’s talk about HTTP hijacking and DNS hijacking.

      HTTP hijacking

      What is HTTP hijacking? In most cases, it is operator’s HTTP hijacking. When we use HTTP request to request a website page, the network operator will insert a well-designed network data packet into the normal data stream to let the client (usually the browser) display “wrong” data, usually some pop-up windows, Publicity ads or direct display of the content of a website, we should have encountered.

      DNS hijacking

      DNS hijacking is to hijack the DNS server, obtain the control of the resolution record of a domain name by some means, and then modify the resolution result of the domain name, resulting in the access to the domain name from the original IP address to the modified designated IP address, and the result is that the specific web address cannot be accessed or the access is a fake Web address, So as to achieve the purpose of stealing information or destroying the original normal service.

      DNS hijacking is more excessive than HTTP hijacking. In short, what we requested is http://www.a.com/index.html , directly redirected http://www.b.com/index.html This article will not discuss this situation too much.

      XSS cross site scripting

      XSS means that an attacker uses a vulnerability to inject malicious code into a web page. When a user browses the page, the injected code will be executed to achieve the special purpose of the attack.

      How to generate these attacks and how attackers inject malicious code into the page are not discussed in this paper. As long as we know that malicious code such as HTTP hijacking and XSS is ultimately executed on the client side, usually the user’s browser side, this paper will discuss how to make effective front-end protection by using JavaScript assuming that the injection already exists.

      The page is embedded in the iframe and the iframe is redirected

      Let’s talk about our page is embedded with iframe. In other words, in order to reduce the impact of implanted ads on the original website page as much as possible, network operators usually put the original website page into an iframe with the same size as the original page, so they can isolate the impact of advertising code on the original page through this iframe.

      This situation is easy to handle. We only need to know whether our page is nested in the iframe. If so, we can redirect the outer page to our normal page.

      So is there any way to know that our page currently exists in the iframe? Yes, they are window.self and window.top.

      window.self

      Returns a reference to the current window object.

      window.top

      Returns the reference of the topmost window in the window system.

      For non homologous domain names, the iframe child page cannot get the specific page address through parent.location or top.location, but it can write to top.location, that is, it can control the jump of the parent page.

      The two attributes can be abbreviated as self and top respectively, so when we find that our page is nested in iframe, we can redirect the parent page:

      if (self != top) {
        //Our normal page
        var url = location.href;
        //Parent page redirection
        top.location = url;
      }

      Use white list to release normal iframe nesting

      Of course, many times, maybe our pages will be promoted in various ways, or normal business needs to be nested in the iframe. At this time, we need a white list or blacklist. When our pages are nested in the iframe and the parent page domain name exists in the white list, we will not do the redirection operation.

      As mentioned above, you can’t get the URL of the parent page by using top.location.html. In this case, you need to use document.referrer.

      You can get the URL of the cross domain iframe parent page through document. Referrer.

      //Create a white list
      var whiteList = [
        'www.aaa.com',
        'res.bbb.com'
      ];
       
      if (self != top) {
        var
          //Use document. Referrer to get the URL of the parent page of the cross domain iframe
          parentUrl = document.referrer,
          length = whiteList.length,
          i = 0;
       
        for(; i<length; i++){
          //Create a white list正则
          var reg = new RegExp(whiteList[i],'i');
       
          //In the white list, release
          if(reg.test(parentUrl)){
            return;
          }
        }
       
        //Our normal page
        var url = location.href;
        //Parent page redirection
        top.location = url;
      }

      Change URL parameters to bypass operator logo

      Is that the end? No, although we have redirected the parent page, since it can be nested for the first time in the process of redirection, the page may be nested by iframe again in the process of this redirection, which is really painful.

      Of course, the hijacking of operators is usually traceable. The most common method is to set a parameter in the page URL, such as http://www.example.com/index.html?iframe_ hijack_ Redirected = 1, where iframe_ hijack_ Redirected = 1 indicates that the page has been hijacked, so the iframe is no longer nested. So according to this feature, we can rewrite our URL to make it look hijacked:

      var flag = 'iframe_hijack_redirected';
      //The current page exists in an iframe
      //A white list matching rule needs to be established here, and the white list is released by default
      if (self != top) {
        var
          //Use document. Referrer to get the URL of the parent page of the cross domain iframe
          parentUrl = document.referrer,
          length = whiteList.length,
          i = 0;
       
        for(; i<length; i++){
          //Establish a white list
          var reg = new RegExp(whiteList[i],'i');
       
          //In the white list, release
          if(reg.test(parentUrl)){
            return;
          }
        }
       
        var url = location.href;
        var parts = url.split('#');
        if (location.search) {
          parts[0] += '&' + flag + '=1';
        } else {
          parts[0] += '?' + flag + '=1';
        }
        try {
          Console.log ('page is embedded in iframe: ', URL');
          top.location.href = parts.join('#');
        } catch (e) {}
      }

      Of course, if this parameter is changed, the anti nesting code will be invalid. Therefore, we also need to establish a reporting system. When we find that a page is nested, we will send an interception report. Even if the redirection fails, we can also know the URL embedded in the iframe. According to the analysis of these URLs, we will continue to strengthen our protection measures, which will be mentioned later.

      Inline event and inline script interception

      In XSS, there are many ways to inject scripts. Especially after HTML5 comes out, many new tags can be used to inject executable scripts.

      List some common injection methods:

      1.<a href=”javascript:alert(1)” rel=”external nofollow” _fcksavedurl=”javascript:alert(1)” ></a>

      2.<iframe src=”javascript:alert(1)” />

      3.<img src=’x’ onerror=”alert(1)” />

      4.<video src=’x’ onerror=”alert(1)” ></video>

      5.<div onmouseover=”alert(2)” ><div>

      Except for some rare injection methods not listed, most of them are J avascript:… And inline events on *.

      Assuming that injection has occurred, is there any way to intercept these inline events and the execution of inline scripts?

      For (1) (5) listed above, we have a way to defend scripts that require users to click or execute certain events.

      Browser event model

      To be able to intercept is related to the principle of event model.

      As we all know, the standard browser event model has three stages

      • Capture phase
      • Target phase
      • bubbling phase

      For a avascript:alert (222)” rel=”external nofollow” rel=”external nofollow” _ fcksavedurl=”j avascript:alert (222) “> < / a >, the real trigger element alert (222) is in the target stage of click event.

      
      <a href="javascript:alert(222)" rel="external nofollow"  rel="external nofollow" >Click Me</a>
      
      <script>
        document.addEventListener('click', function(e) {
          alert(111);
        }, true);
      </script>

      Click me above to pop up 111 first and then 222.

      Then, we only need to update the tag in the capture phase of the click event model avascript:… The content of the establishment of keyword blacklist, filter review, we can do what we want to intercept the effect.

      The same is true for on * type inline events, but for too many such events, we can’t enumerate them manually. We can use code automatic enumeration to intercept inline events and inline scripts.

      To intercept the avascript:… For example, we can write as follows:

      //Establish keyword blacklist
      var keywordBlackList = [
        'xss',
        'BAIDU_SSP__wrapper',
        'BAIDU_DSPUI_FLOWBAR'
      ];
         
      document.addEventListener('click', function(e) {
        var code = "";
       
        //Scan the scripts of < a = "javascript:" rel = "external nofollow" >
        if (elem.tagName == 'A' && elem.protocol == 'javascript:') {
          var code = elem.href.substr(11);
       
          if (blackListMatch(keywordBlackList, code)) {
            //Logout code
            elem.href = 'javascript:void(0)';
            Console.log ('intercept suspicious events: '+ code');
          }
        }
      }, true);
       
      /**
       *[blacklist matching]
       *@ param {[array]} blacklist
       *@ param {[string]} value [string to verify]
       *@ return {[Boolean]} [false -- failed verification, true -- passed verification]
       */
      function blackListMatch(blackList, value) {
        var length = blackList.length,
          i = 0;
       
        for (; i < length; i++) {
          //Establish a blacklist
          var reg = new RegExp(whiteList[i], 'i');
       
          //In the blacklist, intercept
          if (reg.test(value)) {
            return true;
          }
        }
        return false;
      }

      Click these buttons in the figure to see the following:

      Here we use the blacklist matching, which will be described in detail below.

      Static script interception

      The essence of XSS cross site script is not “cross site”, but “script”.

      Generally speaking, the attacker or operator will inject a < script > script into the page, and the specific operation is implemented in the script. This hijacking method only needs to be injected once, and it does not need to be reinjected every time if there are changes.

      Let’s assume that a < script SRC is now injected into the page=“ http://attack.com/xss.js “> script, our goal is to intercept the execution of this script.

      It sounds very difficult. What do you mean. It is to find the suspicious script before the script is executed, and destroy it to make it unable to execute the internal code.

      Therefore, we need to use some advanced APIs to detect the generated nodes when the page is loaded.

      MutationObserver

      Mutationobserver is a new API of HTML5, which is very powerful. It provides developers with the ability to react appropriately when the DOM tree in a certain range changes.

      It’s very mysterious, which means that it can monitor the transformation of DOM tree on the page and react.

      Mutationobserver() this constructor is used to instantiate a new mutationobserver object.

      
      MutationObserver(
        function callback
      );

      What’s the big part? This means that the mutationobserver does not call back immediately when it finds a new element, but transfers all the elements in a time segment together. So we need batch processing in callback. What’s more, some of themcallbackIs called when the specified DOM node (target node) changes. When called, the observer object will pass two parameters to the function. The first parameter is an array containing several mutationrecord objects, and the second parameter is the observer object itself.

      Therefore, using mutationobserver, we can monitor each static script file loaded on the page

      //Different compatible writing methods of mutationobserver
      var MutationObserver = window.MutationObserver || window.WebKitMutationObserver ||
      window.MozMutationObserver;
      //This constructor is used to instantiate a new mutation observer object
      //The observer object can monitor the DOM tree changes within a certain range
      var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
          //Return the added node, or null
          var nodes = mutation.addedNodes;
       
          for (var i = 0; i < nodes.length; i++) {
            var node = nodes[i];
            if (/xss/i.test(node.src))) {
              try {
                node.parentNode.removeChild(node);
                Console.log ('intercept suspicious static script: ', node. SRC');
              } catch (e) {}
            }
          }
        });
      });
       
      //Incoming destination node and observation options
      //If the target is document or document.documentelement
      //Then all the node addition and deletion operations in the current document will be observed
      observer.observe(document, {
        subtree: true,
        childList: true
      });

      < script type = “text / JavaScript” SRC =. / XSS / A.js “> < / script > is a static script that exists at the beginning of page loading (view page structure). We can use mutationobserver to regularly match the content of the script after loading and before execution. If malicious code is found, removechild () will be dropped, making it impossible to execute.

      Using white list to match and filter SRC

      In the above code, we use this sentence to judge whether a JS script is malicious

      
      if (/xss/i.test(node.src)) {}

      Of course, in practice, people who inject malicious code will not be so stupid and change their name to XSS. Therefore, it is necessary for us to use the white list for filtering and establish an interception and reporting system.

      //Create a white list
      var whiteList = [
        'www.aaa.com',
        'res.bbb.com'
      ];
       
      /**
       *[white list matching]
       *@ param {[array]} whitelist
       *@ param {[string]} value [string to verify]
       *@ return {[Boolean]} [false -- failed verification, true -- passed verification]
       */
      function whileListMatch(whileList, value) {
        var length = whileList.length,
          i = 0;
       
        for (; i < length; i++) {
          //Create a white list正则
          var reg = new RegExp(whiteList[i], 'i');
       
          //In the white list, release
          if (reg.test(value)) {
            return true;
          }
        }
        return false;
      }
       
      //White list only
      if (!whileListMatch(blackList, node.src)) {
        node.parentNode.removeChild(node);
      }

      We have mentioned whitelist matching many times, and we will use it later, so we can simply encapsulate it as a method call here.

      Dynamic script interception

      Above, mutationobserver is used to intercept static scripts. In addition to static scripts, the corresponding scripts are dynamically generated.

      
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.src = 'http://www.example.com/xss/b.js';
       
      document.getElementsByTagName('body')[0].appendChild(script); 

      To intercept this kind of dynamically generated script, and the interception time should be when it is inserted into the DOM tree. Before execution, you can listen to the domnodeinserted event in the mutation events.

      Mutation events and domnodeinserted

      Open MDN, the first sentence is:

      This feature has been removed from the web standard. Although it is still supported by some browsers, it may stop supporting at some time in the future. Please try not to use this feature.

      Although it can’t be used, you can also understand:

      document.addEventListener('DOMNodeInserted', function(e) {
        var node = e.target;
        if (/xss/i.test(node.src) || /xss/i.test(node.innerHTML)) {
          node.parentNode.removeChild(node);
          Console.log ('intercept suspicious dynamic scripts: ', node');
        }
      }, true);

      Unfortunately, using the above code to intercept dynamically generated scripts, you can intercept them, but the code is also executed: domnodeinserted, as the name suggests, can monitor structural changes within a certain DOM range, and its execution time is earlier than that of mutationobserver.

      However, domnodeinserted is no longer recommended, so the task of listening to dynamic scripts should also be left to the mutationobserver.

      Unfortunately, in practice, the result of using mutationobserver is the same as domnodeinserted. You can listen and intercept the generation of dynamic scripts, but you can’t use removechild to remove the scripts before they are executed. So we need to think of other ways.

      Rewrite setAttribute and document. Write

      Override the native element. Prototype. SetAttribute method

      Before the dynamic script is inserted and executed, it is impossible to intercept the DOM tree by listening to its changes, and the script will still be executed.

      So we need to look up and capture the script before it is inserted into the DOM tree, which is the time to create the script.

      Suppose there is a dynamic script created like this:

      
      var script = document.createElement('script');
      script.setAttribute('type', 'text/javascript');
      script.setAttribute('src', 'http://www.example.com/xss/c.js');
       
      document.getElementsByTagName('body')[0].appendChild(script);

      It is also feasible to rewrite element.prototype.setattribute: we found that the setAttribute method is used here. If we can rewrite the native method, listen to the value when setting SRC attribute, and judge it by blacklist or whitelist, we can judge the legality of the tag.

      //Save the original interface
      var old_setAttribute = Element.prototype.setAttribute;
       
      //Override setAttribute interface
      Element.prototype.setAttribute = function(name, value) {
       
        //Match to < script SRC = xxx '> type
        if (this.tagName == 'SCRIPT' && /^src$/i.test(name)) {
          //White list matching
          if (!whileListMatch(whiteList, value)) {
            Console.log ('block suspicious module: ', value');
            return;
          }
        }
         
        //Calling the original interface
        old_setAttribute.apply(this, arguments);
      };
       
      //Create a white list
      var whiteList = [
      'www.yy.com',
      'res.cont.yy.com'
      ];
       
      /**
       *[white list matching]
       *@ param {[array]} whitelist
       *@ param {[string]} value [string to verify]
       *@ return {[Boolean]} [false -- failed verification, true -- passed verification]
       */
      function whileListMatch(whileList, value) {
        var length = whileList.length,
          i = 0;
       
        for (; i < length; i++) {
          //Create a white list正则
          var reg = new RegExp(whiteList[i], 'i');
       
          //In the white list, release
          if (reg.test(value)) {
            return true;
          }
        }
        return false;
      }

      To rewrite element.prototype.setattribute is to first save the original interface, and then when an element calls setAttribute, check whether the incoming SRC exists in the white list. If it exists, it will be released. If it does not exist, it will be regarded as a suspicious element, and it will be reported and not executed. Finally, execute the native setAttribute, or old, on the released element_ setAttribute.apply(this, arguments);。

      The above white list matching can also be replaced by black list matching.

      Override element.prototype.setattribute in nested iframes

      Of course, it’s written as old_ If setAttribute = element.prototype.setattribute is exposed to the attacker, use old directly_ SetAttribute can bypass our overriding method, so this code must be wrapped in a closure.

      Of course, this is not safe, although the element. Prototype. SetAttribute in the current window has been rewritten. But there is still a way to get the original element. Prototype. SetAttribute, just a new iframe.

      
      var newIframe = document.createElement('iframe');
      document.body.appendChild(newIframe);
       
      Element.prototype.setAttribute = newIframe.contentWindow.Element.prototype.setAttribute;

      Through this method, you can get the original element. Prototype. SetAttribute again, because the environment inside the iframe is completely isolated from the outer window. wtf?

      What should I do? We see that the creation of iframe uses the createElement, so can we rewrite the original createElement? But in addition to create element, there are also create element ns, and there may be iframe on the page, so it is not appropriate.

      When a new iframe is created, protect and rewrite setAttribute. Here, mutationobserver is used

      /**
       *Use mutationobserver to monitor the generated iframe page,
       *Prevent calling internal native setAttribute and document. Write
       * @return {[type]} [description]
       */
      function defenseIframe() {
        //Protect the current page first
        installHook(window);
      }
       
      /**
       *SetAttribute protection of single window
       *@ param {[BOM]} window [browser window object]
       * @return {[type]}       [description]
       */
      function installHook(window) {
        //Rewrite the setAttribute property of a single window
        resetSetAttribute(window);
       
        //Different compatible writing methods of mutationobserver
        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
       
        //This constructor is used to instantiate a new mutation observer object
        //The observer object can monitor the DOM tree changes within a certain range
        var observer = new MutationObserver(function(mutations) {
          mutations.forEach(function(mutation) {
            //Return the added node, or null
            var nodes = mutation.addedNodes;
       
            //Traverse one by one
            for (var i = 0; i < nodes.length; i++) {
              var node = nodes[i];
       
              //The environment in the generated iframe is also equipped with an override hook
              if (node.tagName == 'IFRAME') {
                installHook(node.contentWindow);
              }
            }
          });
        });
       
        observer.observe(document, {
          subtree: true,
          childList: true
        });
      }
       
      /**
       *Rewrite the setAttribute property of a single window
       *@ param {[BOM]} window [browser window object]
       * @return {[type]} [description]
       */
      function resetSetAttribute(window) {
        //Save the original interface
        var old_setAttribute = window.Element.prototype.setAttribute;
       
        //Override setAttribute interface
        window.Element.prototype.setAttribute = function(name, value) {
          ...
        };
      }

      We define an installhook method with the parameter of a window. In this method, we will rewrite the setAttribute under the incoming window, install a mutationobserver, and listen for iframes that may be created in the future under this window. If an iframe is created in the future under this window, we will also install the installhook method on the new iframe, In order to protect layer by layer.

      Rewrite document.write

      According to the above methods, we can continue to explore what methods can be rewritten to better protect the page.

      Document. Write is a good choice. Attackers usually use this method to inject pop-up ads into the page.

      We can rewrite document. Write and use keyword blacklist to match the content.

      What is more suitable for keywords when blacklist? We can look at some pages with lots of advertisements:

      Here, an iframe is embedded at the bottom of the page, which contains the advertising code. The ID name of the outermost layer here is id = Baidu_ SSP__ wrapper_ u2444091_ 0 “is very suitable for us to judge whether it is malicious code. Suppose we have collected a batch of blacklists according to the interception report:

      //Establish regular interception keywords
      var keywordBlackList = [
      'xss',
      'BAIDU_SSP__wrapper',
      'BAIDU_DSPUI_FLOWBAR'
      ];

      Next, we only need to use these keywords to make regular judgment on the incoming content of document. Write, and then we can determine whether to intercept the code of document. Write.

      //Establish keyword blacklist
      var keywordBlackList = [
        'xss',
        'BAIDU_SSP__wrapper',
        'BAIDU_DSPUI_FLOWBAR'
      ];
       
      /**
       *Rewrite the document. Write property of a single window
       *@ param {[BOM]} window [browser window object]
       * @return {[type]}       [description]
       */
      function resetDocumentWrite(window) {
        var old_write = window.document.write;
       
        window.document.write = function(string) {
          if (blackListMatch(keywordBlackList, string)) {
            Console.log ('block suspicious module: ', string');
            return;
          }
       
          //Calling the original interface
          old_write.apply(document, arguments);
        }
      }
       
      /**
       *[blacklist matching]
       *@ param {[array]} blacklist
       *@ param {[string]} value [string to verify]
       *@ return {[Boolean]} [false -- failed verification, true -- passed verification]
       */
      function blackListMatch(blackList, value) {
        var length = blackList.length,
          i = 0;
       
        for (; i < length; i++) {
          //Establish a blacklist
          var reg = new RegExp(whiteList[i], 'i');
       
          //In the blacklist, intercept
          if (reg.test(value)) {
            return true;
          }
        }
        return false;
      }

      We can put resetdocumentwrite into the above installhook method to rewrite the document. Write in the current window and all generated iframes.

      Lock up apply and call

      Next, we will introduce locking the native function. Prototype. Apply and function. Prototype. Call methods. Locking means that they cannot be rewritten.

      Object. Defineproperty is used to lock application and call.

      Object.defineProperty

      The object. Defineproperty () method directly defines a new property on an object, or modifies an existing property and returns the object.

      
      Object.defineProperty(obj, prop, descriptor)

      Among them:

      • Obj – the object whose attributes need to be defined
      • Prop – the name of the property to be defined or modified
      • Descriptor – the descriptor of the attribute to be defined or modified

      We can use the following code to prevent call and apply from being rewritten.

      //Lock call
      Object.defineProperty(Function.prototype, 'call', {
        value: Function.prototype.call,
        //If and only if the writable of the property is true, the property can be changed by the assignment operator
        writable: false,
        //If and only if the configurable value of the attribute is true, the attribute can be changed or deleted
        configurable: false,
        enumerable: true
      });
      //Lock apple
      Object.defineProperty(Function.prototype, 'apply', {
        value: Function.prototype.apply,
        writable: false,
        configurable: false,
        enumerable: true
      });

      Why write like this? In fact, it has something to do with rewriting setAttribute above.

      Although we save the original element. Prototype. SetAttribute in a closure, there are still some tricks to “steal” it from the closure.

      want a go:

      (function() {})(
          //Save the original interface
          var old_setAttribute = Element.prototype.setAttribute;
          //Override setAttribute interface
          Element.prototype.setAttribute = function(name, value) {
              //Details
              if (this.tagName == 'SCRIPT' && /^src$/i.test(name)) {}
              //Calling the original interface
              old_setAttribute.apply(this, arguments);
          };
      )();
      //Rewrite apply
      Function.prototype.apply = function(){
          console.log(this);
      }
      //Call setAttribute
      document.getElementsByTagName('body')[0].setAttribute('data-test','123');

      Guess what the above paragraph will output? have a look:

      Actually returned the native setAttribute method!

      This is because we have old in the end when we rewrite element. Prototype. SetAttribute_ setAttribute.apply(this, arguments); In this sentence, the apply method is used, so we rewrite apply again and output this. When we call the rewritten setAttribute, we can get the original old from it_ SetAttribute.

      In this way, our nested iframe rewriting setAttribute above is meaningless.

      Use the object. Defineproperty above to lock the call of application and similar usage. So that it cannot be overridden, we cannot steal our native interface from the closure. At this time, we are really successful in rewriting the attributes we want to rewrite.

      Establish interception Report

      There are also some defense methods. Next, we need to establish a reporting system to replace the console. Log () log in the above.

      What’s the use of the reporting system? Because we use the whitelist, keyword blacklist, these data need to continue to enrich, rely on the reporting system, the information intercepted each time to the server, not only can let our programmers know the attack at the first time, but also can let us continue to collect such related information in order to better deal with.

      In this example, I use nodejs to build a very simple server to accept HTTP Reporting requests.

      First, define a reporting function

      /**
       *Custom report -- replace console.log ()
       *@ param {[string]} name [interception type]
       *@ param {[string]} value [intercept value]
       */
      function hijackReport(name, value) {
        var img = document.createElement('img'),
          hijackName = name,
          hijackValue = value.toString(),
          curDate = new Date().getTime();
       
        //Report
        img.src = 'http://www.reportServer.com/report/?msg=' + hijackName + '&value=' + hijackValue + '&time=' + curDate;
      }

      Suppose our server address is www.reportServer.com Here, we use img. SRC to send an HTTP request to the server http://www.reportServer.com/report/ , each time we will bring our custom interception type, interception content and reporting time.

      Set up nodejs server with express and write a simple receiving route:

      var express = require('express');
      var app = express();
       
      app.get('/report/', function(req, res) {
          var queryMsg = req.query.msg,
              queryValue = req.query.value,
              queryTime = new Date(parseInt(req.query.time));
       
          if (queryMsg) {
              Console.log ('intercept type: '+ querymsg');
          }
       
          if (queryValue) {
              Console.log ('intercept value: '+ queryvalue');
          }
       
          if (queryTime) {
              Console.log ('intercept time: '+ req. Query. Time');
          }
      });
       
      app.listen(3002, function() {
          console.log('HttpHijack Server listening on port 3002!');
      });

      Running the server, when a report occurs, we will receive the following data:

      OK, the next step is data warehousing, analysis, adding blacklist, using nodejs, of course, sending email to inform programmers when interception occurs, and so on.

      HTTPS and CSP

      Finally, let’s talk about HTTPS and CSP. In fact, the best way to prevent hijacking is to start from the back end. The front end can do too little. Moreover, due to the exposure of source code, it is easy for attackers to bypass our defense means.

      CSP

      CSP is content security policy, translated as content security policy. This specification is related to content security. It is mainly used to define which resources can be loaded on a page to reduce the occurrence of XSS.

      MDN –CSP

      HTTPS

      The root cause of the implementation of HTTP hijacking is that the HTTP protocol has no way to verify the identity of the other party and the data integrity. If this problem can be solved, hijacking will not happen easily.

      HTTPS means HTTP over SSL. SSL protocol is a network protocol first proposed by Netscape in 1995 to solve the security problem of transport layer. Its core is based on the theory of public key cryptography, which realizes the functions of server identity authentication, data privacy protection and data integrity verification.

      Because it has little relevance to the main content of this article, more content about CSP and HTTPS can be downloaded by Google itself.

      The above is the detailed content of JavaScript anti HTTP hijacking and XSS of front-end security. For more information about JavaScript anti HTTP hijacking and XSS of front-end security, please pay attention to other related articles of developer!

      Recommended Today

      The selector returned by ngrx store createselector performs one-step debugging of fetching logic

      Test source code: import { Component } from ‘@angular/core’; import { createSelector } from ‘@ngrx/store’; export interface State { counter1: number; counter2: number; } export const selectCounter1 = (state: State) => state.counter1; export const selectCounter2 = (state: State) => state.counter2; export const selectTotal = createSelector( selectCounter1, selectCounter2, (counter1, counter2) => counter1 + counter2 ); // […]