检测到数据库被篡改,有可能吗?

老听众,第一次打电话。

’假设您有一个负责记录用户活动的数据库表。此日志的完整性非常重要,因此您希望能够检测是否有人修改了表中的任何数据。为了让事情变得更有趣,还要考虑这样一个事实: 您的系统可能是由一个邪恶的 SQL 管理员操作的,他完全控制了这个糟糕的系统。哎呀..。

您将如何保护您的数据?

如何检测是否有人篡改了您的数据?

你可以使用无限的工具(比如散列、加密等等)

10967 次浏览

将您的系统设置为将日志数据写入邪恶的 SQL 管理员无法控制的远程系统。这不会阻止说管理员删除或篡改您的日志程序,但它会阻止他修改后的事实。

您可以使用触发器来审核插入、更新和删除。现在,如果“邪恶的 SQL 管理员”禁用触发器,那么您将遇到一些更困难的问题。如果我想保护我的数据,我不会允许邪恶的管理员完全控制系统。

这是一个常见的数据安全问题。简单的答案是——如果您处于一个“邪恶的 SQL 管理员”可以访问您的整个环境的情况下,那么您就没有办法保护您的数据。

关键任务数据的常见做法是记录到多个备份,并通过确保没有单个人拥有权限来进行保护。

如果“邪恶管理员”无法访问填充数据库的应用程序,那么每个表上的一个额外的列将完成这项工作,该列由其余列的 加密签名加密签名组成。“无法访问”的条件是必要的,这样他们就不能只是提取您的私钥和签署他们的虚假数据。

编辑: 啊,正如评论者指出的那样,我没有考虑管理员只是删除一行。为此,您将需要一个额外的行,其中包含每次更新的加密签名行数(或者表内容其余部分的签名散列,或者最后访问时间,或者您选择的任何指示器)。

创建一个影子表,用一个只有您和应用程序知道的 key/salt 散列每个文件。如果要检查数据篡改,请重新散列用户表并与影子表进行比较。

如果你真的想要安全的使用-写一次为该表阅读多媒体。

如果你的应用程序总是在运行,你可以在数据库上启动一个事务,直到你的应用程序关闭才释放它... ... 这样除了你的应用程序,没有任何东西可以查看表... ..。

还有,如果你有时间的话,加密所有进出程序的文本字符串数据。

我也喜欢鲍比 · 沙夫托的回答... ... 不过再深入一点,看看你能不能触发“睡觉”之类的东西,这样几分钟后所有的记录都会恢复原样... ... 所以我们邪恶的管理员认为他做了改动,但它们只会被恢复。

如果您确实必须检测到篡改已经发生,那么向表中添加校验和字段。每个新行的校验和必须包括前一行的校验和。然后,为了验证内容,在前进时遍历数据集计算校验和。如果计算出的校验和与表中的值不匹配,那么某些值已被篡改。

麦克

除了用于审计、校验和等的触发器之外,您还可以考虑将数据库复制到另一个从数据库-没有人能够直接对其执行任何操作。

你仍然有可能有人破坏了触发器等等,但是当他们被破坏的时候,它会非常明显,所以你能够检测到复制被破坏的时间点。

您可以添加一个触发器来发送数据的副本,因为数据被输入到一个非生产数据库,而邪恶的管理员也不能访问该数据库。管理员可以停止触发器的工作,但问题是如何检测操作,而不是阻止它。

我认为这是一个很好的问题! 但是您的场景违背了数据库的设计原则。

行校验和、导出到其他数据库的触发器——您所做的任何事情都将是一种妥协!

我只能建议一些框外的东西-它会有所帮助,如果你是应用某种类型的标准,如 PCI符合性?

如果失败了,我建议你再找一份工作!在我们这个行业有很多工作你不需要和这种人一起工作。

用你的交易 ID 运行一个纸质日志,把打印机放在一个只有一把钥匙的房间里。与金融系统一起工作,你会发现许多金融系统仍然依赖于它们的纸质备份。几乎不可能不可追踪地“黑进”一个纸质日志... ... 这就是为什么人们不断推动在投票机上进行纸质日志记录。

很多人说,“只要添加另一个数据库”,虽然我实际上 练习这种类型的日志自己,我不信任它。一个恶意的内部人士可以通过十几种方式破坏这种安全措施。

我们现在要做的就是想办法让大家知道发生了什么事。你会失去你的记录。您将无法信任它们: 如果我遇到一个具有万无一失的日志记录系统的系统,我要么将其填充为垃圾数据,要么将其完全删除。不要陷入马其诺防线的思维模式。

但是,如果您准备 够了,这样就会发生太多的故障,您可以将破坏行为缩小到一个内部源。你需要记录 在附近的数据库,你需要保持广泛的系统日志,你需要监控 IP 流量,在服务器机房放一个摄像头,在控制台上留一个键盘记录器,等等。即使是最好的捕鼠器也会在某个地方出错,如果你周围有足够多的捕鼠器,你可能会不小心在某个地方抓到它们。

首先,要非常小心你雇佣谁来管理你的系统。

由触发器填充的下一个审计表。即使他绕过了更改的触发器,您至少可以查看在他更改之前的数据(特别是从备份中)。

第三个自动备份被移除到异地。这样,即使坏人删除了数据库并删除了现场备份,你也有了一个备用位置。确保数据库管理员无法访问异地备份,只有其他人拥有权限,而这些人对数据库服务器没有生产权限。

接下来,除了管理员之外,任何人都不能直接使用表。这意味着使用没有动态 SQL 的存储进程。这至少可以防止其他人以未经授权的方式更改数据。现在你的会计人员更难欺诈了。

除了作为备份的管理员和其他人之外,任何人都没有生产管理员权限。这样如果你发现触发器变了,你就知道是谁干的了。如果出了什么差错,你们只有两个嫌疑人。

SQLServer2008具有 DDL 触发器,它可以告诉您谁进行了结构更改。同样,如果触发器没有记录更改,那么默认情况下它是由管理员做出的。

加密备份和某些个人数据,使得窃取更加困难。现在,非现场的备份送货人将有一个更困难的时间窃取您的数据。

开除任何被证明不值得信任的管理员,即使这些数据不是他不值得信任的。如果他会伪造时间表或者偷办公用品,他就会偷数据。如果他因为一些严重的犯罪(不是交通违章)而被捕,如果需要的话,你可以让他停职,看看这个指控是否被证实。

当管理员决定转移到另一个工作时,不要让他从他告诉你他要去的那一刻起就访问你的系统。如果你要解雇他,这一点尤其重要。

我发现这个 文章,它看起来很有趣,可能是一个可能的解决方案,尽管我还没有花时间去尝试和思考漏洞。


在我的脑海中,我可以想象有两个独立的数据库,“邪恶的”系统管理员只能访问其中一个。

一个数据库将向另一个数据库提供一次性记事本,并记录请求记事本的人和时间。可以对这个垫以及当前的时间和行数据进行散列处理。

这样,如果邪恶的系统管理员改变了一些散列不会检查出来的东西,如果他试图重新散列你会有一个什么时候事情 应该已经发生的日志。

如果系统管理员可以存储时间和一次性垫,那么整个系统崩溃。

这是一个看似困难的问题,我不确定任何协议是否真的有效,但是添加物理安全性和审计日志将是一个好主意。

如果您想要一个自动化的方法,您首先必须知道用户类型允许什么样的操作和上下文。这是相当困难的,因为在正确的上下文中,下降是可以接受的,但是对于日常用户就不行了。

我确实喜欢纸质备份的想法,但是产生的信息量可以变得非常大,用户基础很大,数据库使用量很大。

考虑创建一个滚动的、快速的、离线的、自动化的数据备份。如今,中三非常便宜,以至于人们可能会偶尔使用 mysqldump类型的进程来将整个数据存储库传输到跨大西洋备份存储区。确切的频率取决于您的 DBA 的邪恶程度。

为了使这个过程成为可能,只需在您的网络中找到或建立一台机器,而邪恶的管理员对这台机器一无所知,或者如果她怀疑有任何问题,她也不会关心这台机器。插头电脑的简单和优雅在这里怎么强调都不为过。

关于实际导出机制的注意事项: 对您的特定系统一无所知,我建议将 mysqldump或 Oracle exp作为最简单和最愚蠢的解决方案。如果你的应用程序可以导出 本地人格式的数据(比如 XML、 JSON,甚至是协议缓冲格式——换句话说,就是 SOA 应用程序中各部分之间通信所使用的任何格式) ,那么这种格式就可以作为你的滚动转储的格式。

我已经在我的 gitosis机器上实现了这种方法。每三个小时,里面的东西就会被倒进一个欧洲 S3桶里。这是一个穷人的 VCS 的另一个 VCS。

让我们弄清楚: 如果你假设一个邪恶的系统管理员,没有加密解决方案可以阻止他们以一种不可追踪的方式修改系统中的数据——有解决方案可以阻止他们解密信息,但没有任何方法可以阻止他们以任何他们认为合适的方式写入新信息。

这种情况要求满足以下条件:

  1. 这个系统必须是独立的。如果您可以添加另一个系统,因为邪恶的 Sysadmin 无法作为日志主机(比如 syslog 服务器)访问,那么突然之间,问题就变成了定期传输日志或散列的小问题。

  2. 系统没有非软件一次写入组件。正如其他人建议的那样,最简单的就是打印机之类的东西,但是您可以使用 CD 或自定义一次写入硬件来防止这种问题。如果邪恶系统管理员对机器有物理访问权限,这些问题会变得更棘手,但并非不可克服。

  3. 你需要的是确定性,而不是统计上的可能性。如果 # 1和 # 2是不可能的,你唯一剩下的解决方案是模糊化-设计的欺骗性陷阱的实施,以捕捉篡改,如果邪恶的系统管理员不知道的陷阱。

有效的第三条秘诀就是战术突袭。其目的是向攻击者传达这样一种印象,即他们知道所有的反制措施,而事实上他们还有更多的不知道的反制措施。一般来说,这需要至少两层保护——你需要至少有一层保护,邪恶系统管理员可能会妥协,因为他们会寻找它,如果他们没有找到它,他们会起疑心,挖得更深,直到他们找到。

重要的一点是,这个封面应该是如此令人信服,以满足邪恶的系统管理员,一旦他们发现了它,他们不需要看了。然后,第二层使用替代技术识别篡改,并产生适当的警报。在这个线程重新事务等有各种各样的建议,可以实现。解决方案的级别越低,成功的可能性就越大(例如,修补数据库源代码的可见性远远低于进行连接和查询的标准进程,修补内核的可见性再次低于修改固件的可见性。.).

重要的是要强调,这不是一个完美的解决方案。无论您的设置多么复杂,都有可能有人已经找到/破坏了足够的信息来实现对策。对于 # 1和 # 2(做得恰当) ,情况并非如此。也就是说,如果你所保护的信息的价值足够低,拥有必要技能的人不会有兴趣去获取它,它应该提供一个可行的防御。

每隔几个小时,对表中的内容进行一次散列。还要记录开始和结束行。对于第二个散列和 on-ward,同时对整个表的内容和前一个散列(检查散列)中的行进行散列。如果上一个散列和检查散列不匹配,则数据库表已被篡改。我会把这些哈希发邮件给你,这样你就可以检查是否流氓管理员已经通过并重新生成了所有的哈希。我知道这里有一个缺口,但是我认为除了这个或者已经提到的,我们不能做更多的事情(除了消除他们的访问权限)。

我喜欢 MikeMontana 的解决方案,但我认为可能值得添加一个附录。遗憾的是,我现在还不能留言,所以我把它发布在一个新的答案中,原文引用如下:

如果你一定要发现的话 发生篡改,然后添加一个 表的校验和字段 每个新行的校验和必须包括 前一行的校验和。然后到 验证内容,遍历 数据集计算校验和 向前迈进 中的值不匹配 表,然后一些价值已被 被篡改了。

麦克

有几个人指出: 系统管理员可以重新计算校验和(如果你想在他的服务器上编写代码,这个问题就更严重了) ,我在其中添加了以下增强:

当数据被插入到表中时,它是用公钥加密的,因此任何人都可以添加到数据库中(假设有多个人在使用它)。定期使用私钥解密数据并计算校验和。如果不同,则表示数据库已被修改(您想要测试的内容)。然后重新计算校验和并将其插入到表中(当然,公钥也是加密的)。

如果邪恶的系统管理员试图重新计算一个新的检查和,他正在做加密数据。

另外,如果您远程访问这些数据,那么这种方法通过在本地盒子上进行解密和校验和计算,可以免受中间人的攻击。截获的数据将保持加密,因此不可用。

该系统的唯一缺陷是检测到数据库的任何事务。你可以通过抽象来解决这个问题,然后说:

  • 验证校验和
  • 插入数据
  • 重新计算校验和

但是这样就消除了让任何你想要访问数据的人在不泄露你的私钥的情况下访问数据的优势。

现在我们可以用另一种方法来解决这个问题,对此我建议你们:

解决网格计算中的信任不对称问题

作者: Peter Dinda

Http://portal.acm.org/citation.cfm?id=1066656

但实现细节变得更长。

虽然这里有一些非常好的建议,但是它们都将被淘汰。

因为您有一个“不受信任”的参与者,即邪恶的管理员,作为您的数据的保管人,您无法保护自己。在网络协议和现实世界中有各种各样的方案,使您能够保护您的数据免受不可信的传输/信使的篡改。但据我所知,没有什么能保护你不受不信任的保管人的伤害比如说“你好”。我是麦道夫先生,我曾经是纽约证券交易所的主席,你可以相信我... ...”。

分离电源/双电源控制。

我喜欢迄今为止提出的想法。我想加上我自己的2分钱。

在金融业,权力分立一直是防止一个人变得完全邪恶的关键。我们的核心处理解决方案是由我们的簿记部门管理的(上帝保佑他们) ,所以我们程序员实际上并没有获得对实时数据的大量访问。

另外,第三方会记录与系统关键部分的交互。

总的来说,没有一个人有足够的控制权来影响所有的制衡,使得收益减少到不值得协调的程度。

由于邪恶的管理员可以完全控制服务器,因此可能需要一个外部审计解决方案,该解决方案旨在监视拥有特权的 SQLServer 用户的活动。

Guardium 创建一个网络设备,该设备可以记录数据库或服务器上的所有查询活动,并在网络级别(包括本地连接)执行此操作,因此您无法在 SQL Server 级别执行任何操作来干扰它。

这并不能阻止邪恶的管理员更改表,但是,因为它是一个被锁定的设备,邪恶的管理员不能更改表然后说服设备说他没有这样做。

关于这个话题有两篇有趣的研究论文 其中一个建议使用 HMAC 路由器,另一个建议使用浓缩- RSA 方案与 BGLS 签名方案。

外包数据库中的认证与完整性

Http://www.isoc.org/isoc/conferences/ndss/04/proceedings/papers/mykletun.pdf

一种面向关系数据库的通用无失真水印技术

Http://www.dsi.unive.it/~cortesi/paperi/iciss09.pdf

我觉得两者都是基于感知风险的可行解决方案。 —— Kiran. Kumar

我在研究如何实现这样一个解决方案时发现了这个线程。我想到的一个(非常理论化的)解决方案很像使用一个完美的转发密钥系统。

我认为,如果你有一个私有-公共密钥对(称为 Kpr 和 Kpb)和一组算法(A 和 B) ,这样:

A(K_pr)=K'_pr

B(K_pb)=K'_pb

(其中 K’pr 和 K’pb 是与 Kpr 和 Kpb 不同的有效私钥-公钥对)

使用这种方法,您可以对数据库中的每一行进行签名,在使用后丢弃每一个私钥,但是使用签名保存公钥。然后你可以把第一个公钥保存在一个邪恶的管理员无法改变的地方(比如发送给你认识的每个人,把它印在报纸上,把它纹在你的脸上,所有这些)。

没有办法重新签名每个记录,因为没有私钥了,您可以检查是否所有的公钥都是连续的。我能想到的只有两个缺点:

  • 如果邪恶的管理员获得一个私钥的副本,他将能够从那一刻起更改任何记录。这可以通过使用硬件模块来创建签名来规避,因此私钥不能从软件中访问
  • 邪恶的管理员将能够将数据追加到表中。

问题是,我没有意识到一组像我所描述的那样的算法。不过,我不是密码破译员,所以有可能。

编辑:

经过更多的思考,我可能已经找到了一种方法,使现有的工具可以做到这一点。如果在(n-1) st 记录中包含第 n 条记录的公钥及其签名(您可以这样做,因为在写入记录时,可以可以访问下一个私钥) ,那么您将使用前一个记录保护所有记录。删除私钥后,无法重新创建签名,因此只要您拥有第一个公钥,就可以始终验证整个表。这也消除了拥有“顺序”私钥的需要,您可以简单地为每一行生成一个新的私钥(尽管这将是非常昂贵的)。同样的缺陷仍然存在。

2016年这个问题的答案是使用 区块链数据库。根据维基百科:

块链主要是通过将最近有效事务的批次散列标记为“块”来防止篡改,从而证明数据当时一定存在。每个区块包括先前的时间戳,形成一个区块链,每个额外的时间戳加强之前的区块。