QSB-118: Willekeurige code-uitvoering in Dom0 via foutrapportage van qvm-copy-to-vm

We hebben Qubes Security Bulletin (QSB) 118 gepubliceerd: Dom0 arbitrary code execution in qvm-copy-to-vm error reporting. De tekst van dit QSB is hieronder gereproduceerd.

---

Qubes Security Bulletin 118

Datum: 28 augustus 2026 Onderwerp: Willekeurige code-uitvoering in Dom0 via foutrapportage van qvm-copy-to-vm

Gebruikersactie

Ga door met het normale updateproces om de beveiligingsupdates te ontvangen die worden beschreven in de sectie "Patchen" hieronder. Er is geen andere actie van de gebruiker vereist naar aanleiding van dit QSB.

Samenvatting

Wanneer qvm-copy-to-vm wordt gebruikt om een bestand van dom0 naar een kwaadaardige qube te kopiëren, kan die qube een willekeurig commando in dom0 injecteren.

Impact

Als een aanvaller een qube heeft gecompromitteerd en de gebruiker een qvm-copy-to-vm-aanroep start vanuit dom0 naar deze gecompromitteerde qube, kan de aanvaller deze kwetsbaarheid exploiteren om een willekeurig commando in dom0 te injecteren. Dit stelt de aanvaller in staat om de volledige controle over Qubes OS over te nemen.

Technische details

De tool qvm-copy-to-vm maakt het mogelijk om bestanden van dom0 naar een gespecificeerde qube te kopiëren. Hiervoor wordt het "qfile"-protocol gebruikt, een vereenvoudigd archiefformaat dat eenvoudige bestandsmetadata bevat (veel eenvoudiger dan tar of cpio). Het protocol bevat aan het einde een bevestiging van de overdracht, die door het doelwit wordt teruggestuurd naar de bron. Deze bevestiging bevat een checksum van alle overgedragen bestanden, een foutcode (indien van toepassing) en de naam van het laatst ontvangen bestand.

In het geval van een fout, zoals gerapporteerd door het veld met de foutcode, toont dom0 een GUI-bericht met de foutinformatie en de naam van het betreffende bestand, zoals gerapporteerd door de doel-qube. De kwetsbaarheid bevindt zich in de verwerking van die bestandsnaam:

  1. De functie waitforresult() roept sanitizeremotefilename() aan op de ontvangen naam voordat deze aan de error handler wordt doorgegeven:

linux-utils/qrexec-lib/pack.c:

55 static void sanitize_remote_filename(char *untrusted_filename)
56 {
57     for (; *untrusted_filename; ++untrusted_filename) {
58         if (*untrusted_filename < ' ' ||
59             *untrusted_filename > '~' ||
60             *untrusted_filename == '"')
61             *untrusted_filename = '_';
62     }
63 }
64
65 void wait_for_result(void)
66 {
...
98     /* sanitize the remote filename */
99     sanitize_remote_filename(last_filename);
100
101     errno = hdr.error_code;
102     if (hdr.error_code != 0) {
103         switch (hdr.error_code) {
104             case EEXIST:
105                 call_error_handler("A file named \"%s\" already exists in QubesIncoming dir", last_filename);
106                 break;
...
  1. Vervolgens roept callerrorhandler() de dom0-variant van de foutrapportagefunctie aan — guifatal() -> displayerror(), die system() gebruikt om de eigenlijke foutdialoog te starten:

core-admin-linux/file-copy-vm/qfile-dom0-agent.c:

15 void display_error(const char *fmt, va_list args) {
16     char *dialog_cmd;
17     char buf[1024];
18     struct stat st_buf;
19     int ret;
20
21     (void) vsnprintf(buf, sizeof(buf), fmt, args);
22     ret = stat("/usr/bin/kdialog", &st_buf);
23 #define KDIALOG_CMD "kdialog --title 'File copy/move error' --sorry "
24 #define ZENITY_CMD "zenity --title 'File copy/move error' --warning --text "
25     if (asprintf(&dialog_cmd, "%s '%s: %s (error type: %s)'",
26                 ret==0 ? KDIALOG_CMD : ZENITY_CMD,
27                 program_invocation_short_name, buf, strerror(errno)) < 0) {
28         fprintf(stderr, "Failed to allocate memory for error message :(\n");
29         return;
30     }
31 #undef KDIALOG_CMD
32 #undef ZENITY_CMD
33     fprintf(stderr, "%s\n", buf);
34     system(dialog_cmd);
35 }
36
37 _Noreturn void gui_fatal(const char *fmt, ...) {
38     va_list args;
39     va_start(args, fmt);
40     display_error(fmt, args);
41     va_end(args);
42     exit(1);
43 }

Het probleem is dat sanitizeremotefilename() alleen non-ASCII-tekens (en dubbele aanhalingstekens) verwijdert, maar shell-metakarakters laat staan. Vervolgens voert system() het geconstrueerde commando uit, inclusief de door de aanvaller gecontroleerde naam via de shell.

Let op dat de VM-variant van qvm-copy-to-vm niet is getroffen, aangezien de versie van de foutrapportagefunctie daar geen gebruik maakt van system():

core-agent-linux/qubes-rpc/gui-fatal.c:

16 static void produce_message(const char *type, const char *fmt, va_list args)
17 {
...
31     if (progress_type && !strcmp(progress_type, "gui"))
32     {
33         switch (fork())
34         {
35         case -1:
36             exit(1); // what else
37         case 0:
38             if (geteuid() == 0) {
39                 if (setuid(getuid()) != 0) {
40                     perror("setuid failed, not calling zenity/kdialog");
41                     exit(1);
42                 }
43             }
44             fix_display();
45             execlp("/usr/bin/zenity", "zenity", "--error", "--text", dialog_msg, NULL);
46             execlp("/usr/bin/kdialog", "kdialog", "--sorry", dialog_msg, NULL);
47             exit(1);
48         default:;
49         }
50     }
51     free(dialog_msg);
52 }
53
54 void gui_fatal(const char *fmt, ...)
55 {
56     va_list args;
57     va_start(args, fmt);
58     produce_message("Fatal error", fmt, args);
59     va_end(args);
60     exit(1);
61 }

Getroffen systemen

Alle Qubes OS-releases zijn getroffen.

Patchen

Het volgende pakket bevat de beveiligingsupdate die de kwetsbaarheid in dit bulletin aanpakt:

Voor Qubes 4.3, in dom0:

  • qubes-core-dom0-linux, versie 4.3.22

Dit pakket zal na een korte testperiode door de community migreren van de security-testing repository naar de huidige (stabiele) repository. Zodra het beschikbaar is, moet het pakket worden geïnstalleerd via de Qubes Update tool of de equivalente opdrachtregelcommando's.

Credits

De kwetsbaarheid is ontdekt door Tim C.

Referenties

  • [1] https://doc.qubes-os.org/en/latest/user/how-to-guides/how-to-update.html
  • [2] https://doc.qubes-os.org/en/latest/user/downloading-installing-upgrading/testing.html