关于wcf:保护REST API / Web服务的最佳实践

Best Practices for securing a REST API / web service

在设计RESTAPI或服务时,是否存在处理安全性(身份验证、授权、身份管理)的既定最佳实践?

在构建SOAP API时,您可以将WS-Security作为指南,并且有很多关于这个主题的文献。我发现有关保护REST端点的信息较少。

虽然我知道REST故意没有类似于WS-*的规范,但我希望已经出现了最佳实践或推荐的模式。

任何讨论或相关文件的链接将非常感谢。如果这很重要,我们将使用wcf和pox/json序列化消息,用于使用.NET框架的v3.5构建的RESTAPI/服务。


正如Tweakt所说,AmazonS3是一个很好的模型。它们的请求签名确实具有一些功能(例如合并时间戳),有助于防止意外和恶意的请求重播。

关于HTTPBasic的好处是几乎所有的HTTP库都支持它。当然,在这种情况下,您需要使用SSL,因为通过网络发送纯文本密码几乎是一件坏事。使用ssl时,basic比digest更好,因为即使调用方已经知道需要凭据,digest也需要额外的往返以交换nonce值。使用basic,调用者只需第一次发送凭证。

一旦建立了客户机的身份,授权实际上只是一个实现问题。但是,您可以使用现有的授权模型将授权委托给其他某个组件。同样,basic的好处在于,您的服务器最终得到了客户机密码的纯文本副本,您可以根据需要简单地将其传递给基础结构中的另一个组件。


除了HTTP之外,没有其他标准。有现成的休息服务。我建议你看一眼,看看他们是怎么工作的。

例如,在开发自己的S3 REST服务时,我们借鉴了很多亚马逊的想法。但是我们选择不使用基于请求签名的更高级的安全模型。更简单的方法是通过SSL进行HTTP基本身份验证。你必须决定什么在你的情况下最有效。

另外,我强烈推荐O'Reilly的书Restful Web服务。它解释了核心概念,并提供了一些最佳实践。您通常可以采用他们提供的模型,并将其映射到您自己的应用程序。


您可能还想看看OAuth,这是一种新兴的开放式协议,专门针对HTTP API进行基于令牌的授权。

它非常类似于Flickr所采用的方法,并记住牛奶"rest"API(不一定是RESTful API的好例子,而是基于令牌的方法的好例子)。


Github上有一个很好的清单:

认证

  • 不要在身份验证、令牌生成、密码存储中重新发明轮子。使用标准。

  • 在登录时使用Max Retry和监禁功能。

  • 对所有敏感数据使用加密。

JWT(JSON Web令牌)

  • 使用一个随机复杂的密钥(JWT秘密)使得暴力强制令牌非常困难。

  • 不要从有效载荷中提取算法。强制后端中的算法(hs256或rs256)。

  • 尽可能缩短令牌到期时间(TTLRTTL)。

  • 不要在JWT有效载荷中存储敏感数据,它可以很容易地解码。

奥瑙

  • 始终验证服务器端的redirect_uri以仅允许白名单URL。

  • 始终尝试交换代码而不是令牌(不允许使用response_type=token)。

  • 使用带有随机散列的状态参数来防止OAuth身份验证过程中的CSRF

  • 定义默认范围,并验证每个应用程序的范围参数。

通路

  • 限制请求(限制)以避免ddos/暴力攻击。

  • 在服务器端使用HTTPS以避免MITM(中间人攻击)

  • 使用带ssl的HSTS头避免ssl条带攻击。

输入

  • 根据操作使用适当的HTTP方法:GET(read)、POST(create)、PUT/PATCH(replace/update)、DELETE(删除一条记录),如果请求的方法不适合请求的资源,用405 Method Not Allowed响应。

  • 根据要求验证内容类型Accept头(内容协商),仅允许您支持的格式(如application/xmlapplication/json等),如果不匹配,则使用406 Not Acceptable响应。

  • 在您接受时验证已发布数据的content-type(如application/x-www-form-urlencodedmultipart/form-dataapplication/json等)。

  • 验证用户输入以避免常见的漏洞(如XSS、SQL注入、远程代码执行等)。

  • 不要在URL中使用任何敏感数据(凭证、密码、安全令牌或API密钥),而是使用标准的Authorization头。

  • 使用API网关服务启用缓存、Rate Limit策略(例如配额、峰值停止、并发速率限制)并动态部署API资源。

处理

  • 检查所有端点是否在身份验证之后受到保护,以避免破坏身份验证过程。

  • 应避免使用用户自己的资源ID。使用/me/orders而不是/user/654321/orders。

  • 不要自动增加ID。改为使用UUID。

  • 如果要分析XML文件,请确保未启用实体分析以避免XXE(XML外部实体攻击)。

  • 如果您正在分析XML文件,请确保未启用实体扩展,以避免通过指数实体扩展攻击造成数十亿次笑声/XML爆炸。

  • 使用cdn进行文件上载。

  • 如果您处理的是大量的数据,请使用工作者和队列尽可能多地在后台处理,并快速返回响应以避免HTTP阻塞。

  • 不要忘记关闭调试模式。

产量

  • 发送X-Content-Type-Options: nosniff头。

  • 发送X-Frame-Options: deny头。

  • 发送Content-Security-Policy: default-src 'none'头。

  • 拆下指纹头段-X-Powered-ByServerX-AspNet-Version等。

  • 强制content-type响应,如果返回application/json,则响应内容类型为application/json

  • 不要返回敏感数据,如凭据、密码、安全令牌。

  • 根据完成的操作返回正确的状态代码。(如200 OK400 Bad Request401 Unauthorized405 Method Not Allowed等)。


我有点惊讶带有客户端证书的SSL还没有被提到。当然,这种方法只有在您可以依靠由证书标识的用户社区时才真正有用。但许多政府/公司确实向其用户发布了它们。用户不必担心创建另一个用户名/密码组合,并且在每个连接上都建立了标识,因此与服务器的通信可以完全无状态,不需要用户会话。(不意味着上述任何/所有其他解决方案都需要会议)


这些答案中的每个人都忽略了真正的访问控制/授权。

例如,如果您的RESTAPI/Web服务是关于发布/获取医疗记录的,那么您可能需要定义访问控制策略,以确定谁可以访问数据以及在什么情况下访问数据。例如:

  • 医生可以得到与他们有护理关系的病人的病历。
  • 没有人可以在实习时间以外发布医疗数据(例如9到5)
  • 最终用户可以获得他们自己的病历或他们作为监护人的患者的病历。
  • 护士可以更新与护士属于同一单位的患者的病历。

为了定义和实现这些细粒度授权,需要使用一种基于属性的访问控制语言xacml,即可扩展的访问控制标记语言。

其他标准如下:

  • OAuth:id.联盟和授权委托,例如让服务代表我执行其他服务(Facebook可以发布到我的Twitter)
  • SAML:Identity Federation/Web SSO。SAML非常关注用户是谁。
  • WS-Security/WS-*标准:这些关注于SOAP服务之间的通信。它们是特定于应用程序级消息传递格式(SOAP)的,它们处理消息传递的各个方面,例如可靠性、安全性、机密性、完整性、原子性、事件…无覆盖访问控制,所有都是特定于SOAP的。

XACML是技术不可知论者。它可以应用于Java应用程序,.NET,Python,露比…Web服务、REST API等。

以下是有趣的资源:

  • Oasis Xacml网站
  • NIST ABAC标准


我使用过OAuth几次,还使用了其他一些方法(基本/摘要)。我全心全意地建议Oauth。以下链接是我见过的关于使用OAuth的最佳教程:

网址:http://hueniverse.com/oauth/guide/


我遇到过的关于安全的最好的一个帖子是在一个雨点结束。MySpace API使用OAuth也是出于安全考虑,您可以在restchess代码中完全访问它们的自定义通道,我对此做了很多探索。这是Mix的演示,你可以在这里找到帖子。


谢谢你的建议。最后,我们使用一个自定义HTTP头将标识令牌从客户端传递到服务,以准备将我们的RESTfulAPI和即将到来的Microsoft Zermatt标识框架集成在一起。我在这里描述了这个问题和我们的解决方案。我还听取了Tweakt的建议,购买了RESTful Web服务——如果您正在构建任何类型的RESTful API,这是一本非常好的书。


OWASP(OpenWebApplicationSecurityProject)有一些介绍Web应用程序开发各个方面的备忘表。这个项目是一个非常有价值和可靠的信息来源。关于REST服务,您可以查看:https://www.owasp.org/index.php/rest_security_作弊表


我会推荐Oauth 2/3。您可以在http://oauth.net/2上找到更多信息。/


我搜索了很多关于RESTful WS-Security的内容,最后我们还通过cookie从客户机到服务器使用令牌对请求进行身份验证。我使用Spring Security对服务中的请求进行授权,因为我必须根据已经在DB中的指定安全策略对每个请求进行身份验证和授权。


事实上,SOAP世界被安全标准很好地覆盖并不意味着它在默认情况下是安全的。首先,标准非常复杂。复杂性不是安全的好朋友,而XML签名包装攻击等实现漏洞在这里很普遍。

对于.NET环境,我没有多大帮助,但是"用Java构建Web服务"(一个10个作者的砖块)确实帮助了我理解WS-*安全体系,尤其是它的怪癖。


我想添加(与臭马特一致),最简单的解决方案是向您的站点添加SSL证书。换句话说,请确保您的URL是https://。这将包括你的交通安全(公事公办)。使用restful url的想法是保持简单(不像ws*security/saml),您可以使用oauth2/openid connect甚至基本身份验证(在简单的情况下)。但您仍然需要SSL/HTTPS。请检查ASP.NET Web API 2安全性:http://www.asp.net/web-api/overview/security(文章和视频)


REST本身没有提供安全标准,但是像OAuth和SAML这样的东西正在迅速成为这个领域的标准。但是,认证和授权只是您需要考虑的一小部分。许多与Web应用程序相关的已知漏洞非常适用于RESTAPI。您必须考虑输入验证、会话破解、不适当的错误消息、内部员工漏洞等。这是一个大问题。


因为@nathan最后得到了一个简单的HTTP头,一些人说OAuth2和客户端SSL证书。关键是…您的RESTAPI不需要处理安全性,因为这实际上应该超出API的范围。

相反,无论是Web代理背后的HTTP头(一种常见的方法,如SiteMinder、Zermatt甚至ApacheHTTPD),还是像OAuth2一样复杂,都应该在其上放置一个安全层。

关键是请求应该在没有任何终端用户交互的情况下工作。所需要的只是确保与RESTAPI的连接经过身份验证。在JavaEE中,我们有一个EDOCX1 0的概念,它可以在EDCOX1 1中获得。部署描述符中还管理了URL模式的安全性,因此不需要再检查其余的API代码。

在WCF世界中,我将使用ServiceSecurityContext.Current来获取当前的安全上下文。您需要将应用程序配置为需要身份验证。

我上面的语句有一个例外,那就是使用nonce来防止重播(可能是攻击或者有人只提交了两次相同的数据)。该部分只能在应用程序层中处理。


对于Web应用程序的安全性,您应该看看owasp(https://www.owasp.org/index.php/main_page),它为各种安全攻击提供了欺骗表。您可以采取尽可能多的措施来保护您的应用程序。关于API安全性(授权、身份验证、身份管理),有多种方法(基本、摘要和OAuth)。OAuth1.0中有循环孔,因此可以使用OAuth1.0a(由于与规范有关,OAuth2.0没有被广泛采用)。


已经有一段时间了,但这个问题仍然是相关的,尽管答案可能有点改变。

API网关将是一个灵活且高度可配置的解决方案。我测试和使用了金刚相当多,真的很喜欢我所看到的。Kong提供了自己的admin rest API,您可以使用它来管理用户。

express-gateway.io是最新的,也是一个API网关。