Reasons for this output:

I have read a lot of web security articles and summarized front-end website attack and defense methods, but the front-end is basically cookie, session and authentication mechanism, and the specific implementation is mainly in the back end. Recently, I happened to learn egg. I found the egg-Security plug-in, and then spent time studying its usage and source code, so as to have a deeper understanding of its principle, make up for the blind spots of other attacks, and at the same time, it will be convenient to understand some technical points and communicate with other developers in the future. It will also be more comprehensive to consider the problem and use it easily.

After summarizing, I learned:

  • What is CSP
  • How does js implement filtering and inserting CSRF or nonce
  • Learn more about common security vulnerabilities and how to defend against them
  • Have a body of knowledge for overall Web security

Note: Security plug-ins for the framework are enabled by default

I. Web security threats

1. Reflective XSS: The server receives insecure input from the client and triggers execution on the client to launch Web attacks

  • When your site needs to output user input directly, be sure to wrap it in helper.escape(), as in egg-view-nunjucks, which overwrites the built-in escape.
const str = '><script>alert("abc") </script><';
console.log(ctx.helper.escape(str));
// => > < script> alert(" abc") < /script> <
Copy the code
  • The output of the site is made available to JavaScript for use. You need to use helper.sjs() for filtering.

Helper.sjs () is used to ENCODE variables in JavaScript (including onload events) and escape all non-whitelisted characters into \x form to prevent XSS attacks. Also ensure correct output in JS.

const foo = '"hello"';

// SJS is not used
console.log(`var foo = "${foo}"; `);
// => var foo = ""hello"";

/ / use SJS
console.log(`var foo = "The ${this.helper.sjs(foo)}"; `);
// => var foo = "\\x22hello\\x22";
Copy the code
  • Output JSON in JavaScript, if not escaped, is easily exploited as an XSS vulnerability. The framework provides the helper.sjson() macro to do json encode, which iterates through the key in json and escapes all non-whitelisted characters in the value to the form \x to prevent XSS attacks. The JSON structure remains the same. If there is a scenario where the template outputs a JSON string for JavaScript use, escape it using helper.sjson(variable name).

The processing process is complex and has high performance loss. Therefore, use it only when necessary

<script>
    window.locals = {{ helper.sjson(locals) }};
  </script>
Copy the code

Periodic summary: The main defense means of reflective XSS is character filtering. Common scenarios are summarized as follows:

  1. Helper.escape () encoding is used when the site needs to directly output the results of user input
  2. The output from the site is made available to JavaScript to use, using helper.sjs() to escape all non-whitelist characters into \x form
  3. To output json in JavaScript, use helper.sjson() to escape all non-whitelisted characters in value to form \x

2. Stored XSS attacks: by submitting content with malicious scripts stored on the server

  1. Helper.shtml () is used to handle rich text (text containing HTML code) as variables that are exported directly to the template. It can be used to output HTML tags and perform XSS filtering to filter out illegal scripts.
const value = ` < a href = "http://www.domain.com" > Google < / a > < script > evilcode... `;

{{ helper.shtml(value) }}

// => google< script> Evilcode... < /script>
Copy the code

SHTML adds domain name filtering based on XSS module, you can see custom rules and default rules,

{a: [‘title’]} whiteList: {a: [‘title’]}

Config. Helper. SHTML. DomainWhiteList: [] can expand the href and SRC is allowed in the domain to white list.

Note:

  1. SHTML uses a strict whitelist mechanism that filters out all tags and attRs outside the default rules, except for XSS risky strings. So,SHTML is used for rich text input from users. If it is abused, its functions will be limited and the server performance will be affected. These scenarios are usually forums, comment systems, etc., and even forums that don't support HTML input, don't use this Helper, just use Escape.
  1. It is a very complex security process that affects server performance. Do not use it unless you output HTML.

3. JSONP XSS

We all know that JSONP is a JSON-formatted solution for cross-domain request resources. It is used to make cross-domain requests from Script, followed by concatenation of callback parameters, but this approach has two risks that can lead to XSS:

  1. Callback argument accidentally truncates JS code, special characters single and double quotes, and newlines are at risk.

  2. Callback arguments maliciously add labels (such as

Jsonp-body is used internally by the framework to secure JSONP requests. See JSONP security attack defense

Defense content:

  1. Callback function nouns have a maximum of 50 characters
  2. Callback function names are allowed only[,], a-za-z0123456789_, $,., to prevent normal XSS, UTF-7 XSSSuch attacks.

Definable configuration:

  • Callback defaults to _callback, which can be renamed.
  • Limit – The length limit of the function name. Default is 50.

4. Other XSS defense methods

  • CSP

Refer to my other article about what is CSP

  • X-Download-Options:noopen

This function is enabled by default. Disable the Open button in the Download box of Internet Explorer to prevent files downloaded from Internet Explorer from being opened by default.

  • X-Content-Type-Options:nosniff

Disable IE8’s automatic sniffing of MIME functions such as text/plain and rendering as text/ HTML, especially if the content served on the site may not be trusted.

  • X-XSS-Protection

Some XSS detection and defense provided by IE is enabled by default

Close The default value is false, which is set to 1. mode=block

5. Cross-site Request Forgery (CSRF) prevention

Generally speaking, there are some common defense schemes for CSRF attacks. Several common defense schemes are briefly introduced:

  • Synchronizer Tokens: When passing a response pageRender the token to the page and submit it through a hidden field when the form is submitted.
  • Double Cookie Defense:Set the token in the CookieCookie is submitted when the request (POST, PUT, PATCH, DELETE, etc.) is submitted, and the server carries the token in the Cookie through the header or body for comparison and verification.
  • The Custom Header:Trust requests With a specific header, such as X-requested-with: XMLHttpRequest. This scheme can be bypassed, so frameworks like Rails and Django abandon this defense.

The framework combines the above defense modes and provides a configurable CSRF defense policy:

  1. Synchronize CSRF validation of forms

CSRF = ctx.csrf; CSRF = ctx.csrf; CSRF = ctx.csrf;

<form method="POST" action="/upload? _csrf={{ ctx.csrf | safe }}" enctype="multipart/form-data">
  title: <input name="title" />
  file: <input name="file" type="file" />
  <button type="submit">upload</button>
</form>
Copy the code

The fields passing CSRF tokens can be changed in the configuration:

// config/config.default.js
module.exports = {
  security: {
    csrf: {
      queryName: '_csrf'.The default field for passing a CSRF token through query is _csrf
      bodyName: '_csrf'.// The default field for passing a CSRF token through body is _csrf,}}};Copy the code

To guard against BREACH attacks, CSRF tokens rendered synchronously to pages change with each request, and view plug-ins such as egg-view-Nunjucks inject forms automatically, unaware of the application developer.

BREACH attacks:

  1. An AJAX request

In the default CSRF configuration, the token is set in a Cookie. In AJAX requests, the token can be fetched from the Cookie and sent to the server in the query, body, or header.

var csrftoken = Cookies.get('csrfToken');

function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
  beforeSend: function(xhr, settings) {
    if(! csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader('x-csrf-token', csrftoken); }}});Copy the code

The fields that pass the CSRF token through the header can also be changed in the configuration:

// config/config.default.js
module.exports = {
  security: {
    csrf: {
      headerName: 'x-csrf-token'.// The default field for passing a CSRF token through header is x-CSRF-token,}}};Copy the code
  1. Session vs. Cookie storage

By default, the framework stores CSRF tokens in cookies for AJAX requests. However, all subdomains can set cookies. Therefore, when our application cannot guarantee that all subdomains are controlled, storing cookies may be attacked by CSRF. The framework provides a configuration item that stores tokens in a Session.

// config/config.default.js
module.exports = {
  security: {
    csrf: {
      useSession: true.// Default is false. When set to true, CSRF tokens are saved to Session
      cookieName: 'csrfToken'.// The field name in the Cookie. The default value is csrfToken
      sessionName: 'csrfToken'.// The field name in the Session, csrfToken by default
      ignoreJSON: true.// Default is false. When set to true, all requests whose content-type is' application/json 'will be ignored,}}};Copy the code

Under the SOP’s security policy,Almost all modern browsers do not allow cross-domain requests with content-type JSON, so we can just let go of jSON-formatted requests of type.

  1. The refresh CSRF token

When the CSRF token is stored in a Cookie, once a user switch occurs on the same browser, the newly logged in user will still use the old token (used by the previous user), which brings security risks. Therefore, the CSRF token must be refreshed every time the user logs in.

exports.login = function* (ctx) {
  const { username, password } = ctx.request.body;
  const user = yield ctx.service.user.find({ username, password });
  if(! user) ctx.throw(403);
  ctx.session = { user };

  // Call rotateCsrfSecret to refresh the user's CSRF token
  ctx.rotateCsrfSecret();

  ctx.body = { success: true };
}
Copy the code

Periodic summary framework’s defense against CSRF:

  • Form validation. CSRF token is submitted when the form is submitted
  • By default, the token is set in a Cookie, which can be placed in a Query, body, or header and sent to the server
  • It is better to store the token in the Session, which can be configured
  • Call rotateCsrfSecret to refresh the user’s CSRF token

The methods learned from this framework are common defense schemes for CSRF attacks.

6. Prevention of XST(Cross-site Tracing)

The client sends a TRACE request to the server. If the server implements a TRACE response according to the standard, the complete header information of the request will be returned in the Response Body. In this way, the client can retrieve certain sensitive header fields, such as httpOnly cookies.

Curl -x TRACE -b a=1 -i http://127.0.0.1:7001

  HTTP/1.1 200 OK
  X-Powered-By: koa
  Set-Cookie: a=1; path=/; httponly
  Content-Type: text/plain; charset=utf-8
  Content-Length: 73
  Date: Thu, 06 Nov 2014 05:07:47 GMT
  Connection: keep-alive

  user-agent: curl/7.371.
  host: 127.0. 01.:7001
  accept: */* cookie: a=1Copy the code

We can see the full header in the response body, so we bypass the httpOnly constraint and get cookie=1, which is a big risk.

The framework has disabled trace, track, and options dangerous requests.

7. Phishing attack prevention

There are many ways to fish. Here are URL fishing, picture fishing, and iframe fishing.

The url to go fishing

If the server does not check and control the incoming redirect URL variable, any malicious address can be maliciously constructed and users can be induced to redirect to malicious websites, which may be phishing like this:

  • Steal user information by going to a malicious site to trick users into entering their username and password
  • Tricking users into making money transactions
  • Possible XSS vulnerability (mainly the jump often uses 302 jump, i.e. setting HTTP response header Locatioin: URL, if the URL contains CRLF, will cause XSS)

Prevention methods:

    1. If the jump URL can be determined in advance, including the URL and parameter values, thenYou can configure url parameters in the background. The URL parameters only need to be transmitted to the index of the corresponding URL, and then the corresponding URL can be found through the index;
    1. If the jump URL is uncertain in advance, but its input is generated by the background (not by the user through the parameters of the transmission), you can be a good jump link and then sign;
    1. If both 1 and 2 are not met, the URL cannot be determined in advance and can only be passed in using front-end parameters. In this case, the URL must be verified based on the following rules: The URL is in the whitelist of application authorization.

The framework provides a way to safely jump to avoid this risk by configuring whitelists.

  • Ctx. redirect(URL) If the url is not in the configured whitelist, the url is disabled.
  • Ctx. unsafeRedirect(URL) is not recommended. Use it after you understand the risks.
  • The security solution overrides the default CTx. redirect method, and all redirects are judged by the security domain name.

To use the CTx. redirect method, you need to configure the following parameters in the application configuration file:

Exports. security = {domainWhiteList:['.domain.com'], // security whitelist with. The first};Copy the code
  • If domainWhiteList is not configured or the array is empty, all forward requests will be allowed by default. This is the same as ctx.unsaferedirect (url).

Pictures of fishing

If users are allowed to insert unauthenticated images into a web page, this can be a phishing risk.

For example, in the common 401 phishing, when an attacker visits the page, the page pops up a verification page asking the user to enter an account and password. When the user enters, the account and password are stored in the hacker’s server. This is usually the case in .

Prevention methods:

  • The framework provides the.surl() macro for URL filtering
<a href="helper.surl($value)" /> <a href="http://ww.safe.com&lt; script&gt;" />Copy the code

The iframe fishing

Frame phishing: By embedding an Iframe into the attacked web page, the attacker can guide users to click on the dangerous website pointed to by the iframe, or even cover up, affect the normal function of the website, and hijack the user’s click operation.

Prevention methods:

  • The framework provides x-frame-options security headers.The default value is SAMEORIGIN, which only allows the same domain to embed this page as iframe. You can turn this off when you need to embed some trusted third party networks.

8. HPP(Http Parameter Pollution) defense

In THE HTTP protocol, parameters with the same name are allowed to appear multiple times. However, due to the non-standard implementation of the application, the attacker transmits parameters with the same key but different value when transmitting parameters, so as to bypass some protection consequences.

HPP may cause the following security threats:

  • Bypass guard and parameter verification.
  • Logic bugs and errors occur, affecting application code execution.

Prevention methods:

  • The framework itself will transfer parameters with the same key but different value to the client,Force the first argument, so it does not cause HPP attacks.

9. Man-in-the-middle attacks versus HTTP/HTTPS

Middlemen (browsers, router manufacturers, WIFI providers, communication operators, etc., and more middlemen will be introduced if proxy or wall climbing software is used) can monitor, hijack, and block HTTP requests.

Possible security threats include:

  • Without HTTPS, carriers can jump directly to an AD when a user makes a request, or change search results to insert their own ads. If there is a BUG in the hijacked code, the user is directly unable to use it and a blank screen appears.

  • Data leakage, request hijacking, content tampering and other problems, the core reason is HTTP is a completely naked plaintext request, domain name, path and parameters are clearly seen by the middle people. What HTTPS does is encrypt the request to make it more secure for the user. For themselves, in addition to protecting the interests of users, but also to avoid their own traffic hijacked, to protect their own interests.

Although HTTPS is not completely secure, organizations with root certificates and encryption algorithms can also carry out man-in-the-middle attacks. However, HTTPS is the most secure solution under the current architecture, and it significantly increases the cost of man-in-the-middle attacks.

Prevention methods:

  • Developers who use the Egg framework to develop their sites must push to upgrade to HTTPS

  • HSTS strict-transport-Security is turned off by default. Ensure that HTTPS sites do not redirect to HTTP. Ensure that HTTPS is enabled if the site supports HTTPS.

  • If our Web site is an HTTP site, we need to turn this header off. The configuration is as follows:

    • MaxAge The default value is 365 x 24 x 3600.
    • IncludeSubdomains default false to add subdomains and ensure that all subdomains are accessed using HTTPS.

10. Defend against Server Side Request Forgery (SSRF)

SSRF security vulnerability is common: the developer directly requests the URL resources passed in by the client on the server, and once the attacker passes in some internal urls, the SSRF attack can be launched.

Prevention methods:

  • The Intranet IP address blacklist is used to defend against SSRF attacks. The IP addresses obtained after domain names are resolved are filtered to prevent access to internal IP addresses

Usage:

The framework provides the safeCurl method on CTX, APP, and Agent, which filters the specified Intranet IP address when initiating a network request. In addition, this method is consistent with the curl method provided by the framework.

ctx.safeCurl(url, options)
app.safeCurl(url, options)
agent.safeCurl(url, options)
Copy the code

Calling the safeCurl method directly doesn’t really serve any purpose, as it also requires security configuration items.

  • IpBlackList (Array) – Configures the Intranet IP address list. The IP addresses in these network segments cannot be accessed.
  • CheckAddress (Function) – Directly configures a Function that checks the IP address and determines whether it is allowed to be accessed in safeCurl based on the return value of the Function. If the return value is not true, the IP address cannot be accessed. CheckAddress has a higher priority than ipBlackList.
// config/config.default.js
exports.security = {
  ssrf: {
    ipBlackList: [
      '10.0.0.0/8'.// IP network segments are supported
      '0.0.0.0/32'.'127.0.0.1'.// You can specify an IP address].// If checkAddress is configured, ipBlackList does not take effect
    checkAddress(ip) {
      returnip ! = ='127.0.0.1'; ,}}};Copy the code

11. Other safety tools

  • ctx.isSafeDomain(domain)

Whether it is a secure domain name. For details about how to configure secure domain names, see ctx.redirect.

  • app.injectCsrf(str)

Template preprocessing – automatic insert CSRF key ability, can automatically insert CSRF hidden fields in all form tags, users do not need to manually write.

const INPUT_CSRF = '\r\n<input type="hidden" name="_csrf" value="{{ctx.csrf}}" /></form>';

exports.injectCsrf = function injectCsrf(tmplStr) {
  tmplStr = tmplStr.replace(/(
      
       )([\s\S]*?) <\/form>/gi
      *?>.function replaceCsrf(_, $1, $2) {
    const match = $2;
    if (match.indexOf('name="_csrf"')! = = -1 || match.indexOf('name=\'_csrf\'')! = = -1) {
      return $1 + match + '</form>';
    }
    return $1 + match + INPUT_CSRF;
  });

  return tmplStr;
};
Copy the code
  • app.injectNonce(str)

Template preprocessing – will scan the script tag in the template and automatically add the nonce header. This function can be used if the site has CSP security header enabled and you want to use the CSP 2.0 nonce feature.

exports.injectNonce = function injectNonce(tmplStr) {
  tmplStr = tmplStr.replace(/
      (.*?)>.function replaceNonce(_, $1, $2) {
    if ($1.indexOf('nonce=') = = = -1) {$1+ =' nonce="{{ctx.nonce}}"';
    }

    return '<script' + $1 + '>' + $2 + '</script>';
  });
  return tmplStr;
};
Copy the code
  • app.injectHijackingDefense(str)

For websites that do not have HTTPS enabled, this function can effectively prevent hijacking by carriers.

const INJECTION_DEFENSE = '<! --for injection--><! --</html>--><! --for injection-->';

exports.injectHijackingDefense = function injectHijackingDefense(tmplStr) {
  return INJECTION_DEFENSE + tmplStr + INJECTION_DEFENSE;
};
Copy the code

Second, source code analysis

xframe

The default is SAMEORIGIN

module.exports = options= > {
  return async function xframe(ctx, next) {
    await next();

    const opts = utils.merge(options, ctx.securityOptions.xframe);
    if (utils.checkIfIgnore(opts, ctx)) return;

    // DENY,SAMEORIGIN,ALLOW-FROM
    // https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options?redirectlocale=en-US&redirectslug=The_X-FRAME-OPTIONS_resp onse_header
    const value = opts.value || 'SAMEORIGIN';

    ctx.set('x-frame-options', value);
  };
};
Copy the code

csp

const HEADER = [
  'x-content-security-policy'.'content-security-policy',];const REPORT_ONLY_HEADER = [
  'x-content-security-policy-report-only'.'content-security-policy-report-only',];module.exports = options= > {
  return async function csp(ctx, next) {
    await next();

    const opts = utils.merge(options, ctx.securityOptions.csp);
    if (utils.checkIfIgnore(opts, ctx)) return;

    let finalHeader;
    let value;
    const matchedOption = extend(true, {}, opts.policy);
    const isIE = platform.parse(ctx.header['user-agent']).name === 'IE';
    const bufArray = [];

    const headers = opts.reportOnly ? REPORT_ONLY_HEADER : HEADER;
    if (isIE && opts.supportIE) {
      finalHeader = headers[0];
    } else {
      finalHeader = headers[1];
    }

    for (const key in matchedOption) {

      value = matchedOption[key];
      value = Array.isArray(value) ? value : [ value ];

      // Other arrays are splitted into strings EXCEPT `sandbox`
      if (key === 'sandbox' && value[0= = =true) {
        bufArray.push(key);
      } else {
        if (key === 'script-src') {
          const hasNonce = value.some(function(val) {
            return val.indexOf('nonce-')! = = -1;
          });

          if(! hasNonce) { value.push('\'nonce-' + ctx.nonce + '\' ');
          }
        }

        value = value.map(function(d) {
          if (d.startsWith('. ')) {
            d = The '*' + d;
          }
          return d;
        });
        bufArray.push(key + ' ' + value.join(' ')); }}const headerString = bufArray.join('; ');
    ctx.set(finalHeader, headerString);
    ctx.set('x-csp-nonce', ctx.nonce);
  };
};
Copy the code

csrf

function csrf(ctx, next) {
    if (utils.checkIfIgnore(options, ctx)) {
      return next();
    }
    // ensure csrf token exists
    if ([ 'any'.'all'.'ctoken' ].includes(options.type)) {
      ctx.ensureCsrfSecret();
    }
    // Ignore requests: get, head, options, and trace ignore these method requests
    const method = ctx.method;
    if (method === 'GET' ||
      method === 'HEAD' ||
      method === 'OPTIONS' ||
      method === 'TRACE') {
      return next();
    }
	/ / ignore json
    if (options.ignoreJSON && typeis.is(ctx.get('content-type'), 'json')) {
      return next();
    }

    const body = ctx.request.body || {};
    debug('%s %s, got %j', ctx.method, ctx.url, body);
    ctx.assertCsrf();
    return next();
  };
Copy the code

Dta (Directory_traversal_attack)

En.wikipedia.org/wiki/Direct…

function dta(ctx, next) {
  const path = ctx.path;
  if(! isSafePath(path, ctx)) { ctx.throw(400);
  }
  return next();
};
Copy the code

HSTS (HTTP Strict Transport Security)

Set strict – transport ws-security header

async function hsts(ctx, next) {
    await next();
    const opts = utils.merge(options, ctx.securityOptions.hsts);
    if (utils.checkIfIgnore(opts, ctx)) return;

    let val = 'max-age=' + opts.maxAge;
    // If opts.includeSubdomains is defined,the rule is also valid for all the sub domains of the website
    if (opts.includeSubdomains) {
      val += '; includeSubdomains';
    }
    ctx.set('strict-transport-security', val);
 };
Copy the code

methodnoallow

const methods = require('methods');
const METHODS_NOT_ALLOWED = [ 'trace'.'track' ];
const safeHttpMethodsMap = {};

for (const method of methods) {
  if(! METHODS_NOT_ALLOWED.includes(method)) { safeHttpMethodsMap[method.toUpperCase()] =true; }}// https://www.owasp.org/index.php/Cross_Site_Tracing
// http://jsperf.com/find-by-map-with-find-by-array
module.exports = () = > {
  return function notAllow(ctx, next) {
    // ctx.method is upper case
    if(! safeHttpMethodsMap[ctx.method]) { ctx.throw(405);
    }
    return next();
  };
};
Copy the code

noopen

// @see http://blogs.msdn.com/b/ieinternals/archive/2009/06/30/internet-explorer-custom-http-headers.aspx
module.exports = options= > {
  return async function noopen(ctx, next) {
    await next();

    const opts = utils.merge(options, ctx.securityOptions.noopen);
    if (utils.checkIfIgnore(opts, ctx)) return;

    ctx.set('x-download-options'.'noopen');
  };
};
Copy the code

nosniff

const statuses = require('statuses');
const utils = require('.. /utils');

module.exports = options= > {
  return async function nosniff(ctx, next) {
    await next();

    // ignore redirect response
    if (statuses.redirect[ctx.status]) return;

    const opts = utils.merge(options, ctx.securityOptions.nosniff);
    if (utils.checkIfIgnore(opts, ctx)) return;

    ctx.set('x-content-type-options'.'nosniff');
  };
};
Copy the code

referrerPolicy

// https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Referrer-Policy
const ALLOWED_POLICIES_ENUM = [
  'no-referrer'.'no-referrer-when-downgrade'.'origin'.'origin-when-cross-origin'.'same-origin'.'strict-origin'.'strict-origin-when-cross-origin'.'unsafe-url'.' ',];module.exports = options= > {
  return async function referrerPolicy(ctx, next) {
    await next();

    const opts = utils.merge(options, ctx.securityOptions.refererPolicy);
    if (utils.checkIfIgnore(opts, ctx)) { return; }
    const policy = opts.value;
    if(! ALLOWED_POLICIES_ENUM.includes(policy)) {throw new Error('"' + policy + '" is not available."');
    }

    ctx.set('referrer-policy', policy);
  };
};
Copy the code

xssProtection

module.exports = options= > {
  return async function xssProtection(ctx, next) {
    await next();

    const opts = utils.merge(options, ctx.securityOptions.xssProtection);
    if (utils.checkIfIgnore(opts, ctx)) return;

    ctx.set('x-xss-protection', opts.value);
  };
};
Copy the code

Third, summary

The following security threats are summarized:

1. Reflective XSS (JSONPXSS)

  • When a website needs to directly output user input,Be sure to use helper.escape() encodingIn egg-view-bunjunks, the built-in escape is overridden
  • The output from the site is made available to JavaScript to use, using helper.sjs() to escape all non-whitelist characters into \x form
  • To output json in JavaScript, use helper.sjson() to escape all non-whitelisted characters in value to form \x

2. Storage XSS

  • Helper.shtml () is used to handle rich text (text containing HTML code) as variables that are exported directly to the template

3. JSONP XSS

  • Callback function nouns have a maximum of 50 characters
  • Callback names only allow [,], A-za-z0123456789_, $,., to prevent XSS, UTF-7 XSS, etc.

4. Other XSS defense methods

  • CSP
  • X-Download-Options:noopen
  • X-Content-Type-Options:nosniff
  • XSS-Protection

5. CSRF

  • Form validation. CSRF token is submitted when the form is submitted
  • By default, the token is set in a Cookie, which can be placed in a Query, body, or header and sent to the server
  • It is better to store the token in the Session, which can be configured
  • Call rotateCsrfSecret to refresh the user’s CSRF token

6. XST(Cross-Site Tracing)

  • The framework has disabled trace, track, and options dangerous requests.

7. Fishing (URL fishing, picture fishing, iframe fishing)

  • The url to go fishing
    • Ctx. redirect(URL) Whitelist is configured.
    • Ctx. unsafeRedirect(URL) is not recommended. Use it after you understand the risks.
  • Image phishing: Frames provide the.surl() macro to do URL filtering
  • Iframe phishing: The framework provides the X-frame-options security header, which defaults to SAMEORIGIN and allows only the same domain to embed this page as iframe. You can turn this off when you need to embed some trusted third party networks

8. HPP(Http Parameter Pollution)

  • The framework itself forces the first parameter to be used when the client transmits a parameter with the same key but different value, thus preventing HPP attacks.

9. Man-in-the-middle attacks versus HTTP/HTTPS

  • Developers who use the Egg framework to develop their sites must push to upgrade to HTTPS

  • HSTS strict-transport-Security is turned off by default. Ensure that HTTPS sites do not redirect to HTTP. Ensure that HTTPS is enabled if the site supports HTTPS.

  • If our Web site is an HTTP site, we need to turn this header off

10. SSRF(Server-Side Request Forgery)

  • The Intranet IP address blacklist is used to defend against SSRF attacks. The IP addresses obtained after domain names are resolved are filtered to prevent access to internal IP addresses

11. Other safety tools

  • ctx.isSafeDomain(domain)
  • app.injectCsrf(str)
  • app.injectNonce(str)
  • app.injectHijackingDefense(str)

The application of egg-Security framework to the security defense against the above threats is summarized, and other common security methods are also listed

At the same time analysis framework means of source code implementation

To summarize the rich solutions built into the framework:

  • Various template filtering functions are provided to prevent phishing or XSS attacks
  • Common Web security header support
  • Flexible security configuration to match different request urls
  • Customizable whitelist for secure jump and URL filtering
  • Various template-related tool functions do preprocessing.

Reference:

Github.com/eggjs/egg-s…

Github.com/eggjs/egg/b…