WEB开发的安全之旅 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的的第6天
Web安全一窥
web安全问题其实比我们想象的常见的多,在我老师经常使用的一个文件管理平台就有很严重的XSS漏洞,而且至今也没解决,steam的免费变强💴bug也是很好的例子
两个角度看Web安全
hacker——攻击
Cross-Site Scripting(XSS)
通过恶意脚本的注入完成攻击
XSS=
盲目信任用户的提交内容+
string->Dom
document.write
element.innerHtml=anyString;
SSR(user_data)//伪代码
特点
- 通常XSS难以从UI上感知,暗地的执行脚本
- 窃取用户信息(cookie/token)
- 绘制UI(弹窗、广告),诱骗用户点击、填写表单
demo
public async submit(ctx){
const { content, id } = ctx.request.body;
//没有对content的内容进行过滤便直接提交
await db.save({
content,
id
})
}
public async render(ctx){
const { content } = await db.query({
id:ctx.query.id
})
//获取数据也没与对content进行过滤便直接渲染到页面上
ctx.body=`<div>${content}</div>`
}
fetch("/submit",{
body:JSON.stringfy({
id:"1",
content:`<script>alert("XSS");</script>`
})
})//黑客就可以通过修改ctx.body的内容将脚本注入到页面,并在服务器端渲染到这一段内容时便会执行该脚本,完成攻击
XSS类型
-
Stored XSS
- 恶意脚本被存在数据库中
- 访问页面->读取数据===被攻击
- 危害最大,对所有用户攻击
-
Reflected XSS
- 在服务端完成注入但是不涉及数据库
- 从URL上完成攻击
-
Dom-based XSS
- 完全在浏览器端完成攻击
- 攻击形式类似与Reflected XSS
-
Mutation-based XSS
-
利用浏览器渲染DOM的特性(独特优化)
-
不同的浏览器会有区别,按浏览器进行攻击
-
例:
<noscript><p title="</noscript><img> src=x onerror=alert('XSS')>">过滤工具🔬会认为他是一个p标签的普普通通的title属性
但事实上在chrome中运行会发现他构建的Dom树是这样子的
以一种巧妙的方式达成了执行脚本的目的
-
Cross-site request forgery(CSRF)
特点
- 在用户不知情的前提下
- 利用用户的权限(cookie)
- 构造指定的HTTP请求,窃取或修改用户的敏感信息
Demo
- 用户没有访问银行页面
- 而已页面利用保存在本地的cookie,请求银行中的特定接口
- 请求执行成功
-
GET
<a href="https://bank.com/transfer?to=hacker&amount=100">点我抽奖</a>黑客通过伪装按钮,点击即可发起请求
<img style="display:none" src="https://bank.com/transfer?tohacker&amount=100"/>用户只要访问带有这样子的img标签的页面便会发起请求
-
beyond GET
<form astion="https://bank/transfer_tons_of_money" method="POST"> <input name="ampunt" value="100000000000" type="hidden"/> <input name="to" value="hacker" type="hidden"/> </form>通过藏的表单,伪装成用户发送post请求
Injection
SQL Injection
特点
- 在请求中恶意注入sql参数
- 服务端直接运行参数
- 数据库危险
demo
public async renderForm(ctx){
const { username , form_id } = ctx.query;
const result = await sql.query(`
SELECT a, b, c FROM table
WHERE username = ${username}
AND form_id = ${form_id}
`);
ctx.body = renderFoem(resut);
}
- 读取请求字段
- 直接以字符串形式拼接SQL语句
fetch('/api',{
method:"POST",
headers:{
"Content-type":"application/json"
},
body:JSON.stringfy({
username:"any;Droup Table table;",
})
})
- 达成删库跑路成就恭喜🎉
Injection 不止于 SQL
Demo2
public async convertVideo(ctx){
const { video , options } = ctx.request.body;
exec(`convert-cli ${video} -o ${options}`);//options字段未进行过滤
ctx.body = 'ok!';
}
fetch("/api",{
method:"POST",
body:JSO.stringfy({
options:`'&& rm -rf xxx'`
})
})
直接删除服务器的某些文件
Server-Side Request Forgery(SSRF)
特点
- 由攻击者构造,由服务端发起请求的一个网络攻击
- 一般用来在外网探测或攻击内网服务
demo
public async webhook(ctx){
//callback 可能是内网 url
// e.g https://secret.com/get_employ_payrolls
cts.body=await fetch(ctx.query.callback);
}
- 请求【用户自定义】的callback URL
- web server 通常有内网访问权限
Denial of Service(Dos)
通过某种方式(构造特定请求),导致服务器资源被显著消耗,来不及相应更多请求,导致请求被积压,进而雪崩效应
插播:正则表达式——贪婪模式
重复匹配时[?] vs [no ?]:满足一个即可 vs 尽量多
ReDos:基于正则表达式的Dos
- 利用正则表达式中的贪婪模式产生的回溯行为
Distributed Dos(DDos)
短时间内,来自大量僵尸设备的请求流量(只负责发送请求),纯粹的量大,直接访问ip的任意api,消耗大量带宽
中间人攻击
原因
- 明文传输
- 信息篡改不得而知
- 对方身份未验证
Developer——防御
XSS
- 永远不要相信用户的提交内容
- 永远不要将用户提交的内容直接转换成Dom
工具
-
服务端
- 前端框架默认防御XSS
- google-closure-library
-
服务端
- npm包(DomPurify)
-
耗子尾汁
- string->dom:转义过滤!
- 上传svg:扫描过滤!
- 自定义跳转链接:尽量别,做过滤!
- 自定义样式:过滤!
-
Content Security Policy(CSP)
- 域名白名单
- 域名黑名单
- 对eval + inline script 说 哒咩🚫
CSRF
-
if ’伪造请求‘ === ’异常来源‘ then ‘限制请求来源’ -> '限制伪造请求'
- 对origin和referer的内容进行校验(例:同源请求中,Get请求不发送head)
-
现有页面再有请求
- token
-
X-Frame-Options:DENY/SAMEORIGIN->iframe攻击模式
-
GET!==POST&GET->anti-pattern
-
避免用户信息被携带:SameSite Cookie
Injection
-
sql
- 找到项目中查询sql的地方,使用Perpared Statement
-
beyond sql
- 最小权限原则
- 建立允许名单+过滤
- 对URL类型参数进行协议、域名、IP等限制
Dos
-
Regex Dos
- Code Review,不要出现被人回溯的regex
- 代码扫描,正则性能测试
- 拒绝用户提供正则的方式
-
DDos
- 流量治理(过滤:负载均衡、API网关,抗量:CDN、快速扩容、非核心服务降级)
中间人攻击
- https
- Subresource Integrity(SRI)——资源篡改
总结
安全无小事,我这学期期末的时候就有大作业就要完成了,两天没备份数据库然后就出现了数据库被删,就留下一条付钱还原的记录的惨痛经历,以至于我们又额外花了两天时间去还原数据库,加强安全防护,以及备份,必须对安全加以重视,学习相关知识,保持学习心态完善自己的防范手段