跳转到主要内容
Chinese, Simplified

category

Spring Boot极大地简化了Spring应用程序的开发。它的自动配置和启动器依赖关系减少了启动应用程序所需的代码和配置量。

Spring Boot于2014年首次发布,自那以后发生了很多变化。就像代码质量和测试一样,安全性已经成为开发人员关注的问题。如果您是一名开发人员,并且不关心安全性,那么您可能认为您应该关心安全性。本文的目的是向您介绍如何创建更安全的Spring引导应用程序。

我与Simon Maple合作撰写了这篇文章,他是斯奈德的Java冠军和开发人员关系主管。我们都为安全行业的公司工作,热爱Java,并希望帮助开发人员创建更安全的应用程序。我们认为写这篇文章将是一个回馈社区的有趣方式。如果您对我们列出的有其他建议,请在评论中添加!

1. 在生产中使用HTTPS

传输层安全性(TLS)是HTTPS的官方名称。您可能听说过它被称为SSL(安全套接字层)。SSL是不推荐的名称。TLS是一种通过计算机网络提供安全通信的加密协议。它的主要目标是确保计算机应用程序之间的隐私和数据完整性。

TLS/SSL证书过去很昂贵,HTTPS被认为很慢。机器变得更快,解决了性能问题,让我们加密提供免费的TLS证书。这两个发展已经改变了游戏,并使TLS成为主流。

自2018年7月24日起,谷歌Chrome浏览器将HTTP站点标记为“不安全”。虽然这在web社区中引起了相当多的争议,但它仍然存在。特洛伊亨特,一位著名的安全研究员,创造了一个为什么没有HTTPS?跟踪不使用HTTPS的大型网站的站点。你可能不会开发下一个主要的网站,但是为什么要限制自己呢?

生成和更新Let 's加密的TLS证书可以实现自动化。既然他们是免费的,就没有理由不去做!Let 's Encrypt保护的Spring引导是关于如何做到这一点的有用指南。

要在Spring Boot应用程序中强制使用HTTPS,可以扩展WebSecurityConfigurerAdapter并要求安全连接。

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
 @Override
 protected void configure(HttpSecurity http) throws Exception {
 http.requiresChannel().requiresSecure();
 }
}

此配置还将强制HTTPS进入开发,这可能会带来麻烦,因为您必须使用自签名证书。如果使用Heroku、Cloud Foundry或其他云提供商,更合理的配置是寻找x - forward - proto头文件。

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
 @Override
 protected void configure(HttpSecurity http) throws Exception {
 http.requiresChannel()
 .requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null)
 .requiresSecure();
 }
}

云提供商可以极大地简化TLS证书。Amazon证书管理器与Let 's加密完全一样,只是默认情况下它内置在所有AWS产品/服务中。它允许您提供100%免费的SSL证书,并处理自动更新等,几乎不需要任何工作/配置。Heroku也有自动的证书管理。

另一个要做的重要事情是使用HTTP严格传输安全(HSTS)。HSTS是一种web安全策略机制,用于保护网站免受协议降级攻击和cookie劫持。服务器使用名为Strict-Transport-Security的响应头字段将HSTS策略与浏览器通信。Spring Security在缺省情况下发送此头,以避免在开始时不必要的HTTP跳转。

2. 使用斯奈德(Snyk)检查依赖

您很可能不知道应用程序使用了多少直接依赖项。您极有可能不知道应用程序使用了多少传递依赖项。这通常是正确的,尽管依赖关系构成了整个应用程序的大部分。攻击者越来越多地瞄准开源依赖关系,因为它们的重用为恶意黑客提供了许多受害者。确保应用程序的整个依赖树中没有已知的漏洞是很重要的。

斯奈德测试你的应用程序构建构件,标记那些已知漏洞的依赖关系。它为您提供了一个存在于您的应用程序中用作仪表板的包中的漏洞列表。

security

此外,它将建议升级版本或提供补丁,通过对源代码存储库发出拉请求来修复安全性问题。snyder还保护您的环境,通过确保将来在您的存储库中提出的任何pull请求都被自动测试(通过webhook),以确保它们不会引入新的已知漏洞。

每天都会在现有的项目和库中发现新的漏洞,因此监视和保护生产部署非常重要。斯奈德会拍快照并监控你的部署,这样当发现新的漏洞时,你可以通过你喜欢的频道,JIRA, slack或电子邮件自动通知你,并创建拉请求来为新的漏洞提供升级和补丁。

snyder k通过web UI和CLI可用,因此您可以轻松地将其集成到CI环境中,并在漏洞严重程度超过设置阈值时配置它来破坏构建。

你可以免费使用斯奈德的开源项目或私人项目,每月测试的次数有限。

3.升级到最新版本

定期升级应用程序中的依赖项有多种原因。安全性是促使您进行升级的最重要原因之一。start.spring。io starter页面尽可能使用最新版本的Spring包以及依赖项。

“我发现,在依赖关系中寻找漏洞可能有助于激励人们进行升级。然而,有大量证据表明,并不是所有的cve都被报道。一般来说,我发现理想的解决方案(可能不实用)是最新的和最好的。——Rob Winch

基础设施升级的破坏性通常小于依赖项升级,因为库的作者对向后兼容性和版本之间的行为变化的敏感性不同。也就是说,当您在配置中发现安全漏洞时,您有三个选项:升级、补丁或忽略。

升级是最安全的,就应用程序的整体健康而言,在您对应用程序进行任何必要的更改以使用新版本之后。

脆弱项目的补丁将从包中消除该漏洞,但通常会留下一个配置,该配置可能没有经过很好的测试。对库的代码更改会更少,因为补丁只会更改易受攻击的代码,所以破坏向后兼容性或引入行为更改的几率会降低。第三方安全公司,如斯奈德手工修补了许多漏洞,所以如果不能升级到一个新的版本的库,你仍然可以使用旧版本的补丁。

忽略漏洞当然是一种选择,但不是一个好的选择。也许您知道某个漏洞,但是不相信它是可以直接利用的。请记住,它现在可能不在您的应用程序流中,但是在某个时候,开发人员可能会添加使用脆弱路径的额外代码。

4. 使CSRF保护

跨站点请求伪造是一种攻击,它迫使用户在当前登录的应用程序中执行不需要的操作。如果用户是普通用户,则成功的攻击可能涉及状态更改请求,如转移资金或更改电子邮件地址。如果用户拥有更高的权限,CSRF攻击可能危及整个应用程序。

Spring Security默认支持优秀的CSRF。如果您使用Spring MVC的标记或Thymeleaf和@EnableWebSecurity, CSRF令牌将自动添加为一个隐藏的输入字段。

如果您正在使用像Angular或React这样的JavaScript框架,则需要配置CookieCsrfTokenRepository,以便JavaScript能够读取cookie。

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 @Override
 protected void configure(HttpSecurity http) throws Exception {
 http
 .csrf()
 .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
 }
}

如果你使用Angular,这就是你需要做的。如果使用React,则需要读取XSRF-TOKEN cookie并将其作为X-XSRF-TOKEN头发送回去。

当通过HTTPS发出请求时,Spring Security会自动向XSRF-TOKEN cookie添加一个安全标志。Spring Security对CSRF cookie不使用SameSite=strict标志,但在使用Spring会话或WebFlux会话处理时使用。这对于会话cookie是有意义的,因为它被用来标识用户。它没有为CSRF cookie提供太多的价值,因为CSRF令牌也需要在请求中。

5. 使用内容安全策略来防止XSS攻击

内容安全策略(CSP)是一种附加的安全层,有助于减轻跨站点脚本攻击和数据注入攻击。要启用它,您需要将应用程序配置为返回Content-Security-Policy头。还可以在HTML页面中使用标记。

Spring security在默认情况下提供了许多安全头:

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

Spring Security默认情况下不添加CSP。您可以使用下面的配置在Spring Boot应用程序中启用CSP头。

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 @Override
 protected void configure(HttpSecurity http) throws Exception {
 http.headers()
 .contentSecurityPolicy("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/");
 }
}

CSP是防止XSS攻击的一种很好的防御手段。请记住,打开您的CSP以允许使用CDN通常会允许访问许多非常古老和脆弱的JavaScript库。这意味着使用CDN通常意味着您不再为应用程序的安全性增加很多价值。

您可以使用securityheaders.com测试您的CSP头文件。

6. 使用OpenID Connect进行身份验证

OAuth 2.0是用于授权的行业标准协议。它使用范围来定义授权用户可以执行哪些操作的权限。但是,OAuth 2.0不是一个身份验证协议,它不提供关于经过身份验证的用户的任何信息。

OpenID Connect (OIDC)是一个提供用户信息的OAuth 2.0扩展。除了访问令牌之外,它还添加了ID令牌,以及/userinfo端点,您可以从该端点获得附加信息。它还添加了端点发现特性和动态客户端注册。

下图显示了OIDC如何进行身份验证。

security

如果使用OIDC进行身份验证,就不必担心存储用户、密码或身份验证用户。相反,您将使用标识提供程序(IdP)为您完成这项工作。您的IdP甚至可能提供安全附加组件,比如多因素身份验证(multi-factor authentication, MFA)。

要了解如何在Spring引导应用程序中使用OIDC,请参阅Spring Security 5.0和OIDC入门。要总结如何使用它,您需要向项目添加一些依赖项,然后在应用程序中配置一些属性。yml文件。

spring:
 security:
 oauth2:
 client:
 registration:
 okta:
 client-id: {clientId}
 client-secret: {clientSecret}
 scope: openid email profile
 provider:
 okta:
 issuer-uri: https://{yourOktaDomain}/oauth2/default

注意:使用发布器uri只在Spring Security 5.1中得到支持,Spring Security 5.1正在积极开发中,计划于2018年9月发布。

您可以使用像Keycloak这样的开源系统来设置自己的OIDC服务器。如果您不希望在生产中维护自己的服务器,可以使用Okta的开发人员api。今天注册一个免费帐户,每月在developer.okta.com/signup上获得1000个活跃用户!

如果您想使用OAuth 2.0、OIDC以及它所允许的不同流,请参见https://www.oauth.com/playground。这个站点不需要您创建帐户,但是它确实在幕后使用了Okta的开发人员api。

7. 管理密码吗?使用密码散列!

对于应用程序的安全性来说,用纯文本存储密码是最糟糕的做法之一。幸运的是,Spring security默认不允许使用纯文本密码。它还附带一个加密模块,您可以使用该模块进行对称加密、密钥生成和密码散列(也称为密码散列)。、密码编码)。

PasswordEncoder是Spring Security中密码散列的主要接口,其外观如下:

public interface PasswordEncoder {
 String encode(String rawPassword);
 boolean matches(String rawPassword, String encodedPassword);
}

Pbkdf2PasswordEncoder。

对于一般的密码管理,我们建议使用SCrypt或Argon2。SCrypt现在很老了(已经有一段时间了),并且有一个BCrypt没有的额外复杂性因素,这使得使用蛮力变得更加困难/昂贵。它由著名的密码学者/安全专家(Colin Percival)编写,几乎每种编程语言都有很棒的库。SCrypt也得到了Latacora的认可。

Okta开发人员关系团队的密码学专家Randall Degges说:

Argon2相对较新(现在已经有几年的历史了),但是已经得到了广泛的审计/审查,并且是许多组织在几年的过程中参与的密码散列挑战的结果。毫无疑问,它们中“最强”的哈希算法增加了scrypt所没有的另一层复杂性,这使得与scrypt相比,使用暴力的代价要高得多/困难得多。Argon2非常棒,我已经在好几种语言中成功地使用了它,但是如果您担心过于尖端的scrypt是一个安全的选择,而且没有争议。

From Rob Winch, Spring Security Lead:

“我喜欢BCrypt,但一般的建议是单向自适应散列。出于遵从性的原因,一些用户可能需要使用PBKDF2。有一个Argon2支持的票据记录,但是我没有找到任何Apache 2原生Java实现(如果您知道任何实现,请让我知道!)相反,库依赖于它们委托给的二进制文件,在我看来这并不理想。对于等待还是利用委托给二进制的实现之一,我们持观望态度。”

对于那些希望使用SCrypt的用户,在SCryptPasswordEncoder中有通过Bouncy Castle实现Spring安全性的支持。Spring Security 5.1 (est. 2018年9月下旬)将附带一个UserDetailsPasswordService API,允许您升级密码存储。

8. 存储机密安全

密码、访问令牌等敏感信息应谨慎处理。您不能将它们放在周围,不能以纯文本形式传递它们,或者如果将它们保存在本地存储中,则不能进行预测。正如(GitHub)的历史一次又一次地证明,开发人员对于如何存储他们的秘密考虑得不够仔细。

当然,您可以也应该加密您的敏感数据,比如密码。现在您的密码是安全的,您有一个新的秘密,您的解密密钥!你打算怎么处理这个新秘密?也许在本地存储?也许在另一个地方,某个你认为攻击者很难找到它的地方。这并不能解决问题;它只是推迟了它。如果没有适当的程序,黑客想要破解你的秘密只会稍微困难一点。

一个好的实践是将秘密存储在一个保险库中,该保险库可用于存储、提供对应用程序可能使用的服务的访问,甚至生成凭据。HashiCorp的Vault使得存储秘密变得微不足道,同时还提供了许多额外的服务。Vault可以配置为不允许任何人访问所有数据,从而不提供单一的控制点。根密钥库定期使用更改,并且只存储在内存中。有一个主开关,当触发时将密封你的保险库,阻止它分享秘密,如果发生问题。Vault使用被分配给策略的令牌,这些策略可以作用于特定的用户、服务或应用程序。还可以与常见的身份验证机制(如LDAP)集成以获得令牌。

除了不存在问题的gold -path视图之外,Vault还帮助您处理被黑客攻击时存在的场景。此时,重要的是撤销单个或多个秘密,可能由特定用户或特定类型的用户来撤销。Vault提供了一种自动化的方法,当时机成熟时,可以快速完成这项工作。

如果您对此感兴趣,请务必花一些时间研究Spring Vault,它在HashiCorp Vault上添加了一个抽象,为客户端提供基于Spring注释的访问,允许他们访问、存储和撤销机密,而不会在基础设施中丢失。下面的代码片段显示了使用注释从Spring Vault提取密码是多么容易。

@Value("${password}")

String password;

9. 使用OWASP的ZAP测试您的应用程序

OWASP ZAP安全工具是一个代理,它在运行时对您的活动应用程序执行渗透测试。这是一个流行的(超过4k明星)免费开源项目,托管在GitHub上。

OWASP ZAP用于发现漏洞的两种方法是Spider和Active Scan。Spider工具从url种子开始,它将通过每个响应访问和解析url种子,识别超链接并将它们添加到列表中。然后,它将访问这些新发现的url并递归地继续,为web应用程序创建url映射。活动扫描工具将自动测试您所选择的目标,针对一系列潜在的漏洞。它向您提供了一个报告,显示您的web应用程序可以在何处被利用,以及关于该漏洞的详细信息。

10. 您的安全团队是否进行了代码评审

代码评审对于任何高性能的软件开发团队都是必不可少的。在Okta,我们所有的生产代码和官方开源项目都需要经过专家安全团队的分析。您的公司可能没有安全专家,但是如果您正在处理敏感数据,那么您应该这样做!

不要让你的缺乏安全感成为困扰

Okta有一些很棒的t恤,上面写着“我发现你缺乏安全保障,令人不安”。当我们在机场旅行时,我们喜欢听到乳胶手套被戴上的声音。不要成为在Spring引导应用程序中缺乏安全性的开发人员!

我发现你缺乏安全保障令人不安

要了解更多关于Spring引导和应用程序中的安全性,请参阅以下教程和文章:

  1. 开始使用Spring Security 5.0和OIDC
  2. 使用React和Spring Boot构建一个简单的CRUD应用程序
  3. 使用Spring Security和Thymeleaf将基于角色的访问控制添加到您的应用程序中
  4. 安全性和API之旅
  5. 准备在Heroku上生产一个Spring Boot应用程序
本文地址
Article

微信

知识星球

微信公众号

视频号