2009-02-18 71 views
17

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

+1

将密码置于o/s用户环境变量中。 – 2013-11-03 00:06:38

回答

21

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

首先,您在配置文件中使用纯文本密码。这是不好的,任何人都可以看到这些文件。

第二次,我们会加密密码!但是现在代码需要知道如何解密密码,所以您需要将解密密钥置于代码中的某处。这个问题刚刚被推到一个水平。

如何使用公钥/私钥?与密码相同的问题,密钥必须位于代码中。

未存储在版本控制中的本地配置文件的使用仍会将密码以及在磁盘上进行加密并读取它们的方式提供给攻击者。通过确保配置文件的权限非常有限,您可以稍微加强一点,但是如果该框根深蒂固,那么您就被搞砸了。

这引出我们为什么把密码放在磁盘上是一个坏主意。它违反了安全防火墙的概念。一台包含登录信息的受损机器意味着其他机器将受到危害。一台维护不善的机器可能会推倒整个组织。

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

最后一点是确保登录信息应该被破坏(并且您应该始终假设它会)A)攻击者无法用它做很多事情B)您可以快速关闭受感染的账户。前者意味着只为帐户提供尽可能多的访问权限。例如,如果您的程序只需要从数据库中读取,那么它只能登录限于SELECT的帐户。通常,删除所有访问权限,然后仅在必要时添加它。小心删除权利,以免你从little Bobby Tables访问。

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

-8

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

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

Boshfpngvba qbrf abg cebivqr frphevgl! – Schwern 2009-02-18 03:15:32

+0

eewwwwwwwwwwwww – 2010-02-27 20:59:18

-5

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

+3

那么你把解密密钥放在哪里? – Schwern 2009-02-18 03:38:53

-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 
+0

我们的构建/部署过程是ANT。我们的应用程序代码恰好是Java。 – 2009-02-18 02:36:52

+3

MD5? TripleDes的?该死的,MD5已经妥协了,3DES正在出路。使用AES和SHA256。更重要的是,一旦你加密了登录凭证,你在哪里放置解密密钥?鸡蛋。 – Schwern 2009-02-18 03:48:20

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" 
1

我已经建立了数据库用户ID /密码对不是代码放下的一部分的系统。关键是要设置一个特定于站点的配置机制。然后你可以把这些信息放在有问题的盒子里,而不用作为代码库的一部分。

还有一个好处:你不仅可以针对不同的代码丢弃,而且针对不同的开发者有不同的密码。 :-)