{"id":26207,"date":"2026-09-21T15:15:47","date_gmt":"2026-09-21T23:15:47","guid":{"rendered":"https:\/\/www.palada.net\/index.php\/2026\/09\/21\/how-to-defend-arm64-cloud-infrastructure-from-itscape\/"},"modified":"2026-09-21T15:15:47","modified_gmt":"2026-09-21T23:15:47","slug":"how-to-defend-arm64-cloud-infrastructure-from-itscape","status":"publish","type":"post","link":"http:\/\/www.palada.net\/index.php\/2026\/09\/21\/how-to-defend-arm64-cloud-infrastructure-from-itscape\/","title":{"rendered":"How to defend ARM64 cloud infrastructure from ITScape"},"content":{"rendered":"<div class=\"rich-text_richText__UyrDZ\" data-anchor-headings=\"true\" data-component=\"rich-text\" data-reader-view=\"false\">\n<div class=\"payload-richtext\">\n<p>ITScape (CVE-2026-46316) is a guest-to-host escape vulnerability in the <em>vGIC-ITS<\/em> (Interrupt Translation Service) emulation within KVM\/arm64, disclosed by researcher Hyunwoo Kim (V4bel) via <em>oss-security<\/em> on June 10. The root cause is a race condition in the <em>vgic_its_invalidate_cache()<\/em> function that produces a double-put use-after-free, ultimately enabling host kernel code execution.\u00a0<\/p>\n<p>Because the bug lives entirely within in-kernel KVM rather than QEMU user-space, successful exploitation yields host kernel privilege rather than user-process compromise, making it a direct threat to multi-tenant arm64 cloud environments that accept untrusted guests.<\/p>\n<p>In scenarios where the attacker lacks guest root, ITScape can be chained with a local privilege escalation. The vulnerability affects kernels from commit <em>8201d1028caa<\/em> (2024-04-25) through <em>13031fb6b835<\/em> (2026-06-05), at which point the patch landed in mainline.<\/p>\n<p>Here\u2019s what you need to know about ITScape \u2014\u00a0including recommendations for discovery, how to detect exploits with YARA rules, and Indicators of Compromise (IoCs).\u00a0<\/p>\n<h2 id=\"yara-detection\">YARA detection<\/h2>\n<p>Two YARA rules have been developed to detect this threat. <em>ITScape_ExploitConstants_1<\/em> targets nine hardcoded 64-bit constants present in the PoC source: kernel symbol addresses <em>(ORDERLY_POWEROFF, POWEROFF_CMD, NEIGH_GC_WORK_FUNC, PMU_FN_LINKED, gadget_rt)<\/em>, an anti-leak sentinel <em>(LEAKLEAD)<\/em>, and the three packed u64 values that compose the <em>\/bin\/touch \/ITScape<\/em> host command string. All constants are encoded little-endian as they appear in a compiled ARM64 ELF.\u00a0<\/p>\n<p>Testing against the known PoC binary confirms seven of nine strings match; <em>$pmu_fn_linked<\/em> and <em>$gadget_rt<\/em> are absent from this build, most likely because <em>gadget_rt<\/em> is only ever materialized at runtime as base + voff and the linker does not emit either constant as a bare relocatable literal in this particular build. Both strings are retained in the rule defensively: a statically linked build, a differently optimized build, or a future variant may resolve these constants differently and produce hits where the known sample does not. The constants as found in the poc.c source code are shown in the figures below.<\/p>\n<div class=\"rich-media_container__AH6jG media-block_mediaBlock__nZBDJ\" data-position=\"left\" data-restrict=\"true\" data-size=\"fill\">\n<div class=\"rich-media_media__trppT\"><template id=\"P:f\"><\/template><\/p>\n<div class=\"rich-media_overlay__LSRfe\"><svg aria-hidden=\"true\" class=\"lucide lucide-expand\" fill=\"none\" height=\"24\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" viewbox=\"0 0 24 24\" width=\"24\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"m15 15 6 6\"><\/path><path d=\"m15 9 6-6\"><\/path><path d=\"M21 16v5h-5\"><\/path><path d=\"M21 8V3h-5\"><\/path><path d=\"M3 16v5h5\"><\/path><path d=\"m3 21 6-6\"><\/path><path d=\"M3 8V3h5\"><\/path><path d=\"M9 9 3 3\"><\/path><\/svg><\/div>\n<\/div>\n<\/div>\n<p><em>Figure 1: First set of constants defined in the exploit <\/em>poc.c<\/p>\n<div class=\"rich-media_container__AH6jG media-block_mediaBlock__nZBDJ\" data-position=\"left\" data-restrict=\"true\" data-size=\"fill\">\n<div class=\"rich-media_media__trppT\"><template id=\"P:10\"><\/template><\/p>\n<div class=\"rich-media_overlay__LSRfe\"><svg aria-hidden=\"true\" class=\"lucide lucide-expand\" fill=\"none\" height=\"24\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" viewbox=\"0 0 24 24\" width=\"24\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"m15 15 6 6\"><\/path><path d=\"m15 9 6-6\"><\/path><path d=\"M21 16v5h-5\"><\/path><path d=\"M21 8V3h-5\"><\/path><path d=\"M3 16v5h5\"><\/path><path d=\"m3 21 6-6\"><\/path><path d=\"M3 8V3h5\"><\/path><path d=\"M9 9 3 3\"><\/path><\/svg><\/div>\n<\/div>\n<\/div>\n<p><em>Figure 2: Second set of constants<\/em><\/p>\n<p><em>ITScape_KVM_PrivDrop_1<\/em> takes a behavioral approach, targeting a semantically unique instruction sequence in the compiled binary: a <em>stat(2)<\/em> group permission check (st_mode &amp; 0x6 == 0x6) on <em>\/dev\/kvm<\/em> followed immediately by <em>setgroups(0, NULL) \/ setgid(1000) \/ setuid(1000)<\/em> with error-checked cbnz branches after each call. Branch offsets and stack frame offsets are wildcarded at the byte and nibble level using ARM64 instruction encoding semantics, making the pattern robust to recompilation while keeping all semantically meaningful immediates as exact matches. The region of disassembled code detected by this rule is shown in the next figure.<\/p>\n<div class=\"rich-media_container__AH6jG media-block_mediaBlock__nZBDJ\" data-position=\"left\" data-restrict=\"true\" data-size=\"fill\">\n<div class=\"rich-media_media__trppT\"><template id=\"P:11\"><\/template><\/p>\n<div class=\"rich-media_overlay__LSRfe\"><svg aria-hidden=\"true\" class=\"lucide lucide-expand\" fill=\"none\" height=\"24\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" viewbox=\"0 0 24 24\" width=\"24\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"m15 15 6 6\"><\/path><path d=\"m15 9 6-6\"><\/path><path d=\"M21 16v5h-5\"><\/path><path d=\"M21 8V3h-5\"><\/path><path d=\"M3 16v5h5\"><\/path><path d=\"m3 21 6-6\"><\/path><path d=\"M3 8V3h5\"><\/path><path d=\"M9 9 3 3\"><\/path><\/svg><\/div>\n<\/div>\n<\/div>\n<p><em>Figure 3: Privilege drop on <\/em>\/dev\/kvm<\/p>\n<h2 id=\"recommendations\">Recommendations<\/h2>\n<p>Defenders running arm64 KVM hosts should prioritize applying the mainline patch at commit <em>13031fb6b835<\/em> and the two companion fixes for CVE-2026-46316. Organizations operating multi-tenant arm64 infrastructure, particularly public cloud providers, should closely evaluate this issue given that exploitation requires only guest kernel privilege and yields host root. Since this represents a new vulnerability class, additional variants and follow-up vulnerabilities are expected, so continued monitoring of the <em>vgic-its<\/em> code path is warranted even after patching.<\/p>\n<h2 id=\"iocs\">IoCs<\/h2>\n<h3>PoC SHA256<\/h3>\n<div class=\"p code-block_codeBlock__uEaiL\" data-component=\"code-block\">\n<pre><code>e0ab84da2d2783c8cae3624e8ce58b99ad79219753b249671ff7f743abdacc35<\/code><\/pre>\n<\/div>\n<h3>YARA Rules<\/h3>\n<div class=\"p code-block_codeBlock__uEaiL\" data-component=\"code-block\">\n<pre><code>rule ITScape_ExploitConstants_1\n{\n\u00a0\u00a0\u00a0\u00a0meta:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0author = \"Malware Utkonos\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0date = \"2026-05-11\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0description = \"Detects constants used in ITScape exploit PoC.\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0reference = \"https:\/\/github.com\/V4bel\/ITScape\/blob\/main\/poc.c\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0poc = \"e0ab84da2d2783c8cae3624e8ce58b99ad79219753b249671ff7f743abdacc35\"\n\u00a0\u00a0\u00a0\u00a0strings:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$orderly_poweroff \u00a0 = { 2cf90d800080ffff }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$poweroff_cmd \u00a0 \u00a0 \u00a0 = { c803d0820080ffff }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$neigh_gc_work_func = { 502d1d830080ffff }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$pmu_fn_linked\u00a0 \u00a0 \u00a0 = { b80e09800080ffff }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$gadget_rt\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 = { dcc6d7800080ffff }\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ canary magic (\"LEAKLEAD\" = 0x4c45414b4c454144 byte-swapped)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$leak_sentinel\u00a0 \u00a0 \u00a0 = { 4441454c4b41454c }\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ payload: \"\/bin\/touch \/ITScape\" packed as three u64s\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$sc_write_bin_tou \u00a0 = { 2f62696e2f746f75 }\u00a0 \/\/ \/bin\/tou\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$sc_write_ch_ITSc \u00a0 = { 6368202f49545363 }\u00a0 \/\/ ch \/ITSc\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$sc_write_ape \u00a0 \u00a0 \u00a0 = { 6170650000000000 }\u00a0 \/\/ ape\\0\n\u00a0\u00a0\u00a0\u00a0condition:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a05 of them\n}\n\nrule ITScape_KVM_PrivDrop_1\n{\n\u00a0\u00a0\u00a0\u00a0meta:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0author = \"Malware Utkonos\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0date = \"2026-05-11\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0description = \"Detects \/dev\/kvm group rw check and drop to setgroups\/setgid\/setuid(1000) used in ITScape PoC.\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0reference = \"https:\/\/github.com\/V4bel\/ITScape\/blob\/main\/poc.c\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0poc = \"e0ab84da2d2783c8cae3624e8ce58b99ad79219753b249671ff7f743abdacc35\"\n\u00a0\u00a0\u00a0\u00a0strings:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$kvm = \"\/dev\/kvm\"\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$op = { e0??4?b9 00041f12 1f180071 ?1[2]54 010080d2 000080d2 [3]9? 007d8052 [3]9? ?0[2]35 007d8052 [3]9? ?0[2]35 }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ 004025cc\u00a0 e0c340b9 \u00a0 ldr \u00a0 \u00a0 w0, [sp, #0xc0 {guest_memfd.reserved[0].d}]\u00a0 \/\/ load stat st_mode; offset floats\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ 004025d0\u00a0 00041f12 \u00a0 and \u00a0 \u00a0 w0, w0, #0x6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ mask S_IRGRP|S_IWGRP (0x4|0x2)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ 004025d4\u00a0 1f180071 \u00a0 cmp \u00a0 \u00a0 w0, #0x6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ both group rw bits must be set\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ 004025d8\u00a0 c1f0ff54 \u00a0 b.ne\u00a0 \u00a0 0x4023f0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ 004025dc\u00a0 010080d2 \u00a0 mov \u00a0 \u00a0 x1, #0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ setgroups(0, NULL)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ 004025e0\u00a0 000080d2 \u00a0 mov \u00a0 \u00a0 x0, #0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ 004025e4\u00a0 b3feff97 \u00a0 bl\u00a0 \u00a0 \u00a0 setgroups\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ 004025e8\u00a0 007d8052 \u00a0 mov \u00a0 \u00a0 w0, #0x3e8 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ setgid(1000)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ 004025ec\u00a0 71feff97 \u00a0 bl\u00a0 \u00a0 \u00a0 setgid\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ 004025f0\u00a0 00f0ff35 \u00a0 cbnz\u00a0 \u00a0 w0, 0x4023f0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ 004025f4\u00a0 007d8052 \u00a0 mov \u00a0 \u00a0 w0, #0x3e8 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ setuid(1000)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ 004025f8\u00a0 a6fdff97 \u00a0 bl\u00a0 \u00a0 \u00a0 setuid\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ 004025fc\u00a0 a0efff35 \u00a0 cbnz\u00a0 \u00a0 w0, 0x4023f0\n\n\u00a0\u00a0\u00a0\u00a0condition:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$kvm and $op\n}<\/code><\/pre>\n<\/div>\n<p><small class=\"small-text-block_smallText__HEOYA\" data-component=\"small-text-block\"><\/p>\n<div class=\"rich-text_richText__UyrDZ\" data-component=\"rich-text\" data-reader-view=\"false\">\n<div class=\"payload-richtext\">\n<p><em>This post was assembled with assistance from generative AI.<\/em><\/p>\n<\/div>\n<\/div>\n<p><\/small><\/p>\n<\/p>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>ITScape (CVE-2026-46316) is a guest-to-host escape vulnerability in thevGIC-ITS(Interrupt Translation Service) emulation within KVM\/arm64, disclosed by researcher Hyunwoo Kim (V4bel) viaoss-securityon June 10. The root cause is a race condition in thevgic_its_invalidate_cache()function that produces a double-put use-after-free, ultimately enabling host kernel code execution.Because the bug lives entirely within in-kernel KVM rather than QEMU user-space, successful exploitation yields host kernel<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[32775],"tags":[],"class_list":["post-26207","post","type-post","status-publish","format-standard","hentry","category-reversinglabs"],"_links":{"self":[{"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/26207","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/comments?post=26207"}],"version-history":[{"count":0,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/26207\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/media?parent=26207"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/categories?post=26207"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/tags?post=26207"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}