【问题标题】:Is Jboss 5.1.0 Password Based Encryption Secure?Jboss 5.1.0 基于密码的加密安全吗?
【发布时间】:2017-06-30 13:53:12
【问题描述】:

我正在使用基于密码的 Jboss 5.1.0 加密来保护我们的服务器。

我已阅读 RFC 的部分内容:

https://www.rfc-editor.org/rfc/rfc2898

Jboss的几篇文档我已经看了好几遍了:

https://docs.jboss.org/jbosssecurity/docs/6.0/security_guide/html/Encrypting_Data_Source_Passwords.html(适用于 6.0,但适用于 5.1.0)

现在,让我解释一下我的问题。

在上面列出的官方 JBoss 文档中,他们将“安全身份”加密视为安全的。哎呀,它在文件中。 更糟糕的是,我看到其他人在 Stack Overflow 上就如何使用它提出问题这不安全。为了使其安全,必须编写自己的加密类来覆盖 org.jboss.resource.security.SecureIdentityLoginModule。

我可以通过在谷歌上快速搜索“解密 Jboss 5.1.0 密码”来证明这一点,第一个结果是一个 jar 文件,它使用官方 Jboss 文档中推荐的方法解密了 Jboss 密码。

输入基于密码的加密。

知道我已经在第一种方法中发现了一个安全漏洞,我已经厌倦了从这个文档中获取建议——如果你错了一次,你可能错了两次。但是,我似乎没有我必须使用方法 2:基于密码的加密。

我担心的是,文档让我生成一个“master.password”文件。我假设这是 RFC 中提到的派生密钥函数。不过,我不确定。

总而言之,我的直觉告诉我: 你让我在我的服务器上存储一个 master.password。包含派生密钥函数的 master.password 文件可以被某处的某些代码用来简单地解密我的加密密码。那是因为我在其他文件的其他地方指定了盐和迭代。

整个过程看起来像是一个数学函数。在我看来,它看起来像这样:

? = DerivedKeyFunction(Salt, Iterations, Password)

但对于黑客来说,它看起来像这样:

EncodedPassword = DerivedKeyFunction(Salt, Iterations, ?)

我声称自己既不是密码学家也不是 Jboss 专家,但我的直觉告诉我,黑客需要做的就是查看 Jboss 源代码(据我所知是开源的)并做一些事情使用 server.password 文件进行一些逆向工程以获取密码。

所以我的问题是:Jboss 上基于密码的加密有多安全(假设黑客获得了对服务器的访问权限)?有没有人真正研究过这个?

------------ 编辑 -----

澄清: 这是为了让 JBoss 连接到我们的数据库。这不适用于最终用户在 Web 应用程序上登录其用户帐户。

JBoss 使用包含某种加密字符串的 master.password(或 server.password...它只是一个文件名)。我不确定这里有什么,它没有很好的记录(或者它可能是,我只是不明白)。

配置完成后,不再输入密码。我不明白这是如何安全的。我猜我可以以某种方式使用在步骤 1 中创建的 server.password 文件来解密我的数据库密码。有人只是还没有写一个方便的 jar 文件。但是代码是开源的,所以我猜合适的人知道如何很容易地做到这一点。

我正在分享这些步骤,因为我看到人们在堆栈溢出时使用了许多糟糕的设置。步骤如下:

  1. 从 jboss/common/lib 文件夹,创建 server.password 文件。放在 server/conf 目录下。:

     java -cp jbosssx.jar org.jboss.security.plugins.FilePassword <8Charactersalt> <iterationsMoreThan1000> <aLongRandomPassword> server.password
     #outputs server.password file which contains encrypted string.
    
  2. 加密数据库密码

     java -cp jbosssx.jar org.jboss.security.plugins.PBEUtils <8Charactersalt> <iterationsMoreThan1000> <aLongRandomPassword> <databaseConnectionPassword>
     #outputs encrypted DB Password
    
  3. 删除用户名和密码并更新数据源 XML

     <security-domain>EncryptedMySqlDbRealm</security-domain>
     <depends>jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword</depends>
    
  4. 将 Mbean 添加到数据源 XML。它指定 server.password 文件、盐和迭代。

    {CLASS}org.jboss.security.plugins.FilePassword:${jboss.server.home.dir}/conf/server.password ${8Charactersalt} ${iterationsMoreThan1000}

  5. 将应用程序策略添加到登录配置 XML。指定用户名、加密密码和要加密的数据源。应用程序策略和数据源之间存在 1 对 1 的映射,因此如果您有两个数据源,那么您似乎也需要 2 个应用程序策略。否则启动 jboss 会出错。

    ${数据库用户名} ${加密密码} jboss.jca:service=LocalTxCM,name=${DataSourceNameFromDatasourceXML} jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword

【问题讨论】:

    标签: security jboss cryptography


    【解决方案1】:

    听起来您只是想混淆您的密码。对其进行加密只会使这成为一个循环过程:您需要选择一个密码来加密您的密码,您将使用该密码来加密您将要使用的密码.....

    只需 Base-64 编码即可。或者其他类型的(非加密)编码。

    【讨论】:

    • 谢谢。当它实际上只是混淆它时,它被称为“加密密码”是一种误导。加密和混淆是两个完全不同的东西。
    • 尽管如此,我还是对基于密码的加密感到满意,尽管它只会让攻击者对密码进行去混淆处理更加不方便。
    • 不过,使用默认“jaas is the way”和“Blowfish”的安全身份的用户应该真正将他们的加密/混淆更新为我上面概述的方法
    【解决方案2】:

    首先,请注意:我对您所指的 JBoss 系统一无所知。但我相当确定系统不会要求您“在我的服务器上存储 master.password”。但是,我对加密足够熟悉,可以提供以下解释:

    您想存储一些纯文本数据并用密码保护它。因此,您要求用户输入密码,对其进行加密并存储加密文本(称为“密文”),然后丢弃密码。当用户想要检索它时,您要求输入密码,然后解密“密文”。如果密码正确,您将得到原始的纯文本。

    加密(和解密)过程需要密钥。这是数值,而不是密码。因此,您需要一种从某些文本密码短语中派生键值的方法。 DerivedKeyFunction 执行此操作。返回的结果不是编码密码。它是一个传递给加密/解密过程的Key值。

    因此,您要求用户输入密码,然后调用 DerivedKeyFunction 以获取密钥值,然后将纯文本加密为密文(使用 密钥),存储生成的密文,然后丢弃密码短语和密钥。 要解密,您需要输入密码,重新导出密钥,然后解密。

    基本上,DerivedKeyFunction 是一个哈希函数(或过程);您可以使用它将密码短语“转换”为加密过程可以使用的数值。

    现在,您将注意到DerivedKeyFunction 的另外两个参数:“Salt”和“Iterations”。这些是增加对您的数据进行攻击的难度所必需的。 “迭代”(显然)指定重新散列密码短语的次数。而“盐”在这个迭代过程中注入了一个随机数。 希望您现在看到这两个值您需要与密文一起存储。每当您想从您的密码短语中获取密钥时,您必须每次都以相同的方式进行;这意味着迭代相同的次数注入相同的“Salt”值。

    所以,现在你的流程是:

    1) 选择一个随机 Salt 值(是的,一个随机数)。

    2) 确定迭代次数,例如 100,000。 (这应该是一个很大的数字,所以DerivedKeyFunction需要很长时间;稍后解释)

    3) 向用户询问密码。

    4) 调用DerivedKeyFunction,将密码短语、随机盐值和 100,000 交给它。这将返回一个键值(由这 3 个参数暗示)。

    5) 使用 Key-value 将纯文本加密为密文。

    6) 存储密文盐值迭代次数(100,000)

    7) 丢弃密码短语和键值。

    解密:

    1) 询问密码。

    2) 调用DerivedKeyFunction,将密码短语、存储的盐值和存储的迭代计数交给它。如果 Pass-Phrase 正确,则返回相同(正确)的 Key-value。

    3) 使用 Key-value 将 Cipher-Text 解密为 Plain-Text。

    好的,那为什么要为迭代计数选择一个大数字呢?好吧,攻击者将只是在密码之后尝试密码,直到他们成功解密密文。但是他们每次尝试都必须致电DerivedKeyFunction并且,它们必须使用您在加密数据时使用的正确 Salt 值和 迭代计数。而且,是的,由于您必须存储它们以供使用,攻击者会知道它们是什么;但他们仍然必须一遍又一遍地致电DerivedKeyFunction。因此,您应该看到迭代次数越多,攻击者每秒可以尝试的尝试次数就越少。

    虽然你没有提到,但是在使用CBC(Cipher-Block-Chain)类型的加密算法时,还有一个参数叫做IV或Initialization Vector。该值是作为密钥伴侣的加密/解密的输入。由于与上述过程有关,因此将其视为 Key 的扩展:使用的 DerivedKeyFunction 应同时提供 Key-value 和 IV-value。而且,与 Key-value 一样,IV-value 永远不会被存储,并且会在 Key-value 被丢弃的同一点被丢弃。

    【讨论】:

    • 您的答案包含大量信息。谢谢你。但是,我想我需要解释一下密码学的用途。我正在加密连接到数据库的密码。实际上并不要求用户输入任何密码,JBoss 是用户。每个人都说“XML 中的密码不好”,但我发现的解决方案似乎只是让人讨厌,并非不可能解密密码。如果要求用户输入密码(例如网站的登录表单),您建议的方法是有意义的。但是 Jboss 没有被要求输入密码,它只是启动并连接。
    • 好吧......我假设你要更新你的问题......但是,我描述的过程非常笼统(即,不特定于 JBoss 或任何其他框架或编程语言/系统)。无论您的“纯文本”是什么,无论您的存储系统是什么,无论您出于何种原因使用加密保护它,您都需要按照我列出的步骤进行操作。
    • 听起来你只是想混淆密码。如果你加密它,你会追逐你的尾巴。也就是说,您需要选择一个密码来对 JBoss 密码进行加密,然后将其存储在某个地方(因为正如您所说,没有人被要求输入密码)。那里有一个非常循环的问题。也许只是 Base-64 编码您要使用的 JBoss 密码? (或其他一些晦涩的编码)。攻击者需要密码的文本表示(编码)版本您选择使用的编码算法。
    • 这应该是显而易见的,也许你不想听到它,但便利的代价会显着降低(如果不是破坏)这个 JBoss 系统的安全性。只是说'n。
    • 我猜另一种选择是只选择一个键值来加密您的密码,然后将该数字存储在您的 XML 中。请记住,键值(数字)加密的实际“密码”。 DerivedKeyFunction 步骤用于帮助我们这些可怜的人类:所以我们可以使用文本短语作为我们的密码,而不是一些巨大的数字。因此,您只需选择一个(大)数字,将其存储在您的 XML 中,然后只调用加密/解密。你根本不需要打电话给DerivedKeyFunction.....
    猜你喜欢
    • 2014-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多