XSS详解
什么是XSS(跨站脚本攻击)
XSS又叫CSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往Web页面里插入恶意html代码或者javascript代码,当用户浏览该页之时,嵌入其中Web里面的html代码或者javascript代码会被执行,从而达到恶意的特殊目的。
XSS攻击涉及到三方:攻击者,用户,web server。用户是通过浏览器来访问web server上的网页,XSS攻击就是攻击者通过各种办法,在用户访问的网页中插入自己的脚本,让其在用户访问网页时在其浏览器中进行执行。攻击者通过插入的脚本的执行,来获得用户的信息,比如cookie,发送到攻击者自己的网站(跨站了)。
XSS属于被动式的攻击,因为其被动且不好利用,所以许多人常呼略其危害性。
在WEB2.0时代,强调的是互动,使得用户输入信息的机会大增,在这个情况下,我们作为开发者,在开发的时候,要提高警惕。
XSS的攻击手段(或者叫攻击的目的)
盗用Cookie获取到一些敏感的信息:在网页浏览中我们常常涉及到用户登录,登录完毕之后服务端会返回一个cookie值。这个cookie值相当于一个令牌,拿着这张令牌就等同于证明了你是某个用户
如果你的cookie值被窃取,那么攻击者很可能能够直接利用你的这张令牌不用密码就登录你的账户。如果想要通过script脚本获得当前页面的cookie值,通常会用到document.cookie。
破坏正常的页面结构:比如修改页面的样式等,在页面中插入一些其他的信息(比如色情,广告等)
劫持流量实现恶意跳转:就是在网页中想办法插入一句像这样的语句,那么所访问的网站就会被跳转到百度的首页
<script>window.location.href="http://www.baidu.com";</script>
早在2011年新浪就曾爆出过严重的xss漏洞,导致大量用户自动关注某个微博号并自动转发某条微博。
XSS的攻击方式—反射型
发出请求时,xss代码出现在URL中,作为输入提交到服务器端,服务器端解析后响应,xss代码随响应内容一起传回给浏览器,最后浏览器解析执行xss代码,这个过程像一次反射,故叫反射型xss。
也就是攻击相对于访问者而言是一次性的,具体表现在我们把我们的恶意脚本通过url的方式传递给了服务器,而服务器则只是不加处理的把脚本“反射”回访问者的浏览器而使访问者的浏览器执行相应的脚本。也就是说想要触发漏洞,需要访问特定的链接才能够实现。
反射型的攻击特点:XSS攻击代码非持久性,也就是没有保存在web server中,而是出现在URL地址中;非持久性,那么攻击方式就不同了。一般是攻击者通过邮件,聊天软件等等方式发送攻击URL,然后用户点击来达到攻击的;
反射型攻击的演示如下:首先创建一个express的node服务
安装依赖
接下来编写接口,在接口中解析url后面的参数内容
然后再模板中渲染url解析后的内容
PS:-号表示不对html进行转义,如果说这个标签内允许解析HTML的那么就用-号,这样不会对html标签进行转义。=号表示对html进行转义成字符串
接下来,运行项目,在url后面加上xss内容
这是正常的内容,那么我们输入一些具有攻击性的内容,在此之前先去掉浏览器的异常代码检测和拦截
这里浏览器进行检测到异常代码进行了拦截,导致页面不能访问,那么解除浏览器异常代码并拦截,需要在接口代码中加入下面一行代码
res.set('x-xss-Protection',0);
第一种,自动执行脚本攻击,这里使用一个img标签,当src为null,就会执行onerror事件
第二种引导用户点击,从而执行攻击代码
第三种,往页面中嵌入iframe,iframe是一个插入广告的代码
从上面实例中可以看到,当接口解析url的内容并且下发到模板中,这种反射型攻击就会生效,如果当接口不解析这个url内容的话或者去掉xss的内容下发,那么这个攻击就不会生效了,
XSS的攻击方式—存储型
存储型xss和反射型xss的差别仅仅在于,提交的代码会存储在服务器端(数据库,内存,文件系统等),下次请求目标页面时不用再提交xss代码
它与反射型XSS最大的不同就是服务器再接收到我们的恶意脚本时会将其做一些处理。
例如储存到数据库中,然后当我们再次访问相同页面时,将恶意脚本从数据库中取出并返回给浏览器执行。这就意味着只要访问了这个页面的访客,都有可能会执行这段恶意脚本,因此储存型XSS的危害会更大
比如评论区中通常就是储存型XSS。当有人在评论内容中插入恶意脚本时,由于服务器要像每一个访客展示之前的评论内容,所以后面的访客自然会接收到之前留言中的恶意脚本而不幸躺枪。
这个过程一般而言只要用户访问这个界面就行了,不像反射型XSS,需要访问特定的URL。存储型的攻击演示查看:XSS的防范措施实例
XSS的防范措施概述
认证cookie设置HttpOnly
编码:对用户输入的数据进行HTML Entity编码(就像html的字符编码一样)
过滤:移除用户上传的DOM属性,比如onerror,onclick等等,除非业务上有特殊的需求,一般是没有这样的需求的。用户上传的Style节点(会对页面的样式进行篡改),Script节点(引入外部的js文件,或者使用这个标签进行编写js代码进行操作页面的内容),Ifram节点和fram节点(防止用户引入其他页面比如广告等等)等
校正:避免直接对HTML Entity解码。使用DOM Parse转换,校正不配对的DOM标签
XSS的防范措施实例(通过构建Node服务和建立一个评论功能)
在此之前需要准备下面两个插件:domParse.js 和 encode.js 直接在最底下的github地址上下载即可
然后再需要使用的页面中引入这两个插件
<script src="/javascripts/encode.js" charset="utf-8"></script>
<script src="/javascripts/domParse.js.js" charset="utf-8"></script>
接下来首先创建express项目来进行演示,创建一个express的node服务
安装依赖
然后在服务端构造两个接口,分别是提交评论的接口和获取评论的接口,并且模拟一个数据存储(实际项目中是将数据存储到数据库中并且数据库中拉取数据)
获取到评论数据后,需要一个编码的过程,编码后保存在缓存中(实际项目中是保存到数据库中)
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(/>/,">");
s = s.replace(/\s/g," ");
s = s.replace(/\'/g,"'");
s = s.replace(/\"/g,""");
s = s.replace(/\n/g,"<br>");
return s;
} 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);
console.log(comments.v)
}); 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 src="/javascripts/encode.js" charset="utf-8"></script>
<script src="/javascripts/domParse.js.js" charset="utf-8"></script>
</head>
<body>
<textarea name="name" rows="8" cols="80" id="txt">
<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> </body>
</html>
首先获取需要操作的dom
//获取元素
var btn = document.getElementById('btn');
var get = document.getElementById('get');
var txt = document.getElementById('text');
然后使用ajax与后端进行通信,提交评论
//监听评论按钮事件
btn.addEventListener('click',function(){
var xhr = new XMLHttpRequest();
var url = '/comment?comment='+ txt.value;
xhr.open('GET',url,true);
xhr.onreadystatechange=function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
console.log(xhr);
}else{
console.log('error');
}
}
}
xhr.send();
});
在前端中获取后台数据需要明确两个点:解码和校验配对(这是必须的两个步骤)这个解码和校验配对的过程比较复杂,所以需要单独创建一个函数进行调用,并且在这个函数中需要将一些异常的标签进行过滤和过滤掉标签的属性
<script type="text/javascript">
var parse = function(str){
var results = '';
try{
HTMLParser(he.unescape(str,{strict:true}),{
start:function(tag,attrs,unary){ //过滤掉一些有威胁的标签
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?"/":"")+">";
},
end:function(tag){
results += "</"+tag+">";
},
chars:function(text){
results += text;
},
comment:function(text){
results +="<!--"+text+"-->";
}
});
return results;
}catch(e){
console.log(e);
}finally{ }
}
</script>
然后在获取评论的代码中进行调用这个parser方法
//监听获取评论按钮事件
get.addEventListener('click',function(){
console.log('2');
var xhr = new XMLHttpRequest();
var url = '/getComment';
xhr.open('GET',url,true);
xhr.onreadystatechange=function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
var com = parse(JSON.parse(xhr.response).comment);
var txt = document.createElement('span');
txt.innerHTML = com;
document.body.appendChild(txt);
}else{
console.log('error');
}
}
}
xhr.send();
});
总结
在开发的时候,每当有用户输入的内容时,都要加倍小心。请记住两条原则:过滤输入和转义输出。前端xss防御整体代码实例如下
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<script src="/javascripts/encode.js" type="text/javascript"></script>
<script src="/javascripts/domParse.js" type="text/javascript"></script>
<script type="text/javascript">
var parse = function(str){
var results = '';
try{
HTMLParser(he.unescape(str,{strict:true}),{
start:function(tag,attrs,unary){ //过滤掉一些有威胁的标签
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?"/":"")+">";
},
end:function(tag){
results += "</"+tag+">";
},
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" rows="8" cols="80" id="text">
<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('text'); //监听评论按钮事件
btn.addEventListener('click',function(){
var xhr = new XMLHttpRequest();
var url = '/comment?comment='+ txt.value;
xhr.open('GET',url,true);
xhr.onreadystatechange=function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
console.log(xhr);
}else{
console.log('error');
}
}
}
xhr.send();
}); //监听获取评论按钮事件
get.addEventListener('click',function(){
console.log('2');
var xhr = new XMLHttpRequest();
var url = '/getComment';
xhr.open('GET',url,true);
xhr.onreadystatechange=function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
var com = parse(JSON.parse(xhr.response).comment);
var txt = document.createElement('span');
txt.innerHTML = com;
document.body.appendChild(txt);
}else{
console.log('error');
}
}
}
xhr.send();
});
</script>
</body>
</html>
github地址为:https://github.com/SmileHong0121/xss
Ifram
XSS详解的更多相关文章
- Pentester中的XSS详解
本次做的是Web For Pentester靶机里面的XSS题目,一共有9道题目. 关于靶机搭建参考这篇文章:渗透测试靶机的搭建 第1题(无过滤措施) 首先在后面输入xss: http://10.21 ...
- XSS详解【1】---基本概念和攻击原理
这节主要讲述XSS的基本概念和攻击原理. 一 XSS基本概念 人们经常将跨站脚本攻击(Cross Site Scripting)缩写为CSS,但这会与层叠样式表(Cascading Style She ...
- DOM XSS详解
DOM XSS简介 DOM XSS与反射性XSS.存储型XSS的主要区别在于DOM XSS的XSS代码不需要服务端解析响应的直接参与,触发XSS的是浏览器端的DOM解析. DOM XSS复现 环境搭建 ...
- pikachu靶场XSS详解
一.反射型XSS 1.get型 源码前后区别 前 <form method="get"> <input class="xssr_in" typ ...
- XSS与CSRF详解
XSS与CSRF详解 随着Web2.0.社交网络.微博等等一系列新型的互联网产品的诞生,基于Web环境的互联网应用越来越广泛,企业信息化的过程中各种应用都架设在Web平台上,Web业务的迅速发展也引起 ...
- DVWA(六):XSS-Reflected 反射型XSS全等级详解
XSS 概念: 由于web应用程序对用户的输入过滤不严,通过html注入篡改网页,插入恶意脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击. XSS类型: Reflected(反射型):只是简单的 ...
- PHP开发中常见的安全问题详解和解决方法(如Sql注入、CSRF、Xss、CC等
页面导航: 首页 → 网络编程 → PHP编程 → php技巧 → 正文内容 PHP安全 PHP开发中常见的安全问题详解和解决方法(如Sql注入.CSRF.Xss.CC等) 作者: 字体:[增加 减小 ...
- 第六天实验详解——dedecms通过xss漏洞写马
第六天实验详解 **XSS跨站攻击的分类** XSS漏洞类型主要分为持久型和非持久型两种: 1. 非持久型XSS漏洞一般存在于URL参数中,需要访问黑客构造好的特定URL才能触发漏洞. 2. 持久型X ...
- web框架详解之 tornado 四 模板引擎、session、验证码、xss
一.模板引擎 基本使用 继承,extends 页面整体布局用继承 导入,include 如果是小组件等重复的那么就用导入 下面是目录 首先在controllers里面创建一个文件,文件里面是页面类 # ...
随机推荐
- .39-浅析webpack源码之parser.parse
因为换了个工作,所以博客停了一段时间. 这是上个月留下来的坑,webpack的源码已经不太想看了,又臭又长,恶心的要死,想去看node的源码……总之先补完这个 上一节完成了babel-loader对J ...
- c3p0 配置文件的设置。解决编码乱码问题等
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <named-confi ...
- java基础-基础语法
一.标识符 java中对各种变量.方法和类等要素命名的时候使用的字符序列称为标识符. java中标识符的命名规则:1.由字母.数字.下划线(_)以及美元符号($)组成 2.标识符应该以字母或者下划线开 ...
- POJ1811(SummerTrainingDay04-G miller-rabin判断素性 && pollard-rho分解质因数)
Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 35528 Accepted: 9479 Case ...
- APP中内嵌H5页面为什么不能下载?
在APP中内嵌H5页面,若页面上存在下载链接,没有任何反应,为什么呢? 原因是app中内嵌的H5页面是WebView解析的,什么是WebView呢? 在Android手机中内置了一款高性能webkit ...
- multipartUpload上传图片到阿里云
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 水平方向margin:auto
先上图 由图可看到,块级元素的水平方向上又"7大属性":margin-left.border-left.padding-left.margin-left.width.paddi ...
- element-ui Tag、Dialog组件源码分析整理笔记(五)
Tag 标签组件 <script> export default { name: 'ElTag', props: { text: String, closable: Boolean, // ...
- Mybatis中使用循环遍历
Mybatis中传参数的方法 1.使用注解绑定,mapper.xml 对应方法 不需要指定 parameterType,(推荐使用注解绑定方式) 方法接口: List<CalculateIdea ...
- vue中监听window.resize的变化
我只想说每个人遇到的bug真的不能一概而论,解决办法也会有不同.在vue中使用echarts的时候,会想要实现window.resize窗体变化大小的时候让图形大小跟着变化.实现的过程中各种bug,也 ...