作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Gergely曾担任Alexa 50强网站的首席开发人员,该网站每月为数百万独立访问者提供服务.
编者注:本文由我们的编辑团队于2022年12月8日更新. 它已被修改,以包括最近的来源,并与我们目前的编辑标准保持一致.
对于太多的公司来说,直到 after a security breach 网络安全最佳实践是否已经成为优先事项. 在我从事IT安全专业工作的这些年里, 我一次又一次地看到,web开发安全问题的世界对我的许多人来说是多么模糊 fellow programmers.
根据定义,应对网络安全威胁的有效方法必须是主动和防御的. Toward that end, 我们的目标是激发一种安全思维,给读者注入一剂健康的偏执.
In particular, 本指南的重点是培养对10个常见和重要的网络安全缺陷的认识并减轻这些缺陷.
程序员和IT专业人员经常对授权和身份验证之间的区别表示困惑. 缩写的用法 auth 因为这两个词都增加了它们周围的朦胧.
让我们来定义和澄清它们的区别:
Stated another way, authentication 知道一个实体是谁,而 authorization 是一个给定的实体能做什么. 考虑到这一点,让我们来探索10个常见的互联网漏洞问题.
注入缺陷源于过滤不可信输入的典型失败. 当我们将未经过滤的数据传递给SQL服务器(SQL注入)时,可能会发生注入缺陷。, to the browser (via Cross Site Scripting)、到LDAP服务器(LDAP注入)或其他任何地方. 这里的问题是攻击者可以注入命令来劫持客户端的浏览器, resulting in loss of data.
应用程序从不受信任的源接收的任何内容都必须进行过滤, 最好是根据白名单. 由于配置困难,不建议使用黑名单. 黑名单也被认为很容易被黑客绕过. 杀毒软件产品通常会提供黑名单失败的典型例子. 模式匹配不起作用.
Prevention: 防止注入“简单地”就是过滤我们的输入并考虑哪些发送者是可信的. 过滤是一项相当艰巨的任务,因为我们需要处理所有输入,除非它毫无疑问是可信的.
如果我们在一个有1的系统中过滤999个输入,000 inputs, 我们仍然有一个领域可以成为阿喀琉斯之踵,摧毁我们的系统.
Using 二级SQL注入 将一个SQL查询结果注入另一个SQL查询结果也被认为是危险的. 这似乎是个好主意,因为数据库是可信的. 但如果边界不在,我们的输入可能间接来自恶意来源.
因为过滤是很难做到正确的, 我们建议使用框架的过滤函数. 它们被证明是有效的,并经过了彻底的审查. 如果您还没有使用框架,请考虑使用框架对服务器安全性的好处. .
在身份验证失败期间可能发生的问题不一定源于相同的根本原因. 不建议滚动您自己的身份验证代码,因为很难做到正确. 有无数可能的陷阱,这里有几个:
Prevention: 避免与身份验证失败相关的web安全漏洞的最直接方法是实现框架. If you roll your own code, 要极度偏执,对可能出现的潜在问题进行自我教育.
攻击者向您的web应用程序发送输入JavaScript标记. 当这个输入未经过处理返回给用户时,用户的浏览器将执行它. 这是一个相当普遍的输入消毒失败,本质上是一个子类 injection flaws). CSS可以像制作一个链接并说服用户点击它一样简单, 也可能是更邪恶的东西. 例如,在页面加载时,脚本将运行并被用来将您的cookie发送给攻击者.
Prevention: 简单地说,不要向客户机返回HTML标记. 这也可以保护您免受HTML注入, 当攻击者注入纯HTML内容(如图像或响亮但不可见的flash播放器). 要实现此解决方案,请转换所有 HTML entities to return something else. For example, convert to return
<script>
. 或者,您可以使用正则表达式去除HTML标记,使用正则表达式 <
and >
. 但这很危险,因为有些浏览器可能无法解释严重损坏的HTML. 最好将所有字符转换为转义的对应字符.
这是信任用户输入并通过继承结果付出代价的典型案例 security vulnerability. 直接对象引用意味着内部对象(例如.g.(如文件或数据库密钥)暴露给用户,使我们容易受到攻击. 攻击者可以提供这个引用, 如果授权没有得到执行或被破坏, the attacker gets in.
例如,代码中有 download.php
模块,该模块读取并允许用户下载文件, 使用CGI参数指定文件名(例如.g., download.php?file=something.txt
). 如果开发人员从代码中省略了授权, 攻击者现在可以使用它来下载运行PHP的用户可以访问的系统文件.g.(应用程序代码或随机服务器数据,如备份).
另一个不安全的直接对象引用漏洞的例子是依赖于用户输入来确定其身份的密码重置功能. 攻击者单击有效的URL后,可以修改 username
字段中输入“admin”之类的内容.”
顺便说一句,我经常在“野外”看到这两个例子.”
Prevention: 正确且一致地执行用户授权,并将选择列入白名单. More often than not, 通过在内部存储数据,而不依赖于通过CGI参数从客户端传递的数据,可以完全避免该漏洞. 大多数框架中的会话变量都非常适合这个目的.
根据我的经验,经常会遇到配置错误的web服务器和应用程序. Some examples:
Prevention: 有一个好的(最好是自动化的)“构建和部署”过程,它可以在部署上运行测试. 可怜的人的安全错误配置解决方案是提交后钩子, 防止带有默认密码和/或内置开发内容的代码泄露.
这个web安全漏洞是关于加密和资源保护的. 敏感数据在任何时候都应该加密,包括在传输和静止时. No exceptions. 信用卡信息和用户密码 never 不加密的旅行或存储,密码应该总是散列的. 显然,加密/散列算法不能是弱算法. 当有疑问时,web安全标准建议 AES (256 bits and up) and RSA (2048 bits and up).
会话id和敏感数据不应该在url中传播,这一点再怎么强调也不为过. 带有敏感数据的cookie应该打开“安全”标志.
Prevention:
In transit: Use HTTPS 有适当的证书和 PFS(完全转发保密). 不接受任何非http连接. 饼干上有“安全”标志吗.
In storage: 减少暴露于此漏洞的风险. 如果你不需要敏感数据,那就把它撕碎. 你没有的数据是不可能的 stolen. 不存储信用卡信息,你就不需要再处理了吗 PCI compliant. 注册一个支付处理程序,比如 Stripe or Braintree. 存储和加密敏感数据,并确保所有密码散列使用 bcrypt. 如果你不使用加密,那就自学一下 salting and rainbow tables.
恕我直言, 不要将加密密钥存储在受保护数据附近. 这就像把你的自行车放在锁里,锁里有钥匙. 用加密保护您的备份,并保持密钥的私密性. 当然,别把钥匙弄丢了!
如果在服务器上调用函数时没有执行适当的授权,就会发生这种故障. 开发人员倾向于认为,既然是服务器端生成UI, 客户端将无法访问服务器不提供的功能. 事情并没有那么简单,因为攻击者总是可以伪造对“隐藏”功能的请求. 攻击者不会因为期望的功能不容易访问而却步. Imagine there’s an /admin
面板,并且该按钮仅在用户实际上是管理员时才出现在UI中. 如果缺少授权,没有什么可以阻止攻击者发现和滥用此功能.
Prevention: 在服务器端,授权必须 always be performed.
在csrf中,也被称为 confused deputy 攻击—恶意的第三方欺骗浏览器,使其滥用其权限为攻击者做某些事情.
In the case of CSRF, 第三方网站使用您的浏览器, cookies, 和会话发出请求到目标站点(例如.g., your bank). 如果在一个浏览器标签你登录到你的银行, 如果你的银行很容易受到这种攻击, 然后可以控制另一个选项卡,使您的浏览器以攻击者的名义滥用其凭据, 这导致了混乱的代理问题. 代理是滥用其权限(会话cookie)来执行攻击者指令的浏览器.
考虑一下这个例子:攻击者Alice想通过将目标Todd的一些钱转移到她的账户来减轻他的钱包.
要汇款,Todd访问以下URL:
http://example.com/app/transferFunds?amount=1500&destinationAccount = 4673243243
顺便说一句,他的银行很容易受到CSRF的攻击. Todd执行他的事务后,显示一个成功页面,转账完成.
爱丽丝知道托德经常访问一个由她控制的网站 http://blog.aliceisawesome.com
,因此Alice在她的网站上放置了以下代码片段:
当Todd再次访问Alice的网站时,他的浏览器错误地认为这个片段链接到一个图片. 浏览器会自动发出一个 HTTP GET
请求获取图片. 但不是让图像显示在浏览器中, 请求指示托德的银行转账1美元,500 to Alice.
Incidentally, 除了演示CSRF漏洞之外, 此示例还演示了使用控件更改服务器状态 idempotent (safe)HTTP GET
request. 这本身就是一个严重的弱点. HTTP GET
requests must 是幂等的,这意味着它们不能改变被访问的资源. 永远不要使用幂等方法来更改服务器状态.
有趣的事实:CSRF也是过去人们用来填充饼干的方法,直到附属机构变得更聪明.
Prevention: 将秘密令牌存储在第三方站点无法访问的隐藏表单字段中. 当然,这需要您验证隐藏字段. 有些网站在允许你修改敏感设置(比如密码提醒邮件)之前可能会要求你输入密码。. 我怀疑这可能是为了防止您在公共计算机上放弃的会话被滥用.
The title says it all. 我将这个问题更多地归类为维护/部署问题. 在合并新代码之前,做一些研究,并可能进行一些审核. 用一个随机的人的代码 GitHub,例如,它可能很方便,但并非没有严重的网络安全漏洞的风险.
我见过很多网站被拥有的例子.e.,其中外部人员获得对系统的管理访问权限),因为第三方软件(例如.g.(WordPress插件)在生产中多年未打补丁. 如果你认为他们不会发现你的隐藏 phpmyadmin
安装,让我给你介绍一下 DirBuster.
这里的教训是,软件开发并没有在应用程序部署后结束. 必须要有文件证明, tests, 以及如何维护和保持应用程序更新的计划, 特别是如果它包含第三方或开源组件.
Prevention:
不要做一个复制粘贴编码员. 仔细检查将要放入软件的代码, as it might be broken or, in some cases, intentionally malicious. Web安全攻击有时会以这种方式在不知不觉中引起.
使用你信任的所有软件的最新版本, 制定一个定期更新的计划. 要随时掌握新的安全漏洞,请订阅您的产品时事通讯.
这是另一个输入过滤问题. 假设目标站点有 redirect.php
模块,该模块接受URL作为 GET
parameter. 操作该参数可以在上创建一个URL targetsite.com
将浏览器重定向到 malwareinstall.com
. 用户将看到链接为 targetsite.com/blahblahblah
,它看起来无害,足以让人信任和点击. 但是点击这个链接可能会将用户转移到一个恶意软件删除(或任何其他恶意)页面. 或者,攻击者可能会将浏览器重定向到 targetsite.com/deleteprofile?confirm=1
.
值得一提的是,将未经处理的用户定义输入填充到 HTTP
header might lead to header injection, which is pretty bad.
Prevention: Options include:
我希望我能逗乐你的大脑,并介绍一剂健康的偏执狂和网站安全漏洞意识.
这里的核心要点是,古老的软件实践存在是有原因的. 在今天的Python中,用于缓冲区溢出的方法仍然适用于pickle字符串. 安全协议帮助我们编写更好、更安全的程序,这是我们应该追求的.
请负责任地使用这些知识,不要在未经允许的情况下测试页面!
For more information, see 特定的服务器端攻击 and OWASP’s Attacks page.
欢迎对这篇文章及其缓解建议的反馈和赞赏. 要求我将来写一篇关于网络保护的文章, 请直接通过gergely@toptal与我联系.com.
这里是网站安全! Cheers.
互联网安全威胁是滥用网络技术损害网站的方法, its users, 甚至是整个互联网. 威胁来自于配置错误的网站, 无意中编写了漏洞, 或者依赖于自身脆弱的组件.
最大的互联网安全威胁总是在不断发展, 注入和身份验证漏洞通常排在最前面. 开放Web应用程序安全项目(OWASP), 国际非营利组织, 编制并每年发布其OWASP十佳榜单.
确保任何重定向你的网站做(e).g., via HTTP headers, meta tags, JavaScript)不依赖于用户输入, 或者任何用户输入都是经过处理的.g., via a whitelist).
跨站点请求伪造(CSRF)令牌让服务器知道请求来自该站点上的某个用户,而不是来自该用户正在访问的另一个网站. 这是因为令牌是通过隐藏的表单字段随每个请求一起传递的, 防止恶意网站通过CSRF攻击代表其浏览者行事.
也称为“脏”或“不可信”输入, 未经验证的输入可能是发送到服务器的任何输入. 使用此类输入而不首先对其进行消毒是一个安全漏洞,可能会针对您或您的用户.
SQL注入是指代码将未经验证的输入直接添加到SQL语句中, 而不是使用参数化查询. Fortunately, 每个数据库库都内置了参数化查询支持, 所以SQL注入攻击是最容易缓解的攻击之一.
XSS(跨站点脚本)利用了一个常见的web应用程序特性的错误实现:从一个用户接收HTML并将其呈现给其他用户的能力. 因为未经过滤的HTML可以包含JavaScript, 攻击者可以接收到, 然后,当另一个用户返回web应用程序时,代表另一个用户(或多个用户)运行代码.
安全错误配置是指在生产环境中的应用程序中不希望出现的默认值. 配置错误还指没有及时安装安全更新.
这是指服务器没有被编程为验证给定函数的授权. 破坏访问控制可能是由于“通过模糊实现安全”的思维方式造成的:一种错误的假设,即如果敏感功能没有显着显示, 潜在的攻击者永远也找不到它.
敏感数据暴露是指应用程序(由于其自身的缺陷或攻击者滥用漏洞)泄露用户的私人数据(例如,数据泄露).g.(信用卡号码)给未经授权的第三方.
Gergely曾担任Alexa 50强网站的首席开发人员,该网站每月为数百万独立访问者提供服务.
世界级的文章,每周发一次.
世界级的文章,每周发一次.
Join the Toptal® community.