安全这种东西就是不发生则已,一发生则惊人。作为前端,平时对这方面的知识没啥研究,最近了解了下,特此沉淀。文章内容包括以下几个典型的 web 安全知识点:XSS、CSRF、点击劫持、SQL 注入和上传问题等(下文以小王代指攻击者),话不多说,我们直接开车🚗(附带的例子浅显易懂哦😯)。
XSS 中文叫做跨站脚本攻击。
一句话解释:小王在网页中注入恶意代码,当用户访问页面时,代码会自动运行。
具体点说:凡是在页面中可输入的地方(如地址栏、搜索框和评论区等等)都有隐藏的风险,小王可以在这些地方输入一些特殊的代码(形如 <script>alert(1)</script>
),于是乎本来只是单纯的文本变成了可执行的代码,从而造成了攻击。你可能会觉得 alert(1)
能有多大点事,但把它换成别的威力就不一样了,它可以重定向到一个由小王控制的页面、冒充用户发送请求、窃取用户信息发送到小王的服务器上等等。当然了,这还不够具体,例子才是最直白的👇。
因为 XSS 攻击有反射型、存储型和 DOM 型三种类型,所以我们每种都举个简单的栗子🌰:
反射型 XSS 主要有以下两个步骤:
www.a.com/?name=hh
页面,后端会把其中的 name
参数取出来并拼接到 html 中(形如 <p>你好啊,hh</p>
)返回给用户。www.a.com/?name=hh<script>alert(1)</script>
页面,此时后端会返回形如 <p>你好啊,hh<script>alert(1)</script></p>
这样的一个 html,其中的 script 脚本就会在我们的浏览器上加载执行,从而造成攻击。你可能会觉得这种 url 看起来就有嫌疑,我们一般不访问,但如果把这个 url 转成一个短网址(所谓短网址就是把 url 转成一个 看起来简约又正常的链接),并在网上散播(通常伴随一些美女图片、外挂和金钱💰等一些具有诱惑力的内容),从而骗取用户点击这个 url,造成攻击。所以日常生活中不要乱扫二维码、乱点链接。
当然了,拼接的形式多种多样:
拼接前 | 拼接字符串 | 拼接后 |
---|---|---|
<div>#{msg}</div> | <script>alert(1)</script> | <div><script>alert(1)</script></div> |
<img src="#{image}" /> | 1" onerror="alert(1) | <img src="1" onerror="alert(1)" /> |
var data = "#{data}" | hello";alert(1);" | var data = "hello";alert(1);"" |
这种类型一般出现在评论区、论坛、留言等类似的地方,基本流程是小王提交了一个恶意评论(就是包含一些恶意代码,和上面类似,形如这样的评论 <img src="1" onerror="alert(1)" />
),只不过该评论被保存到了数据库中,而评论对大家又都是可见的,所以任何用户访问该页面时,恶意代码就会从数据库中取出,拼接在 html 中返回给用户,页面加载评论的同时也执行了其中的恶意代码。与反射型相比,存储型的辐射范围更加广泛,处理起来也较为麻烦,有时还需要查好多库删好几张表。
典型的例子就是你连接了一个公共 wifi,浏览页面的时候在底部或者四周有时会有一些小广告的出现,因为这种网络劫持会动态修改页面的内容,比如在 html 中追加一些广告或暗链(暗链就是偷偷加入几个 a 标签,一般可用来增加搜索排名),要注意的是这种攻击是不涉及到服务器的,它的核心是动态修改 dom。
总的来说就是页面可输入或拼接显示的地方就可能会有潜在的风险。我们演示个小的 demo,虽然实际上不是这样的😂,但意思到了: 当我们第一次输入 <script>alert(1)</script>
的时候,alert
不生效是因为 H5 中规定用 innerHTML
插入的 script 将不被执行,但是我们可以写别的,比如 <img src='x' onerror="alert(1)">
,此时 alert 就被执行了,这个在 MDN 上有明确的说明,这里给大家截图看一下👀: 作为前端平时要注意 innerHTML 等一些有字符串拼接并展示的地方。
一般来可以使用编码或转义的方式来防御 XSS 攻击,就像下面这样:
function escape(str) {
if (!str) return ''
str = str.replace(/&/g, '&')
str = str.replace(/</g, '<')
str = str.replace(/>/g, '>')
str = str.replace(/"/g, '"')
str = str.replace(/'/g, ''')
return str
}
对于富文本内容,因为其需要保留 html,所以不好直接使用转义的方法,通常使用白名单过滤(就是允许特定的 html 标签和属性),以抵御 XSS 攻击。当然了更不要相信用户的任何输入,对用户的输入进行特殊字符(如尖括号)的检查也是有必要的。
这个其实就是设置个响应头信息(Content-Security-Policy
),告诉浏览器哪些资源是可加载执行的(实质就是白名单制度),为对应的内容指定相应的策略。具体设置大家可以查阅 MDN,这里截个 github 的图作为示例: 或者加个 meta 标签:
<meta http-equiv="Content-Security-Policy" content="img-src 'self';">
CSRF 中文叫做跨站请求伪造。 一句话解释:小王盗用你的身份,以你的名义发送恶意请求(发邮件、转账之类的)。
这个没有分类,所以我们直接上栗子🌰:
https://www.a.com/index.php?money=100&to=xx
,这个请求能够把 100 块转到 xx 同学的账户上。<img src="https://www.a.com/index.php?money=100&to=wo">
这样的标签,于是浏览器就会自动发起一个转账请求,并且这个请求会携带上 a 网站的 cookie(即便这个标签根本不在 www.a.com 内),所以能请求成功。CSRF 攻击通常有以下两个特点:
针对以上两点我们可以有以下几种预防措施:
因为请求头中的 referer 记录了请求的来源地址,referer 会指向 b 网站,所以我们可以对 referer 进行检测,以此来禁止来自第三方网站的请求。 但每个浏览器对于 referer 的具体实现可能有差别,也不能保证浏览器自身没有安全漏洞。在有些情况下,攻击者甚至可以隐藏、修改自己请求的 referer。另外 origin 也是一样的道理(origin 只包含了域名信息,不包括具体的 url 路径)
由于 CSRF 是利用了浏览器自动携带 cookie 的特性,所以我们可以多加一个校验的字段(不通过 cookie 传递),简单点说就是:
至于 token 是啥,这里简单说明以下,其实它是个字符串,你可以当做个临时 id,一般由 userId、随机数、时间戳通过散列算法得到(形如:let token = md5('userId' + 'time' + 'Math.random() + '...')
,其实就是调用一个函数)。
加验证码的本质和 token 是一样的,这两种类型的原理都是在 cookie 之外的某个地方多增加一个字段供后端校验,这里增加的字段就是验证码。这样一来第三方只能携带上 cookie 但是带不上这个验证码字段,也就预防了 csrf 攻击。
可以通过设置 SameSite 的值来禁止第三方网站携带 cookie。SameSite 有三个值可以设置:Strict、Lax、None。具体作用如下:
Set-Cookie: CookieName=CookieValue; SameSite=Strict;
这个比较好理解,我们直接看例子: 其实就是通过覆盖不可见的页面,诱导用户点击而造成的攻击行为。稍微高级一点的伪装可以怎么样呢,就是做成一个游戏界面,让你在页面上狂点,而实际上呢,则会触发一些攻击事件,比如打开摄像头、发送邮件之类的。至于我们为什么会点击,因为骗子通常知道你想要什么😎,好奇心也驱使你这样做,并且我们当时并不觉得会有什么危险,所以我们都愿意试试看。
让自己的网站不要被目标网站内嵌,可以通过 js 和设置头部 X-Frame-Options 实现:
if (top.location !== window.location) top.location = window.location
setHeader('X-Frame-Options', 'DENY')
增加攻击成本。
因为这个和 XSS 有点小像,所以在这里稍微提及一下😯。
一句话解释:小王利用潜在的数据库漏洞访问或修改数据。
select * from user where username = '${data.username}' and pwd='${data.pwd}'
,并返回登录成功。1' or '1'='1
,结果后端一拼接 SQL 语句就变成了 select * from user where username = 'xiaowang' and pwd = '1' or '1'='1'
,显然这是成立的,也会返回成功。是不是和 XSS 的拼接漏洞很像呢,本来是数据的东西变成程序执行了。
以下内容可跳过,仅作为了解:
一句话解释:上传的文件被当做程序解析执行。
<?php
phpinfo();
?>
if (ext === 'js') throw new Error('xxx')
if (file.type !== 'images/png') throw new Error('xxx')
DoS(Denial of Service)攻击就是利用合理的服务请求来占用过多的服务资源,从而使得合法用户无法得到服务的响应。比如 SYNflood 攻击、IP 欺骗、带宽DoS攻击、塞满服务器的硬盘等攻击手段,这个作为了解就行,具体可自行百度。
主要都是提高攻击门槛:
没有绝对安全的网站,我们要做的就是提高攻击成本,问题的关键也不在于小王能不能破译,而是值不值得,毕竟付出与收获不成正比,谁愿意倒贴呢?🙌
😝朋友们如果有需要全套《黑客&网络安全入门&进阶学习资源包》,可以扫描下方二维码免费领取
点击链接也可直接获取 CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
同时每个成长路线对应的板块都有配套的视频提供:
因篇幅有限,仅展示部分资料
因篇幅有限,仅展示部分资料
上述所有资料 ?? ,朋友们如果有需要全套 📦《网络安全入门+进阶学习资源包》,可以扫描下方二维码免费领取 🆓
点击链接也可直接获取 CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享