31

常见的网站安全问题

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzI3NzIzMDY0NA%3D%3D&%3Bmid=2247494832&%3Bidx=1&%3Bsn=eaa847ef20457ca1b5dde549d30090d8
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
// 每日前端夜话 第425篇
// 正文共:1900 字
// 预计阅读时间:9 分钟
EBrymuE.png!mobile

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

SQL 注入

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

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

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

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

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

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

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

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

7r6R7bn.png!mobile

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

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

  • 检查 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-16BE" src="external-script-with-array-literal"></script>

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

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

rYNvUzy.gif!mobilezyyeqeA.png!mobile精彩文章回顾,点击直达 j6zmiq7.png!mobile

6BJJJzR.gif!mobile

转了吗

a2iEFfB.gif!mobile

赞了吗

FfiMvyn.gif!mobile

在看吗


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK