ACIDRain attack paper by Todd Warszawski, Peter Bailis.
A high-level overview blogpost在这篇论文上。
发现许多应用程序容易受此影响,例如。 WooCommerce,Opencart。
ACIDRain攻击可能会触发两种类型的异常,具体取决于所涉及的应用程序:
听起来两者都可以通过强制执行Serializable隔离级别来解决。这是对的吗?
此外,某些数据库没有真正的Serializable隔离级别,例如Oracle。可以采取哪些措施来保护他们免受此类攻击?
要使用SERIALIZABLE来保证真正的串行事务,每个事务都必须获取数据库中所有表的全局锁。没有办法事先知道您的交易将尝试读取或更新哪些数据,因此全局锁定是唯一真正的保证。
Oracle和MySQL都有一个事务隔离级别,他们称之为SERIALIZABLE,但他们采取乐观的策略。虽然每个都以不同的方式这样做,但我没有如上所述的全局锁定。
MySQL以一种简单的方式实现SERIALIZABLE:每个SELECT
都是隐含的SELECT...LOCK IN SHARE MODE
(在8.0中称为SELECT...FOR SHARE
)。这意味着如果两个会话读取数据然后尝试更新它,如本文中的余额借记示例所示,它们将导致死锁,因为两个更新都将等待另一个释放其共享读锁定。
Oracle允许您读取和更新数据,并乐观地获取锁(即在您阅读或更新时)。但是,如果您尝试更新自事务开始以来已修改的数据,则会收到以下错误:
ORA-08177: can't serialize access for this transaction
在Oracle和MySQL中,ACIDRain漏洞的最佳补救措施与隔离级别无关。解决方法是使用explicit locking reads查询选项使用FOR UPDATE
来避免竞争条件。这确保了在您读取数据时从数据开始的独占访问。
另一种解决方法是发出显式的表锁定命令,例如MySQL中的LOCK TABLES或Oracle中的LOCK TABLE。
参考文献:
在PostgreSQL中,情况很简单:如果你使用SERIALIZABLE
隔离级别,你可以自动防止这种攻击。这是因为PostgreSQL中的SERIALIZABLE
保证了“真正的”可串行化:如果涉及的所有事务都在该级别运行,则工作负载的结果等同于某些序列化的事务执行。没有异常是可能的。
您支付的价格是双重的:
SERIALIZABLE
会产生额外的费用,因为必须保持谓词锁定。当然,如果应用程序根本不使用事务,则无法使其安全......