作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Gergely曾担任Alexa 50强网站的首席开发人员,该网站每月为数百万独立访问者提供服务.
编者注:本文由我们的编辑团队于2022年12月8日更新. 它已被修改,以包括最近的来源,并与我们目前的编辑标准保持一致.
For all too many companies, it’s not until after a security breach 网络安全最佳实践是否已经成为优先事项. 在我从事IT安全专业工作的这些年里, 我一次又一次地看到,web开发安全问题的世界对我的许多人来说是多么模糊 fellow programmers.
根据定义,应对网络安全威胁的有效方法必须是主动和防御的. Toward that end, 我们的目标是激发一种安全思维,给读者注入一剂健康的偏执.
In particular, 本指南的重点是培养对10个常见和重要的网络安全缺陷的认识并减轻这些缺陷.
程序员和IT专业人员经常对授权和身份验证之间的区别表示困惑. The use of the abbreviation auth 因为这两个词都增加了它们周围的朦胧.
Let’s define and clarify the distinction:
Stated another way, authentication is knowing who an entity is, while authorization is what a given entity can do. 考虑到这一点,让我们来探索10个常见的互联网漏洞问题.
注入缺陷源于过滤不可信输入的典型失败. 当我们将未经过滤的数据传递给SQL服务器(SQL注入)时,可能会发生注入缺陷。, to the browser (via Cross Site Scripting)、到LDAP服务器(LDAP注入)或其他任何地方. 这里的问题是攻击者可以注入命令来劫持客户端的浏览器, resulting in loss of data.
应用程序从不受信任的源接收的任何内容都必须进行过滤, preferably according to a whitelist. 由于配置困难,不建议使用黑名单. 黑名单也被认为很容易被黑客绕过. 杀毒软件产品通常会提供黑名单失败的典型例子. Pattern matching does not work.
Prevention: 防止注入“简单地”就是过滤我们的输入并考虑哪些发送者是可信的. 过滤是一项相当艰巨的任务,因为我们需要处理所有输入,除非它毫无疑问是可信的.
If we filter 999 inputs in a system with 1,000 inputs, 我们仍然有一个领域可以成为阿喀琉斯之踵,摧毁我们的系统.
Using Second Order SQL Injection 将一个SQL查询结果注入另一个SQL查询结果也被认为是危险的. 这似乎是个好主意,因为数据库是可信的. 但如果边界不在,我们的输入可能间接来自恶意来源.
Since filtering is pretty hard to get right, 我们建议使用框架的过滤函数. They are proven to work and thoroughly scrutinized. 如果您还没有使用框架,请考虑使用框架对服务器安全性的好处. .
在身份验证失败期间可能发生的问题不一定源于相同的根本原因. 不建议滚动您自己的身份验证代码,因为很难做到正确. 有无数可能的陷阱,这里有几个:
Prevention: 避免与身份验证失败相关的web安全漏洞的最直接方法是实现框架. If you roll your own code, 要极度偏执,对可能出现的潜在问题进行自我教育.
攻击者向您的web应用程序发送输入JavaScript标记. 当这个输入未经过处理返回给用户时,用户的浏览器将执行它. 这是一个相当普遍的输入消毒失败,本质上是一个子类 injection flaws). CSS可以像制作一个链接并说服用户点击它一样简单, or it can be something much more sinister. 例如,在页面加载时,脚本将运行并被用来将您的cookie发送给攻击者.
Prevention: Simply put, don’t return HTML tags to the client. This would also protect you from HTML injection, 当攻击者注入纯HTML内容(如图像或响亮但不可见的flash播放器). To implement this solution, convert all HTML entities to return something else. For example, convert to return
<script>
. 或者,您可以使用正则表达式去除HTML标记,使用正则表达式 <
and >
. 但这很危险,因为有些浏览器可能无法解释严重损坏的HTML. 最好将所有字符转换为转义的对应字符.
这是信任用户输入并通过继承结果付出代价的典型案例 security vulnerability. 直接对象引用意味着内部对象(例如.g.(如文件或数据库密钥)暴露给用户,使我们容易受到攻击. The attacker can provide this reference, 如果授权没有得到执行或被破坏, the attacker gets in.
For example, the code has a download.php
module that reads and lets the user download files, using a CGI parameter to specify the file name (e.g., download.php?file=something.txt
). 如果开发人员从代码中省略了授权, 攻击者现在可以使用它来下载运行PHP的用户可以访问的系统文件.g.(应用程序代码或随机服务器数据,如备份).
另一个不安全的直接对象引用漏洞的例子是依赖于用户输入来确定其身份的密码重置功能. 攻击者单击有效的URL后,可以修改 username
field in the URL to say something like “admin.”
顺便说一句,我经常在“野外”看到这两个例子.”
Prevention: 正确且一致地执行用户授权,并将选择列入白名单. More often than not, 通过在内部存储数据,而不依赖于通过CGI参数从客户端传递的数据,可以完全避免该漏洞. 大多数框架中的会话变量都非常适合这个目的.
根据我的经验,经常会遇到配置错误的web服务器和应用程序. Some examples:
Prevention: 有一个好的(最好是自动化的)“构建和部署”过程,它可以在部署上运行测试. 可怜的人的安全错误配置解决方案是提交后钩子, 防止带有默认密码和/或内置开发内容的代码泄露.
这个web安全漏洞是关于加密和资源保护的. 敏感数据在任何时候都应该加密,包括在传输和静止时. No exceptions. Credit card information and user passwords should never 不加密的旅行或存储,密码应该总是散列的. 显然,加密/散列算法不能是弱算法. When in doubt, web security standards recommend AES (256 bits and up) and RSA (2048 bits and up).
会话id和敏感数据不应该在url中传播,这一点再怎么强调也不为过. 带有敏感数据的cookie应该打开“安全”标志.
Prevention:
In transit: Use HTTPS with a proper certificate and PFS (Perfect Forward Secrecy). Do not accept anything over non-HTTPS connections. Have the “secure” flag on cookies.
In storage: Reduce your exposure to this vulnerability. 如果你不需要敏感数据,那就把它撕碎. The data you don’t have can’t be stolen. 不存储信用卡信息,你就不需要再处理了吗 PCI compliant. Sign up with a payment processor like Stripe or Braintree. 存储和加密敏感数据,并确保所有密码散列使用 bcrypt. If you don’t use bcrypt, educate yourself on salting and rainbow tables.
And at the risk of stating the obvious, 不要将加密密钥存储在受保护数据附近. 这就像把你的自行车放在锁里,锁里有钥匙. 用加密保护您的备份,并保持密钥的私密性. And of course, don’t lose the keys!
如果在服务器上调用函数时没有执行适当的授权,就会发生这种故障. 开发人员倾向于认为,既然是服务器端生成UI, 客户端将无法访问服务器不提供的功能. 事情并没有那么简单,因为攻击者总是可以伪造对“隐藏”功能的请求. 攻击者不会因为期望的功能不容易访问而却步. Imagine there’s an /admin
面板,并且该按钮仅在用户实际上是管理员时才出现在UI中. 如果缺少授权,没有什么可以阻止攻击者发现和滥用此功能.
Prevention: On the server side, authorization must always be performed.
In a CSRF—also referred to as a confused deputy 攻击—恶意的第三方欺骗浏览器,使其滥用其权限为攻击者做某些事情.
In the case of CSRF, a third-party site uses your browser, cookies, and session to issue a request to a target site (e.g., your bank). 如果在一个浏览器标签你登录到你的银行, 如果你的银行很容易受到这种攻击, 然后可以控制另一个选项卡,使您的浏览器以攻击者的名义滥用其凭据, which results in the confused deputy problem. 代理是滥用其权限(会话cookie)来执行攻击者指令的浏览器.
考虑一下这个例子:攻击者Alice想通过将目标Todd的一些钱转移到她的账户来减轻他的钱包.
To send money, Todd accesses the following URL:
http://example.com/app/transferFunds?amount=1500&destinationAccount=4673243243
顺便说一句,他的银行很容易受到CSRF的攻击. Todd执行他的事务后,显示一个成功页面,转账完成.
爱丽丝知道托德经常访问一个由她控制的网站 http://blog.aliceisawesome.com
,因此Alice在她的网站上放置了以下代码片段:
当Todd再次访问Alice的网站时,他的浏览器错误地认为这个片段链接到一个图片. The browser automatically issues an HTTP GET
request to fetch the picture. 但不是让图像显示在浏览器中, the request instructs Todd’s bank to transfer $1,500 to Alice.
Incidentally, in addition to demonstrating the CSRF vulnerability, 此示例还演示了使用控件更改服务器状态 idempotent (safe)HTTP GET
request. This in itself a serious vulnerability. HTTP GET
requests must 是幂等的,这意味着它们不能改变被访问的资源. 永远不要使用幂等方法来更改服务器状态.
有趣的事实:CSRF也是过去人们用来填充饼干的方法,直到附属机构变得更聪明.
Prevention: 将秘密令牌存储在第三方站点无法访问的隐藏表单字段中. 当然,这需要您验证隐藏字段. 有些网站在允许你修改敏感设置(比如密码提醒邮件)之前可能会要求你输入密码。. 我怀疑这可能是为了防止您在公共计算机上放弃的会话被滥用.
The title says it all. 我将这个问题更多地归类为维护/部署问题. 在合并新代码之前,做一些研究,并可能进行一些审核. Using code from a random person on GitHub,例如,它可能很方便,但并非没有严重的网络安全漏洞的风险.
我见过很多网站被拥有的例子.e.,其中外部人员获得对系统的管理访问权限),因为第三方软件(例如.g.(WordPress插件)在生产中多年未打补丁. If you think they will not find your hidden phpmyadmin
installation, let me introduce you to DirBuster.
这里的教训是,软件开发并没有在应用程序部署后结束. There has to be documentation, tests, 以及如何维护和保持应用程序更新的计划, 特别是如果它包含第三方或开源组件.
Prevention:
Do not be a copy-paste coder. 仔细检查将要放入软件的代码, as it might be broken or, in some cases, intentionally malicious. Web安全攻击有时会以这种方式在不知不觉中引起.
使用你信任的所有软件的最新版本, and have a plan to update regularly. 要随时掌握新的安全漏洞,请订阅您的产品时事通讯.
This is yet another input filtering issue. Suppose that the target site has a redirect.php
module that takes a URL as a GET
parameter. Manipulating the parameter can create a URL on targetsite.com
that redirects the browser to malwareinstall.com
. A user would see the link as targetsite.com/blahblahblah
, which looks innocuous enough to trust and click. 但是点击这个链接可能会将用户转移到一个恶意软件删除(或任何其他恶意)页面. 或者,攻击者可能会将浏览器重定向到 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 specific server side attacks and OWASP’s Attacks page.
欢迎对这篇文章及其缓解建议的反馈和赞赏. 要求我将来写一篇关于网络保护的文章, feel free to contact me directly at gergely@wxzjnt.com.
Here’s to website security! Cheers.
互联网安全威胁是滥用网络技术损害网站的方法, its users, or even the internet at large. Threats arise from websites that are misconfigured, were inadvertently programmed with vulnerabilities, 或者依赖于自身脆弱的组件.
最大的互联网安全威胁总是在不断发展, 注入和身份验证漏洞通常排在最前面. Open Web Application Security Project (OWASP), an international nonprofit organization, compiles and publishes its OWASP Top 10 annually.
Make sure that any redirects your site makes (e.g., via HTTP headers, meta tags, JavaScript) do not rely on user input, or that any user input is sanitized (e.g., via a whitelist).
跨站点请求伪造(CSRF)令牌让服务器知道请求来自该站点上的某个用户,而不是来自该用户正在访问的另一个网站. 这是因为令牌是通过隐藏的表单字段随每个请求一起传递的, 防止恶意网站通过CSRF攻击代表其浏览者行事.
Also known as “dirty” or “untrusted” input, 未经验证的输入可能是发送到服务器的任何输入. 使用此类输入而不首先对其进行消毒是一个安全漏洞,可能会针对您或您的用户.
SQL注入是指代码将未经验证的输入直接添加到SQL语句中, instead of using a parameterized query. Fortunately, 每个数据库库都内置了参数化查询支持, 所以SQL注入攻击是最容易缓解的攻击之一.
XSS(跨站点脚本)利用了一个常见的web应用程序特性的错误实现:从一个用户接收HTML并将其呈现给其他用户的能力. Because unfiltered HTML can contain JavaScript, an attacker can receive it, 然后,当另一个用户返回web应用程序时,代表另一个用户(或多个用户)运行代码.
安全错误配置是指在生产环境中的应用程序中不希望出现的默认值. 配置错误还指没有及时安装安全更新.
这是指服务器没有被编程为验证给定函数的授权. 破坏访问控制可能是由于“通过模糊实现安全”的思维方式造成的:一种错误的假设,即如果敏感功能没有显着显示, potential attackers will never find it.
敏感数据暴露是指应用程序(由于其自身的缺陷或攻击者滥用漏洞)泄露用户的私人数据(例如,数据泄露).g.(信用卡号码)给未经授权的第三方.
Gergely曾担任Alexa 50强网站的首席开发人员,该网站每月为数百万独立访问者提供服务.
World-class articles, delivered weekly.
World-class articles, delivered weekly.
Join the Toptal® community.