作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Hrvoje是一名软件工程师,拥有5年以上使用PHP等语言的经验, Python, JavaScript, SQL, and HTML.
在过去十年中,Web应用程序的复杂性呈爆炸式增长. 它们已经从用于联系表单和投票的简单容器演变为成熟的应用程序. 我们可以将它们与大型桌面应用程序在大小和性能上进行比较. 随着复杂性的急剧上升和功能丰富的应用程序数量的增加, 投入大量时间和精力使所有应用程序组件尽可能安全已成为一种必要. 互联网用户的大量增加使得解决数据和应用程序用户的保护问题变得更加重要. 有大量的威胁试图潜入其中,给所有相关人员带来严重的头痛.
2001年,一个新的组织进入了舞台. 它的目标是对抗影响网站和应用程序的安全问题. 它被恰当地命名为开放Web应用程序安全项目(OWASP). Nowadays, 它发布资源, 组织会议, 并提出了web和应用程序安全标准. 事实上的标准 Web应用程序安全性 OWASP十大项目是什么. 它列出了十大最普遍的安全威胁. 决定什么可以进入的影响因素是大量的数据和社区反馈. 2017年底,该项目进行了更新. 对许多现代web应用程序至关重要的几个新问题得到了重视, 而有些人从名单上逃了出来.
本文补充了原始列表,并说明了列表的最新更改. 它描述了威胁, 试图提供清晰的例子,以便更容易理解, 并提出了应对安全威胁的方法.
在2017年更新之前,2013年的榜单是最新的. 考虑到web应用程序现在构建和使用方式的变化, 只有彻底修改才有意义. 微服务正在分一杯羹, 新的酷炫框架正在取代普通的代码战斗装备. 这些事实意味着之前列出的一些威胁被移除,取而代之的是一些新的威胁.
在本文中,我们将确保刷新我们对长期被遗忘的问题的记忆, 同时也介绍了新的恶狼. 了解历史是避免重蹈覆辙的唯一可靠方法.
跨站点请求伪造(CSRF)是项目最近迭代中的“失败者”之一. 它消失了,因为许多现代web框架都包含CSRF防御机制. 因此,将应用程序暴露于威胁的可能性会迅速降低.
不管CSRF是否退出列表,刷新一下我们的记忆还是有好处的. 让我们确保它不会比以往任何时候都更加强大.
从本质上讲,CSRF是一个让人感觉像是烟雾弹的漏洞. 攻击者欺骗不知情的用户在web应用程序中执行不想要的请求或操作. Simply put, 攻击者强迫受害者向第三方应用程序发送请求, 而受害者对请求的发送毫不知情. 该请求可以是检索资源的HTTP GET请求, or even worse, 改变受害者控制下的资源的HTTP POST请求. During the attack, 受害者认为一切都很好, 大多数情况下,他们甚至没有注意到后台正在发生的事情. 空气散去后,损害已经造成,或者有什么东西不见了,没有人知道发生了什么.
目标应用程序中成功的先前用户身份验证是使陷阱有效的原因. 该用户在攻击前的某个时刻已登录到应用程序. 应用程序向受害者发送了一个cookie来记住他们. 一旦web浏览器发送恶意请求, cookie会自动与任何潜在的有效负载一起发送,并且应用程序不会反对将请求提供给它已经知道的用户.
最著名的例子之一是欺骗用户将资金从他们的帐户转移到攻击者控制的帐户. 用户登录到一个电子银行系统来检查他们的账户余额. 之后,他们访问一个在线论坛,查看对新手机的评论. An attacker, 用炸药钓鱼, 发布一个评论,其中包括一个看似破碎的图像超链接的图像. 而不是一个真正的超链接, 攻击者使用电子银行系统内部使用的超链接将资金从帐户a转移到帐户B: http://payments.dummybank.com?receiver=attacker&amount=100
. 银行系统将经过身份验证的用户作为发送方,并将“receiver”参数的值作为资金的接收方. 当然,攻击者指定他们的离岸账户作为接收者.
因为浏览器在渲染页面时会自动加载图像, 请求在后台发生. 如果银行的支付系统使用HTTP GET请求实现转账, 没有什么能阻止灾难的发生. 注意,这个例子很简单,而且传输很可能不是通过HTTP GET处理的. However, the attacker can, 只是稍微困难一点, 设法更改论坛的HTML消息发布表单中的属性" action ". 然后浏览器将请求发送到银行的支付系统,而不是论坛的后端.
偷钱只是众多例子中的一个. 更改用户的电子邮件地址或进行意外购买也属于这一类. As it often happens, 社会工程和一些技术知识是对抗软件工程错误的有效杠杆.
在设计系统时,请牢记以下几点:
当与跨站点脚本(XSS)结合使用时,此漏洞的影响甚至更糟。. 如果攻击者可以将恶意代码注入喜爱的网站或应用程序, 攻击的范围变得更加重大和危险. Even more critical, 如果可能发生XSS攻击,攻击者可以绕过一些针对CSRF的保护机制.
请记住,CSRF并没有消失,只是不像以前那么常见了.
有很多应用, 完成一个动作后, 重定向或转发用户到同一部分的另一部分, or even some other, application. For example, 成功登录到应用程序将触发重定向到主页或用户最初访问的页面. 通常,目的地是表单操作地址或链接地址的一部分. 如果处理重定向或转发的组件不能确保目标地址确实是应用程序生成的地址, 潜在的威胁出现了. 这是一个称为“未经验证的重定向和转发”的安全漏洞.”
未经验证的重定向和转发被认为是危险的两个主要原因是网络钓鱼和凭据劫持. 攻击者可以设法改变重定向/转发目标位置,并将用户发送到与原始应用程序几乎没有区别的恶意应用程序. 毫无戒心的用户将其凭据和机密信息泄露给恶意的第三方. 在他们意识到发生了什么之前,已经太晚了.
As an example, Web应用程序经常实现支持重定向到最后访问页面的登录. 为了方便地做到这一点,HTML表单的action属性可能看起来像这样 http://myapp.example.com/signin?url=http://myapp.example.com/puppies. 你是一个超级喜欢小狗的人, 所以安装一个浏览器扩展是有意义的,它可以用你最喜欢的小狗的缩略图取代网站的favicons. 不幸的是,这是一个狗咬狗的世界. 浏览器扩展的作者决定利用你无条件的爱,并引入一个额外的“功能”.“每次你访问你最喜欢的小狗粉丝网站, 它将表单的action属性中的“url”参数替换为指向自己站点的链接. 因为网站看起来一模一样, 当你给你的信用卡细节买小狗打牌, 你实际上是在资助一个恶意攻击者, not your hobby.
解决这个漏洞需要检查目标位置,确保它是预定的位置. 如果框架或库完成了完整的重定向或转发逻辑, 检查实现并在必要时更新代码是有益的. 否则,需要手工检查,防止攻击.
你可以开几种类型的支票. 为了最好的保护, 使用几种方法的组合,而不是只坚持其中一种.
列表上的大多数问题都可以被标记为实现中的缺陷, 要么是因为缺乏知识,要么是因为对潜在威胁的调查不够深入. 这两个原因都可以归因于缺乏经验,未来考虑到这些问题的解决方案很容易——只要确保学得更多、更彻底. 一个特别棘手的问题依赖于做出太多假设的危险(但非常人性化)特征,以及开发和维护复杂计算机系统的困难. 属于这一类的一个漏洞是“访问控制中断”.”
脆弱是由不充分造成的, 或者完全没有, 对应用程序的某些部分进行授权和访问控制. 在OWASP十大项目的前几次迭代中, 有两个问题:不安全的直接对象引用和缺少函数级访问控制. 由于它们的相似性,它们现在合并为一个.
在url中经常使用直接对象引用来标识要操作的资源. For example, 当用户登录时, 他们可以通过点击包含他们的个人资料标识符的链接来访问他们的个人资料. 如果相同的标识符存储在数据库中并用于检索概要信息, 该应用程序假定人们只能通过登录页面进入个人资料页面, 更改URL中的概要标识符会暴露另一个用户的概要信息.
一个设置删除配置文件表单URL的应用程序 http://myapp.example.com/users/15/delete 明确表示该应用程序中至少有14个其他用户. 在这种情况下,弄清楚如何获取其他用户的删除表单并不是什么难事.
这个问题的解决方案是对每个资源执行授权检查,而不假设只有某些路径可以到达应用程序的某些部分. In addition, 删除直接引用并使用间接引用是向前迈出的另一步,因为这使得恶意用户很难弄清楚如何创建引用.
在开发过程中,作为预防措施,写下一个简单的状态机图. 让这些状态代表应用程序中的不同页面,以及用户可以采取的动作的转换. 这使得它更容易列出所有需要特别注意的过渡和页面.
缺少函数级访问控制与不安全的直接对象引用非常相似. In this case, 用户修改URL或其他参数来尝试访问应用程序中受保护的部分. 如果没有适当的访问控制检查访问级别, 用户可以获得对应用程序资源的特权访问,或者至少了解它们的存在.
从例子中借用直接对象引用, 如果应用程序假设访问删除表单的用户是超级用户,因为超级用户可以看到到删除表单的链接, 无需进一步授权, 一个巨大的安全漏洞出现了. 依靠某些UI元素的可用性并不是适当的访问控制.
通过始终确保在应用程序的所有层执行检查,可以解决这个问题. 前端接口可能不是恶意用户访问您的域层的唯一途径. 此外,不要依赖用户传递的有关其访问级别的信息. 执行适当的会话控制,并始终仔细检查接收到的数据. 仅仅因为请求体说用户是管理员,这并不意味着他们真的是管理员.
访问控制中断现在结合了与访问控制不足相关的所有问题, 无论是在应用程序级别还是在系统级别, 比如文件系统配置错误.
新的前端框架的出现和新的软件开发实践的采用将安全问题转移到了全新的主题上. 新技术还设法解决了我们以前手工处理的一些常见问题. 因此,修订名单并根据现代趋势进行调整是有益的.
XML标准提供了一个鲜为人知的概念,称为外部实体, 它是文档数据类型定义(DTD)的一部分. 它允许文档作者指定指向外部实体的链接,然后这些实体可以被引用并包含在主文档中. 一个非常简单的例子是:
]>
&bar;
在解析过程中,引用 &bar;
被定义实体的内容所替换,从而产生
.
如果应用程序接受外部输入并包含它, without any checks, 直接转换为XML文档定义, 大范围的数据泄露和攻击将成为可能.
神奇的是,实体不必是一个简单的字符串—它可以是对文件系统上文件的引用. XML解析器将乐于接受指定文件的内容,并将其包含到生成的响应中, 可能泄露敏感的系统信息. 如OWASP所示, 通过将实体定义为,很容易获得关于系统用户的信息
]>
此漏洞的一个特别麻烦的“特性”是容易执行拒绝服务攻击的可能性. 一种简单的方法是列出无尽文件的内容,例如 /dev/random
. 另一种方法是创建一个实体序列,每个实体多次引用前一个实体. 这将最终引用转换为可能非常宽且非常深的树的根,其解析可能耗尽系统内存. 这次攻击甚至被称为“十亿笑”. 如维基百科所示, 定义了一系列虚拟实体, 使攻击者有机会在最终文档中包含10亿个lol.
]>
&lol9;
可以通过使用不那么复杂的数据格式来防止XML外部实体漏洞. JSON是一个很好的替代品, 提供一些预防措施,以及由于可能的攻击. 必须更新XML库,同时禁用外部实体处理和DTD. As always, 在使用来自不受信任来源的数据或将其包含在文档中之前,对其进行验证和消毒.
When writing code, 开发人员有能力使用他们编写的代码来控制他们正在开发的系统. 如果能够控制第三方系统只编写少量甚至不编写代码的行为,该有多棒? 因为人不是完美的,图书馆也有缺陷, 这是完全可能的.
应用程序状态和配置通常是序列化和存储的. 如果序列化的数据与当前用户紧密耦合,有时浏览器充当存储引擎. 一个想要聪明一点并节省处理时间的应用程序可以使用cookie来标记用户已经登录. 因为cookie只能在登录成功后创建, 将用户名存储在cookie中是有意义的. 然后根据cookie的存在和内容对用户进行身份验证和授权. 如果人们没有恶意,就不会出错. 老实说,他们也不应该好奇.
如果一个好奇的用户在他们的机器上发现了一个cookie,他们会看到这样的内容:
{"username": "joe.Doe ", "expires": "2018-06-01 10:28:16"}
一个完全有效的序列化为JSON的Python字典,没有什么特别的. 好奇的用户可能会更改过期日期,以防止应用程序强制注销. 更好奇的用户可能会尝试将用户名修改为 "jane.doe"
. 如果这个用户名存在, 它将为现在可以访问私人数据的毫无戒心的用户打开一个全新的世界.
将数据序列化为JSON并保持所有内容透明的简单示例远远不是可能发生在您身上的最糟糕的事情. 如果攻击者实现了修改一些序列化数据, 他们可能会以某种方式修改它,迫使您的系统执行任意代码.
假设你正在构建一个REST API,它允许人们用Python编写自己的机器学习模型并将其上传到你的服务. 该服务将评估上传的模型并使用您的数据集进行训练. 这允许人们使用您的计算资源和大量可用数据集来快速轻松地构建模型.
该服务不以纯文本格式存储代码. Users pickle 他们的代码,使用他们的私钥加密,并将其发送到API进行培训. 当服务需要运行一个模型时,它会解密代码、解pickle并运行它. 棘手的部分是pickle协议是不安全的. 代码的构造方式可以允许在反序列化期间执行任意恶意代码.
Python的pickle协议允许类定义一个方法 __reduce__
,它返回有关如何反序列化自定义对象的信息. 支持的返回值之一是由两个参数组成的元组:一个可调用对象和一个由要传递给可调用对象的参数组成的元组. 考虑到你的机器学习模型训练系统旨在提供代码结构的最大灵活性, 可以编写以下代码:
类算法(对象):
def run(self):
pass
def __reduce__(自我):
import itertools
返回list, itertools.count(1), ))
一旦对象需要反序列化(取消pickle),一个函数 list
只带一个参数调用. The function list
是Python中的一个列表构造函数,而函数 itertools.count
从传递的形参开始,生成一个无限迭代器. 将无限迭代器转换为有限列表可能会对系统的性能和稳定性造成灾难性的后果.
解决这类漏洞的唯一方法是选择不对来自外部的数据进行反序列化. 如果这是不可能的, 建议使用校验和或数字签名来防止可能被恶意用户修改的数据反序列化. Also, 尝试设置一个与主系统分离的沙盒环境,以限制可能出现的问题的影响.
使用外部库对数据进行反序列化时, 例如XML或JSON, 尝试选择那些允许您在执行实际反序列化过程之前进行对象类型检查的类型. 这可能会捕获意外的对象类型,其唯一目的是损害您的系统.
与应用程序执行的所有其他操作一样,执行广泛的日志记录和监视. 反序列化经常发生或比正常情况更频繁地失败是正在发生不好的事情的信号. 及早发现问题.
您花了多少时间来确保记录应用程序中发生的所有警告和错误? 您是只存储代码中发生的错误,还是也记录验证错误? 当您的域的业务规则不满足时会发生什么? 如果不能在应用程序中持久化所有错误和可疑的活动,就会危及安全性和数据.
想象一下下面的场景. 与大多数应用程序一样,您的应用程序包含一个登录页面. 该表单有两个字段,一个用于输入电子邮件,另一个用于输入密码. 如果用户尝试登录并且他们提供了错误的密码,他们可以再试一次. Unfortunately, 错误尝试的次数没有限制, 所以登录页面不会在N次尝试失败后被锁定. 攻击者可以利用这个机会, 给定一个正确的电子邮件, 一直从彩虹表中输入密码,直到一个组合最终成功. 前提是您的应用程序足够安全,并且在将密码输入数据库之前对其进行了散列处理, 这种特殊的攻击是行不通的. 但是,您有识别入侵的机制吗?
就因为这一次没能打开你的登录页面, 这并不意味着其他人不会. 登录页面可能也不是你唯一的潜在后门. 如果不是因为其他原因,有人可能会试图使用破坏的访问控制来对付您. 即使是精心设计的应用程序也应该知道有人试图攻击它们, 即使这是不可能的. 但它总是这样.
要尽量保护自己免受这类攻击,请采取以下步骤:
在解决该问题时,要特别注意不要将错误日志泄露给外部用户. 如果不这样做,你的敏感信息就会暴露. 日志记录和监视应该可以帮助您解决问题, 而不是攻击者更有效率地工作.
了解web应用程序中的潜在威胁和漏洞非常重要. 更重要的是开始在应用程序中识别它们并应用补丁来删除它们.
注意应用程序的安全性是软件开发项目所有步骤的重要组成部分. 软件架构师, developers, 测试人员必须将软件测试过程整合到他们的工作流程中. 在软件开发过程的适当步骤中利用安全性检查表和自动化测试来减少安全性风险是有益的.
无论您是在分析现有的应用程序还是开发一个新的应用程序, 你应该调查一下 OWASP应用安全验证标准项目 (ASVS). 该项目的目标是为应用程序安全性验证开发一个标准. 该标准列举了开发安全web应用程序的测试和要求. 测试分为1到3级, 1表示危险最小,3表示潜在威胁最大. 分类允许应用程序管理人员决定哪些威胁更有可能发生,也更重要. 没有必要在每个应用程序中包含每个测试.
新的和现有的web应用程序项目, 尤其是那些遵循敏捷原则的, 受益于保护其应用程序的结构化计划. 如果您决定使用,OWASP ASVS测试的计划会更容易 OWASP安全知识框架. 它是一个用于管理面向安全测试的sprint的应用程序, 还提供了一组关于如何解决常见安全问题的示例, 以及易于遵循的基于OWASP ASVS的清单.
如果您刚刚开始探索web应用程序安全性,并且需要一个安全的沙盒游乐场, 使用OWASP实现的web应用程序WebGoat. 这是一个故意不安全的web应用程序实现. 该应用程序指导您完成课程, 每节课都集中在一个安全威胁上.
在应用程序开发期间,请确保:
Even though, 顾名思义, OWASP十大项目只列出了十个安全漏洞, 有成千上万的陷阱和后门威胁着你的应用程序, most importantly, 用户和他们的数据. 一定要时刻保持警惕,不断更新自己的知识,因为技术的变化和改进既有好处也有坏处.
哦,还有,别忘了,世界不是非黑即白的. Security vulnerabilities don’t come alone; they are often intertwined. 接触到一个通常意味着周围有一群人, 等着长出他们丑陋的脑袋, 即使这不是你的错, as the 系统安全开发人员,你仍然要修补漏洞来遏制网络犯罪. 使用示例请参见 被黑客入侵的信用卡号码仍然可以在谷歌上搜索到.
OWASP是开放Web应用程序安全项目的缩写. 它是一个在线社区,提供有关web应用程序安全的学习资源和工具.
OWASP十大威胁是最常见的web应用程序安全威胁的列表, 由安全专家制作, 考虑社区反馈.
跨站点请求伪造是一种攻击,它使用户对其身份验证的应用程序执行不希望的请求.
未经验证的重定向和转发是一个安全漏洞,允许攻击者将用户重定向到不安全的web应用程序, 获得对受保护的应用程序资源的访问, 或者窃取特权用户信息, 所有这些都是通过注入攻击实现的.
注入攻击是一种允许攻击者将不需要的代码注入应用程序的攻击类型. 有几种类型的攻击, 基于应用, 其中最常见的是SQL注入和跨站脚本.
反序列化是将字节流转换为加载到内存中的代码的过程. 原始字节流是由执行相反操作的序列化过程生成的.
攻击向量表示利用应用程序中的安全漏洞的方法. 注入无效的HTML img元素向银行的API资源发出请求,这是CSRF攻击中使用的攻击向量的一个示例.
XML实体是一种机制,用于定义XML文档或文档类型定义(DTD)中使用的项的别名。.
外部实体是一种XML实体,使得文档作者很容易使用统一资源标识符(URI)将外部资源包含到文档中。.
OWASP WebGoat是一个故意不安全的web应用程序实现,它作为一种学习机制来教授web应用程序安全课程.
Hrvoje是一名软件工程师,拥有5年以上使用PHP等语言的经验, Python, JavaScript, SQL, and HTML.
世界级的文章,每周发一次.
世界级的文章,每周发一次.
Join the Toptal® community.