当前位置: 首页 > Web前端 > HTML

吃透XSS和CSRF

时间:2023-04-02 22:33:14 HTML

一、XSS简介XSS的全称是(CrossSiteScripting),即跨站脚本攻击。同时,为了不与层叠样式表(CSS)混淆,跨站脚本攻击简称为XSS。它是Web应用程序中的常见漏洞。攻击者在网页中注入一个客户端脚本(通常是JavaScript),当用户浏览该网页时,该脚本就会被执行,从而达到攻击的目的。2.XSS分类①反射型XSS所谓反射型就是用户在网页中输入的内容被页面提交给服务器后,服务器不把数据存入数据库,而是反射回来到页面原封不动,即无论用户输入什么内容,服务器都会原封不动地显示在页面上,从而让用户立即受到攻击。最常见的是搜索引擎。当我们搜索一个找不到的内容时,搜索引擎通常会在页面上直接提示找不到该内容。这时候,如果用户搜索的内容中包含一些攻击性的脚本,而服务器如果不对这些内容进行处理,就会受到攻击,比如:②存储型XSS(StoredXSS)所谓存储型XSS就是经过用户在网页中输入的内容通过页面提交给服务器,服务器首先将数据原封不动地保存在数据库中,当其他用户访问该网站时,从服务器读取数据,这样脚本包含in里面可以执行,所以存储的类型不会马上被攻击,而是等待其他用户访问网站。它生效了,但是因为它存储在数据库中,所以它的攻击范围更广,可以覆盖网站的所有访问者。最常见的是黑客用户提交一篇文章,然后在文章中注入一个脚本,文章就会提交到数据库中,所以其他用户访问文章的时候就会被攻击。反射型XSS和存储型XSS的区别在于看用户提交的数据是否被服务端存储。③基于DOM(DOM-basedorlocalXSS)所谓基于DOM类型是指使用的数据不经过服务器,而是直接从DOM、Window等对象中获取,比如document.location,document.URL,document.referrer,将这些数据插入到DOM中引起的XSS攻击。比较常见的是,当我们在一个网站上注册成功后,通常会跳转到一个验证页面。验证页面的内容主要包括多少秒自动跳转到某个页面,或者点击链接立即跳转到某个页面,比如:http://localhost:3000/validate.html?redirectTo=javascript:alert('xss'),我们的页面会根据传入的redirectTo的值进行跳转,比如:立即跳转还有一个客户端输入验证,当客户端检查用户输入无效时,它会在输入框后面显示用户输入的内容,并提示输入无效,如:document.getElementById("xss").innerHTML=做cument.getElementById("ipt").value;此时如果用户输入,也会发生xss攻击。基于DOM的XSS攻击的关键是数据没有经过服务器,而是来自DOM操作。到这里我们可能会有疑惑,我们使用innerText代替innerHTML是否可以避免XSS攻击呢?,其实XSS攻击与是否使用innerHTML关系不大。对于客户端页面,我们可以使用innerHTML和innerText来修改DOM的值,但是对于服务端页面,我们不需要通过innerHTML和innerText来修改DOM的值,后面会有实例演示,你就明白了。3、XSS的危害前面介绍的XSS的分类已经提到了一些XSS的危害。好像只是在用户界面上弹出几个框,并没有太大的作用。但是,漏洞所能造成的危害并不在于漏洞本身,而是取决于攻击者如何利用漏洞。如果攻击者只是利用XSS漏洞在用户页面弹出一个框,那么危害自然是很小的,但是XSS的本质是在用户页面注入客户端脚本,而客户端脚本可以做到很多东西,其中危害比较大的就是窃取用户的cookie。我们先来看看cookie被盗的严重后果。这里我们以百度网站为例:①首先打开百度网站,然后使用用户名和密码登录百度账号,如:②打开网页调试窗口下Application下的Cookies,你可以看到当前百度页面保存的cookies,用httpOnly查找Cookies,这类cookies往往比较重要,其中BDUSS与登录相关。③打开另一个浏览器,进入百度页面。此时你还没有登录。同样打开网页调试窗口,输入document.cookie="BDUSS=上一步查看的BDUSS属性值",如:④刷新页面,查看页面在登录status,发现在另一个浏览器中的百度页面也成功登录了。所以一旦攻击者通过XSS漏洞获取到用户的cookie,就可以登录用户的账号,危害会非常严重。4.XSS实例演示如果有一个搜索页面,提供一个输入框供用户搜索,当用户点击搜索按钮,进入搜索结果页面,会显示用户搜索的关键字内容和结果,如//搜索页面索引。html搜索//普通服务器代码constexpress=require("express");constsession=require("快速会话");constapp=express();app.use(session({secret:'keyboardcat',//必须设置key字符串resave:false,//每次请求重新设置sessioncookie的过期时间saveUninitialized:true,//是否保存未初始化的用户访问服务器后的session,即是否立即生成sessionname:"BDUSS",//sessionIdcookie的名称:{httpOnly:false//设置SessionId对应的cookie可以通过客户端脚本}}));app.use(express.static("public"));app.use("/search",(req,res)=>{res.send(`

你的搜索关键字是${req.query.keyword}

你的搜索结果如下:

!!!你发现了一个xss漏洞!!!

`);});app.listen(3000);服务器返回一个搜索结果页面,直接把用户的搜索关键词放在显示的页面上。可以看出服务器返回的页面并没有使用innerHTML和innerText修改DOM的值。//黑客服务器代码constexpress=require("express");constapp=express();constcookies=[];app.use("/cookie",(req,res)=>{console.log(req.query.cookie);if(req.query.cookie){cookies.push(req.query.cookie);}res.send(`

Stolenusercookie:

${cookies}`);});app.listen(4000);①现在用户可以在浏览器中输入http://localhost:3000/访问搜索页面,会生成一个sessionId放入cookie中(模拟用户有登录)。②当用户在搜索中输入黑客注入的脚本是在搜索结果页面添加一张宽高为0的图片。图片加载完成后,会向黑客的服务器发起请求http://localhost:4000/cookie,并将受害者的cookie发送给黑客的服务器。③点击搜索按钮进入搜索结果页面,如:④此时黑客在访问http://localhost:4000/cookie页面时可以看到窃取的用户cookie,如:5.XSS防御①将用于登录相关的cookie设置为httpOnly以避免被客户端脚本直接读取。对于上面提到的例子,注入的脚本会通过document.cookie读取我们的登录cookie,所以我们需要将登录cookie设置为httpOnly,如:app.use(session({secret:'keyboardcat',//Thekeystringmustbesetresave:false,//每次请求都会重置sessioncookie的过期时间saveUninitialized:true,//用户访问服务器后是否保存未初始化的session,即是否生成sessionimmediatelyname:"BDUSS",//sessionId的名称cookie:{httpOnly:true//禁止客户端通过js获取session对应的cookie}}));②过滤用户输入输出,并进行转换注入的脚本上面提到的例子,虽然通过给cookie设置httpOnly无法读取用于登录的cookie,但是如果我们输入,仍然可以弹出窗口。对于这种情况,我们需要对用户的输入进行转义,我们可以安装一个xss模块来过滤用户的输入输出,如:constxss=require("xss");//导入安装好的xss模块,用于数据过滤app.use("/search",(req,res)=>{res.send(`

你的搜索关键字是${xss(req.query.keyword)}

你的搜索结果如下:

!!!你发现了一个xss漏洞!!!

`);});转义后搜索结果页面显示如下:六、CSRF简介CSRF全称For(Cross-SiteRequestForgery),即跨站请求伪造,也称为OneClickAttack,一键式攻击,因为它通常会诱使用户点击图片或链接。当用户点击这个图片或链接时,这个链接通常包含一些攻击性的动作和参数,也就是所谓的伪造请求,会以用户的身份向服务器发起这个伪造的请求。服务器收到伪造的请求后,会认为是用户允许的操作,导致用户数据丢失等。由于CSRF是伪造用户请求,以用户身份向服务器发起请求,会导致用户丢失数据。因此,用户必须先登录获取相应的登录cookie,伪造的请求才会生效,导致用户数据丢失。因此,CSRF攻击的前提条件是:用户首先要登录一个可信的网站,并在本地生成相应的cookie;用户在未退出的情况下访问危险网站;7.CSRF示例和危害如果用户登录一个网站,并在该网站上发表了多篇文章,然后在没有退出的情况下访问了一个危险网站,然后点击了该危险网站中的一个链接,导致其发表的所有文章被删除.①用户先登录。这里只是为了模拟用户登录,所以直接为其设置了一个用户名,如:app.use("/login",(req,res)=>{req.session.user="lihb";//模拟用户登录,直接设置一个用户名res.send(`

登录成功,欢迎回来${req.session.user}!

`);});用户在浏览器中输入并访问http://localhost:3000/login,然后显示用户登录成功页面。②登录成功后,访问http://localhost:3000/articles可以查看发布的文章。letarticles=[//模拟用户文章数据{id:1,title:"Thisisarticletitle1",content:"Thisisarticlecontent1"},{id:2,title:"Thisisarticletitle2",content:"这是文章内容2"}];app.use("/articles",(req,res)=>{if(req.session.user==="lihb"){if(articles.length>0){consttemplate=articles.map((article)=>{return`

${article.title}

${article.content}

`}).join("");res.send(`

${req.session.user}发布文章:

${template}`);}else{res.send(`

${req.session.user}还没有发表文章。

`);}}else{res.send(`

请先登录

`);}});③服务器有一个http://localhost:3000/deleteAll请求,可以直接删除所有文章,如:app.use("/deleteAll",(req,res)=>{if(req.session.user==="lihb"){articles=[];res.send(`

${req.session.user}的文章被清除

`);}else{res.send(`

请先登录

`);}});④然后访问了一个危险网站http://localhost:4000/csrf.html,该危险网站包含一个诱饵链接,会诱导用户点击,这个链接对应的地址就是删除所有文章的链接,一旦用户点击这个链接,所有发表的文章都会被删除。
点击领取爱奇艺会员
⑤用户点击上面链接后显示页面如下:⑥此时再次访问http://localhost:3000/articles,发现文章全部被删除,导致用户数据丢失。至此,模拟了一次CSRF攻击。需要注意的是,这只有在用户已经登录的情况下才会成功,如果我们在没有登录的情况下访问http://localhost:4000/csrf.html页面,则攻击无效,会提示用户登录infirst,如:8.CSRF防御CSRF攻击成功的关键是服务器无法识别该请求是否被用户授权。所以为了防御CSRF攻击,我们需要让服务器知道请求的真实性。常用的方法有以下几种:①增加token校验:用户登录成功后,服务器端生成一个token返回给客户端。客户端收到令牌后,将其存储在cookie或localStorage中。cookie和localStorage都不能跨域访问,所以攻击者无法拿到里面的数据,然后每次请求都带上这个token,服务器验证token成功后才会响应请求。②验证请求头的referer属性值:对于点击网站(不是网站本身)链接后发起的请求,请求头会携带referer属性,即点击链接所在网站的url地址位于。所以我们可以根据请求头的referer属性来判断这个请求是否来自这个网站。如果不是,则可以识别为CSRF攻击,如:app.use("/deleteAll",(req,res)=>{//添加headerreferer的请求验证if(req.headers.referer&&!req.headers.referer.includes("http://localhost:3000")){res.send(`

这是一个CSRF请求,已被拦截

`);return;}if(req.session.user==="lihb"){articles=[];res.send(`

${req.session.user}'sarticlesareClear

`);}else{res.send(`

请先登录

`);}});