ACIDRain attack paper by Todd Warszawski, Peter Bailis.
A high-level overview blogpost在本文上。
许多应用程序容易受到此攻击,例如。 WooCommerce,Opencart。
ACIDRain攻击可能会触发两种类型的异常,具体取决于所涉及的应用程序:
听起来这两种方法都可以通过对事务强制执行Serializable隔离级别来解决。这是对的吗?
此外,某些数据库没有真正的可序列化隔离级别,例如Oracle。如何保护他们免受此类攻击?
答案 0 :(得分:3)
要使用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漏洞的最佳方法与隔离级别无关。补救措施是通过使用FOR UPDATE
查询选项使用explicit locking reads来避免争用情况。这样可以确保从读取数据开始就对数据进行独占访问。
另一种补救方法是发出明确的表锁定命令,例如MySQL中的LOCK TABLES或Oracle中的LOCK TABLE。
参考文献:
答案 1 :(得分:1)
在PostgreSQL中,情况很简单:如果使用SERIALIZABLE
隔离级别,则可以自动免受此类攻击。这是因为PostgreSQL中的SERIALIZABLE
保证了“真实”的可串行性:如果所有涉及的事务都在该级别上运行,那么工作量的结果就等同于事务的某些序列化执行。没有异常是可能的。
您要支付的价格是两倍:
SERIALIZABLE
会产生额外的费用,因为必须维护谓词锁。
如果您收到“序列化错误”,则必须准备重复每笔交易。
当然,如果应用程序根本不使用事务,则无法使其安全...