This vulnerability was discovered with V12 by Rick de Jager of the V12 security team .
Want to find issues like this in your own code? Try V12 at v12.sh .
Want to find issues like this in your own code? Try V12 at v12.sh .
Fixed in AnyDesk 8.0.3. The vendor appears to have deleted (?) the 8.0.2 build of anydesk upon the release of our poc video. Porting the exploit to 8.0.1 or obtaining a 8.0.2 build is left as an exercise to the reader.
AnyPwn is a pre-approval remote code execution vulnerability in AnyDesk Linux 8.0.2. The session protocol's mode-5 stream packet handler trusts a remote payload length before validating it. Adding the 16-byte object header to that length with 32-bit arithmetic can wrap to a tiny allocation while the object retains the original large logical length. AnyDesk then copies attacker-controlled packet bytes beyond the allocation.
The supplied PoC exploits the resulting heap corruption through the direct, local TCP/7070 transport and executes an arbitrary command. The same vulnerable session-protocol path is reachable over AnyDesk relay connections, which we validated with a minimal Frida trigger. To limit engineering time, the included minimal PoC demonstrates the full exploit only over direct TCP/7070 connections. The service normally runs as root on Linux, so successful exploitation yields root command execution before desktop-control approval.
Run the vulnerable AnyDesk Linux 8.0.2 service with TCP/7070 reachable, then execute:
Verify command execution:
For a directly reachable remote target, replace 127.0.0.1 with the target host. The exploit requires Python 3 and the rich package.
The included offsets target this exact build and environment:
Heap layout is probabilistic. If the victim client object is not immediately after the undersized buffer, the exploit crashes the service instead of executing the command. Other AnyDesk builds require different offsets.
A mode-5 packet on an assigned stream has this form:
For a valid packet, mode5_declared_len must not exceed the bytes remaining in the frame. The vulnerable path instead calculates a backing allocation from the unvalidated 32-bit declared length. AnyPwn declares 0xfffffff0 bytes:
Values from 0xfffffff0 through 0xffffffff therefore allocate only 0 through 15 bytes. The object data pointer remains allocation_base + 0x10 , and its length remains the original large value, so copying even one body byte writes outside the allocation. The attacker does not need to send four gigabytes: the outer frame remains small, its varint causes the integer wrap, and its body supplies the overflow bytes.
The PoC uses two complementary heap-spraying strategies. First, it sends 100 persistent mode-5 objects at each size from 0x1 through 0x17f1 in 0x10 increments. Covering that range populates the allocator's relevant size classes and reduces dependence on one exact allocation size. It then opens ten additional client connections, placing candidate victim objects among the groomed allocations. This remains probabilistic: the overflow is useful only when one of those victims is adjacent to the wrapped allocation.
The later ROP spray serves a different purpose. Twenty identical 0xf000 -byte objects contain a long ret -gadget sled followed by the actual chain. Repeating the object and providing a wide sled gives the corrupted stack pivot many equivalent landing points instead of requiring an exact address within a single copy.
The PoC turns the primitive into command execution as follows:
Complete service setup and obtain an assigned stream.
Send a normal profile object to enter the profile/session mode-5 path.
Groom the allocator with the size-graded mode-5 spray, then open the ten candidate victim clients.
Send a packet declaring mode5_declared_len = 0xfffffff0 . Its body overflows the wrapped allocation and replaces dispatch-related fields in an adjacent victim, including a chosen vtable and stack-pivot gadget.
Spray the repeated ROP objects so the pivot can land in a ret sled and advance to the chain.
Continue setup on each victim client. Processing the corrupted victim uses the overwritten control data and transfers execution through the pivot into a sprayed chain.
The chain writes the requested command into fixed scratch memory, loads its address as the first argument, and calls the target build's system() PLT entry.
Found with V12 by Rick de Jager of the V12 security team: v12.sh : dangerously powerful agentic security.
The full story
This article is one source in a clustered incident — the cluster page carries the summary, timeline and every other outlet covering it.
