web安全

本文最后更新于:2022年3月24日 下午

同源策略

定义

  • 两个URl !同协议 !同域名 !同端口
  • 同源策略限制了同一个源加载的脚本和文档如何与其他源的资源进行交互,包括js脚本,缓存的读取,cookie,ajax等
  • 三种标签不受同源限制script link img

跨域的方法

  • 代理服务器nginx,各种devServer

  • document.domain

    前提是两个页面主要域相同

    'someWebSite.com/dir1/pageA.html'
    'someWebSite.com/dir2/pageB.html'
    
    都设置document.domain = 'someWebSite.com'
    则他们之间通信将通过同源检测,并都访问父源的cookie
  • window.name

  • postMessage

    对新打开的窗口或者iframe的contentWindow属性、执行window.open返回的窗口对象

    // pageA通过iframe嵌入了pageB
    // pageA中代码
    window.iframe[i].postMessage('data','pageB的URL')
    
    // pageB中的代码
    window.addEventListener('message',function(e){
        console.log(e.data)     // data
        console.log(e.source)   // a中window的引用
        console.log(e.origin)  // pageA的URL
    },false)
    
    // 反过来pageB向pageA发送数据
    // 在pageA中加入window.addEventListener
    // 在pageB中e.source.postMessage
    
  • iframe+hash

    // pageA通过iframe嵌入了pageB
    var B = document.getElementByTagName("iframe");
    B.src = B.src + "#" + "data";
    
    // pageB中的代码
    window.onhashchange = function(data) {
    data = window.location.hash; //  <-  pageB就获取到了hash值
    };
  • jsonp

    function jsonp({ url, params, callback }) {
      const attrs = []
      for(let [key,value] of Object.entries(params)){
        attrs.push(`${key}=${value}`)
      }
      attrs.push(`callback=${callback}`)
      url+= attrs.join('&')
      return new Promise((resolve,reject)=>{
        const script = document.createElement('script')
        script.src = url
        document.body.appendChild(script);
        try{
          window[callback] = function(data){
            resolve(data)
            document.removeChild(script)
          }
        }catch(err){
          reject(err)
        }
      })
    }
    // 发送
    jsonp({
    url: "http://localhost:3000/jsptest",
    params: { msg: "jsptestmessage" },
    callback: "jsonpCallback"
    }).then(data => {
    //处理data
        });
  • imgPing添加img标签src中放入get请求

    只能发送GET请求,无法接受返回

    var img = new Image();
    img.onload = img.onerror = function() {
        console.log("已发送");
    };
    img.src = "http://xxx.xxx.com/query?key=value";
    // 设置完src属性那一刻开始请求就发送了
  • CORS跨域资源共享(详见下文)

  • websocket协议

  • FetchAPI

    function postData(url, data) {
    // Default options are marked with *
      return fetch(url, {
          body: JSON.stringify(data), // must match 'Content-Type' header
          // ...
          mode: "cors", // no-cors, cors, *same-origin
          // ... 
          }).then(response => response.json()); // parses response to JSON
      }

CORS跨域

简单请求

  • 方法POST GET HEAD,
  • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain
请求
  • request header中添加Origin字段
响应
  • Access-Control-Allow-Origin:允许跨域访问的域,可以是一个域的列表,也可以是通配符”*“

  • Access-Control-Allow-Credentials:是否允许请求带有 cookie

    如果要发送CookieAccess-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名

    并且 ajax 中要打开

    var xhr = new XMLHttpRequest();
    xhr.withCredentials = true;  <-------
  • Access-Control-Expose-Headers: 自定义字段

非简单请求

  • 非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json
  • 正式通信前会先发起”预检”请求
  • 一旦服务器通过了”预检”请求,以后每次浏览器正常的 CORS 请求,就都跟简单请求一样
请求
  • OPTIONS请求发送预检请求
  • Origin来源域
  • Access-Control-Request-Method接下来请求的方法
  • Access-Control-Request-Headers自定义首部
响应
  • Access-Control-Allow-Origin允许跨域访问的域
  • Access-Control-Allow-Methods服务器支持的所有跨域请求的方法
  • Access-Control-Max-Age预检请求有效期
  • Access-Control-Allow-Credentials与简单请求相同

跨页面通信

  • 透明iframe+postMessage
  • service worker+postMessage
  • 使用localStorage的回调监听变化window.addEventListener('storage', e=>e.key)

XSS跨域脚本攻击

Cross-site scripting

浏览器渲染过程中执行了预期外的恶意代码

XSS利用web开发过程中的漏洞执行攻击

  • 存储型XSS

    input, textarea等)中写入恶意脚本上传到服务器,其他人下载带有该脚本的html页面至浏览器时脚本运行

  • 反射型XSS

    将恶意代码加入URL中提交给服务器,服务器返回内容就带上了恶意代码,浏览器下载页面则执行了恶意代码,服务器不存储恶意代码

  • DOM XSS

    • JavaScript 的 eval()setTimeout()setInterval() 等函数
    • <a>标签的href属性
    • DOM中的内联事件监视器,location,onclick,onerror,onload
    • 都可以将字符串作为代码执行

防范XSS

  • 使用内容安全策略CSPContent Security Policy,限制该页面可以获取的资源和来源

  • 对所有用户提交内容进行可靠的输入验证,包括URL、查询关键字、HTTP头、REFER、POST数据等

  • 任何内容输出到页面之前都必须加以en-code编码,避免生成意外的html标签;

  • cookie 内不存储敏感信息如账号密码等,并设施http only

CSRF跨域请求伪造

Cross-site request forgery

利用用户登录态

防御CSRF

  • 验证http请求的来源originreferrer
  • 设置cookieSameSite属性,使cookie只可被第一方使用
  • 设置客户端请求携带session token,并在服务器端验证token
  • 验证码

其他

SQl注入

  1. 黑客提交畸形数据改变语义提交sql查询得到非法数据

  2. 防御

    1. 过滤sql保留字
    2. 减少抛出不必要的数据库错误信息
    3. 禁止动态拼接sql语句访问数据库

点击劫持

  1. 点击透明iframe
  2. 监听鼠标移动位置
  3. H5拖拽
  4. 防御:
    1. 服务端添加 X-Frame-Options 响应头
    2. js判断顶层视口是否同源
    3. 敏感操作复杂操作(验证码,二次确认

window.opener

  1. 修改window.opener.location可以改写来源站点的地址
  2. 防御:
    1. 设置a标签的rel属性rel=noopener,禁止新页面传递源页面地址
    2. 外部链接改为经由服务器跳转
    3. 使用window.open打开外链

web安全
http://yoursite.com/2022/02/24/同源策略/
作者
tatekii
发布于
2022年2月24日
许可协议