cPanel multidominio e account reseller: sembrano simili, ma la separazione dei privilegi è un’altra cosa

Addon domain nello stesso account, account separati sotto un reseller, sottoscrizioni Plesk e CageFS: dove passa davvero il confine tra un sito e l’altro.

A sinistra un unico blocco con tre domini e un solo utente, con una crepa rossa che li attraversa tutti; a destra tre blocchi separati, ciascuno con il proprio utente, collegati in alto a una chiave con la scritta WHM che li apre tutti

«I siti sono separati, ognuno ha il suo dominio e la sua cartella». Lo sentiamo dire spesso quando chiediamo come è organizzato un hosting con più siti WordPress, e quasi sempre la frase descrive ciò che si vede nel pannello, non ciò che vede il sistema operativo. Dieci domini aggiunti allo stesso account cPanel hanno dieci cartelle diverse, ma un solo proprietario. Dieci account creati da un reseller hanno invece dieci proprietari distinti, ma una sola persona che può entrare in tutti. Sono due situazioni che nel pannello si assomigliano e che, durante un’infezione, si comportano in modo opposto.

Il confine che conta non è la cartella del dominio, ma l’utente Unix con cui gira PHP. Tutto ciò che quell’utente può scrivere, una webshell lo può scrivere.

Nell’articolo sulla contaminazione incrociata negli hosting condivisi abbiamo visto come un’infezione salta da un sito all’altro quando condividono l’utente di sistema. Qui facciamo un passo in più: confrontiamo i modelli di cPanel e WHM, l’analogo in Plesk e l’isolamento di CloudLinux, vediamo come capire in quale situazione ci si trova e come si pianifica la migrazione dai domini aggiuntivi ad account separati senza portarsi dietro il malware.

Domini aggiuntivi: un utente, molti siti

In cPanel ogni account corrisponde a un utente Linux con la propria home, di norma /home/nomeutente. Dall’interfaccia Domains il titolare può creare altri domini, gli addon domain, e sottodomini: ciascuno riceve la propria document root, spesso una sottocartella della home o di public_html, ma tutti restano dentro lo stesso account. Il pannello li mostra come siti distinti; per il kernel sono file dello stesso proprietario.

Da questo derivano conseguenze che vanno ben oltre i file. L’utente ha un solo crontab, quindi un’attività pianificata inserita da un sito compromesso gira con i permessi necessari per riscrivere tutti gli altri, come descriviamo nell’articolo sulle backdoor nascoste nei cron job. I database hanno tutti lo stesso prefisso, nomeutente_, e spesso lo stesso utente MySQL, creato una volta e riutilizzato per comodità. Le caselle di posta stanno in /home/nomeutente/mail, leggibili dallo stesso utente. Le chiavi SSH autorizzate, i file .bashrc e .profile, le cartelle temporanee e le sessioni PHP, se non configurate diversamente, sono comuni a tutti i domini dell’account.

Il pool PHP-FPM può anche essere definito per dominio, ma gira comunque con l’utente dell’account: separa le risorse e le impostazioni di PHP, non i permessi. Lo stesso vale per open_basedir, che limita le funzioni di file di PHP ma non i comandi esterni lanciati con exec() o system(). In pratica, un account cPanel con quindici addon domain è un unico sito dal punto di vista della sicurezza, con quindici porte d’ingresso: basta un plugin vulnerabile in uno qualsiasi di essi per esporre tutti gli altri.

Il reseller: account separati, ma una chiave comune

Un reseller, come lo definisce la guida di cPanel agli account reseller, è il titolare di un account che vende a sua volta account cPanel ad altri. Ogni sito creato da WHM come account a sé riceve il proprio utente Linux, la propria home, il proprio crontab, i propri database con un prefisso diverso e le proprie caselle di posta. Qui la separazione dei privilegi è reale: una webshell nel sito del cliente A gira come utente A e non può scrivere nei file del cliente B, a meno di permessi sbagliati o di una vulnerabilità del sistema.

Il punto debole si sposta più in alto. Dall’interfaccia List Accounts di WHM, il reseller può aprire il cPanel di ciascuno dei suoi account con un clic, usando la propria password, grazie a una sessione temporanea creata dal sistema di single sign-on. È una funzione comoda per chi gestisce i siti dei clienti, ed è anche il motivo per cui una credenziale WHM rubata vale quanto tutte le credenziali dei singoli account messe insieme. Da lì si caricano file, si creano cron e si reimpostano password in ogni account posseduto.

La stessa guida di cPanel è esplicita sui privilegi da non concedere: sconsiglia di attivare per i reseller l’opzione All Features della categoria Root Access, che scavalca i limiti e permette di vedere tutti gli account del server, e le cosiddette Super Privileges. Un reseller con quei privilegi non è più un confine tra clienti, è un amministratore del server con un nome diverso. Per un’agenzia il reseller è il modello giusto solo se l’accesso a WHM è trattato come amministrativo: password unica, secondo fattore, nessuna condivisione tra colleghi. Del secondo fattore parliamo nell’articolo sull’autenticazione a due fattori; le credenziali salvate nei client e rubate dagli infostealer, che valgono anche per WHM, sono il tema dell’articolo sulle credenziali FTP rubate.

Tre modelli affiancati. A sinistra, un solo account cPanel con utente cliente e uid 1001 che contiene tre domini: tutti condividono home, crontab, prefisso dei database e posta, e una webshell in un dominio scrive negli altri due. Al centro, un reseller in WHM con tre account separati, ciascuno con il proprio utente e uid: la webshell resta confinata nel suo account, ma sopra i tre account c’è il login del reseller che può aprire il cPanel di tutti. A destra, gli stessi account separati racchiusi in gabbie CageFS, con LVE indicato come limite di risorse.
Tre modelli che nel pannello si assomigliano: con gli addon domain il perimetro è l’account, con il reseller è il singolo account ma il login WHM li apre tutti, con CageFS ogni account è anche invisibile agli altri.

Plesk: sottoscrizioni e domini aggiuntivi

Plesk usa parole diverse per la stessa distinzione. Nella documentazione per i clienti si legge che per ogni sottoscrizione di hosting Plesk crea un utente di sistema, e che i domini aggiunti alla stessa sottoscrizione ne condividono le risorse. Una sottoscrizione con cinque domini è quindi l’equivalente di un account cPanel con cinque addon domain: un utente, un perimetro. Per separare davvero due siti bisogna metterli in due sottoscrizioni, anche se appartengono allo stesso cliente, e la documentazione cita proprio la volontà di non condividere le risorse tra siti come motivo per sottoscrivere un piano aggiuntivo.

Anche in Plesk il livello superiore è una chiave comune. La guida dell’amministratore descrive per esempio il pulsante Log In as Reseller, con cui l’amministratore entra nel pannello di un reseller e ne modifica piani, clienti e sottoscrizioni, e il reseller a sua volta gestisce le sottoscrizioni dei propri clienti senza conoscerne le password. Il ragionamento è lo stesso di WHM: la separazione tra sottoscrizioni protegge un sito dall’altro, non protegge nessuno da chi ha l’accesso amministrativo al pannello.

CloudLinux: CageFS e LVE, cosa aggiungono

Molti hosting condivisi basati su cPanel usano CloudLinux, che aggiunge due componenti spesso confusi tra loro. Il primo è CageFS, un file system virtualizzato che, secondo la documentazione di CloudLinux, chiude ogni utente in una propria gabbia: l’utente non vede gli altri utenti né i loro nomi, non accede ai file di configurazione del server come quelli di Apache, ha una vista ristretta di /proc e non vede i processi altrui, dispone solo di binari considerati sicuri e di una propria cartella /tmp. Contro i tentativi di un sito compromesso di esplorare il server o di leggere i file degli altri account, è una difesa concreta.

Il secondo è LVE, e qui l’equivoco è frequente. La documentazione sui limiti lo descrive come una tecnologia del kernel basata sui cgroup il cui obiettivo è evitare che un singolo sito metta in ginocchio il server: limita CPU, memoria fisica, I/O, operazioni al secondo, processi di ingresso e numero di processi. È un limite di risorse, non un confine di sicurezza. Serve, per esempio, a impedire che un cryptominer in un account rallenti tutti gli altri, ma non impedisce a una webshell di scrivere nei file del proprio utente.

Soprattutto, né CageFS né LVE separano i domini dentro lo stesso account. La gabbia è per utente: dieci addon domain dello stesso utente stanno nella stessa gabbia, con lo stesso crontab e gli stessi file. CloudLinux rafforza il confine tra account, non ne crea uno nuovo dove prima non c’era.

Tabella con nove righe di risorse e tre colonne. Le righe sono utente Unix e file, crontab, database e utente MySQL, posta, chiavi SSH e file di shell, pool PHP-FPM, tmp e sessioni, visibilità degli altri utenti e dei processi, accesso dal livello superiore. Colonna addon domain nello stesso account: tutto condiviso, in rosso, tranne il pool PHP che è separabile ma con lo stesso utente. Colonna account separati sotto un reseller: tutto separato, in verde, tranne tmp e visibilità che dipendono dalla configurazione del server e l’accesso dal livello superiore, in rosso, perché il reseller entra in tutti gli account. Colonna account separati con CageFS: tutto separato, compresi tmp e visibilità, con l’accesso del reseller sempre in rosso.
Cosa condividono i siti nei tre modelli. L’ultima riga resta rossa ovunque: chi controlla il livello superiore, root o reseller, entra in tutti gli account.

Come capire in quale situazione ci si trova

Prima di pianificare una bonifica o una migrazione serve una mappa verificata, non ricordata. Con un accesso SSH all’account, tre comandi dicono quasi tutto: con quale utente si lavora, quali domini gli appartengono secondo cPanel e quali installazioni WordPress ci sono davvero sul disco.

# Utente e gruppi con cui si lavora (lo stesso con cui gira PHP)
id
# Domini dell'account secondo cPanel: principale, addon, sottodomini, alias
uapi --output=jsonpretty DomainInfo list_domains
# Installazioni WordPress effettivamente presenti nella home
find ~ -name wp-config.php -not -path '*/node_modules/*' 2>/dev/null
# Attività pianificate dell'utente: valgono per tutti i domini dell'account
crontab -l

Chi amministra il server vede il quadro completo. cPanel tiene in /etc/userdomains l’associazione tra ogni dominio e l’utente proprietario, e in /etc/trueuserowners l’associazione tra ogni account e chi lo possiede, cioè root o un reseller. Contando i domini per utente si trovano subito gli account che raccolgono molti siti; filtrando per proprietario si vede il perimetro di ogni reseller, cioè quanti siti sono esposti se quella credenziale viene rubata.

# Come root: quanti domini per ciascun utente (i più affollati in cima)
awk -F': ' '{print $2}' /etc/userdomains | sort | uniq -c | sort -rn | head
# Tutti i domini di un utente
awk -F': ' '$2=="cliente" {print $1}' /etc/userdomains
# Account posseduti da un reseller: il suo perimetro in caso di furto del login
awk -F': ' '$2=="agenzia" {print $1}' /etc/trueuserowners
# Lo stesso tramite l'API di WHM
whmapi1 listaccts want=user,domain,owner
# Su CloudLinux: utenti con CageFS attivo
cagefsctl --list-enabled

Due verifiche completano la mappa. La prima riguarda i database: se più siti dello stesso account usano lo stesso utente MySQL, la password letta da un wp-config.php apre tutti i database, e una compromissione può passare dal database anche quando i file sono separati, per esempio creando amministratori fantasma. La seconda riguarda i permessi delle home: su un server senza CageFS, una home con permessi 755 permette a qualunque utente di elencarne il contenuto, e un file di configurazione leggibile da tutti annulla qualsiasi separazione tra account.

# Come root: quali utenti MySQL hanno accesso ai database dell'account
mysql -e "SELECT User, Host, Db FROM mysql.db WHERE Db LIKE 'cliente\\_%' ORDER BY User"
# Home leggibili da tutti e wp-config.php con lettura per "altri"
stat -c '%a %U %n' /home/*/ | awk '$1 !~ /^7[15]0$|^711$/'
find /home/*/ -name wp-config.php -perm -o=r 2>/dev/null

Dagli addon domain ad account separati

Separare i siti è la correzione strutturale, e cPanel offre uno strumento dedicato: Convert Addon Domain to Account, nella sezione Transfers di WHM. Secondo la documentazione sposta nel nuovo account i contenuti della document root, i file di inclusione del virtual host, il certificato SSL, caselle di posta, inoltri e risposte automatiche, i database, con la scelta tra copia e spostamento, gli utenti del database, gli account FTP e Web Disk e i record DNS personalizzati. Richiede il privilegio rearrange-accts, spazio libero pari ad alcune volte quello del dominio e l’eliminazione preventiva dei sottodomini dell’addon domain.

Due dettagli della documentazione hanno conseguenze dirette sulla sicurezza. Il nuovo account applica ai database il proprio prefisso, quindi nomi e utenti cambiano e il wp-config.php va aggiornato. E i dati originali restano nell’account di partenza finché non vengono cancellati a mano: una copia completa del sito, con le sue eventuali backdoor, continua a vivere accanto agli altri domini.

L’errore più comune è convertire prima di pulire. Il convertitore copia file e database così come sono, quindi un sito infetto diventa un account separato ma infetto, e una backdoor nascosta nella home comune, fuori dalla document root, resta dov’era a disposizione degli altri siti. Per questo l’ordine che seguiamo è sempre lo stesso:

  1. Mappa e congelamento. Inventario di domini, installazioni, database e utenti MySQL; sospensione del crontab dell’utente e dei processi in esecuzione, come spieghiamo nell’articolo sui processi PHP che restano in memoria.
  2. Pulizia di tutto l’account. Tutti i siti nella stessa finestra di intervento, insieme alla home: .ssh, file di shell, .htaccess e .user.ini nelle cartelle superiori.
  3. Conversione. Un account per sito, con utenti MySQL distinti, verificando che ogni sito funzioni nel nuovo account prima di proseguire.
  4. Rimozione delle copie. Cancellazione dei dati originali rimasti nell’account di partenza e delle installazioni che non servono più.
  5. Credenziali. Nuove password per database, amministratori WordPress, FTP, cPanel e WHM, nuove chiavi e salt in ogni wp-config.php.
  6. Accesso al livello superiore. Secondo fattore sul reseller o sull’amministratore del pannello, nessun privilegio Root Access o Super non necessario.
Due percorsi a confronto. In alto, in rosso, il percorso sbagliato: un account con tre addon domain di cui uno infetto viene convertito subito in tre account; l’infezione viene copiata nel nuovo account e una copia dei dati originali resta nell’account di partenza con la backdoor nella home. In basso, in verde, il percorso corretto in sei passaggi: mappa e congelamento, pulizia di tutto l’account, conversione in account separati con utenti MySQL distinti, rimozione delle copie originali, cambio delle credenziali, secondo fattore sul login WHM del reseller.
Convertire un addon domain in account separato copia tutto, infezione compresa, e lascia i dati originali dove erano: prima si pulisce, poi si separa.

Cosa cambia per la bonifica

Il modello di hosting decide il perimetro dell’intervento prima ancora di aprire un file. Con gli addon domain il perimetro è l’intero account: tutti i siti vanno considerati compromessi finché non si dimostra il contrario, e vanno puliti insieme, perché qualunque sito lasciato indietro può reinfettare gli altri nel giro di minuti. Con account separati il perimetro si restringe al singolo account, a condizione di verificare che il confine abbia retto: nessun file di proprietà di un altro utente, nessun permesso 777, nessuna home leggibile da tutti, nessun utente MySQL condiviso tra account.

Quando il punto d’ingresso è il login del reseller, invece, il perimetro torna a essere tutto ciò che il reseller possiede, e la ricerca cambia natura. Non si cerca più il plugin vulnerabile, ma le azioni fatte con credenziali valide: file caricati dal File Manager, attività cron create dall’interfaccia, password reimpostate. I log di accesso di cPanel e WHM, in /usr/local/cpanel/logs/access_log, e quelli del File Manager diventano la fonte principale; le tecniche di ricostruzione sono quelle descritte nell’articolo sul log di audit. Un ripristino da backup, in questo scenario, serve a poco se il login resta nelle mani dell’attaccante, come spieghiamo parlando di malware che sopravvive al ripristino.

Quando conviene quale modello

Gli addon domain hanno senso per siti dello stesso soggetto, curati allo stesso modo, che accetterebbero di cadere insieme: il sito principale e il suo blog, per esempio. Non hanno senso per i siti di clienti diversi, per un e-commerce accanto a vecchi siti vetrina non aggiornati, o per installazioni di prova che nessuno segue. Il reseller, o un account per sito creato direttamente dall’amministratore, è la scelta corretta per un’agenzia, purché il suo login sia trattato come la chiave di tutti i siti che è. Su server condivisi, CageFS aggiunge un livello utile tra gli account; su un server dedicato o un VPS, un utente e un pool PHP-FPM per sito ottengono lo stesso principio anche senza pannello, come descritto nella checklist di hardening dopo la bonifica.

Se stai gestendo un’infezione su un account con molti domini, o su più account di un reseller, il primo lavoro è capire fin dove arriva il perimetro. Quando interveniamo mappiamo utenti, domini, database e accessi del pannello, oltre a cron e processi in memoria, e puliamo ogni installazione WordPress dell’account nella stessa finestra, con una pulizia garantita in 6, 12 o 24 ore per installazione. Se vuoi un parere sulla tua situazione, scrivici.

IL PROSSIMO PASSO

Il tuo sito
è infetto?

Ogni ora conta: il malware continua a colpire visitatori e clienti, e Google, l’hosting e le blacklist non aspettano. Scegli il piano, paga online e condividi gli accessi: la bonifica parte subito, a prezzo fisso e con tempi garantiti.

Richiedi la bonifica

Ti porta ai piani: bonifica entro 6, 12 o 24 ore dalla ricezione degli accessi.

MANAGED SERVER S.R.L.info@rimozionemalware.com +39 02 5656 9681

Lunedì – venerdì · 09:30 – 19:30

Preferisci un modulo online?
Contattaci su managedserver.it ↗