Web前端安全之安全编码原则
随着Web和移动应⽤等的快速发展,越来越多的Web安全问题逐渐显⽰出来。⼀个⽹站或⼀个移动应⽤,如果没有做好相关的安全防范⼯作,不仅会造成⽤户信息、服务器或数据库信息的泄露,更可能会造成⽤户财产的损失,因此Web安全问题需要引起⼴⼤开发者的重视。接下来的⼏篇⽂章中,将会对Web常见的⼀些攻击以及相关的防范⽅法进⾏详细的介绍。
系列⽂章:
Web前端安全之安全编码原则
web端登录Web前端安全之跨站脚本攻击(XSS)
Web前端安全之跨站请求伪造(CSRF)
Web前端安全之点击劫持
Web前端安全之⽂件上传漏洞
Web前端安全之任意URL跳转漏洞
本⽂主要介绍了Web前端开发中需要遵守的⼀些安全编码原则,将会对Web安全以及安全编码原则进⾏介绍,欢迎⼤家交流讨论~
1. Web安全
在学习常⽤的Web安全编码原则以及掌握常见的攻击防范⽅法之前,我们有必要先了解⼀下什么是Web安全,以及我们⾯临的Web漏洞或攻击通常有哪些。
1.1 什么是Web安全
随着Web2.0、社交⽹络和移动应⽤等产品的诞⽣,越来越多的信息都被放到互联⽹应⽤上展⽰,⽽Web的快速发展也引起了⿊客们的强烈关注。⿊客们通常会利⽤操作系统或Web存在的漏洞,对各种各样的互联⽹应⽤发起攻击,轻则篡改⽹页内容,重则盗取重要内部数据,并使得应⽤访问者受到侵害。因此,作为Web应⽤的开发者,我们需要了解⽹站或应⽤中可能存在的漏洞,并且对各种可能遭到的攻击提前做好防范。
1.2 Web常见的漏洞
在前端⾯试中,我们可能经常会被⾯试官问到这个问题,“从在浏览器地址栏输⼊url到页⾯展⽰在我们⾯前,这个过程中发⽣了什么?",相信很多同学都能够很快回答上来。但是如果⾯试官问,"从在浏
览器地址栏输⼊url到页⾯展⽰在我们⾯前,这个过程可能存在哪些漏洞或者会遭到哪些攻击?”,可能就会难住很多同学了。下⾯给出了⼀个图,展⽰了Web中常见的⼀些漏洞。
总的来说,我们在开发Web⽹站或应⽤的过程中,可能⾯临的Web安全威胁或漏洞包括以下这些:
XSS跨站脚本攻击
CSRF漏洞
点击劫持
⽂件上传漏洞
任意URL跳转漏洞
SQL注⼊
命令注⼊
XXE漏洞
SSRF漏洞
逻辑漏洞
信息泄露
......
⾯对这么多漏洞或攻击,我们能够做的,就是在进⾏架构设计或功能开发时,就应当全⾯考虑⽤户、APP/浏览器、后台服务器以及各层通讯之间可能存在的安全问题,并且开展安全防护设计,提前做好防范⼯作。
由于笔者是前端开发,因此也会重点关注前端的内容,也就是和前端较为相关的漏洞。接下来,将会对前端开发中常⽤的⼀些安全编
码原则进⾏介绍,并且在后续的⽂章中,也会对上述漏洞中的前5个漏洞的攻击和防范进⾏详细的介绍。
2. 安全编码原则
接下来,将会介绍⼀些常⽤的安全编码⽅法,帮助我们编写符合安全规范的代码。
2.1 登录注册安全
当⽤户想要访问我们⽹站或应⽤时,通常需要做的第⼀步就是进⾏注册和登录。⽽实现登录注册功能时如果没有做好安全防范,很可
能会造成⽤户账户密码信息被盗取。因此,下⾯主要总结了在实现登录注册功能时需要注意的⼀些安全要点。
(1)注册时账户密码要求
注册时需要限制⽤户名合法字符和长度,密码需要禁⽌使⽤弱⼝令,密码长度应当⼤于8位且包含⼤⼩写字母,数字及特殊字符。
(2)登录失败时提⽰要求
登录失败时不应返回详细提⽰⽤户名不存在,防⽌猜解⽤户名。
(3)增加验证码机制
单个⽤户⼝令失败3次后应有验证码机制出现,验证码每校验过⼀次应当⽴即失效防⽌验证码重⽤。
(4)不在常⽤地登录时需要增加⾝份验证
当⽤户登录成功时,后台应该记录⽤户的⽤户名、IP和时间,当尝试登录IP不在历史常登录IP地理位置时,应进⾏多因素⼆次验证⽤户⾝份,防⽌⽤户因密码泄露被盗取账户。
(5)Cookie安全
Cookie中通常会包含⽤户的登录态标识,因此为了保障Cookie的安全,需要设置HttpOnly属性以防⽌
被XSS漏洞/JavaScript操纵泄露。此外,实现全站HTTPS后,Cookie应当设置secure属性,使得浏览器仅在安全加密连接时才能传送使⽤该Cookie。
2.2 访问控制
当⽤户成功到登录⽹站或应⽤之后,接下来就可以开始访问相关的页⾯。但是我们的系统中通常包含不同⾝份的⽤户,⽐如有超级管理员、普通管理员、教师和学⽣等⾝份等,⽽不同⾝份的⽤户可以访问的页⾯应该是不⼀样的,因此我们还需要做好访问控制。
(1)权限控制
⽆论是Web页⾯还是对外的HTTP API接⼝,在系统设计之初就需要考虑⾝份验证和权限校验机制。除了官⽹静态页或新闻页等公开页⾯之外,当⽤户访问其它页⾯时,都需要添加权限校验机制,仅有权限的⽤户才能访问相应的服务和数据,防⽌⽔平越权和垂直越权。
如下⾯代码所⽰,给出了使⽤Vue进⾏权限控制的⼀个例⼦,我们可以通过添加全局拦截路由,在⽤户进⼊页⾯前先对⽤户⾝份进⾏判断,如果该⽤户有权限,才让⽤户访问对应页⾯。
router.beforeEach(async (to, from, next) => {
// 先判断⽤户是否登录
checkIfLogin();
// 若⽤户登录成功,需要拉取该⽤户的信息
getUserInfo();
// 上⾯两个步骤完成之后,需要判断⽤户的权限
if (le === 1 || le === 2) {
next();  // 跳转到⽤户想要访问的页⾯
} else {
alert('您没有权限访问该页⾯);
next('/'); //跳转到默认页⾯
}
});
2.3 输出转义
经过登录以及访问权限的校验,⽤户就可以访问到他们想看的页⾯了。⽽如Web⽹站的页⾯通常是需要经过浏览器的渲染才能最终显⽰在⽤户⾯前,但是在这个过程中,可能也会被⿊客注⼊如XSS的攻击,因此对于输出到⽹页上的数据我们也需要进⾏安全防护,也就是对页⾯上的数据输出进⾏转义编码。
(1)转义编码
使⽤HtmlEncode转义特殊字符,⽐如将“>","<",单引号或双引号等特殊字符进⾏转义,可以避免从HTML节点内容、HTML属性或JavaScript注⼊⽽产⽣的XSS攻击。下⾯给出了⼀个例⼦,可以实现特殊字符的转义。
const htmlEncode = function (handleString){
return handleString
.replace(/&/g,"&")
.replace(/</g,"<")
.replace(/>/g,">")
.replace(/ /g," ")
.replace(/\'/g,"'")
.replace(/\"/g,""");
}
2.4 输⼊限制
除了输出的转义编码之外,对于⼀些需要⽤户提交信息的地⽅如表单,我们也需要对⽤户的输⼊进⾏校验和过滤,防⽌攻击者通过利⽤XSS等漏洞向服务器或数据库注⼊恶意脚本。
(1)输⼊校验
对于不可信的输⼊来源都需要进⾏数据校验,从⽽判断⽤户的输⼊是否符合预期的数据类型、长度和数据范围。有效的输⼊验证⼀般需要基于以下两点原则:
采⽤正则表达式(正则表达式应该限制^开头和$结尾,以免部分匹配⽽被绕过)
采⽤⽩名单思想,因为⽤户的输⼊集合是⽆限的,如果仅仅从⿊名单进⾏过滤,会存在被绕过的可能性。所以应将⽤户的输⼊类型、字符集合和长度限制在安全范围之内。
下⾯给出了常⽤的⼀些字段的正则表达式校验防范。
⽇期:⽇期格式通常为:2018-12-21,2018-12-21 11:34:22,2017/12/21,2017/12/21 11:33:22,正则表达式参考如下。
(^\d{4}[-/]\d{2}[-/]\d{2}$)|(^\d{4}[-/]\d{2}[-
/]\d{2}\s+\d{2}\:\d{2}($|\:\d{2}$))
域名:域名都由英⽂字母和数字组成,每⼀个标号不超过63个字符,也不区分⼤⼩写字母。标号中除连字符(-)外不能使⽤其它的标点符号,完整域名不超过255个字符,正则表达式参考如下。
^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-
9]{0,62})+(.)?$
邮箱地址:Email地址由"@"号分成邮箱名和⽹址两部分,其中邮箱名由单词字符、⼤⼩写字母、数字及下划线组成,并且可以出现"."号,正则表达式参考如下。
^[.0-9a-zA-Z_]{1,18}@([0-9a-zA-Z-]{1,13}\.){1,}[a-zA-Z]{1,3}$
⽤户名:⽤户名通常允许⼤⼩写字母、数字和下划线组成,最⼩6位最⼤12位的长度,正则表达式参考如下。
^[0-9a-zA-Z_]{6,12}$
⼿机号:国内⼿机格式为1开头的数字,长度为11位。
^1\d{10}$
当然,除了我们⾃⼰⼿动编写正则表达式对⽤户输⼊进⾏验证之外,现在⼀些常⽤的UI框架如Element UI,这些框架提供的表单控件,已经具备了⾃动校验的功能。
(2)数据过滤
除了对⽤户输⼊的数据进⾏数据类型等的校验外,对于⽤户提交的数据,还需要结合业务场景,对可能造成SQL注⼊、XSS和命令注⼊中常见的危险字符如"<",">","%”和"&"等字符进⾏过滤。
2.5 ⽂件上传安全
⽂件上传现在也是⽤户在访问⽹站或应⽤时经常进⾏的⼀个操作,为了防⽌⽤户上传恶意⽂件,我们在实现⽂件上传功能时,也需要考虑下⾯这些原则。
(1)⾝份验证
⽂件上传前可以增加验证⽤户⾝份的步骤。
(2)⽂件校验
根据业务场景需要,必须采⽤⽩名单形式校验⽂件上传的⽂件类型,同时还需要验证⽂件的后缀名,并且限制合适的⽂件⼤⼩。
(3)⽂件存储
⽂件应保存在Ceph、对象存储或NoSQL等环境,若保存在Web容器内可能会产⽣WebShell风险被⼊侵。
此外,如果使⽤了第三⽅存储服务如腾讯云COS进⾏⽂件存储时,需要注意权限配置检查,避免由于使⽤默认配置⽽导致的⽂件可直接遍历泄露等问题。
2.6 数据传输安全
数据在⽹络的传输过程中,攻击者通过⼀些⼿段,可能可以获取到传输中的数据信息。因此,在数据的传输过程中,我们也有必要保证数据传输的安全。
(1)采⽤POST⽅法发送请求
增、删、改操作必须使⽤POST⽅法提交。
(2)采⽤HTTPS
所有的页⾯和HTTP API接⼝都通过HTTPS进⾏,⽤HTTPS代替HTTP,当⽤户以HTTP访问时,可以设置⾃动跳转到HTTPS。
(3)加密算法选择
如果在通信过程中涉及到使⽤加密算法,在选择加密算法时,对称加密算法可以使⽤AES-128以上,公钥加密可以使⽤RSA-2048以上,哈希算法采⽤SHA-2以上。
2.7 数据保护
在⼀些业务场景中,我们可以需要将某些信息存储在客户端或LocalStorage中,因此我们也应该加强对⽤户数据的保护,防⽌⽤户信息或隐私泄露。
(1)不在客户端存储敏感信息
不要在客户端或LocalStorage上明⽂保存密码或其它敏感信息。
(2)数据脱敏或加密
涉及个⼈隐私的敏感信息须加密存储并且脱敏后显⽰给⽤户。
(3)请求校验
⽤于标记资源的ID参数不能是数序数字以防⽌被遍历,对访问资源ID的每个请求做权限校验。
3. 总结
在上⾯的⽂章中,⾸先主要先介绍了什么是Web安全以及常见的Web漏洞,并且在后续的介绍中对平时开发中需要注意的⼀些安全编码原则进⾏了介绍。
总的来说,在进⾏编码时,我们不能太过信任⽤户的输⼊,凡是⽤户的输⼊需要渲染到页⾯的地⽅都需要进⾏转义和过滤,并在信息提交前做好校验。此外,还需要充分考虑到数据的传输安全和存储安全,并且做好权限的访问控制。接下来就让我们记住安全编码原则,开始编写符合安全规范的代码吧。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。