源代码管理中的密码存储

时间:2009-02-18 02:21:53

标签: password-protection password-storage

我们将所有应用程序和数据库密码以纯文本形式存储在源代码管理中。我们这样做是因为我们的构建/部署过程生成了所需的配置文件,并且还进行了需要这些密码的实际部署(即:针对数据库运行sql需要您使用有效凭据登录到db)。有没有人有类似的需求,你可以实现这种类型的功能,而不是以纯文本形式存储密码?

6 个答案:

答案 0 :(得分:21)

如果您的计划是存储所有代码和配置信息以直接从版本控制运行生产系统,并且无需人工干预,那么您就搞砸了。为什么?这完全违反了旧的安全公理“永远不会写下你的密码”。让我们通过否定来做证明。

首先,您在配置文件中有明文密码。这不好,任何能看到文件的人都可以阅读。

第二次削减,我们将加密密码!但现在代码需要知道如何解密密码,因此您需要将解密密钥放在代码中的某个位置。问题刚刚被推到了一个水平。

使用公钥/私钥怎么样?与密码相同的问题,密钥必须在代码中。

使用未存储在版本控制中的本地配置文件仍会将密码以及在磁盘上加密时读取它们的方法放在磁盘上并且可供攻击者使用。你可以通过确保配置文件的权限非常有限来强化一些事情,但是如果这个框被植根了你就搞砸了。

这让我们知道为什么将密码放在磁盘上是一个坏主意。它违反了安全防火墙的概念。一台包含登录信息的受感染机器意味着其他机器将受到损害。一台维护不善的机器可以拆除整个组织。

在某些时候,人类将不得不注入重要的秘密来启动信任链。你可以做的是加密代码中的所有秘密,然后当系统启动时,人工手动输入密钥来解密所有密码。这就像Firefox使用的主密码系统。它可以被滥用,因为一旦密码遭到破坏,许多系统可能会受到损害,但它很方便,而且可能更安全,因为用户只需记住一个密码而不太可能将其写下来。

最后一步是确保登录信息遭到入侵(并且您应该始终认为它将会受到影响)A)攻击者无法对其进行多少操作而且B)您可以快速关闭受感染的帐户。前者意味着只为帐户提供所需的访问权限。例如,如果您的程序只需要从数据库中读取,则必须在限制为SELECT的帐户上登录。通常,删除所有访问权限,然后仅在必要时添加。吝啬删除的权利,以免你从little Bobby Tables访问。

后者意味着您为每个用户/组织/项目提供自己的登录,即使他们可以拥有完全相同的权限和权限并访问相同的数据。这有点麻烦,但这意味着如果一个系统遭到入侵,您可以在不关闭整个业务的情况下快速关闭该帐户。

答案 1 :(得分:6)

我认为目标是您不希望公司的私人密码可用,加密,解密或以其他方式提供给任何应该允许访问其他来源的人。

我是这样做的。我已经从TikiWiki复制了这个模式,它也是这样做的。

在某些通常包含密码的文件中,将它们设置为虚拟值,无关紧要。将其设置为客户应该看到的任何内容。在附近添加注释,供开发人员单独保留此文件并更改第二个文件。

在第二个文件中,如果不存在则创建它,输入实际的密码。安排这个文件被第一个文件包含,导入,等等。

安排您的源代码管理忽略该文件。看起来像这样:

# in .gitignore
localsettings.py

# in settings.py
## Alter this value to log into the snack machine:
## developers: DON'T alter this, instead alter 'localsettings.py'
SECRET_VALUE = ""
try:
  from localsettings import *
except:
  pass

# in localsettings.py
SECRET_VALUE = "vi>emacs"

答案 2 :(得分:1)

我构建了数据库用户ID /密码对不属于代码丢弃的系统。关键是要设置特定于站点的配置机制。然后,您可以将此类信息放在相关的框中,而不会成为代码库的一部分。

有一个好处:您不仅可以为不同的代码丢弃设置不同的密码,还可以为不同的开发人员设置密码。 : - )

答案 3 :(得分:-1)

你没有提到这种语言,所以这是我们使用的vb.net解决方案:

Imports System.Web.Security
Imports System.Security.Cryptography
Imports System.Text
Imports Microsoft.Win32

Public Class myCrypt

Private myKey As String = "somekeyhere"
Private cryptDES3 As New TripleDESCryptoServiceProvider()
Private cryptMD5Hash As New MD5CryptoServiceProvider()


Private Function Decrypt(ByVal myString As String) As String
    cryptDES3.Key = cryptMD5Hash.ComputeHash(ASCIIEncoding.ASCII.GetBytes(myKey))
    cryptDES3.Mode = CipherMode.ECB
    Dim desdencrypt As ICryptoTransform = cryptDES3.CreateDecryptor()
    Dim buff() As Byte = Convert.FromBase64String(myString)
    Decrypt = ASCIIEncoding.ASCII.GetString(desdencrypt.TransformFinalBlock(buff, 0, buff.Length))
End Function

Private Function Encrypt(ByVal myString As String) As String
    cryptDES3.Key = cryptMD5Hash.ComputeHash(ASCIIEncoding.ASCII.GetBytes(myKey))
    cryptDES3.Mode = CipherMode.ECB
    Dim desdencrypt As ICryptoTransform = cryptDES3.CreateEncryptor()
    Dim MyASCIIEncoding = New ASCIIEncoding()
    Dim buff() As Byte = ASCIIEncoding.ASCII.GetBytes(myString)
    Encrypt = Convert.ToBase64String(desdencrypt.TransformFinalBlock(buff, 0, buff.Length))
End Function

End Class

答案 4 :(得分:-5)

以加密形式存储密码。编写一个自定义例程,解密密码并在构建时更新配置文件。这可以很容易地与像Ant一样的构建工具集成。

答案 5 :(得分:-9)

如果在C中进行,您可以将字符数组存储起来并将字符作为十进制引用。不确定这是否会破坏字符串,但可能有助于缓解一些问题。

char pass[]={72, 101, 108, 108, 111};