Systemd: Aus den Wirren des Paketmanagements

„Aus den Wirren der Paketabhängigkeiten im Dschungel von Systemd“ man könnte einen Roman damit betiteln 🙂  Gestern abend, es war mal wieder Serverupdatezeit, flutschte eine Anzeige eines Fedora-Paketes, daß keinen Sinn machte, über den Bildschirm: qrencode-libs

QR Codes auf einem Server?

Ja, wenn man eine Webseite hat, die z.b. QR Codes ausgibt, weil eine HandyApp einen Bestätigungscode haben will, warum nicht. Dummerweise hatte dieser Server genau einen Job und der hatte nichts mit QR Codes zu tun. „Naja,ok, das wird jemand mal irgendwann für was ausprobiert haben… kann weg!“ denkste Dir so.. und dann kommt das Erwachen: „Wieso will dnf jetzt systemd löschen?“

$ sudo dnf erase qrencode-libs
[sudo] Passwort für  ….. :
Fehler:
Problem: The operation would result in removing the following protected packages: systemd

Das kommt so …

Der Systemd hat eine harte Abhängigkeit auf die lib von dem qrencoder :

$ rpm -q -R systemd | grep qrenc
libqrencode.so.3()(64bit)

ganz genau genommen ist es journalctl:

$ ldd /usr/bin/journalctl |grep qrenc
libqrencode.so.3 => /lib64/libqrencode.so.3 (0x00007fef36540000)

„Kann mir bitte einer erklären, wieso journalctl QR CODES bauen können müßte ?????“

Kann ja wohl nur ein Fehler sein 😉   Der Maintainer bei Redhat war da jetzt anderer Meinung:

What do you mean "wrongfully"? It's "rightfullly" linking against qrencode-libs because that functionality is used by journalctl.
While somewhat unfortunate, it's correct.

Steht aber allein da, denn auch bei Manjaro Linux ist das schon mal jemandem vor mir aufgefallen und siehe:

https://forum.manjaro.org/t/systemd-238-51-1-has-picked-up-a-dependency-on-qrencode/43070

Could this be due to a dirty chroot?

$ ldd `which journalctl`
	linux-vdso.so.1 (0x00007fff47fc9000)
	libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f55fd82e000)
	libc.so.6 => /usr/lib/libc.so.6 (0x00007f55fd477000)
	libsystemd-shared-238.so => /usr/lib/systemd/libsystemd-shared-238.so (0x00007f55fd027000)
	libqrencode.so.4 => not found

I’m pretty certain journalctl doesn’t need qrencode?

Das sehe ich auch so, trotzdem habe ich mal etwas geforscht und die Ursache gefunden:

journalctl .c

#if HAVE_QRENCODE
/* If this is not an UTF-8 system don’t print any QR codes */
if (is_locale_utf8()) {
fputs(„\nTo transfer the verification key to your phone please scan the QR code below:\n\n“, stderr);
print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
}
#endif

Jetzt wirds spannend:

Wozu wird das benutzt?

Um, wenn es ein UTF8-System ist UND der Code mit dem QR Support kompiliert wurde, einen Verifikations Schlüssel als QR CODE fürs Handy auszugeben, um mit dem Versiegelungs-Schlüssel abgesicherte Journaleinträge zu prüfen.

Das Verfahren heißt bei Systemd Forward Secure Sealing (FSS).  Keine Ahnung wer das Feature von Journald nutzt. Es klingt jedenfalls nach einer brauchbaren Idee, falls ein Hacker die Einträge manipuliert. Ich bezweifle aber stark, daß der Key dabei per QR Code an ein Handy übermittelt werden muß, statt per SCP an einen anderen Server.

Für diese eine Zeile Code da oben, die kaum jemand jemals einsetzen wird (Bitte Zahlen liefern, wer welche hat), immer noch diese Lib mit sich rumschleppen… was solls, GB sind billig  😉

Warnung: Libreswan kann Ihren Bootprozess stören – F29

Argss! Ja Argss! Da upgraded man 7800 Schritte lang seinen Desktop-PC auf ein Fedora 29, das auf den Servern ohne Probleme eingespielt werden konnte, auf dem Tablet und Laptop läuft, wo es exakt so per DNF eingespielt wurde, nur um dann festzustellen, daß das System nicht mehr bootet! Warum? Weil das Libreswan Paket wohl „defekt“ ist. ARGS!

Da tust Du alles um sicher zu sein und dann das!

Von dem Gedanken, das mein Desktop schnell mal eben auf ein neues Fedora hochgezogen werden kann, habe ich mich ja schon vor Jahren verabschiedet. Seit 0AD da drauf ist, dauert allein das  Herunterladen der Paket 25 Minuten und mehr, und 7800 Updateschritte brauchen auch mit SSD Support so um die 2 Stunden. Also schnappt man sich das Tablet, während der Desktop sein Upgrade fährt und macht was sinnvolles.. Kernel Updates einspielen z.B. 😉

Irgendwann war auch der Desktop durch und das obligatorische „reboot“ war fällig. Getan, gewartet, Festplattenpasswort eingetippt und …. tod.

Weil sich das schwer beschreiben läßt, hier der Bootlogauszug dazu:

Jun 14 19:13:06 meinpc systemd[1]: Started Restorecon maintaining path file context.
Jun 14 19:13:06 meinpc systemd[1]: Started LSB: Init script for live image..
Jun 14 19:13:06 meinpc systemd[1]: avahi-daemon.service: Start operation timed out. Terminating.
Jun 14 19:13:06 meinpc systemd[1]: systemd-logind.service: Start operation timed out. Terminating.
Jun 14 19:13:06 meinpc systemd[1]: ModemManager.service: Start operation timed out. Terminating.
Jun 14 19:13:06 meinpc ModemManager[1625]: <info> Caught signal, shutting down...
Jun 14 19:13:06 meinpc ModemManager[1625]: <info> ModemManager is shut down
Jun 14 19:13:06 meinpc systemd[1]: rtkit-daemon.service: Start operation timed out. Terminating.
Jun 14 19:13:06 meinpc systemd[1]: accounts-daemon.service: Start operation timed out. Terminating.
Jun 14 19:13:06 meinpc systemd[1]: systemd-machined.service: Start operation timed out. Terminating.
Jun 14 19:13:06 meinpc systemd[1]: NetworkManager.service: Start operation timed out. Terminating.
Jun 14 19:13:06 meinpc systemd[1]: rtkit-daemon.service: Failed with result 'timeout'.
Jun 14 19:13:06 meinpc systemd[1]: Failed to start RealtimeKit Scheduling Policy Service.
Jun 14 19:13:06 meinpc systemd[1]: accounts-daemon.service: Failed with result 'timeout'.
Jun 14 19:13:06 meinpc systemd[1]: Failed to start Accounts Service.
Jun 14 19:13:06 meinpc systemd[1]: ModemManager.service: Failed with result 'timeout'.
Jun 14 19:13:06 meinpc systemd[1]: Failed to start Modem Manager.
Jun 14 19:13:06 meinpc systemd[1]: Started NTP client/server.
Jun 14 19:13:06 meinpc systemd[1]: Started Hardware Monitoring Sensors.
Jun 14 19:13:06 meinpc systemd[1]: Starting SYSV: Late init script for live image....
Jun 14 19:13:06 meinpc systemd[1]: Starting ABRT Automated Bug Reporting Tool...
Jun 14 19:14:37 meinpc systemd[1]: Failed to get initial list of names: Connection timed out
Jun 14 19:14:37 meinpc systemd[1]: systemd-logind.service: Failed with result 'timeout'.
Jun 14 19:14:37 meinpc systemd[1]: Failed to start Login Service.
Jun 14 19:14:37 meinpc systemd[1]: systemd-machined.service: Failed with result 'timeout'.
Jun 14 19:14:37 meinpc systemd-coredump[1749]: Due to PID 1 having crashed coredump collection will now be turned off.
Jun 14 19:14:37 meinpc systemd[1]: Caught <ABRT>, dumped core as pid 1748.
Jun 14 19:14:37 meinpc systemd[1]: Freezing execution.
Jun 14 19:14:37 meinpc kernel: printk: systemd: 61 output lines suppressed due to ratelimiting
Jun 14 19:14:37 meinpc systemd-coredump[1749]: Process 1748 (systemd) of user 0 dumped core.

Stack trace of thread 1748:
#0 0x00007fa4b3f9087b kill (libc.so.6)
#1 0x00005583475eeeda n/a (systemd)
#2 0x00007fa4b4133070 __restore_rt (libpthread.so.0)
#3 0x00007fa4b3f9057f raise (libc.so.6)
#4 0x00007fa4b3f7a895 abort (libc.so.6)
#5 0x00007fa4b3fd39c7 __libc_message (libc.so.6)
#6 0x00007fa4b3fda2cc malloc_printerr (libc.so.6)
#7 0x00007fa4b3fdbafc _int_free (libc.so.6)
#8 0x00007fa4b4066ac7 __vasprintf_chk (libc.so.6)
#9 0x00007fa4b43d0630 log_format_iovec (libsystemd-shared-239.so)
#10 0x00007fa4b43d0b09 log_struct_internal (libsystemd-shared-239.so)
#11 0x0000558347610a0f n/a (systemd)
#12 0x00005583476132cb n/a (systemd)
#13 0x000055834766368e n/a (systemd)
#14 0x000055834763fb3b n/a (systemd)
#15 0x00005583476436aa n/a (systemd)
#16 0x0000558347626eed n/a (systemd)
#17 0x00007fa4b4455f02 n/a (libsystemd-shared-239.so)
#18 0x00007fa4b4457da5 sd_event_dispatch (libsystemd-shared-239.so)
#19 0x00007fa4b4457f30 sd_event_run (libsystemd-shared-239.so)
#20 0x00005583476300f6 n/a (systemd)
#21 0x00005583475ea78b n/a (systemd)
#22 0x00007fa4b3f7c413 __libc_start_main (libc.so.6)
#23 0x00005583475ec41e n/a (systemd)

So, jetzt sitzt der User da und hat kein System mit dem er was machen könnte, weiß nicht, was da nicht ging und hat natürlich auch kein Backup gemacht, von dem der User jetzt eh nicht wüßte, wie er es in dem Zustand zurückspielen sollte 🙂

Was also machen ?

  1.  Resetknopf drücken, wenn alle Festplattenindikatoren aufgehört haben zu blinken.
  2.  Kernelbootmenü abwarten
  3.  „e“ drücken, und die Zeile „linux ……“ um “ 1 init=/bin/bash“ am Ende erweitern, ggf. noch „splash quite rghb“ entfernen,  damit man bei nächsten boot was sieht.
  4.  STRG+x drücken
  5.  Jede Menge Kernel Meldungen laufen über den Bildschirm, wenn die aufhören, RETURN drücken.
  6.  /etc/init.d/network start
  7.  mount / -o remount,rw
  8.  dnf update

Jetzt wird uns dnf erzählen, daß crypto-policies wegen libreswan-libs nicht installiert werden kann. Das löst man so auf:

dnf erase libreswan*

es fliegen runter :

NetworkManager-libreswan-gnome-1.2.10-1.fc29.x86_64
NetworkManager-libreswan-1.2.10-1.fc29.x86_64
libreswan-3.27-1.fc29.x86_64

und jetzt kann man mit dnf update auch das letzte Paket für einen aktuelles Fedora installieren und oh Wunder, der Rechner booted wieder. Bugreport filed!

Hinweis: Dieses Problem wird natürlich nur ausgelöst, wenn man libreswan auch mal irgendwann installiert hatte 😉

Bitte lesen Sie auch das Update dazu : Update: Fedora 29 bootet nicht nach Upgrade

Exim < 4.92 mit CVE-2019-10149

Jetzt muß ich es Euch doch erzählen, wo ich doch dachte, es dauert noch länger bis die Katze aus dem Sack ist. Ok, Exim < 4.92 hat eine schwerwiegende Sicherheitslücke, die man auch noch trivial ausnutzen kann: CVE-2019-10149

Um die Schwachstelle wurde viel Wirbel gemacht, dummerweise bekam bislang niemand die Zähne auseinander, ob man das auch ohne Update abwehren kann. Schauen wir uns mal an worum es überhaupt geht.

Was ist der triviale Exploit?

Es reicht, wenn man als lokaler Angreifer eine Email mit dem Sendmailersatz von Exim an „<${run{bash}}@zieldomain.de>“ sendet. Im Augenblick wo die zugestellt wird, wird der eingebettete Befehle (hier bash) als Root ausgeführt.

Das ganze kann man ggf. auch per Remote ausführen, so daß es eine richtig fiese Schwachstelle ist. Betroffen sind aber nur Versionen  > 4.87 < 4.92 . Dazu müssen aber diverse Dinge in der Config erlaubt sein, was in der Defaultkonfig nur teilweise der Fall ist. z.b. kann man keine „/“ in dem Befehl unterbringen, weil das unerlaubte Zeichen sind. Das schränkt den Angreifer natürlich stark sein.

Da selbst auf der Eximliste bis heute viel Geheimniskrämerrei im Spiel war, hier die ebenso triviale Gegenmaßnahmen:

Gegenmaßnamen

Einfach kein „$“ in Emailadressen erlauben 😀 Das war es. Da fiel mir nur ARGS zu ein 😀

Das hier kommt in Eure Exim Konfiguration rein, dann Exim neu starten:

acl_check_rcpt:

deny message = Restricted characters in address
domains = +local_domains
local_parts = ^[.] : ^.*[\$@%!/|]

deny message = Restricted characters in address
domains = !+local_domains
local_parts = ^[./|] : ^.*[\$@%!] : ^.*/\\.\\./

….

acl_check_mail:

drop message = Restricted characters in address
condition = ${if match{$sender_address}{\N.*\$.*run.*\N}{1}{0}}

# WICHTIG: Vor dieser Anweisung reinschreiben, sonst Essig!

accept hosts = +relay_from_hosts

Das würgt den Angreifer ab, bevor die Email zugestellt wird.

Die bessere Gegenmaßnahme wäre natürlich auf einen aktuelleren Exim umzusteigen. Aber wie das so ist, es gibt halt immer „Gründe“ warum und wieso was nicht aktualisiert werden kann.

Keiner bekommt die Zähne auseinander…

Was mich am allermeisten an der Lücke nervt ist, daß diese billige Gegenmaßnahme im Advisory von Qualys und in den Hinweisen vom Exim Team nicht vorkommen. Bei den Exim Leuten kann ich es noch verstehen, weil die den Bug selbstständig schon Anfang des Jahres gefixt hatten und halt mit Recht sagen können: Mach halt Updates.

Bei Qualyssieht anders aus, die schreiben :

As per the distros list policy:

Below is an abridged version of our advisory (with all the vulnerability
details, but without exploitation details); we will publish the complete
version in 24 hours, or as soon as third-party exploits are published,
whichever happens first.

We believe that it makes no sense to delay this any longer than that:
this vulnerability is trivially exploitable in the local and non-default
cases (attackers will have working exploits before that, public or not);
and in the default case, a remote attack takes a long time to succeed
(to the best of our knowledge).

Schön das Ihr den Exploit weggelassen habt, wie wär es mal mit dem Workaround, so das die guten Jungs einen kleinen Vorsprung haben?  Und dieser kryptische Hinweis „a remote attack takes a long time to succeed“ meint übrigens, das man seinen Exim mal alle 24h neu starten sollte, weil es da wohl irgend einen Scheiß mit „Teergruben“ gibt.

Das sind i.d.R. Spamfallen, die so langsam antworten, daß der Angriff des Angreifers einfach zäh wie in einer Teergrube abläuft, bis hin zu „gar nicht voran kommt“. So was in der Art nutzen die Angreifer hier aus. Daher einmal im Cron „killall -9 exim; systemctl restart exim“ per Cron: Fertig.