通过一番 996,精心打造的网站眼看就要部属上线了,但在网站正式上线以前,你有没有想过本身的网站是否安全吗?尽管你的网站用了不少高大上的技术,可是若是网站的安全性不足,没法保护网站的数据,甚至成为恶意程序的寄生温床,那前面堆砌了再多的美好也都成了枉然。javascript
在众多安全性漏洞中,SQL 注入绝对是最严重但也是最好处理的一种安全漏洞。在数据库执行查询句时,若是将恶意用户给出的参数直接拼接在查询句上,就有可能发生。php
举个例子,假设本来某网站登陆验证的查询句长这样:html
strSQL = "SELECT * FROM users WHERE (name = '" + userName + "') and (pw = '"+ passWord +"');"
复制代码
而恶意用户输入的参数为:java
userName = "1' OR '1'='1";
passWord = "1' OR '1'='1";
复制代码
因为代码中是直接将参数与查询句作字串作的拼接,因此 SQL 就成为了这样:mysql
strSQL = "SELECT * FROM users WHERE (name = '1' OR '1'='1') and (pw = '1' OR '1'='1');"
// 至关于
strSQL = "SELECT * FROM users;"
复制代码
这样一来,帐号密码就形同虚设,甚至能够拿到整个数据库的结构(SELECT * FROM sys.tables
)、任意修改、查询数据,整个网站的数据就所有泄露了。sql
不过解决方法也很简单,只要经过参数化查询来避免直接将参数与查询句拼接,并进行适当的输入检查、插入转义字符、严格设定程序权限,就可以有效避免 SQL 注入了。数据库
XSS(跨站攻击)也叫JavaScript 注入,是现代网站最频繁出现的问题之一,它指的是网站被恶意用户植入了其余代码,一般发生在网站将用户输入的内容直接放到网站内容时。例如论坛、留言板等能够输入任意文字的网站,恶意用户若是写入一小段 <script>
,而且前、后端都没有针对输入内容作字符转换和过滤处理,直接把用户输入的字串做为页面内容的话,就有可能遭到 XSS。后端
常见的 XSS 有几个类型:将恶意代码写入数据库,当数据被读取出来时就会执行的储存型 XSS;将用户输入的内容直接带回页面上的反射型 XSS;以及利用 DOM 的特性,各类花式执行恶意代码的DOM-based 型 XSS。跨域
储存型及反射型都很好理解,DOM-based 型就很是有意思了;能够参考OSWAP 整理的XSS Filter Evasion Cheat Sheet,绝大多数的 XSS 方式,都是经过各个元素的 background-image
属性或者元素上的各类事件回调来实现;其中特别值得注意的是 SVG,因为 SVG 中能够写入任意 HTML,还能够加上 onload
事件,若是把 SVG 当成普通图片处理,直接做为网站内容使用,若是遇到恶意用户的话,后果不堪设想。因此在上线上传图片功能时,务必要把 SVG 过滤掉!浏览器
避免 XSS 的方法其实也很简单,只要在数据输入输出时作好字符转换,使恶意代码不被执行,而是被解析成字符就能够了。
CSRF(跨站请求伪造)是一种利用 Cookie 及 Session 认证机制进行攻击的手段;因为 Session 认证的其实不是用户本人,而是浏览器,那么只要经过网页DOM 元素能够跨域的机制,对已经获得认证的网站发出请求,就能够假冒用户,从而拿到敏感信息。
例如某家银行的转帐 API 的URL 是这样的:
http://www.examplebank.com/withdraw?account=AccoutName&amount=1000&for=PayeeName
复制代码
而恶意用户若是在网站中塞进一个 <img />
的话:
<img src="http://www.examplebank.com/withdraw?account=Alice&amount=1000&for=Badman">
复制代码
当不知情的用户浏览到攻击者的网站时,<img/>
会自动发出这个请求,若是用户登陆银行的 Session 还没有过时,那么这个请求极可能就会被银行接受,最后会在用户本人不知情的状况下“被”转账。
这种攻击方式能够与前面所说的 XSS 是相辅相成,例如在没有防范 XSS 的论坛网站中植入 <img/>
,那么其 src
属性就应该是获取敏感信息的 API URL。
解决方法主要有如下几种:
csrftoken
,并检查值是否相同,若是请求来源是本身的网站验证就会经过;反之,因为外部网站没法在代码中获得其余网站的 Cookie,所以没法在请求中带上 csrftoken
。SameSite
属性,确保 Cookie 仅能在本身的网站使用。JSON 劫持是利用现代网站先后端经过 API 进行数据交换的特性,只要能得到使用者权限,并调用获取资料的 API,再加上改写原生的 JavaScript 对象,就能够窃取用户的敏感信息。
得到权限的部分于 CSRF 相同,经过 <script>
能够跨域的特性直接使用浏览器用户的 Cookie;攻击者只须要在网页上经过 <script>
调用获取数据的 API 完成对数据的窃取。
例如:
Object.prototype.__defineSetter__('user',function(obj){
for(var i in obj) {
alert(i + '=' + obj[i]);
}
});
复制代码
当回传的数据中含有 user
属性时,因为 Setter 经过 Object.prototype.__defineSetter__
改写了,user
中的值会被所有读取。
然而 Object.prototype.__defineSetter__
能够修改原生对象所形成的问题,早已经在 ES4 中就被修复了,JSON 劫持也所以销声匿迹,可是从 ES6 开始又添加了 Proxy,使 JSON 劫持又再次成为可能:
<script></script>
<script charset="UTF-16BE" src="external-script-with-array-literal"></script>
复制代码
看起来很恐怖,那么该如何解决呢?除了前面所说的 CSRF Token 外,许多大公司还采用了另外一种有趣的解决方式。即 API 的响应内容开头为 for (;;);
,这也是利用 了<script>
引入的 JavaScript 会当即执行的特性,把攻击者的网站卡死在循环里。
除了文中提到的四种常见的网站安全漏洞外,一个网站还有不少细节须要考虑,例如不要用明码存储密码等敏感信息,针对来源 IP 作流量限制防止 DOS 等等。因此在进行网站开发时要保持安全意识,尽量作好基本的防御措施。