【问题标题】:How can I reduce the surface area of attacking a password in memory in Spring?如何减少在 Spring 中攻击内存中密码的表面积?
【发布时间】:2015-09-23 04:05:20
【问题描述】:

Java 中的Strings 会保留一段时间,可能是a long while。这是一件好事,除非String 包含用户的实际密码。 Character arrays are suggested 因为它们不是不可变的,可以更快地清除。 (让我们希望永远不会有像 Heartbleed 一样有效但针对 JVM(远程堆转储)的“苦咖啡”攻击。

我注意到 Spring Security PasswordEncoder 采用 CharSequence 而不是字符串,可能是因为这个原因。但是,我不确定应该使用什么对象将密码保存在内存预散列中。 StringBuilder 合适吗?那会是什么样子?我什至不确定我是否正在创建一个 REST API(通过 Spring Data 或 Spring MVC 在后台使用 Jackson)如何防止它成为 String

如何编写 JSON REST API 来创建/更新密码,同时尽可能安全并避免使用 Strings 时出现的各种问题?

【问题讨论】:

  • 在使用 Spring Security 之前,您必须避免大多数 REST 框架(包括 Spring Security 内置 Web 安全性)检索密码作为请求参数......这是一个字符串。

标签: java spring security spring-security jackson


【解决方案1】:

如何编写 JSON REST API 来创建/更新密码,同时 尽可能安全并避免各种问题 使用字符串?

API 密钥不是真正的密码。您可以控制 API 密钥的创建方式,因此您可以创建一些随机字符串,这些字符串将具有非常低的冲突(即双 UUID)和非常低的公共子字符串(在重复数据删除的情况下)。在客户端使用密钥通过 REST API 登录后,您可以使用临时令牌,从而提高 API 密钥被垃圾收集的可能性。

至于处理真正的密码,即人类登录的情况(可能是重置 API 密钥),您实际上并没有太多选择,因为几乎每个 servlet 容器都会将请求参数转换为字符串。一个俗气的选择是让客户端通过 Javascript(或任何您的客户端)Base64 对密码进行编码,然后添加分隔符,然后将随机生成的数字或字符串添加到密码中。这并不是真正的混淆,而是再次降低保持相同字符串的可能性。当然,您必须小心解码为 char 或 byte 数组,然后通过操作 char 或 byte 数组删除随​​机后缀(请参阅 CharBuffer)。

另一个复杂的选择是微服务云方法。只需制作一个由几个只进行身份验证的小型循环实例组成的身份验证服务。让那些 JVM 实例频繁重启(以刷新内存)。或者,如果它们足够小,它们有望更频繁地进行垃圾收集。

我当然会假设您的数据存储库有加盐密码(否则这种安全预防措施毫无意义)。

老实说,虽然还有很多其他威胁,但对于 HTTP 服务器环境中的大多数用例,我真的不认为值得付出努力。

Java Swing 之所以使用char[] 作为密码,是因为 Swing 用于桌面环境。桌面环境更有可能存在恶意程序,例如病毒/间谍软件,这些程序可以对密码进行一些内存探测。

考虑到这一点,您真正应该担心的是客户端,而不是服务器。

【讨论】:

  • 是的,我正在构建的 API 主要用于以 Angular 或其他方式编写的后端和用户前端,而我的实体目前正在通过 BCryptPasswordEncoder 进行转换。我有点喜欢你关于什么是有效的客户端盐的想法。为此,可以使用 csrfToken 并对其进行验证。希望永远不会发生远程内存攻击,但我担心“Java Debugger over HTTP”+“String dedup”之类的功能更有可能发生这种情况。也考虑一下,这可能意味着我们可以构建功能来降低它的可能性。
  • 另外请记住,Java 不是 C 或 C++,并且没有无效的指针算法、缓冲区溢出等。因此,虽然将密码挂在内存中仍然有点糟糕,但与它相比并没有那么糟糕到其他没有受保护内存分配的语言。
  • 对,“我的代码”永远不会导致问题。但是Java有热点,并且是用C编写的?确实有那个...我不是说这会发生,而只是考虑假设,最坏的情况。就像让人心血来潮别人的错误......一个语言错误......或者......(你的意思是你通过http在prod上使用password123打开了调试器)。此外,我最初认为这可能只是知识/文档差距。
  • 是的,但它也在一个服务器上,我希望它会被一个相当稳定的 JVM 锁定。真的是您的客户,您需要担心密码泄露(例如钓鱼)。您不想花大量时间在错误的地方建造一堵巨大的墙。
猜你喜欢
  • 1970-01-01
  • 2014-04-07
  • 2017-11-13
  • 2012-04-03
  • 2022-06-10
  • 2010-09-30
  • 2020-06-19
相关资源
最近更新 更多