1 区分并理解XSS攻击方式
- 1.XSS攻击方式手段
-
- 1.盗用Cookie获取敏感信息
-
- 2.破坏正常的页面结构,插入一些恶意内容
-
- 3.植入flash(不是很常用了)
-
- 4.实现Ddos攻击效果,分布式拒绝服务攻击(目前最强大、最难防御的攻击方式之一),理解Ddos,得先理解dos说起,最基本的dos攻击就是利用合理的客户端请求,来占用过多的服务器资源,从而使合法用户无法得到服务器的响应,Ddos攻击手段就是在传统的dos攻击基础之上产生的一类攻击方式,反射型和存储型是可以实现Ddos攻击效果的
-
- 5.severminiDos但httprequest过长的时候,webSever会产生一个404,或者是4开头的错误,如果这些超长的数据保存在cookie中,能够让用户每次访问的时候造成http头超长,这样就会导致一些用户是无法访问这些域名的
- 2.反射型
-
- 1.发出请求时,XSS代码出现在URL中,作为输入提交到服务器端,服务器端解析后响应,XSS代码随响应内容一起传回给浏览器,最后浏览器解析执行XSS代码。这个过程像一次反射,故叫反射型XSS。
-
-
- 1.攻击脚本写在URL中
-
-
-
- 2.服务器解析了XSS代码并传回给浏览器
-
-
-
- 3.XSS代码通常是JavaScript,可以是html、CSS
-
-
-
- 4.浏览器解析执行XSS代码
-
-
- 2.案例代码
植入代码自动触发
/?xss=<img src="null" onerror="alert(1)" />
植入代码引诱触发
/?xss=<p onclick="alert('点我')" />点我</p>
植入代码嵌入页面
/?xss=<iframe src="//www.baidu.com/t.html"></iframe>
- 3.存储型
-
- 存储型XSS和反射型XSS的差
别仅在于,提交的代码会存储在服务器(数据库,内存,文件系统等),下次请求目标页面时不用再提交XSS代码
- 存储型XSS和反射型XSS的差
2 XSS防范措施概述
- 1.掌握XSS的防御措施
-
- 1.编码
-
-
- 对用户输入的数据进行HTML Entity编码
-
-
- 2.过滤
-
-
- 移除用户上传的DOM属性,如onerror等
-
-
-
- 移除用户上传的Style节点、Script节点、Iframe节点等
-
-
- 3.校正
-
-
- 避免直接对HTML Entity解码
-
-
-
- 使用DOM Parse转换,矫正不配对的DOM标签,DOM Parse把整个的字符串或文本转义DOM结构
-
-
- 4.实战
-
-
- 通过构建Node服务和建立一个评论功能,实例演示XSS的攻击及预防
-
3.Nodejs的Express完成安装指导
- 1.安装express
- 2.创建项目
-
- xss(文件夹) express -e ./
-
- -e表示ejs模板支持
-
- ./ 表示当前目录
- 3.安装依赖
-
- npm install
- 4.运行项目
-
- npm start
7.相关库的依赖
- encode.js:可以使用https://github.com/mathiasbynens/he 中的he.js
- domParse:可以用的 https://github.com/blowsie/Pure-JavaScript-HTML5-Parser
8 相关代码
var express = require('express');
var router = express.Router();
//设置缓存
var comments={};
//编码功能的函数
function html_encode(str){
var s='';
if(str.length==0) return ""
// 替换 & 符号
s=str.replace(/&/g,"&");
//替换 < 符号
s=s.replace(/</g,"<");
//替换 > 符号
s=s.replace(/>/g,">");
//替换 s 符号
s=s.replace(/\s/g," ");
//替换 ' 符号
s=s.replace(/\'/g,"'");
//替换 " 符号
s=s.replace(/\"/g,'"');
//替换 n 符号
s=s.replace(/\n/g,"<br>");
return s
}
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
//设置评论
router.get('/comment',function(req,res,next){ //请求、响应、捕获错误
//保存请求
comments.v=html_encode(req.query.comment);
});
// 获取评论
router.get('/getComment',function(req,res,next){
res.json({
comment:comments.v
})
});
module.exports = router;
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<script type="text/javascript" src="/javascripts/he.js"></script>
<script type="text/javascript" src="/javascripts/htmlparser.js"></script>
<script type="text/javascript">
//解码 校验
var parse=function(str){ //片段或纯文本
//最后转换的结果
var results="";
//避免这个函数在转换过程中出错,导致整个页面卡顿、阻塞,需要捕捉错误,因为parse的过程非常容易出错,因为传进来的参数str的内容是不可控的,为了避免它的错误导致整个页面异常,一定要捕获错误,所以使用try...catch
try{
//HTMLParse整个domParse的结构,HTMLParser()在htmlparser.js中定义,
//unescape()对输入进行解码反转义,参数strict:true表示严格模式,he对象来自he.js(编解码的库)
//HTMLParser()进行校验配对
HTMLParser(he.unescape(str,{strict:true}),{
/* 例子:'<h1>jskjfa</h1>'*/
// 解析到<h1>触发
start:function(tag,attrs,unary){ //标签、属性、是否单标签,如img
//过滤掉不安全的标签
if(tag=='script'||tag=='style'||tag=='link'||tag=='iframe'||tag=='frame') return;
results+='<'+tag;
// 过滤掉标签属性
// for(var i=0,len=attrs.length;i<len;i++){
// results+=" "+attrs[i].name+'="'+attrs[i].escaped+'"';
// }
results+=(unary?"/":"")+">"
},
//解析到</h1>触发
end:function(tag){
results+="</"+tag+">";
},
//解析到jskjfa 触发
chars:function(text){
results+=text;
},
//解析到注释时触发
comment:function(text){
results+="<!--"+text+"-->";
}
});
return results;
}catch(e){
console.log(e);
}finally{
}
}
</script>
</head>
<body>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
<textarea name="name" id="txt" cols="80" rows="8">
<p>sks <img src="null" alt="" onerror="alert(1)"/></p>
</textarea>
<button type="button" name="button" id="btn">评论</button>
<button type="button" name="button" id="get">获取评论</button>
<script type="text/javascript">
var btn=document.getElementById('btn');
var get=document.getElementById('get');
var txt=document.getElementById('txt');
//IE下不支持这个方法
btn.addEventListener('click',function(){
//获取XMLhttp
var xhr=new XMLHttpRequest();
//服务端接收内容的接口
var url="/comment?comment="+txt.value;
//打开对象
xhr.open('GET',url,true);
//监听xhr对象和服务端通信之后的连接状态
xhr.onreadystatechange=function(){//通过监听对象的状态,来获取客户端和服务端的通信的过程和进度
console.log(xhr)
//连接通信成功
if(xhr.readyState==4){
//客户端和服务端这次通信完成成功
if(xhr.status==200){
console.log(xhr);
}
else{
console.log('error');
}
}
}
//发起客户端和服务端的连接
xhr.send();
});
get.addEventListener('click',function(){
var xhr=new XMLHttpRequest();
var url="/getComment";
xhr.open('GET',url,true);
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200){
/* (防止XSS攻击的步骤) */
//对数据进行解码
//配对校验
var com=parse(JSON.parse(xhr.response).comment);
var txt=document.createElement('span');
//com经过DOMParse转义后的,com这个文本是包含html标签的文本
txt.innerHTML=com;
document.body.appendChild(txt);
}
else{
console.log('error');
}
}
}
xhr.send();
})
</script>
</body>
</html>