【Web安全】常见的网站安全及解决方案
小刀网络 2023-08-17 07:58:51 0

经过一番 996,精心打造的网站眼看就要部属上线了,但在网站正式上线之前,你有无想过自己的网站会不会安全吗?虽然你的网站用了很多高大上的技术,但是如果网站的安全性不足,没法保护网站的数据,乃至成为歹意程序的寄生温床,那前面堆砌了再多的美好也都成了枉然。


SQL 注入

在众多安全性漏洞中,SQL 注入绝对是最严重但也是最好处理的一种安全漏洞。在数据库履行查询句时,如果将歹意用户给出的参数直接拼接在查询句上,就有可能产生。


举个例子,假定本来某网站登录验证的查询句长这样:


strSQL = "SELECT * FROM users WHERE (name = '" + userName + "') and (pw = '"+ passWord +"');"

1

而歹意用户输入的参数为:


userName = "1' OR '1'='1";

passWord = "1' OR '1'='1";

1

2

由于代码中是直接将参数与查询句做字串做的拼接,所以 SQL 就成了这样:


strSQL = "SELECT * FROM users WHERE (name = '1' OR '1'='1') and (pw = '1' OR '1'='1');"

// 相当于

strSQL = "SELECT * FROM users;"

1

2

3

这样一来,账号密码就形同虚设,乃至可以拿到全部数据库的结构(SELECT * FROM sys.tables)、任意修改、查询数据,全部网站的数据就全部泄漏了。




不过解决方法也很简单,只要通过参数化查询来避免直接将参数与查询句拼接,并进行适当的输入检查、插入转义字符、严格设定程序权限,就可以够有效避免 SQL 注入了。


XSS

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

CSRF(跨站要求捏造)是一种利用 Cookie 及 Session 认证机制进行攻击的手段;由于 Session 认证的其实不是用户本人,而是浏览器,那末只要通过网页DOM 元素可以跨域的机制,对已得到认证的网站发出要求,就能够假冒用户,从而拿到敏感信息。


例如某家银行的转账 API 的URL 是这样的:


http://www.examplebank.com/withdraw?account=AccoutName&amount=1000&for=PayeeName

1

而歹意用户如果在网站中塞进一个 <img /> 的话:


<img src="http://www.examplebank.com/withdraw?account=Alice&amount=1000&for=Badman">

1

当不知情的用户浏览到攻击者的网站时,<img/> 会自动发出这个要求,如果用户登录银行的 Session 还没有过期,那末这个要求极可能就会被银行接受,最后会在用户本人不知情的情况下“被”转帐。


这类攻击方式可以与前面所说的 XSS 是相辅相成,例如在没有防范 XSS 的论坛网站中植入 <img/>,那末其 src 属性就应当是获得敏感信息的 API URL。


解决方法主要有以下几种:


检查 Referer:在服务器端检查要求头中 Referer 的值,也就是检查要求的来源,如果是来自允许的网站,才会正常履行 API 的功能。

CSRF Token:在 Cookie 及要求发送的数据中都加上 csrftoken,并检查值会不会相同,如果要求来源是自己的网站验证就会通过;反之,由于外部网站没法在代码中得到其他网站的 Cookie,因此没法在要求中带上 csrftoken。

SameSite Cookie:在 Cookie 中加上 SameSite 属性,确保 Cookie 仅能在自己的网站使用。

JSON 劫持

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> Object.setPrototypeOf(

__proto__,

new Proxy(__proto__, {

has: function(target, name) {

alert(

name.replace(/./g, function(c) {

c = c.charCodeAt(0)

return String.fromCharCode(c >> 8, c & 0xff)

})

)

}

})

) </script>

<script charset="UTF⑴6BE" src="external-script-with-array-literal"></script>


看起来很恐怖,那末该怎么解决呢?除前面所说的 CSRF Token 外,许多大公司还采取了另外一种有趣的解决方式。即 API 的响应内容开头为 for (;;);,这也是利用 了<script> 引入的 JavaScript 会立即履行的特性,把攻击者的网站卡死在循环里。


总结

除文中提到的四种常见的网站安全漏洞外,一个网站还有很多细节需要斟酌,例如不要用明码存储密码等敏感信息,针对来源 IP 做流量限制避免 DOS 等等。所以在进行网站开发时要保持安全意识,尽量做好基本的防护措施


标签: 歹意网站
相关信息推荐