yxfanxiao / yxfanxiao.github.io

My Blog Space
3 stars 0 forks source link

XSS & CSRF #5

Open yxfanxiao opened 8 years ago

yxfanxiao commented 8 years ago

xss

所有用户的输入都是不可信的。确保任何被输出到HTML页面的数据以HTML的方式进行转义。

浏览器在解析HTML时,是按照一定的格式来编码解析的,为了不扰乱HTML结构,有HTML编码,JS编码,URL编码。

以express 4.x为例:

  1. url转义
在url中输入`http://localhost:3000/?a=<script>b`
根据express的log, chrome和firefox的URL会自动转义:
    GET /?a=%3Cscript%3E 200 15.302 ms - 170
而IE11则不会:
    GET /?a=<script>b 200 8.829 ms - 170    

URI encode的作用是规范URI (可能有些地区中文乱码, IE11不转义"<"这些符号, 但是会自动转义空格?)

encodeURI:用于编码整个URI
    encodeURI("http://localhost:3000/?a=<script>")  //"http://localhost:3000/?a=%3Cscript%3E"
encodeURIComponent:用于编码参数
    "http://localhost:3000?a=" + encodeURIComponent("<script>") //"http://localhost:3000/?a=%3Cscript%3E"

URI decode, 在express\node_modules\express\lib\router\layer.js中,所以req.query就能拿到转码后的参数。


/**
 * Decode param value.
 *
 * @param {string} val
 * @return {string}
 * @private
 */

function decode_param(val) {
  if (typeof val !== 'string' || val.length === 0) {
    return val;
  }

  try {
    return decodeURIComponent(val);
  } catch (err) {
    if (err instanceof URIError) {
      err.message = 'Failed to decode param \'' + val + '\'';
      err.status = err.statusCode = 400;
    }

    throw err;
  }
}
  1. html转义

模板引擎ejs, jade都有转义功能:

  // { "name": "liu<" }
  // ejs
  <%= name %>   =>  liu<
  <%- name %>   =>  liu&lt;

  // jade
  #{ name }   =>  liu<
  !{ name }   =>  liu&lt;

如果像富文本编辑器里,一定要插入一些标签,做法应该是给信任的标签设白名单。

ejs encode html源码

var _ENCODE_HTML_RULES = {
      '&': '&amp;'
    , '<': '&lt;'
    , '>': '&gt;'
    , '"': '&#34;'
    , "'": '&#39;'
    }
  , _MATCH_HTML = /[&<>\'"]/g;

function encode_char(c) {
  return _ENCODE_HTML_RULES[c] || c;
};

防XSS途径:

Chrome中: The XSS Auditor refused to execute a script in
'http://localhost:3000/?a=b%3Cscript%3Ealert(document.cookie)%3C/script%3E'
because its source code was found within the request. The auditor was enabled
as the server sent neither an 'X-XSS-Protection' nor 'Content-Security-Policy'
header.
于是在header里设置了"X-XSS-Protection": 0,才允许注入脚本。

脚本注入,document.cookie就取不到了。
  <img src=1 onerror='alert(document.cookie)'>

csrf

一般通过xss拿到了cookie之后,就可以进行csrf攻击了。

简易防范

RESTFUL设计

除了GET,其余操作均验证 cookie + token

CSRF 后端生成表单的时候生成一串随机 token ,内置到表单里成为一个字段,同时,将此串 token 置入 session 中。每次表单提交到后端时都会检查这两个值是否一致,以此来判断此次表单提交是否是可信的。提交过一次之后,如果这个页面没有生成 CSRF token ,那么 token 将会被清空,如果有新的需求,那么 token 会被更新。