提问人:Nathan 提问时间:8/11/2008 最后编辑:Jakub KubrynskiNathan 更新时间:7/5/2023 访问量:316740
保护 REST API/Web 服务的最佳实践 [已关闭]
Best Practices for securing a REST API / web service [closed]
问:
在设计 REST API 或服务时,是否有任何既定的最佳实践来处理安全性(身份验证、授权、身份管理)?
在构建 SOAP API 时,您有 WS-Security 作为指南,并且有很多关于该主题的文献。我发现有关保护REST端点的信息较少。
虽然我知道REST有意没有类似于WS-*的规范,但我希望已经出现了最佳实践或推荐的模式。
任何讨论或与相关文件的链接将不胜感激。 如果重要的话,我们将使用 WCF 和 POX/JSON 序列化消息,用于使用 .NET Framework v3.5 构建的 REST API/服务。
答:
除了 HTTP 之外,没有其他 REST 标准。那里有成熟的REST服务。我建议你看一看它们,感受一下它们是如何工作的。
例如,在开发自己的S3 REST服务时,我们从Amazon的S3 REST服务中借鉴了很多想法。但我们选择不使用基于请求签名的更高级的安全模型。更简单的方法是通过 SSL 进行 HTTP 基本身份验证。你必须决定什么最适合你的情况。
另外,我强烈推荐 O'reilly 的 RESTful Web Services 一书。它解释了核心概念,并提供了一些最佳实践。您通常可以使用他们提供的模型并将其映射到您自己的应用程序。
评论
正如 tweakt 所说,Amazon S3 是一个很好的模型。它们的请求签名确实具有一些功能(例如合并时间戳),有助于防止意外和恶意请求重播。
HTTP Basic 的好处是几乎所有的 HTTP 库都支持它。当然,在这种情况下,您需要使用SSL,因为通过网络发送明文密码几乎是一件坏事。使用 SSL 时,Basic 比 Digest 更可取,因为即使调用方已经知道需要凭据,Digest 也需要额外的往返行程来交换 nonce 值。使用 Basic,调用方只需在第一次发送凭据即可。
一旦客户端的身份建立起来,授权实际上只是一个实现问题。但是,您可以使用现有授权模型将授权委托给其他组件。同样,Basic 的好处是您的服务器最终会得到客户端密码的明文副本,您可以根据需要简单地将其传递给基础架构中的另一个组件。
评论
"sending plaintext passwords over the net is almost universally a bad thing"
- 你能详细说明一下“几乎”吗?什么时候不是一个坏主意?
感谢您的出色建议。我们最终使用自定义 HTTP 标头将身份令牌从客户端传递到服务,以准备将我们的 RESTful API 与 Microsoft 即将推出的 Zermatt Identity 框架集成。我在这里描述了这个问题,在这里描述了我们的解决方案。我还采纳了 tweakt 的建议,购买了 RESTful Web Services——如果你正在构建任何类型的 RESTful API,这是一本非常好的书。
评论
您可能还想看看 OAuth,这是一种新兴的基于令牌的授权开放协议,专门针对 http api。
它与 flickr 所采用的方法非常相似,并记住 milk “rest” api(不一定是 restful API 的好例子,但基于令牌的方法的好例子)。
评论
我遇到过的关于安全性的最好的帖子之一,因为它与 REST 相关,在 1 RainDrop 结束。MySpace API 也使用 OAuth 来确保安全性,您可以在 RestChess 代码中完全访问它们的自定义通道,我对此进行了大量探索。这是在 Mix 上演示的,您可以在此处找到帖子。
评论
我使用过几次 OAuth,还使用过一些其他方法(BASIC/DIGEST)。我全心全意地推荐 OAuth。以下链接是我见过的关于使用 OAuth 的最佳教程:
评论
我有点惊讶尚未提及带有客户端证书的SSL。诚然,只有当您可以依靠证书标识的用户社区时,这种方法才真正有用。但许多政府/公司确实向用户发行了它们。用户不必担心创建另一个用户名/密码组合,并且在每个连接上都建立了身份,因此与服务器的通信可以完全无状态,不需要用户会话。(并不意味着提到的任何/所有其他解决方案都需要会话)
评论
我搜索了很多关于 restful ws 安全性的信息,我们最终还通过 cookie 从客户端到服务器使用令牌来验证请求。我使用 Spring Security 对服务中的请求进行授权,因为我必须根据数据库中已有的指定安全策略对每个请求进行身份验证和授权。
REST本身没有提供安全标准,但像OAuth和SAML这样的东西正在迅速成为这个领域的标准。但是,身份验证和授权只是您需要考虑的一小部分。许多与 Web 应用程序相关的已知漏洞都非常适用于 REST API。您必须考虑输入验证、会话破解、不适当的错误消息、内部员工漏洞等。这是一个很大的话题。
我会推荐 OAuth 2/3。您可以在 http://oauth.net/2/ 找到更多信息
评论
这些答案中的每个人都忽略了真正的访问控制/授权。
例如,如果您的 REST API/Web 服务是关于 POSTing/GETing 医疗记录的,您可能希望定义关于谁可以访问数据以及在什么情况下访问数据的访问控制策略。例如:
- 医生可以获取与他们有护理关系的患者的病历
- 没有人可以在执业时间之外(例如朝九晚五)发布医疗数据
- 最终用户可以获取他们拥有的医疗记录或他们作为监护人的患者的医疗记录
- 护士可以更新与护士属于同一单位的患者的病历。
为了定义和实现这些细粒度的授权,您需要使用一种基于属性的访问控制语言,称为 XACML,即可扩展访问控制标记语言。
此处的其他标准适用于以下内容:
- OAuth:id.联合和授权授权,例如,让一个服务代表我在另一个服务上执行操作(Facebook可以发布到我的Twitter)
- SAML:联合身份验证/Web SSO。SAML 非常关注用户是谁。
- WS-Security / WS-* 标准:这些标准侧重于 SOAP 服务之间的通信。它们特定于应用程序级消息传递格式 (SOAP),它们处理消息传递的各个方面,例如可靠性、安全性、机密性、完整性、原子性、事件......没有一个涵盖访问控制,并且都特定于 SOAP。
XACML 与技术无关。它可以应用于 java 应用程序、.NET、Python、Ruby......Web 服务、REST API 等。
以下是有趣的资源:
- OASIS XACML 网站
- NIST ABAC标准
评论
事实上,SOAP世界已经很好地覆盖了安全标准,但这并不意味着它默认是安全的。首先,标准非常复杂。复杂性不是安全性和实现的好朋友,XML 签名包装攻击等漏洞在这里很普遍。
至于 .NET 环境,我不会有太大帮助,但是“使用 Java 构建 Web 服务”(一个有 ~10 个作者的砖块)确实对我理解 WS-* 安全架构,尤其是它的怪癖有很大帮助。
OWASP(Open Web Application Security Project)有一些备忘单,涵盖了 Web 应用程序开发的所有方面。这个项目是一个非常有价值和可靠的信息来源。 关于REST服务,您可以检查以下内容: https://www.owasp.org/index.php/REST_Security_Cheat_Sheet
我想添加(与stinkeymatt一致),最简单的解决方案是将SSL证书添加到您的网站。换句话说,请确保您的 URL 已 HTTPS://。这将涵盖您的运输安全(物超所值)。使用 RESTful url,其想法是保持简单(与 WS* 安全性/SAML 不同),您可以使用 oAuth2/openID 连接甚至基本身份验证(在简单情况下)。但是您仍然需要 SSL/HTTPS。请在此处检查 ASP.NET Web API 2 安全性:http://www.asp.net/web-api/overview/security(文章和视频)
@Nathan最终得到了一个简单的 HTTP 标头,有些人说 OAuth2 和客户端 SSL 证书。它的要点是这样的......您的 REST API 不应该处理安全性,因为这实际上应该超出 API 的范围。
相反,无论是在Web代理后面的HTTP标头(SiteMinder,Zermatt甚至Apache HTTPd等常见方法),还是像OAuth 2一样复杂的安全层,都应该在其之上放置一个安全层。
关键是请求应该在没有任何最终用户交互的情况下工作。所需要做的就是确保与 REST API 的连接已通过身份验证。在 Java EE 中,我们有一个概念,可以在 .它还在部署描述符中进行管理,即 URL 模式是安全的,因此 REST API 代码不再需要检查。userPrincipal
HttpServletRequest
在 WCF 世界中,我将用于获取当前的安全上下文。您需要将应用程序配置为要求身份验证。ServiceSecurityContext.Current
我上面的陈述有一个例外,那就是使用随机数来防止重放(这可能是攻击或有人只是两次提交相同的数据)。该部分只能在应用层中处理。
对于 Web 应用程序安全,您应该查看 OWASP (https://www.owasp.org/index.php/Main_Page),它为各种安全攻击提供了备忘单。您可以采用尽可能多的措施来保护您的应用程序。 关于 API 安全性(授权、身份验证、身份管理),如前所述,有多种方法(Basic、Digest 和 OAuth)。OAuth1.0 中存在漏洞,因此可以使用 OAuth1.0a(由于规范问题,OAuth2.0 未被广泛采用)
已经有一段时间了,但这个问题仍然很重要,尽管答案可能已经发生了一些变化。
API 网关将是一个灵活且高度可配置的解决方案。 我测试和使用了KONG很多,真的很喜欢我所看到的。KONG 提供了自己的管理 REST API,您可以使用它来管理用户。
Express-gateway.io 是较新的,也是一个 API 网关。
在 Github 上有一个很好的清单:
认证
不要在身份验证、令牌生成、密码存储方面重新发明轮子。使用标准。
登录中的使用和监狱功能。
Max Retry
对所有敏感数据使用加密。
JWT(JSON Web 令牌)
使用随机的复杂密钥(JWT Secret)使暴力破解令牌变得非常困难。
不要从有效负载中提取算法。在后端(HS256 或 RS256)强制执行算法。
使令牌过期时间 (, ) 尽可能短。
TTL
RTTL
不要将敏感数据存储在有效负载中,它可以轻松解码。
JWT
OAuth的
始终验证服务器端以仅允许列入白名单的 URL。
redirect_uri
始终尝试交换代码而不是令牌(不允许)。
response_type=token
使用带有随机哈希的 state 参数来防止身份验证过程。
CSRF
OAuth
定义默认范围,并验证每个应用程序的范围参数。
访问
限制请求(限制)以避免 DDoS/暴力攻击。
在服务器端使用 HTTPS 来避免 MITM(中间人攻击)
使用带有 SSL 的标头以避免 SSL Strip 攻击。
HSTS
输入
根据操作使用正确的 HTTP 方法:(读取)、(创建)、(替换/更新)和(删除记录),如果请求的方法不适合请求的资源,则进行响应。
GET
POST
PUT/PATCH
DELETE
405 Method Not Allowed
验证请求标头上的 content-type(内容协商)以仅允许支持的格式(例如 、 等),如果不匹配,则使用响应进行响应。
Accept
application/xml
application/json
406 Not Acceptable
在您接受时验证发布的数据(例如、、等)。
content-type
application/x-www-form-urlencoded
multipart/form-data
application/json
验证用户输入以避免常见漏洞(例如 XSS、SQL 注入、远程代码执行等)。
请勿在 URL 中使用任何敏感数据(凭据、密码、安全令牌或 API 密钥),而应使用标准标头。
Authorization
使用 API Gateway 服务启用缓存、策略(例如配额、峰值阻止、并发速率限制)并动态部署 API 资源。
Rate Limit
加工
检查所有端点是否都受到身份验证的保护,以避免身份验证过程中断。
应避免使用用户自己的资源 ID。使用 /me/orders 而不是 /user/654321/orders。
不要自动递增 ID。请改用 UUID。
如果要解析 XML 文件,请确保未启用实体解析以避免 XXE(XML 外部实体攻击)。
如果要解析 XML 文件,请确保未启用实体扩展,以避免通过指数实体扩展攻击进行 Billion Laughs/XML 炸弹。
使用 CDN 上传文件。
如果您正在处理大量数据,请使用 Workers 和 Queues 在后台尽可能多地处理,并快速返回响应以避免 HTTP 阻塞。
不要忘记关闭 DEBUG 模式。
输出
发送标头。
X-Content-Type-Options: nosniff
发送标头。
X-Frame-Options: deny
发送标头。
Content-Security-Policy: default-src 'none'
删除指纹标头 - 、 等。
X-Powered-By
Server
X-AspNet-Version
强制响应,如果返回,则响应内容类型为 。
content-type
application/json
application/json
不要返回敏感数据,如凭据、密码、安全令牌。
根据完成的操作返回正确的状态代码。(例如 、 、 、 等)。
200 OK
400 Bad Request
401 Unauthorized
405 Method Not Allowed
评论