JavaScript

JavaScript Recommendations for OWASP TOP 10 2017

A7 - Cross Site Scripting (XSS)

DOM based XXS

  • DOM based XSS happens when XSS becomes possible based on DOM “environment”-based manipulation.in the victim’s browser used by the original client side script, so that the client side code runs in an “unexpected” manner. The page response does not change , but the client code contained in the page gets executed due to manipulation in the DOM environment.
    • Think of it as a dormant payload, which becomes active only when the DOM manipulates it in certain ways.
  • INput and Output so called Source and Sink
    • Dom XSS will appear when source that can be controlled by the user is used in a dangerous sink
- Popular Sources
  document.URL
  document.documentURI
  location.href
    location.search
      location.*
      window.name
      document.referrer

- Popular sinks
  HTML Modification sinks
  document.write / (element).innerHTML / document.writeln / <ifrane>_srcdoc and DOMParser.parserFromString

    HTML modification to behaviour change
      (element).src

    Execution Related sinks
      eval / setTimout / setInterval / execScript / new Fucntion ()

  • Prevention using DOMPurify
    • For Fixing voilation in the code we use trusted type where we can specify the code which can be detected and can be terminated
    • DOMPurify gives the ability by using as a library , where you can customize and use the literary to pinpoint , DOMPurify supports trusted types which will return Sanitized HTML wrapped in a TrustedHTML
    • In the below example you can create a policy where you can use DOMPurify library
 if (window.trustedTypes && trustedTypes.createPolicy) { // Feature testing
 trustedTypes.createPolicy('default', {
 createHTML: (string, sink) => DOMPurify.sanitize(string, {RETURN_TRUSTED_TYPE: true})
 });
 }

  • basically here we are using the Default policy name, where the createHTML will execute with the default policies which are present in the DOMPurify which will escape the strings in the TrustedType.

Trusted Types

  • TrustedType minimizes the risk for attack of DOM XSS , by detecting the vulnerability similar to the regular programming error.

  • Trusted Types works by using the risky sinks as we have already mention the above sinks and sources point , before using this Trusted Types will process the data before passing it to the sinks

  • invalid

anElement.innerHTML  = location.href;

  • valid
anEliment.innerHTML = aTrustedHTML;

  • list of TrustedTypes
TrustedHTML / TrustedScript / TrustedScriptURL
  • with this TrustedType enabled browser will only accept the TrusteHTML object for the sinks
  • mainly TrustedTypes are created ,by creating policies , you can either create piles of policies or you can create single policies and add TrustedType object all in one .
  • for example you can create a trusted type policie for TrustedHTML and can be added.
if (window.trustedTypes && trustedTypes.createPolicy) { // Feature testing
const escapeHTMLPolicy = trustedTypes.createPolicy('myEscapePolicy', {
createHTML: string => string.replace(/\</g, '&lt;')
});
}

  • You can create a Trusted Tyoe with CSP ,for example - You can add a report-only CSP header , which can eventually report the manipulation/violation to the report uri which you have mentioned

A6- Security Misconfiguration

Clickjacking

  • Preventing the browser from loading the page in frame using the X-Frame-Options or Content Security Policy (frame-ancestors) HTTP headers.

  • Preventing session cookies from being included when the page is loaded in a frame using the SameSite cookie attribute.

  • X-Frame-Options

    • The X-Frame-Options HTTP header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>, <iframe> or <object> tag. It was designed specifically to help protect against clickjacking.
    • DENY " The page cannot be displayed in a frame, regardless of the site attempting to do so."
    • SAMEORIGNE " The page can only be displayed in a frame on the same origin as the page itself."
    • ALLOW-FROM uri “The page can only be displayed in a frame on the specified origins.”
  • CSP: frame-ancestors

Content-Security-Policy: frame-ancestors <source>;
Content-Security-Policy: frame-ancestors <source> <source>;

Content-Security-Policy: frame-ancestors 'none';

Content-Security-Policy: frame-ancestors 'self' https://www.ASDF;

  • Same site cookie
    • Same site cookies allows you to declare if your cookie should be restricted to a first-party or same-site context example :-
    • If the user is on www.web.dev and requests an image from static.web.dev then that is a same-site request
    • SameSite attribute on a cookie provides three different ways to control this behavior. You can choose to not specify the attribute, or you can use Strict or Lax to limit the cookie to same-site requests.
    • SameSite strict
  Set-Cookie: promo_shown=1; SameSite=Strict

  • this comes in to picture when , user visits a site , then usually the cookie will be sent with the same reuqest , however when you are following a lonk or any sort of link the cookie will not be sent.
  • SameSite lax
  Set-Cookie: promo_shown=1; SameSite=LAX

  • This will come in to picture when the user follows the link on some site , that perticular request will include the cookie.
  • This makes Lax a good choice for cookies affecting the display of the site with Strict being useful for cookies related to actions your user is taking.
    • Samesite cookie none
      • This comes in to picture when you widely want to support the cookie over the request , without any restrictions
  Set-Cookie: widget_session=abc123; SameSite=None; Secure

  • Same site with none also comes with secure that means they required secure context.
  • You must ensure that you pair SameSite=None with the Secure attribute.

CORS

  • Access-control-Allow-origin
  • Set origin to its intent domain other then anything
  Access-Control-Allow-Origin: https://mozilla.org
  Vary: Origin
  • Access-Control-Expose-Headers
  Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
  • Access-Control-Allow-Credentials only when request is authenticated
  Access-Control-Allow-Credentials: true

PostMessage XSS

  • Windows.postMessage method helps to solve the Cross-Origin communication, providing a controlled method of communication between two windows.

  • As a simple example - a page from webiste.1 wants information from website.2 which will open in a different window or a iframe as website.2, the “Windows.postMessage” will allow to sent the string or object to a different window or frame using javascript.

  • webiste1 will request the website2 for information, where the website2 should first obtain reference to recipient window and then call the postmessage

        otherWindows.postmessage(message, targetOrigin, [transfer])
  • in the above code “otherWindow” is a reference to other window, “Message” is an object or string to send to the other window, “targetOrigin” is a target message, “Transfer” object which is transferred with the message.

  • eaxmples for the postMessage

    • parent.postMessage()
    • iframe.contentWindow.postmessage()
    • window.opener.postMessage()
    • event.source.postMessage()

NoN-compliant - page which sends message website1.html

var childWin = window.open("http://website2.html","child");
childWin.postMessage("Message for ya!","*");

Non-Compliant - page which receives the message website2.html

function checkMessage(message) {
     alert("Got a message! Contents: " + message.data);
}
window.addEventListener("message", receiveMessage, false);
  • Always specify the exact origin, not “*”, when you use a post message to send the data to other windows.

Compliant - website1.HTML

var childWin = window.open("http://website2.html","child");
childWin.postMessage("Message for ya!","website2.html");

Compliant - website2.html

function checkMessage(message) {
     alert("Got a message! Contents: " + message.data);
}
window.addEventListener("message", receiveMessage, false);
if (event.origin !== "http://website1.HTML")
    return;

Prototype Pollution

  • prototype pollution was introduced a way back where the in the javascript, this was used as an extension method to the prototype of the base object like “Object”, “string” or “function”.

  • Prototype Pollution starts where the attacker has control over the parameter value of “a” and value “obj[a][b] = value "

  • Most vulnerable library used are as below

    • “hoek”

      • hoek.merege
      • hoek.applyToDefaults
    • lodash

      • lodash.defaultsDepp
      • loadash.merege
      • lodash.mergeWith
      • lodash.set
      • lodash.setWith
  • Never let the path argument be user-input unless the user-input is whitelisted

  • example where you define a object, function , where the, the “constructor” or “proto” are the two prototype which points to the prototype of the class

  • example as below

fucntion TESTPAYA() {

}
TESTPAYA.prototype.myfunction = function() {
  return X;
}

var inst = new TESTPAYA();
inst.constructor                          //this will return the function  TESTPAYA
inst.constructor.prototype                //returns the prototype of TESTPAYA
inst.constructor.prototype.myfunction()   //return X

OR

var inst = new TESTPAYA();

inst.__proto__                             // returns the prototype of TESTPAYA
inst.__proto__.myFunc()                    // returns X
inst.__proto__ = { “a” : “123” };           // changing the prototype at runtime.
inst.hasOwnProperty(“__proto__”)            // false. We haven’t redefined the property. It’s still the original getter/setter magic property

  • For mitigating the prototype Freeze the porotype, means One of the API introduced “object.freeze”, when that function is called in an object, any further modification on that object will silently fail.
  • mitigation.js
- Object.freeze(Object.prototype);
- Onject.freeze(object);
- ({})._proto_.test = 123
- ({}).test //undefined

  • Use Null Object Object.create(null)
  • It is possible to create an object in javascript that do not have any Prototype. Use “Object.create” function.
  • Object created through this API won’t have the “proto” and “constructor” attributes. Creating an object in this fashion can help mitigate prototype pollution attacks.
- var obj = Object.create(null);
- obj.__proto__ // undefined
- obj.constructor // undefined
  • Use Map instead of object
  • The Map primitive was introduced in ES6. The Map data structure stores key/value pairs and it is not susceptible to Object prototype pollution. When a key/value structure is needed, Map should be preferred to an Object.
  • Require schema validation of JSON input
  • Avoid using the unsafe recursive merge function
  • Upgrade lodash to version 4.17.11 or higher.

you can read more for the prototype Pollution more from the research paper of Olivier Arteau’s