XSS,即为(Cross Site Scripting),中文名为跨站脚本,跨站脚本的重点不在“跨站”上,而在于“脚本”上。大多数XSS攻击的主要方式是嵌入一段远程或者第三方域上的JS代码,实际上是在目标网站的作用域下执行了这段第三方域上的js代码。
特点:就像镜子反射一样,浏览器发射含XSS的url,服务器将其反射回来
浏览器发生请求时,XSS代码出现在请求URL中,作为参数提交到服务器,服务器解析并响应,响应结果中包含XSS代码,最后浏览器解析并执行。案例:表单提交
//test.html <body> <textarea name="txt" id="txt" cols="80" rows="10"> <button type="button" id="test">测试</button> <script> var test = document.querySelector('#test') test.addEventListener('click', function () { var url = `/test?test=${txt.value}` //1.发送一个GET请求 var xhr = new XMLHttpRequest() xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) { // 3\. 客户端解析JSON,并执行 var str = JSON.parse(xhr.responseText).test var node = `${str}` document.body.insertAdjacentHTML('beforeend', node) } else { console.log('error', xhr.responseText) } } } xhr.open('GET', url, true) xhr.send(null) }, false) </script> </body> 复制代码 //server.js var express = require('express'); var router = express.Router(); router.get('/test', function (req, res, next) { // 2.服务端解析成JSON后响应 res.json({ test: req.query.test }) }) 复制代码现在我们通过给textarea添加一段有攻击目的的img标签:
<figure>[图片上传中...(image-f8c94b-1540438754800-6)]
<figcaption></figcaption>
</figure>
点击<测试>按钮,一个XSS攻击就发生了。下面图片中是获取了本地的部分cookie信息:
<figure>[图片上传中...(image-67f5f4-1540438754800-5)]
<figcaption></figcaption>
</figure>
上面只是模拟攻击,通过alert获取到了个人的cookie信息。一般黑客会注入一段第三方的js代码,然后将获取到的cookie信息存到他们的服务器上,拿到我们的身份认证做一些违法的事情了。
特点:黑客将XSS代码发送给服务器,然后通过服务器散播
黑客将XSS代码发送到服务器(不管是数据库、内存还是文件系统等。)其他人请求页面的时候就会带上XSS代码了。案例:最典型的就是留言板XSS。
黑客提交了一条包含XSS代码的留言到数据库。当目标用户查询留言时,那些留言的内容会从服务器解析之后加载出来。浏览器发现有XSS代码,就当做正常的HTML和JS解析执行。XSS攻击就发生了。特点:DOM XSS代码不需要服务器端的解析响应的直接参与,而是完全通过浏览器端的DOM解析。
浏览器的代码中含有eval,new Function等将字符串内容执行的代码在执行的字符串中嵌入可以执行XSS代码字符串 案例: test.addEventListener('click', function () { var node = window.eval(txt.value) window.alert(node) }, false) //txt中的代码如下: <img src='null' onerror='alert(123)' /> 复制代码XSS攻击可以看出,不能原样的将用户输入的数据直接存到服务器,需要对数据进行一些处理:
过滤危险的DOM节点。如具有执行脚本能力的script, 具有显示广告和色情图片的img, 具有改变样式的link, style, 具有内嵌页面的iframe, frame等元素节点。过滤危险的属性节点。如on-, style, src, href等对cookie设置httpOnly,但是也会导致前台无法操作cookie,不太推荐。CSRF(Cross-site request forgery),中文名称:跨站请求伪造,攻击者盗用了你的身份,以你的名义发送恶意请求。
<figure>[图片上传中...(image-1010c6-1540438754800-4)]
<figcaption></figcaption>
</figure>
特点:
登录受信任网站A,并在本地生成Cookie。在不登出受信任网站A的情况下,访问危险网站B。危险网站会向受信任A的网站发送请求,同时会携带受信任网站A本地生成Cookie(用同一个浏览器访问同一个域的接口)案例:
//钓鱼网站,利用用户的cookie进行权限操作转账 <body onload="steal()"> <iframe name="steal" display="none">    <form method="POST"name="transfer" action="http://www.myBank.com/Transfer.php">      <input type="hidden" name="toBankId" value="11">       <input type="hidden" name="money" value="1000">     </form>   </iframe> </body> 复制代码Token的特点
session是通过cookie传输的,每次访问网站都会自主的带上,所以存在安全问题和浪费带宽,token存储在localstorage,可以选择性发送给后台,由于同源策略,安全性高session在集群服务器中很难实现共享,服务器必须存在一份sessionq清单,token不需要存储清单,共用一个密钥,发送token可以实现共享session销毁后会从清单消失,token的注销不好实现,没有清单证明这个token不能用,所以得用一个黑名单来标注JWT
jwt是实现token的一种方式,一个token分3部分,3部分之间用“.”号做分隔:
header:头部为base64字符串payload:载荷为base64字符串signature:签证 hader+payload经过key加密得出EXP:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
JWT原理: let jwt = { //解码 decode(token,secret){ let [header,content,sign] = token.split('.'); let h = JSON.parse(this.formBase64ToString(header)); let c = JSON.parse(this.formBase64ToString(content)); if(sign !== this.sign([header,content].join('.'),secret){ throw new Error ('Not allowd') } return c }, //加码 encode(payload,secret){ let header = this.toBase64(JSON.stringify({'type':'JWT',alg:'HS25' })); let content = this.toBase64(JSON.stringify(payload)); let sign = this.sign([header,content].join('.'),secret); return [header,content,sign].jion('.'); } //转换为base64 toBase64(str){ return Buffer.from(str).toString('base64'); } //签名 sign(str,secret){ return require('crypto').createHmac('sha256',secret).update(str); } } module.exports = jwt; 复制代码 JWT后台: const express = require('express'); const bodyParser = require('body-parser') const jwt = require('jwt-simple') const userList=[ {id:1,username:'kbz',password:'123456'} ] const SECRET = 'MISS'; let app = express(); app.use(bodyParser.json); //因为请求头中有Authorization字段,这和跨域时要设置name传参数一样,可以参考: //前端必须懂的计算机网络知识—(跨域、代理、本地存储) //https://juejin.im/post/5bb1cc2af265da0ae5052496 app.use(function(req,res,next){ res.setHeader('Access-Control-Allow-Origin',"*"); res.setHeader('Access-Control-Allow-Headers',"Content-Type,Authorization"); res.setHeader('Access-Control-Allow-Methods',"GET,POST,OPTIONS"); if(req.method === 'OPTIONS'){ res.end(); } next(); }) //登陆时发送token app.post('/login',function(req,res,next){ let user = req.body; userList.find(person=>(person.id === user.id)); if(user){ jwt.encode({ id:user.id, username:user.username },SECRET) res.json({ code:0, data:{ token } }) }else{ res.json({ code:1, data:'用户不存在' }) } }) // 需要验证权限,则取token验证 // 请求头Authorization:Bearer token app.get('/order',function(req,res,next){ let authorization = req.headers['authorization']; if(authorization){ let token = authorization.split(' ')[1]; try{ let user = jwt.decode(token,SECRET); req.user = user; }catch(e){ res.status(401).send('Not Allowed') } }else{ res.status(401).send('Not Allowed') } }) app.listen(3000); 复制代码 JWT前台 //login.html <input type="text" id='username' class="form-control"> <input type="text" id='password' class="form-control"> <span onclick='login()'></span> <scrpipt> axios.post('/user').then(res=>{ localStorage.setItem('token',res.data.data.token) location.href='/order' }) </script> //order.html <scrpipt> axios.interceptors.request.use(function(config){ let token = localStorage.getItem('token'); if(token){ config.headers.Authorization = 'Bearer '+ token } }) axios.get('/order').then(res=>{ console.log(res); }) </script> 复制代码TLS/SSL的功能实现主要依赖于三类基本算法:
非对称加密实现身份认证和密钥协商
对称加密算法采用协商的密钥对数据加密
散列函数验证信息的完整性,针对于密钥泄露的不安全性
<figure>[图片上传中...(image-cd5446-1540438754799-1)]
<figcaption></figcaption>
</figure>
结合三类算法的特点,TLS 的基本工作方式:
客户端使用非对称加密与服务器进行通信,实现身份验证并协商对称加密使用的密钥然后对称加密算法采用协商密钥对信息以及信息摘要进行加密通信,不同的节点之间采用的对称密钥不同,从而可以保证信息只能通信双方获取<figure>[图片上传中...(image-88286d-1540438754799-3)]
<figcaption></figcaption>
</figure>
<figure>[图片上传中...(image-f99f09-1540438754799-2)]
<figcaption></figcaption>
</figure>
由于非对称加密无法确保服务器身份的合法性,存在中间人攻击的风险,例如:
客户端 C 和服务器 S 进行通信,中间节点 M 截获了二者的通信
节点 M 自己计算产生一对公钥pub_M和私钥 pri_M
C 向 S 请求公钥时,M 把自己的公钥pub_M发给了 C
C 使用公钥pub_M加密的数据能够被M解密,因为M掌握对应的私钥pri_M,而C无法根据公钥信息判断服务器的身份,从而 C 和 M 之间建立了“可信”加密连接
中间节点 M 和服务器S之间再建立合法的连接,因此 C 和 S 之间通信被M完全掌握,M 可以进行信息的窃听、篡改等操作。
<figure>[图片上传中...(image-512949-1540438754799-0)]
<figcaption></figcaption>
</figure>
服务方 Server 向第三方机构CA提交公钥、组织信息、个人信息(域名)等信息并申请认证;CA通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等;如信息审核通过,CA会向申请者签发认证文件-证书。证书包含以下信息:申请者公钥、申请者的组织信息和个人信息、签发机构CA的信息、有效时间、证书序列号等信息的明文,同时包含一个签名; 签名的产生算法:首先,使用散列函数计算公开的明文信息的信息摘要,然后,采用CA的私钥对信息摘要进行加密,密文即签名;客户端 Client 向服务器 Server 发出请求时,Server 返回证书文件;客户端 Client 读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后,利用对应 CA的公钥解密签名数据,对比证书的信息摘要,如果一致,则可以确认证书的合法性,即公钥合法;客户端还会验证证书相关的域名信息、有效时间等信息;客户端会内置信任CA的证书信息(包含公钥),如果CA不被信任,则找不到对应 CA的证书,证书也会被判定非法。客户端的证书从生产出来之后就内置在主机中搭建一个HTTPS服务器
前端必须懂的计算机网络知识系列已经全部结束,欢迎大家研究讨论!
作者:梦想攻城狮 链接:https://juejin.im/post/5bb2d1c1e51d450e5162a865 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。