源代码管理中的密码存储

发布于 2024-07-13 09:42:25 字数 155 浏览 5 评论 0原文

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

We store all our application and db passwords in plain text in source control. We do this as our build/deploy process generates required configuration files and also does actual deploys that require these passwords (ie: running sql against a database requires you logon to the db using valid credentials). Has anyone had a similar need where you were able to implement this type of functionality while not storing the passwords in plain text?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

不念旧人 2024-07-20 09:42:25

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

首先,配置文件中有纯文本密码。 这不好,任何可以看到这些文件的人都可以阅读它们。

第二次,我们将对密码进行加密! 但现在代码需要知道如何解密密码,因此您需要将解密密钥放在代码中的某个位置。 问题只是被降低了一个层次。

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

使用未存储在版本控制中的本地配置文件仍然会将密码以及读取它们的方法(如果它们已加密)放在磁盘上并可供攻击者使用。 你可以通过确保配置文件的权限非常有限来强化一些东西,但是如果盒子被root了,你就完蛋了。

这让我们明白为什么将密码放在磁盘上是一个坏主意。 它违反了安全防火墙的概念。 一台包含登录信息的受感染计算机意味着其他计算机也将受到威胁。 一台维护不善的机器可能会毁掉您的整个组织。

在某些时候,人类必须注入关键秘密才能启动信任链。 您可以做的是加密代码中的所有秘密,然后当系统启动时让人手动输入密钥来解密所有密码。 这就像 Firefox 使用的主密码系统。 它很容易被滥用,因为一旦一个密码被泄露,许多系统可能会被泄露,但它很方便,而且可能更安全,因为用户只需要记住一个密码,并且不太可能把它写下来。

最后一步是确保如果登录信息被泄露(并且您应该始终假设它会被泄露),A)攻击者无法利用它做太多事情,B)您可以快速关闭受损的帐户。 前者意味着仅授予帐户所需的访问权限。 例如,如果您的程序只需要从数据库中读取数据,则让它登录仅限于 SELECT 的帐户。 一般来说,删除所有访问权限,然后仅根据需要添加它。 对删除权利要吝啬,以免受到小鲍比桌的访问。

后者意味着您为每个用户/组织/项目提供自己的登录名,即使他们可以拥有完全相同的权利和特权并访问相同的数据。 这有点麻烦,但这意味着如果一个系统受到损害,您可以快速关闭该帐户,而无需关闭整个业务。

If your plan is to store all the code and configuration information to run a production system directly from version control, and without human intervention, you're screwed. Why? This is all just a violation of the old security axiom "never write your password down". Let's do a proof by negation.

First cut, you have plain text passwords in the configuration files. That's no good, they can be read by anyone who can see the files.

Second cut, we'll encrypt the passwords! But now the code needs to know how to decrypt the passwords, so you need to put the decryption key somewhere in the code. The problem has just been pushed down a level.

How about using public/private keys? Same problem as the passwords, the key has to be in the code.

The use of a local configuration file not stored in version control still puts the password, and the means to read them if they're encrypted, on disk and available to an attacker. You can harden things a little by ensuring that configuration file's permissions are very limited, but should the box be rooted you're screwed.

Which brings us to why putting passwords on disk is a bad idea. It violates the concept of a security firewall. One compromised machine containing login information means other machines will be compromised. One poorly maintained machine can tear down your whole organization.

At some point a human is going to have to inject the critical secret to start the chain of trust going. What you could do is encrypt all the secrets in the code and then when the system starts up have a human manually enter the key to decrypt all the passwords. This is like the master password system Firefox uses. It is open to abuse since once that one password is compromised, many systems may be compromised, but it is convenient and probably more secure since users only have to remember one password and are less likely to write it down.

The final touch is to ensure that should the login information be compromised (and you should always assume that it will be) that A) the attacker can't do much with it and B) you can quickly shut down the compromised accounts. The former means to only give the accounts as much access as they need. For example, if your program only ever needs to read from a database have it log in on an account restricted to SELECT. In general, remove all access and then add it only as necessary. Be stingy about the rights to delete lest you get a visit from little Bobby Tables.

The latter means you give each user/organization/project their own login, even if they can have the exact same rights and privileges and access the same data. It's a bit more of a hassle, but it means that if one system is compromised you can quickly shut down that account without shutting down your whole business.

挖个坑埋了你 2024-07-20 09:42:25

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

我是这样做的。 我从 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"

I assume the objective is that you don't want your company's private passwords to be available, encrypted, decrypted, or otherwise, to anyone that should otherwise be allowed access to the rest of the source.

Here's how I do it. I've duplicated this pattern from TikiWiki, which does this too.

in some file that normally contains passwords, set them to dummy values, doesn't matter what. Set it to whatever your customer should see. Put a comment nearby for developers to leave this file alone and alter a second file.

In the second file, which gets created if it's not there, put the actual passwords. arrange for this file to be included, imported, whatever, by the first file.

Arrange for your source control to ignore that file. Could look something like this:

# 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"
孤君无依 2024-07-20 09:42:25

我构建的系统中数据库用户名/密码对不属于代码删除的一部分。 关键是建立一个针对特定站点的配置机制。 然后,您可以将这些信息放在有问题的盒子上,而不将其作为代码库的一部分。

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

I've built systems where database userid/password pairs are not part of the code drop. The key is to setup a site-specific configuration mechanism. Then you can put such information on the box in question, without it being part of the code-base.

There's a bonus: you can not only have different passwords for different code drops, but also for different developers. :-)

韶华倾负 2024-07-20 09:42:25

你没有提到语言,所以这是我们使用的 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

You didn't mention the language, so here is a vb.net solution we use:

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
我是男神闪亮亮 2024-07-20 09:42:25

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

Store passwords in encrypted form. Write a custom routine that decrypts the passwords and updates the configuration files at build time. This can be easily integrated with the build tool like Ant.

傾旎 2024-07-20 09:42:25

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

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

If doing in C you could store in as an array of characters and put the characters in as decimal references. Not sure if this will break strings or not, but might help to alleviate some of that problem.

char pass[]={72, 101, 108, 108, 111};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文