🔥 CyberForge CVE of the Day #070
🚨 CVE-2026-61500 — Rejetto HFS: session forgery to remote code execution
HFS 3.0.0–3.2.0 could generate its default session-signing key with Math.random(), then expose outputs from the same generator during unauthenticated login. VulnCheck's CNA advisory describes recovery of that key, a forged administrator session and execution through the legitimate server_code configuration feature.
🗓️ Evidence cutoff: 6 October 2026, 08:46 UTC. First fixed: 3.2.1, released 13 July. This is an older disclosed issue with public research, not a newly discovered October zero-day.
🎯 THE QUICK HIT
Who should act? Owners of HFS 3.0.0–3.2.0, especially reachable file-sharing services. Identify serving builds, access paths and process permissions. Do not import unrelated HFS 2.x exploit mechanics or indicators.
What is the trust failure? Predictable key generation undermines signed-session trust. Password guessing and a broken signature algorithm are not required. Public research describes knowing an existing account name; the CNA rates prior privileges as none.
What fixes it? 3.2.1 changes the default key generator to cryptographic random bytes and the exposed login identifier to a UUID. Use a suitable supported stable release and verify every serving instance. Latest stable at retrieval: 3.3.4. The repair floor is 3.2.1.
First SOC moves? Preserve access/error logs, rotations, configuration history and host/container evidence. Follow login activity into administrative changes and HFS behaviour. API names, HTTP 200 and nonempty server_code are leads requiring context.
What can survive repair? Earlier unapproved configuration, accounts, plugins and altered files. Fixed source still accepts COOKIE_SIGN_KEYS overrides. Retire suspect verification keys with the owner; retaining a compromised old key can preserve acceptance of old signatures.
How urgent? VulnCheck labels its advisory in its own KEV database; retrieved CISA KEV has no exact match. VulnCheck's supporting feed returned 401, leaving incident dates, actors and organisations unverified here. Prioritise exposed affected systems with that distinction intact.
🔑 KEY DETAILS
• Product: Rejetto HFS, the 3.x HTTP file server.
• Weakness: CWE-338 — use of a cryptographically weak pseudo-random number generator.
• VulnCheck CNA CVSS v3.1: 9.8 Critical — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H.
• VulnCheck CNA CVSS v4.0: 9.3 Critical — CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N.
• Published prerequisites: network access, low complexity, no prior privileges and no victim interaction. Exposure and account naming still matter to practical scoping.
• Affected: 3.0.0 through 3.2.0. First fixed: 3.2.1.
• Impact: HFS administrative access and execution as the HFS process; actual file access and downstream reach depend on deployment permissions.
• Disclosure/fix: 13 July 2026. CNA record updated: 1 October 2026. Today's edition: #070, 6 October.
• NVD: Deferred. Its scores are VulnCheck-attributed; no separate NIST score was present.
• CISA KEV: no exact match in catalogue 2026.10.04, released 4 October. Absence is not evidence of an unexploited or clean system.
• FIRST EPSS: 0.009870000 = 0.987%; percentile 0.611160000 = 61.116th percentile, score dated 5 October. This is a modelled exploitation probability over the following 30 days, not the probability your server is already compromised.
• Public research: a repository and reported controlled lab results were verified as published material. We did not run its exploit.
🧠 THE MECHANISM, WITHOUT A REPRODUCTION RECIPE
HFS used Koa session signing. The default key was derived from a generator intended for ordinary application randomness. The login handshake disclosed values from that same generator before authentication. The CNA describes how this combination permits recovering the secret and presenting a session the server accepts as administrator.
The administrative configuration interface then provides a documented code feature. server_code is legitimate application functionality: HFS loads JavaScript for server/plugin-style behaviour. After unauthorised administrative access, that capability can become an execution route. It can run inside the HFS process, so a hunt limited to newly spawned command shells can miss relevant activity.
The CVE-specific patch is included in the 3.2.1 release comparison. Its secure fallback is distinct from explicitly configured signing keys; inspect that deployment choice privately.
For impact, preserve the execution boundary. The researcher's test image ran as root inside its lab container. That result does not establish host-root access, a container escape, SYSTEM on Windows or identical privileges in your installation. Record the running process identity, writable mounts and reachable services before assigning downstream impact.
🔎 THE SOC TRAIL — SIX CHECKS TO TAKE INTO A CASE
01 — SCOPE THE SERVING SYSTEM
Action: inventory every serving instance, including replicas and alternate listeners. Obtain running build, binary/image identity, start time and exposure from the owner. A patched download beside an old process is not completed remediation.
Where: owner inventory, proxy configuration and process/container metadata. Banners can mislead. The version field in config.yaml records configuration-writing state, not independent proof of the serving executable.
Signal: affected or unknown HFS builds reachable by untrusted principals. Record direct/proxy routes and restrict unnecessary exposure through approved changes while upgrading. Restrictions reduce opportunity without repairing the code.
Correlation: join asset ID, route, owner, build and evidence window to the process handling traffic. Shared IPs, NAT and reused container names create ambiguity.
Benign/limit: archived packages and installed images may not be running. Internal hosting does not guarantee trusted reachability. Escalate exposed affected services; missing inventory remains a gap.
02 — PRESERVE THE TRAIL BEFORE CHANGING IT
Action: preserve configured access/error logs, rotations, configuration and available history. Record paths, collection time, offsets, hashes, retention and owner. Restrict raw evidence; share a redacted working view.
Where: 3.2.1 source defaults are logs/access.log and logs/access-error.log; configuration documentation describes access.log. Confirm configured paths and working directory rather than assuming either is universal.
config.yaml may sit near the Windows executable or in a user .hfs area, with custom paths, working directories and container storage. Source can create an adjacent .bak; it is not guaranteed complete history. Confirm the actual deployment paths.
Signal: unexplained changes or missing evidence around administration, restart or rotation. Responses at 400 or above go to the error log. Log timestamps are at request completion, which matters for long transfers.
Correlation: align HFS/proxy/EDR/container times in UTC, retaining offsets. Verify client-IP forwarding. Default logging excludes loopback; API logging can be off, user agents optional. Record those coverage gaps.
Benign/limit: do not enable debug logging for this hunt; it can expose parameters. Keep credentials, cookie values and environment dumps private. Missing retained events make the window incomplete.
03 — HUNT REQUEST SEQUENCES, NOT MAGIC STRINGS
Action: pivot on loginSrp1/loginSrp2 and get_config/set_config/set_config_text. Vendor API base: /~/api/, adjusted for confirmed proxy prefixes. Parse the actual log format rather than assuming JSON events.
Where: retained HFS/proxy records. Native logging is common-log-style with optional quoted JSON metadata; space splitting can corrupt fields. Document your parser and omissions. The JSON timeline below is analyst-defined.
Signal: unexplained login-handshake activity followed by administration. Also examine unexplained administration without visible login: coverage can be incomplete, sources change and sessions can be reused.
Correlation: join asset, bounded interval, source, recorded username and available request/session metadata. hfs_http/hfs_https are normal protocol-specific session-cookie names, not hostile indicators. Keep values private.
Benign/limit: sign-ins, scanners, maintenance and NAT can look similar. HTTP 200 does not prove forgery or a malicious change. Missing login events matter only with established coverage and expected flow.
Escalate unexplained administration plus an unauthorised configuration change. Preserve records and check approved work with the owner. Do not replay credentials, forge sessions or make investigative writes.
04 — CORRELATE CONFIGURATION TO EXECUTION
Action: compare approved history to effective configuration. Review server_code privately with the owner; identify who changed it, when and how, and check the ticket. Metadata alone cannot establish malicious code.
Where: configuration/backup copies, file changes, administrative history and HFS telemetry. CLI/environment/runtime changes affect effective settings; a clean-looking file does not establish a clean running state.
Signal: unapproved code plus HFS-originated connections, writes or child processes near administration. Execution can remain inside HFS. Plugins and maintenance can produce benign activity; validate the baseline.
Correlation: join request completion, config changes, reload/start and host/container events to the actual HFS process. Retain evidence for each link; explicitly mark missing links.
Escalate correlated unapproved configuration and execution to IR. Preserve before authorised cleanup; the incident lead decides isolation, collection and credential response. Removing a setting does not resolve earlier impact.
05 — REMEDIATE THE CODE AND THE SESSION TRUST
Action: upgrade every serving installation to a suitable fixed stable build, starting at 3.2.1. Verify the running executable/image. Review COOKIE_SIGN_KEYS privately: explicit overrides bypass the patched fallback.
A strong independent override is a researcher-attributed mitigation for the weak fallback. Prefer the full patch, which also changes the exposed identifier. Presence alone does not prove strong, secret, uncompromised keys.
Plan replacement/invalidation with the owner. Koa/Keygrip can verify against multiple keys: retaining a compromised old verification key can preserve acceptance. Retire suspect material; never paste keys into tickets.
Correlation: record change window, running build, approval and intended session impact. Restarting with a newly generated default can affect sessions; persistent overrides require separate review. Do not promise universal automatic invalidation.
Benign/limit: planned reauthentication is not attack evidence. Repair does not undo earlier accounts, plugins, configuration or file changes. Run the historical investigation alongside repair where evidence warrants it.
06 — VERIFY, THEN HAND OVER THE GAPS
Action: reconcile every serving instance with its fixed build, reviewed effective configuration, key decision and preserved evidence. Use approved ordinary service-health checks; exploit reproduction is not an acceptance requirement.
Where: release/image records, owner verification, process identity and timeline. Confirm replicas and container replacement. Availability alone does not prove the signing-key repair or historical hunt is complete.
Record interval, datasets, parser/filters, time/source attribution and missing telemetry. Empty results mean “no matches in the examined sources and interval.” Retain disabled logging, expired retention and unavailable runtime settings as limitations.
Escalate unresolved integrity/execution evidence to IR. Record repair and historical investigation states separately, with an owner for outstanding questions. The checklist boxes are deliberately empty.
🧰 TOOLS AND BOUNDED CHECKS
These examples inspect authorised metadata or local copies. They do not contact an exploit endpoint. The helper logic passed 26 synthetic offline scenarios, including missing fields, malformed inputs and private-value exclusion; that is not a live HFS or detector test.
A — Docker inventory, for ONE known container
Save this filter as hfs_container_metadata.jq. Use an owner-supplied inspect export or approved access to ONE known container. Docker access is powerful; avoid wider inventory or environment dumps.
```jq
if type != "array" or length != 1 then
error("expected an inspect array containing one known container")
elif (.[0] | type) != "object" then
error("expected a container object")
else
.[0]
| if (.Config | type) != "object" or (.State | type) != "object" then
error("missing container configuration or state")
elif ((.Config.Env // []) | type) != "array" then
error("expected an environment array")
elif ((.Config.Env // []) | all(.[]; type == "string")) | not then
error("expected environment entries to be strings")
else
(.Config.Env // [] | map(select(startswith("COOKIE_SIGN_KEYS=")))) as $keys
| {name: .Name, image_ref: .Config.Image, image_id: .Image,
configured_user: .Config.User, state: .State.Status,
key_override_present: ($keys | length > 0),
key_override_blank: ($keys | any(.[]; . == "COOKIE_SIGN_KEYS="))}
end
end
```
```sh
docker inspect cf-hfs | jq -e -f hfs_container_metadata.jq
```
Replace cf-hfs with the confirmed container name, or pipe the owner's saved JSON to jq. Output excludes keys. Configured user is not measured runtime identity; verify separately. Tags can move; retain the image ID. Keep errors private.
B — Local configuration metadata
Save as hfs_config_metadata.py; requires PyYAML. It reads up to 2 MiB plus one size-check byte, accepts a mapping and emits only metadata. It executes no configuration and prints no accounts, code or parser excerpts.
```python
"""Offline metadata only. Requires PyYAML; does not execute HFS configuration."""
import json
import sys
from pathlib import Path
import yaml
MAX_BYTES = 2 * 1024 * 1024
def inspect(path):
with Path(path).open("rb") as handle:
raw = http://handle.read(MAX_BYTES + 1)
if len(raw) > MAX_BYTES:
raise ValueError("size")
data = http://yaml.safe_load(raw)
if not isinstance(data, dict):
raise ValueError("mapping")
present = "server_code" in data
value = data.get("server_code")
if present and not isinstance(value, str):
raise ValueError("field type")
return {"bytes_read": len(raw), "server_code_present": present,
"server_code_nonempty": bool(value.strip()) if present else None}
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python3 hfs_config_metadata.py APPROVED_COPY.yaml", file=sys.stderr)
sys.exit(2)
try:
print(json.dumps(inspect(sys.argv[1])))
except (OSError, ValueError, UnicodeError, yaml.YAMLError) as exc:
print("Input/schema check failed: " + type(exc).__name__, file=sys.stderr)
sys.exit(3)
```
```sh
python3 hfs_config_metadata.py hfs-config-copy.yaml
```
Use an approved offline copy. Missing fields remain unknown; null/nonstring, malformed and oversize inputs fail. Nonempty code can be legitimate. This check cannot establish effective overrides, history or absence of compromise.
C — Request pivots from a prepared timeline
Prepare hfs-api-requests.json as a Forge-normalised ARRAY for one recorded UTC interval. Fields: time_utc, asset_id, api_name, method, status, source, username, request_id. These are analyst-defined, not HFS-native columns. Preserve raw logs and document transformation; omit cookies, bodies and secrets.
Save this filter as hfs_api_pivots.jq:
```jq
if type != "array" then
error("expected a Forge-normalised request array")
elif all(.[]; type == "object") | not then
error("expected request objects")
else
{rows: length,
rows_without_api_name: ([.[] | select((.api_name | type) != "string")] | length),
pivots: [.[] | select(.api_name == "loginSrp1" or .api_name == "loginSrp2"
or .api_name == "get_config" or .api_name == "set_config"
or .api_name == "set_config_text")
| {time_utc, asset_id, api_name, method, status, source, username, request_id}]}
end
```
```sh
jq -e -f hfs_api_pivots.jq hfs-api-requests.json
```
Output counts rows and missing API names, then selects metadata. Nulls show missing enrichment. Non-API traffic may legitimately lack API names. Empty results provide no clean verdict. Check maintenance before assigning a case label.
Translate the trail into your deployed SIEM/EDR schema and validate representative events. This is not a tested production rule. Pair requests with config/file changes and HFS process/egress evidence; retain coverage limits.
📍 IOC AND EVIDENCE STATUS
No CVE-specific malicious domain, IP or file-hash set was verified in the reviewed material. The API names, session-cookie names and server_code field are behavioural pivots. Public lab marker strings and image digests are not malicious indicators. Do not manufacture an IOC table to fill a section.
The public research repository reports controlled testing on 26 September: administrative access and execution on 3.2.0. Its 3.2.1 negative control stopped at the changed opaque login identifier and explicitly did not attempt session forgery. That supports the stated test boundary, not a comprehensive audit of the fixed release. We inspected the published evidence, not the exploit program's operation.
CISA's July SSVC enrichment recorded exploitation “none”, automatable “yes” and technical impact “total”. That is a historical dated assessment; it must not override the later public research or today's publisher-attributed VulnCheck KEV label. Neither automatable nor a high CVSS score describes a measured campaign.
Confirmed: CNA range, scores and root cause; vendor patch/release; retrieved source logging/configuration behaviour; dated public feed responses. Reported: the researcher's lab results and VulnCheck's own KEV inclusion label. Forge analysis: the proposed correlations, triage order and response acceptance. Unknown: authenticated KEV incident details, real exposure/keys/configuration, retained telemetry and any particular organisation's compromise state.
💜 CYBERFORGE VERDICT
An accepted cookie is only as trustworthy as the key behind it. For an exposed affected HFS service, repair the running code and review the session trust promptly. Then follow the earlier administrative trail into configuration and HFS activity. Keep the boundary honest: a patch is repair evidence; a quiet or incomplete hunt is not a clean-system certificate.
🔗 SOURCES AND FOLLOW-UP
CNA advisory and VulnCheck KEV label:
https://www.vulncheck.com/advisories/rejetto-hfs-session-forgery-via-predictable-signing-key
CVE record:
https://www.cve.org/CVERecord?id=CVE-2026-61500
Vendor first fixed release:
https://github.com/rejetto/hfs/releases/tag/v3.2.1
CVE-specific patch:
https://github.com/rejetto/hfs/commit/59472e534bf7e056d708382d02935c2eaf956927
NVD:
https://nvd.nist.gov/vuln/detail/CVE-2026-61500
CISA catalogue:
https://www.cisa.gov/known-exploited-vulnerabilities-catalog
FIRST EPSS:
https://api.first.org/data/v1/epss?cve=CVE-2026-61500
Vendor configuration:
https://github.com/rejetto/hfs/blob/v3.2.1/config.md
Vendor logger:
https://github.com/rejetto/hfs/blob/v3.2.1/src/log.ts
Key verification behaviour:
https://github.com/crypto-utils/keygrip
Researcher report, static review only:
https://github.com/aramosf/CVE-2026-61500
#CyberForge #CVE #BlueTeam #SOC #DFIR #HFS