《Web前后端漏洞分析与防御》总结

《Web前后端漏洞分析与防御》是慕课网的一门网课,时长约11小时,原名叫做《腾讯大牛教你web前后端漏洞分析与防御》。尽管原名很山寨,这门课的质量还是不错的,主要讲解了XSS、CSRF、点击劫持、中间人攻击、密码安全、SQL注入和文件上传漏洞几个方面。

名词解释

XSS

全名Cross-site Scripting。XSS的本质是使正常用户浏览的网页包含攻击者的恶意脚本,这些脚本可以让用户登录时就直接把明文用户密码发给攻击者,也可以在用户登陆后获取用户的Cookie,等等。
要实现这个目标,攻击者要假装用户,进行恶意的且会被后台渲染到公共可见的前端的输入,这样用户在浏览时就会遇到攻击者的脚本并执行。举个例子的话,我在某网站评论一段<sciprt src='malJS.js'></sciprt>,如果这个网站的防御没有做好,用户在看到我的评论时就会执行malJS.js脚本。
大多数情况下XSS解决起来其实很简单,只需要将各种可能引起XSS的字符比如<进行转义即可,此外很多场景下的一个简单方案是把用户输入放到span标签内。只有在富文本的场景下,XSS会显得比较棘手,这时可以利用白名单机制,在用户输入中仅允许特定的HTML标签,对其它的进行转义或者过滤。

CSRF

全名Cross-site Request Forgery。CSRF的本质是使正常用户在不知情的情况下在访问A网站时提交B网站的表单或请求。攻击者只需要在A网站添加相应的脚本然后引导B网站的用户访问A网站即可。CSRF的威力在于如果用户登录了B网站,那么在A网站提交的表单或请求就带有B网站的Cookie(登录态),可以进行高权限的操作。
不难发现这个攻击能够生效的症结在于在A网站提交的表单可以带有B网站的Cookie,这个特性可以说是不合理的。Chrome浏览器的Cookie支持samesite属性,如果开启后Cookie就不能跨站使用,CSRF也就无从谈起,但是这一属性现在基本上只有Chrome支持。作为开发者要解决这个问题最好是在自己的表单中加入一个针对CSRF的Token,对每个Cookie随机生成,后端保存,前端在发送表单或请求时带上这个Token。这样CSRF攻击者虽然可以获得Cookie,但是因为无法获得这个Token,无法获取实质上的登录态。

点击劫持

点击劫持是通过诱导用户点击按钮或者进行输入的方式控制用户行为的一种攻击方法。点击劫持让我想起了电影《头号玩家》中的一个情节:反派Boss从VR退回现实时VR遭到了攻击,VR输出了基于现实的,主角们自定义的VR场景,使反派Boss认为自己在现实世界中处于险境,进而做出了对自己不利的行为。这种攻击方法按照本质应该算是中间人攻击,不过和点击劫持也颇为相似。
在HTML中实现点击劫持所依赖的根本小技巧是把目标网站做进一个不可见的iframe里,然后在iframe上层通过图片等方式引导用户点击、输入,这样用户认为自己在,比方说,抽奖,实际却在银行里转账。
避免点击劫持并不困难。HTTP头中有X-Frame-Options字段,设为DENY即可完全禁止自己的网页被嵌入到iframe里,设为SAMEORIGIN也可以防御点击劫持攻击。

中间人攻击

中间人攻击是攻击者在对用户与服务器中间的网络有一定控制权时通过监听或者篡改用户与服务器通讯的数据来进行攻击的方式。这个“有一定控制权”说起来好像很玄,其实只要简单接入局域网(比如和用户连同一个Wifi)就能实现“监听”。监听的主要危害是获取用户敏感信息,比如如果前端将用户的明文密码发送到后端进行用户验证,那么中间人就可以监听到这个密码并获取用户权限。而篡改则显而易见更加危险。
要解决中间人攻击的方法只有一个,那就是使用HTTPS对服务器身份进行验证并将用户与服务器之间的通讯进行加密。利用第三方机构进行服务器身份验证可以防止攻击者冒充服务器欺骗用户,而加密则可以避免通讯被窃听和篡改,两者结合可以对中间人攻击进行非常有效的防御。HTTPS的普及是个大趋势,现在申请HTTPS的成本已经很低了。

密码安全

密码安全其实说白了就一件事,不保存明文用户密码,这个也可以说是常识了。即使加密明文用户密码,其手段也应该足够复杂,如果只是简单md5加密被泄露的加密密码也可以轻易通过彩虹表被还原至明文。还好加密总是比破解容易很多的,因此可以利用为用户的密码生成额外的前后缀(盐)再加密或使用多种加密技术多次加密等技术提高密码安全性。
此外第11章也介绍了一些包含密码安全的方面。简单来说,用户的邮箱、密码、身份证号等敏感信息应该与用户的业务数据分开保存。对于容易出漏洞的业务代码而言,由于仅可访问业务数据,一旦发生安全问题不会导致用户敏感信息的大面积泄露。而敏感信息数据库仅负责对用户身份进行验证,成功后颁发一个验证Token,业务代码凭借Token完成与用户身份有关的逻辑。这样敏感数据部分的实现、运维和风控都更加容易。

SQL注入

SQL注入利用了Web应用中经常会根据用户输入作为检索词在数据库中检索的特点。当攻击者进行特定的恶意输入而后端利用该输入检索数据库时,这部分检索词中包含的与SQL逻辑相关的部分会改变SQL检索语句本身的语义逻辑,导致不可预计的结果。SQL注入是Web安全中非常经典的问题,包含的内容非常广泛,而且学习这门课之前我也有所了解,这里我就不详细说了。
解决SQL注入的最佳方法是使用参数化查询的方法,即把与用户输入有关的SQL查询分为两步,第一步是告诉数据库下一步查询的结构怎样的,相当于定义了一个函数的Prototype,有哪些参数,返回什么值,这一步不涉及用户输入,是程序员在代码里写死的。第二步是告诉数据库具体的参数。这时即使攻击者使用了恶意的用户输入企图改变SQL逻辑,数据库也不会理睬,因为其逻辑已经被代码所规定了。现代SQL查询大多数使用ORM模式,ORM本身对参数化查询做了封装,所以使用ORM基本就保证了对SQL注入的安全性。

文件上传漏洞

文件上传漏洞的原理是(没有正确配置的)服务器会把用户上传文件当做代码来执行。这里最典型的就是PHP了。服务器认为攻击者上传了一个图片文件,实际上攻击者上传了一个PHP文件,那么当攻击者想访问他上传的“图片”文件时服务器就会找到这个PHP文件并执行。这相当于攻击者对服务器拥有了控制权。
除了PHP或者ASP后端遇到文件上传漏洞的概率不大。解决文件上传漏洞的一个很好的方法是把用户上传的文件放到一个静态文件服务器上,使其不能被执行。

我的小项目

我的小项目Web方面是基于FlaskSQLAlchemy的,利用Flask-User管理用户。

  • XSS方面,由于我的小项目渲染的用户输入不是很多,基本上都放在了span里,所以没有XSS的问题。
  • CSRF也用了Flask-User依赖的Flask-WTF中的现成CSRF-Token。
  • 点击劫持的问题在学习这部分内容之前没有留意,了解之后用Flask-Talisman设置了安全的HTTP头。这些HTTP头还包括限制js脚本、图片、字体等资源来源和内嵌脚本的字段,对XSS也有很强的防御作用。
  • 中间人攻击对我的小项目影响比较大,因为项目中包含用户下载由HTML渲染成的Word文档的场景。该场景中渲染是在前端完成的,而HTML由后端发送。这样如果中间人篡改了后端发送的HTML,就可以在生成的Word文档中嵌入恶意代码,对用户的损害巨大。所幸我在考虑密码安全时就采用了HTTPS的方案,消除了这一安全威胁。
  • 密码安全依赖于Flask-User库,这个库默认对用户密码进行bcrypt加密,据说是现在state of the art的加密方式了。特点是加密速度适中且不可被GPU加速(使攻击者难以暴力猜解),还有能调整加密速度(work factor)的参数以保证随着计算机算力发展该技术不会被淘汰。
  • SQL注入的问题由SQLAlchemy解决。
  • 文件上传漏洞不存在。不光因为是基于Flask,更重要的是我的小项目不涉及用户上传的业务:)

其它

  • 这个课程的录制者(TooBug)在演示攻击者引导用户浏览某网站或者点击某按钮时经常会利用类似“点击这里有钱拿”这样的文本。在学习这门课之前坦率讲或许遇到这样的按钮我真的会点——保持警惕,不泄露身份,不转账,点了不会怎么样。实际上轻轻一点它就真的可能对我产生实际的损害。现在我明白了这样的按钮不能随便点,也深刻地感到了计算机网络的不安全性。另外人类这贪小便宜的弱点究竟是怎么来的呢……
  • TooBug对现在的生物密码持谨慎态度,原因是生物密码不具备密码的两个重要特点:不可泄露、允许修改。比如指纹,我相信对于有预谋的人来说获取一个人的指纹太容易了,长相就更不用说。而生物密码不允许修改就更加尴尬:即使我知道我的指纹被泄露了,我也没法修改密码。所以我觉得TooBug的观点还是很有道理的。生物密码解决的痛点有两个,一是用户容易忘了密码,二是复杂的密码带来差的用户体验,但是看起来不足以和其潜在风险相提并论。

总结

所谓魔高一尺道高一丈,互联网在诞生之初设计上存在缺陷,但总的来说通过前后端、浏览器、第三方的合力攻击者想捞点油水也不那么容易。现在的流行框架对常见Web安全问题都有了解决方案,结合HTTPS,基本上就可以做到安全了。至于可以做到却没有做到,那就是另外一个问题了。

附录

可能是这门课留下的所有文字资料,不过也足够了。

1. 课程介绍

介绍安全问题在web开发中的重要性,并对课程整体进行介绍

  1. Web安全课程介绍
  2. 项目总览

2. 环境搭建

本章节我们会搭建项目所需要的环境

  1. 环境搭建上
  2. 环境搭建下

3. 前端XSS

系统介绍XSS攻击的原理、危害,以真实案例讲解XSS带来过的损失,最后以实战代码讲解如何防御XSS攻击

  1. XSS介绍
  2. XSS攻击类型
  3. HTML内容和属性转义
  4. JS转义
  5. 富文本 上
  6. 富文本 下
  7. CSP
  8. PHP-XSS

4. 前端CSRF

系统介绍CSRF攻击的原理、危害,以真实案例讲解CSRF带来过的损失,最后以实战代码讲解如何防御CSRF攻击

  1. CSRF攻击简介和演示
  2. CSRF攻击原理和危害
  3. CSRF防御-samesite
  4. CSRF防御-验证码
  5. CSRF防御-token
  6. CSRF防御-referer
  7. PHP-CSRF

5. 前端Cookies问题

介绍Cookies的作用和特性,以及在web开发过程中Cookies的最佳实践,讲解常见的与Cookies相关的安全问题,并以实战代码讲解如何防止安全问题的发生

  1. Cookies特性
  2. Cookies作用
  3. Cookies和XSS CSRF的关系与案例
  4. Cookies安全策略

6. 前端点击劫持问题

介绍点击劫持的原理和危害,以真实案例讲解点击劫持带来过的损失,最后以实战代码讲解如何防御点击劫持

  1. 点击劫持演示
  2. 点击劫持防御
  3. PHP-点击劫持

7. 传输安全

系统介绍web中使用的HTTP协议的安全问题和危害,以真实案例讲解可能带来的损失。系统讲解HTTPS的原理和实战,以及常见的数据加密方案

  1. HTTP窃听
  2. HTTPS原理
  3. HTTPS部署
  4. 真实服务器申请部署HTTPS
  5. 小结

8. 密码安全

系统介绍web开发中鉴权相关的知识和密码的存储、验证设计。以真实案例讲解密码设计不当导致过的安全问题。最后以实战代码讲解如何设计安全的密码存储系统

  1. 密码的作用
  2. 密码的存储
  3. 密码不安全的案例
  4. 密码加固
  5. 密码传输安全
  6. 生物密码
  7. PHP-密码加固

9. 接入层注入问题

讲解接入层开发中需要考虑的SQL注入原理和危害,以及防御办法。以真实案例讲解SQL注入带来的损失,以实战代码讲解SQL注入的防御方法

  1. 关系型数据库和SQL介绍
  2. SQL注入前置知识
  3. SQL注入演示和危害
  4. SQL注入案例
  5. SQL注入防御上
  6. SQL注入防御下
  7. NoSQL注入和防御
  8. PHP-SQL注入

10. 接入层上传问题

讲解接入层开发中需要考虑的文件上传的安全问题,介绍原理和危害,以真实安全讲解其带来的损失。介绍防御的原则,并以实战代码讲解如何避免上传出现安全问题

  1. 上传漏洞简介
  2. 上传漏洞演示
  3. 上传漏洞案例
  4. 上传漏洞防御
  5. PHP-文件上传

11. 社会工程学和信息泄露

讲解社会工程学的原理、危害和真实案例带来的损失。讲解OAuth的授权思维,并围绕这个授权思维设计系统的读写规则防止信息大范围泄露

  1. 信息泄露和社会工程学
  2. 社会工程学案例
  3. OAuth思想介绍
  4. 利用OAuth思想保护用户资料

12. 其他安全问题

讲解一些其它的安全问题,以实战代码讲解如何进行预防和防御

  1. DOS攻击
  2. 重放攻击

13. 课程总结

总结课程的知识点,回顾安全web开发的关键关注点

  1. 面试
  2. 课程总结