在使用Python开发时如何保护MySQL密码?

19
我正在编写一个使用本地MySQL数据库的Python脚本,该程序将作为源代码交付。因此,MySQL密码会被直接暴露给他人。有没有好的方法来保护它呢?
这个问题的目的是防止一些不良分子查看源代码,直接访问MySQL并做一些... 好吧,不良的事情。

在出货前定义它的中心位置并将其编辑掉? - Jacob
这个会连接到你们的数据库还是购买者的数据库? - Raz
4个回答

19

简短回答

你不能。

如果密码存储在交付给最终用户的构件中,你必须认为它已经被泄露!即使构件是一个编译后的二进制文件,也总有(更或少复杂的)方法可以获取到密码。

保护你的资源的唯一方法是向最终用户公开有限的 API。要么建立一个编程接口(REST、WS+SOAP、RMI、JavaEE+Servlets 等等),要么只通过 SPROCs(见下文)公开数据库中的某些功能。

首先,解释一些事情......

这里的问题不应该是如何隐藏密码,而应该是如何保护数据库的安全。请记住,仅使用密码通常是非常薄弱的保护措施,不应该将其视为保护数据库的唯一机制。你使用 SSL 吗?没有吗?那么,即使你设法在应用程序代码中隐藏密码,也很容易在网络上嗅探到它!

你有多种选择。每种选择都有不同程度的安全性:

“应用程序角色”

为应用程序创建一个数据库用户。对该角色进行授权。一个非常常见的设置是仅允许 CRUD 操作。

优点

  • 非常容易设置
  • 防止 DROP 查询(例如 SQL 注入)

缺点

  • 每个看到密码的人都可以访问数据库中的所有数据。即使这些数据在应用程序中通常是隐藏的。
  • 如果密码被泄露,用户可以运行没有条件的 UPDATEDELETE 查询(即:一次删除或更新整个表)。

原子认证和授权

每个应用/最终用户创建一个数据库用户。这样可以定义原子访问权限,甚至可以基于列级别进行定义。例如:用户X只能从表foo选择列far和baz。什么都不能做。但是,用户Y可以“SELECT”所有内容,但不能更新,而用户Z具有完全的CRUD(select、insert、update、delete)访问权限。

一些数据库允许您重用操作系统级别的凭据。这使得对用户的身份验证透明化(只需要在工作站上登录,该身份就会被转发到数据库)。在完整的MS堆栈(OS = Windows,Auth = ActiveDirectory,DB = MSSQL)中,这很容易实现,但就我所知,也可能适用于其他数据库。

优点

  • 设置相当容易。
  • 非常原子授权方案

缺点

  • 在数据库中设置所有访问权限可能会很繁琐。
  • 具有“UPDATE”和“DELETE”权限的用户仍然可能意外地(或故意地?)无需条件即可删除/更新。您可能会失去表中的所有数据。

带有原子auth&auth的存储过程

在应用程序中不要编写SQL查询。通过SPROCs运行 everything 。然后为每个用户创建数据库帐户,并仅将特权分配给SPROCs。

优点

  • 最有效的保护机制。
  • SPROCs可以强制用户向每个查询(包括“DELETE”和“UPDATE”)传递条件

缺点

  • 不确定这是否适用于MySQL(我在这方面的知识很薄弱)。
  • 复杂的开发周期:您想要做的所有事情必须首先在SPROC中定义。

最后的想法

永远不要允许应用程序执行数据库管理任务。大多数情况下,应用程序只需要执行SELECTINSERTDELETEUPDATE操作。如果您遵循这个指南,则用户发现密码的风险几乎不存在,除了上述提到的几点。

无论如何都要备份数据。我假设您希望保护数据库免受意外删除或更新的影响。但是事故难免发生,要时刻牢记这点;)


7
在这种情况下,我会在我的.my.cnf文件中创建一个新的部分,例如:
[files]
host=127.0.0.1
port=3307
database=files
default-character-set=utf8
password=foobar

并在数据库初始化时使用它

d=MySQLdb.connect(
    read_default_group='files',
    port=0,  # read from .my.cnf
    db='files',
    cursorclass=cursors.DictCursor,
    # amongst other stuff
)

这是正确的,但它并没有与源代码一起分发。但我可能误解了提问者的初衷——我认为他想要防止在源代码中包含的密码被意外分发。 - glglgl
嗯... my.cnf 文件必须位于客户端上。换句话说,它必须在运行应用程序的机器上。此外,应用程序通常在与用户相同的凭据下运行。这意味着用户需要读取文件的访问权限。因此,这将使其不太明显,但是熟练的攻击者仍然可以轻松定位到它。 - exhuma
我和提问者有同样的问题,但是你的回答确实解答了我想问的问题。1UP! - weefwefwqg3

0

类似的未解决问题在这里:https://stackoverflow.com/questions/2850710/connect-to-a-db-with-an-encrypted-password-with-django Python DBAPI(PEP 249)没有接口可以使用加密/哈希密码连接到数据库,而不是明文密码。

虽然其他语言中的此功能很令人放心,但实际上并没有提供任何额外的安全性:密码的哈希值与密码一样好。您仍然必须像exhuma 描述的那样控制对数据库资源的访问。

无论是绑定 Python 还是不绑定,MySQL 本身都不提供任何额外选项。您可以在 MySQL 用户手册的 密码安全 部分中阅读他们的指导。保护密码访问的推荐选项是将其存储在选项文件中并保护该文件,如 glglgl 所述。

从那页上:

您可以在此处列出运行客户端程序时指定密码的方法以及每种方法的风险评估。简而言之,最安全的方法是让客户端程序提示输入密码或在受到适当保护的选项文件中指定密码。


我不同意选项文件。这个文件不会隐藏密码,让好奇的用户无法看到。正如我在对glglgl答案的评论中所解释的那样,客户端应用程序需要读取文件的权限,这又意味着用户需要读取权限。通常,非超级用户无法提升访问权限。 - exhuma
我不反对你的说法,但我也不知道其他选择。您的帖子涵盖了限制曝光的数据库设计要求,但没有解决凭证存储问题。有更好的方法吗? - J.J.

-5

要么使用像 root 这样简单的密码。否则不要使用密码。


如果没有密码,我该如何防止用户更改数据库? - lang2
针对特定的数据库,创建一个无密码的用户,针对其他的数据库则需创建不同的用户和密码。http://www.debuntu.org/how-to-create-a-mysql-database-and-set-privileges-to-a-user - Kracekumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接