我正在使用基于密码的Jboss 5.1.0加密来保护我们的服务器。
我已阅读RFC的部分内容:
https://tools.ietf.org/html/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。
我能够通过快速谷歌搜索“Decrypt Jboss 5.1.0密码”来证明这一点,第一个结果是使用官方Jboss文档中推荐的方法解密Jboss密码的jar文件。
输入基于密码的加密。
知道我已经在第一种方法中发现了安全漏洞,我已经穿着从这个文档中获取建议 - 如果你错了一次,你可能错了两次。但是,似乎我没有必须使用方法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)删除用户名&amp;密码&amp;更新数据源XML
<security-domain>EncryptedMySqlDbRealm</security-domain>
<depends>jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword</depends>
4)将Mbean添加到数据源XML。它指定server.password文件,salt和迭代。
<mbean code="org.jboss.security.plugins.JaasSecurityDomain"
name="jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword">
<constructor>
<arg type="java.lang.String" value="ServerMasterPassword"></arg>
</constructor>
<!-- The opaque master password file used to decrypt the encrypted database password key -->
<attribute name="KeyStorePass">{CLASS}org.jboss.security.plugins.FilePassword:${jboss.server.home.dir}/conf/server.password</attribute>
<attribute name="Salt">${8Charactersalt}</attribute>
<attribute name="IterationCount">${iterationsMoreThan1000}</attribute>
</mbean>
5)添加应用程序策略以登录配置XML。指定要加密的用户名,加密密码和数据源。应用程序策略和数据源之间存在1对1映射,因此如果您有两个数据源,则表明您还需要2个应用程序策略。否则你会在启动jboss时遇到错误。
<application-policy name="EncryptedMySqlDbRealm">
<authentication>
<login-module code = "org.jboss.resource.security.JaasSecurityDomainIdentityLoginModule"
flag = "required">
<module-option name = "username">${DatabaseUsername}</module-option>
<module-option name = "password">${EncryptedPassword}</module-option>
<module-option name = "managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=${DataSourceNameFromDatasourceXML}</module-option>
<module-option name = "jaasSecurityDomain">jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword</module-option>
</login-module>
</authentication>
</application-policy>
答案 0 :(得分:0)
首先,一个问题:我对你所指的JBoss系统一无所知。但我相当确定系统不要求您在我的服务器上存储master.password。&#34;但是,我对加密非常熟悉,可以提供这样的解释:
您希望存储一些纯文本数据并使用密码进行保护。因此,您要求用户输入密码,加密密码并存储加密文本(调用此密码&#34; cipher-text&#34;)然后丢弃密码。当用户想要检索它时,您要求输入密码,然后解密&#34; Cipher-Text&#34;。如果密码正确,您将返回原始纯文本。
加密(和解密)过程需要密钥。这是数值,而不是密码。因此,您需要一种从某些文本Pass-Phrase 派生键值的方法。 DerivedKeyFunction
执行此操作。返回的结果不是编码密码。它是传递给加密/解密过程的Key值。
因此,您要求用户输入Pass-Phrase,然后调用DerivedKeyFunction
获取Key-value,然后将纯文本加密为Cipher-Text(使用键 ),存储生成的密文,然后丢弃密码短语和密钥。
要解密,你要求Pass-Phrase,重新获得密钥,然后解密。
基本上,DerivedKeyFunction
是一个Hash函数(或进程);你用它来转换&#34; Pass-Phrase为加密过程可以使用的数值。
现在,您将注意到DerivedKeyFunction
的其他两个参数:&#34; Salt&#34;和#34;迭代&#34;。这些都是增加攻击数据难度所必需的。 &#34;迭代&#34; (显然)指定重新散列Pass-Phrase的次数。并且&#34; Salt&#34;在这个迭代过程中注入一个随机数。
希望你现在看到这些是你需要用密码文本存储的两个值。无论何时您想从Pass-Phrase中获取Key,您每次都必须以相同的方式执行;这意味着迭代相同的次数和注入相同的次数&#34;盐&#34;值。
所以,现在您的流程是:
1)选择随机盐值(是的,随机数)。
2)决定迭代计数,例如100,000。 (这应该是一个很大的数字,所以DerivedKeyFunction
需要很长时间;稍后解释一下)
3)向用户询问Pass-Phrase。
4)呼叫DerivedKeyFunction
将Pass-Phrase,随机Salt值和100,000交给它。这将返回一个键值(由这3个参数隐含)。
5)使用键值将纯文本加密为密文。
6)存储密文和盐值和迭代次数(100,000)
7)丢弃Pass-Phrase和Key-value。
要解密:
1)要求传递短语。
2)致电DerivedKeyFunction
,将Pass-Phrase,存储的 Salt值和存储的迭代计数交给它。如果Pass-Phrase正确,则返回相同的(正确的)Key-value。
3)使用键值将密码文本解密为纯文本。
好的,为什么选择一个大数字来进行迭代计数呢?好吧,攻击者只需在密码后尝试密码,直到他们成功解密密文。但他们每次尝试都必须致电DerivedKeyFunction
。 ,他们必须使用您加密数据时使用的正确的 Salt 值和迭代次数。并且,是的,因为你必须存储它们供你使用,攻击者才会知道它们是什么;但他们仍然需要一遍又一遍地呼叫DerivedKeyFunction
。因此,您应该看到,迭代计数越高,攻击者可以尝试的每秒尝试次数就越少。
虽然您没有提及它,但在使用CBC(密码 - 块链)类型加密算法时,还有另一个参数称为IV或初始化向量。该值是加密/解密的输入,作为Key的伴随。由于它与上述过程有关,因此将其视为密钥的扩展:使用的DerivedKeyFunction
应提供键值和IV值。并且,与Key-value一样,IV值永远不会被存储,并且会在丢弃Key-value的相同点处被丢弃。
答案 1 :(得分:0)
听起来你只想混淆密码。加密它只是使这个循环过程:您需要选择一个密码来加密您将用于加密密码的密码.......
Simply Base-64编码。或者其他类型的(非加密)编码。