我正在开发一个利用MySQL数据库进行用户身份验证和数据存储的Windows应用程序。
在应用程序中,最高级别的用户(管理员)可以创建和删除其他用户。正因为如此,应用程序本身与具有用户表的SELECT、INSERT、DELETE和UPDATE权限的MySQL用户连接到数据库。
对于一个精明的“标准”用户来说,简单地使用客户端连接到数据库,并修改用户表,例如将自己更改为管理员,这将是非常简单的。(因为他们必须知道MySQL用户和密码才能配置应用程序。应用程序将其MySQL凭据存储在序列化的XML文件中,密码是纯文本,因为用户必须知道才能连接。)
我想提高这个软件的安全性,但我不知道该如何进行。如果我限制数据库用户的权限,应用程序将不会赋予管理员用户修改用户的能力。如果我不这么做,标准用户可以利用这个明显的漏洞。
MySQL用户和应用程序用户(数据库表中的用户)目前完全不同。是否应该重新考虑这一点?
我应该如何重组我的应用程序,使其能够向“管理员”用户提供高级别的权限,同时防止标准用户利用应用程序的身份验证来规避安全性?
发布于 2013-06-26 17:47:23
这是数据库应用程序开发中常见的问题,有一些有效的解决方案。
首先,简单地说,应用程序的一个SQL帐户,拥有程序所能做的任何事情的权限,都是不好的。当该帐户的凭据硬编码到您的应用程序以允许连接时,情况会加倍糟糕。原因就在于您所假设的原因;有人可以将凭据输入SQL控制台并运行delete * from User来破坏您的安全系统。
第一种可能的解决方案是不向表授予任何非管理帐户CRUD权限,当然也不给硬代码,也不将管理帐户授予客户端软件。相反,可以通过对存储过程的执行权限授予对视图的SELECT权限和C_UD权限。这是一个古老且被广泛接受的解决方案,尽管大多数语言和环境的最佳实践现在鼓励其他模式,但它仍然被使用。
第二种解决方案在理论上是相似的,但在实现上有所不同;实现定义可能的数据操作的服务层端点。这是新的最佳实践,特别是在涉及公共网络(web服务)“匿名”使用的情况下。与连接到DB的客户端不同,客户端建立到端点的服务通道,并且从该点只能调用服务层允许的方法,并且可能还需要传递身份验证数据(例如令牌),以便进行除初始登录之外的任何数据调用。
上述两种方法的缺点是,您可能不得不对客户端数据访问进行深入的更改,以调用存储过程或服务方法,而不是直接基于表的操作。您现在在服务器端,甚至在数据层也有业务逻辑,涉及到确保用户只能做他们应该做的事情,而不是试图做他们不应该做的事情。最后,根据需要,您通过公开特定的访问方法来缩小有效数据检索操作的范围,这是DAL设计中的一个倒退,对于大多数现代语言来说,比如.NET和Java (它们有ORMs,比如Hibernate和实体框架,可以提供丰富的查询能力而不需要“魔法字符串”)。
最后一种解决方案需要最少的实现,但更容易受到攻击;硬编码到客户端的用户帐户具有验证用户凭据所需的最小权限(最好是授予单个存储过程“PerformLogin”的执行权限)。作为用户身份验证的一部分,在验证凭据之后,该例程将返回一个DB用户的SQL凭据,该用户具有与经过身份验证的用户帐户相关的数据相关权限。然后,客户端软件在使用所提供的凭据进行身份验证后重新连接到数据库。与其他解决方案相比,与其他解决方案相比,在直接DB连接和表操作的当前系统中实现它只需要对持久性层(以及身份验证成功后的重新连接)进行微小的更改,而不是通过调用存储的procs或服务来对如何获取数据进行更深层次的更改。
缺点是,通过身份验证可用的SQL用户必须表示有用的功能横截面,通常将总体结构更多地用于用户权限的“层”,而不是更加模块化的"a la carte“方案。减轻这种情况的方法(例如在身份验证之后动态地创建和设置用户权限)通常是从安全的角度来看他们自己的can‘蠕虫。然而,您将需要许多“内置”用户,每个层都有一个用户,这样这个两步连接过程才有更大的实际价值(如果Johnny用户的用户级别最低,但是仅仅通过验证他在其会话的其余部分获得了一个接近管理员的SQL用户帐户,您的客户端现在是唯一的安全层,正如我们已经讨论过的那样,可以很容易地绕过它)。最后,即使使用精心定制的SQL用户帐户,所需的权限仍然相当广泛;客户端需要更新表上的更新权限才能更新一条记录,但攻击者可以从控制台恶意使用这些权限来清除所有记录。其他解决方案非常具体地将允许的数据操作限制在这两种方法上。
https://security.stackexchange.com/questions/38059
复制相似问题