[TOC]
引言
Web开发中系统的安全性不容忽视,那么我们该如何审视我们的WEB站点,可以关注以下几项(< www.cnblogs.com/vajoy/p/417…
1.永远不要相信客户端传来的任何信息,对这些信息都应先进行编码或过滤处理;2.谨慎返回用户输入的信息;3.使用黑名单和白名单处理(即“不允许哪些敏感信息”或“只允许哪些信息”,白名单的效果更好但局限性高);4.检查、验证请求来源,对每一个重要的操作都进行重新验证;5.使用SSL防止第三方监听通信(但无法阻止XSS、CSRF、SQL注入攻击);6.不要将重要文件、备份文件存放在公众可访问到的地方;7.会话ID无序化;8.对用户上传的文件进行验证(不单单是格式验证,比方一张gif图片还应将其转为二进制并验证其每帧颜色值<无符号8位>和宽高值<无符号16位>);账号登录提示信息泄漏
漏洞场景
输入错误的用户名,会有明确的提示——帐号不存在。
攻击者可以通过此方法枚举找出存在的帐号,存在安全漏洞
整改建议:帐号密码校验时,无论账号还是账号密码错误统一给以模糊的提示如:"帐号或密码错误"即可。
前端打包之后的静态文件内容泄露(如:static下面的文件)
漏洞描述:在static下存放的不经过webpack打包的文件,页面会直接请求获取,从浏览器的Network中可以看到文件的请求地址和内容,如果其中有关键的信息,就会存在泄露问题。
如: http://xxxxxx/static/configUrl.js 直接获取到前端的静态资源文件中有的关键信息
整改建议:需要对敏感的信息如上面的内部ip地址进行加密、隐藏或不存放在此处配置文件中
input限制特殊字符和长度
漏洞描述: 永远不要相信用户输入的信息,如常规的注入脚本通过input输入之后被页面执行
整改办法
方法1:对于vue项目中ElementUI的el-input 和 原生input
<el-input :placeholder="privateSearchPlaceholder" v-model.trim="privateValue" @keyup.enter.native="querySearchStr" clearable maxlength="100" @clear="clearSearchStr"></el-input>
watch: {/** * 监听文本框值变化 * */privateValue (val) {// 此处不加nextTick,显示的还会使原来的带有特殊字符的字符串;但是实际的值已经改变this.$nextTick(() => {// 去除特殊字符(除去数字字母中文之外都是特殊字符)this.privateValue = val.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]+/g, '') // this.privateValue =this.$myTools.stringFilter(val) // 也可全局注册过滤函数})}
}
方法2:针对ElementUI的el-input
<el-input @input="onInput" v-model.trim="searchStr"></el-input>
methods:{onInput(val){console.log(val)this.searchStr = e.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]+/g, '')}
}
注意:前端禁止了特殊字符,但是抓包工具直接请求还是可以发送特殊字符,所以建议后端关键接口也要对特殊字符做处理,SQL注入也可用类似方法解决部分(当然如果已经做了防重放的话也可以理论上避免抓包重发)。
密码强度要求
漏洞描述:涉及到用户密码的系统,需要限制用户对账号密码的复杂度做要求,不可允许使用弱密码
整改建议:配置安全合理的密码策略,如必须为包含数字、字母、特殊字符,且长度不可短于8位,下面是对复杂度做验证的函数
密码长度8~30位,且必须包含字母、数字、特殊字符的vue表单校验
let pwd = '';
var pwdValidate = function(rule, value, callback){pwd = valueif(!value){return callback(new Error('密码不可为空'))}else{// 正则表达式校验密码if (value.length > 8 && value.length < 30 && value.replace(/[a-zA-Z0-9]/g, '').length > 0) {if (_userAccount && (value.includes(_userAccount) || value == _userAccount)) {return callback(new Error('密码中不允许出现用户名或与用户名相同'))}callback()}else {return callback(new Error('密码长度8~30位,且必须包含字母、数字、特殊字符'));}}
}
敏感数据加密
漏洞描述:用户登录帐号与密码、用户姓名、身份证、电话等关键信息不可明文传输
整改方式:采用加密处理,切记不可只采用单层md5加密,虽然md5不可解密,但是现在采用字典暴力破解的可能性也越来越大
(1)可以在加密时加入salt,减小被碰撞破解的可能;或者采用对称或者非对称加密;
(2)对称加密加密与解密使用的是同样的密钥,速度快,但由于需要将密钥在网络传输,所以安全性不高。
(3) 非对称加密使用了一对密钥,公钥与私钥,所以安全性高,但加密与解密速度慢。
(4) 适当的解决的办法是将对称加密的密钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用私钥进行解密得到对称加密的密钥,然后双方可以使用对称加密来进行沟通。
不安全的http请求方式
现象描述: 在信息安全测试的项中,竟然要求禁止除GET和POST之外的HTTP方法,开始不是很理解,查询之后说法如下:
为什么要禁止除GET和POST之外的HTTP方法?
一、HTTP请求方法有哪些
HTTP1.0定义了三种请求方法: GET、POST、HEAD
HTTP1.1新增了五种请求方法:OPTIONS、PUT、DELETE、TRACE 、CONNECT
二、举例说明不安全的HTTP方法
GET、POST是最为常见方法,而且大部分主流网站只支持这两种方法,因为它们已能满足功能需求。其中,GET方法主要用来获取服务器上的资源,而POST方法是用来向服务器特定URL的资源提交数据。而其它方法出于安全考虑被禁用,所以在实际应用中,九成以上的服务器都不会响应其它方法,并抛出404或405错误提示。以下列举几个HTTP方法的不安全性:
1、OPTIONS方法,将会造成服务器信息暴露,如中间件版本、支持的HTTP方法等。
2、PUT方法,由于PUT方法自身不带验证机制,利用PUT方法即可快捷简单地入侵服务器,上传Webshell或其他恶意文件,从而获取敏感数据或服务器权限。
3、DELETE方法,利用DELETE方法可以删除服务器上特定的资源文件,造成恶意攻击。
建议把除了GET、POST的HTTP方法禁止,有两方面原因:
1、除GET、POST之外的其它HTTP方法,其刚性应用场景较少,且禁止它们的方法简单,即实施成本低;
2、一旦让低权限用户可以访问这些方法,他们就能够以此向服务器实施有效攻击,即威胁影响大。
整改建议:配置仅支持GET,POST方法即可
文件上传安全验证
关于涉及到上传文件的接口一定要严格校验,包括格式,文件内容,文件名进行严格校验
CSRF 跨站请求伪造——请求伪造
特点:用户必须登录
原理:利用网站漏洞去自动执行一些接口
举例:
防御措施
1.Token 验证2.请求头中Referer验证 页面来源判断3.隐藏令牌 在http头或者请求中添加隐藏的口令其中一个是对 referer 的校验通用做法,也就是只允许我们制定的域名发送的请求,其他站点则认为是非法请求,比如下面我们的中间件,只要存在 referer,并且 referer 不在我们的域名白名单下,那么则直接返回 403 拒绝访问。
const baseFun = require('../lib/baseFun');
const whiteList = ['127.0.0.1:3000'
];
module.exports = function () {return async function ( ctx, next ) { if(ctx.request.headers.referer && !whiteList.includes(ctx.request.headers.referer)){baseFun.setResInfo(ctx, false, 'access have been forbidden', null, 403);return; } return await next();}
}
另外一个是后台服务在写操作时,使用 token 校验方式