Schwarze Magie für GNU/Linux-Nerds

“Linux ist der beste Virenschutz”, heißt es in “Fachkreisen”. “Installiere Linux und Du wirst fortan ruhiger schlafen können!” Ähm… falsch.
Ja, Linux ist ein guter Anfang was die Herstellung der Sicherheit auf dem eigenen Rechner betrifft. Aber es hilft einem nichts ohne brain.exe. Vor allem wenn man es mit einem Magier zu tun bekommt…

Mögen die Spiele beginnen!

ps -fu nagios

Wer auf das Monitoring-System Zugriff hat, hat viel Macht.

Wo Bernd recht hat, hat er recht – nicht umsonst nimmt z. B. Gunnars Jabber-Notification-Skript Nutzername und Passwort via Umgebungsvariablen entgegen. Check- und Notification-Skripte, die diesem Beispiel nicht folgen, reißen eine Sicherheitslücke auf, die jeder Systemnutzer ganz einfach ausnutzen kann:

aklimov@icinga2:~$ ps -fu nagios
UID        PID  PPID  C STIME TTY          TIME CMD
nagios    8128     1  0 11:10 ?        00:00:00 /usr/lib/x86_64-linux-gnu/icinga2/sbin/icinga2 --no-stack-rlimit daemon -e /var/log/icinga2/error.log
nagios    8148  8128  0 11:10 ?        00:00:00 /usr/lib/x86_64-linux-gnu/icinga2/sbin/icinga2 --no-stack-rlimit daemon -e /var/log/icinga2/error.log
nagios    8433  8148  0 11:17 ?        00:00:00 /usr/lib/nagios/plugins/check_ping -6 -H ::1 -c 200,15% -w 100,5%
nagios    8434  8433  0 11:17 ?        00:00:00 /bin/ping6 -n -U -w 10 -c 5 ::1
nagios    8435  8148  0 11:17 ?        00:00:00 /usr/lib/nagios/plugins/check_ping -4 -H 127.0.0.1 -c 200,15% -w 100,5%
nagios    8436  8148  0 11:17 ?        00:00:00 /usr/lib/nagios/plugins/check_ping -H 127.0.0.1 -c 5000,100% -w 3000,80%
nagios    8437  8435  0 11:17 ?        00:00:00 /bin/ping -n -U -w 10 -c 5 127.0.0.1
nagios    8438  8436  0 11:17 ?        00:00:00 /bin/ping -n -U -w 30 -c 5 127.0.0.1

Schwarze Magie ist hier noch nicht im Spiel. (Aber dieses Beispiel ist auch nur zum Aufwärmen.)

strace -p

Was tut ein Programm so alles wenn ich gerade mal nicht hinschaue? Um diese Frage zu beantworten, wird nicht zwangsläufig der Quellcode benötigt. In vielen Fällen reicht bereits strace:
aklimov@WS-AKlimov:~$ echo $$  # Prozess-ID der Shell
20901
aklimov@WS-AKlimov:~$ strace -p20901
strace: Process 20901 attached
wait4(-1,

Der Ausgabe können wir entnehmen, dass die Shell gerade darauf wartet, dass ein beliebiger Kindprozess (z. B. strace) sich beendet.
Diese Art der Hexenkunst hat sich bereits rumgesprochen und die Kernel-Entwickler haben ihre Wirkung eingedämmt. Daher konnte ich ohne weiteres nur den Elternprozess von strace als Beispiel nehmen.

gdb -p

Ich erinnere mich noch genau an diese eine AWP-Unterrichtsstunde in der Berufsschule:
Es ging darum, dass ein C/C++-Programm auf mehrere Module aufgeteilt werden kann. Mit dem static-Schlüsselwort sei es möglich, “modulglobale” Variablen zu erstellen – d. h. Variablen, die zwar global, aber nur für das eigene Modul sichtbar sind. Ein Argument des Lehrers für solche Variablen war allen Ernstes die Sicherheit. Und die Übung zu diesem Thema bestand darin, in einem Modul ein Passwort vor den anderen Modulen zu verbergen.
Wenn der wüsste…
Zunächst starte ich in einem neuen Terminal cat:
aklimov@WS-AKlimov:~$ cat
Damit haben wir auch schon unseren “Opfer”-Prozess, der im konkreten Fall auf eingehende Daten wartet.
Darauf hin öffne ich ein zweites Terminal (mit den gleichen Benutzerrechten!) und starte gdb:
aklimov@WS-AKlimov:~$ ps -ef |grep cat
aklimov  10217 10149  0 12:25 pts/11   00:00:00 cat
aklimov  11088 10298  0 12:26 pts/12   00:00:00 grep cat
aklimov@WS-AKlimov:~$ gdb -p 10217
GNU gdb (Debian 7.11.1-2+b1) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
(...)
Attaching to process 10217
(...)
(gdb)

Die schwarze Magie daran…

… besteht darin, dass ich nun innerhalb dieses Prozesses schalten und walten kann wie ich will. (Und sämtlichen Speicher aller Module auslesen.)
Beispielsweise kann ich den Standard-Eingabe-Datenstrom (Stdin) des Prozesses on-the-fly durch /dev/null ersetzen (ohne ihn zu verlieren):

Aktion (Beschreibung) Aktion (GDB) Datei-Deskriptoren
/dev/null öffnen (gdb) p open("/dev/null", 0)
$1 = 3
0 /dev/pts/1
3 /dev/null
Stdin sichern (gdb) p dup(0)
$2 = 4
0, 4 /dev/pts/1
3 /dev/null
Datenstrom umleiten (gdb) p dup2(3, 0)
$3 = 0
4 /dev/pts/1
0, 3 /dev/null
Redundanten Deskriptor schließen (gdb) p close(3)
$4 = 0
4 /dev/pts/1
0 /dev/null
Programm-Ausführung fortsetzen (gdb) c
Continuing.
[Inferior 1 (process 10217) exited normally]
(gdb)
N/A

Fazit

Linux nimmt einem keinerlei Sicherheitsfragen vollständig ab. Es gibt einem lediglich die Möglichkeit, sich selbst um diese zu kümmern (und sie nicht der NSA zu überlassen).
Gehet hin und sichert euch!

Alexander Klimov
Alexander Klimov
Developer

Alexander hat 2017 seine Ausbildung zum Developer bei NETWAYS erfolgreich abgeschlossen. Als leidenschaftlicher Programmierer und begeisterter Anhänger der Idee freier Software, hat er sich dabei innerhalb kürzester Zeit in die Herzen seiner Kollegen im Development geschlichen. Wäre nicht ausgerechnet Gandhi sein Vorbild, würde er von dort aus daran arbeiten, seinen geheimen Plan, erst die Abteilung und dann die Weltherrschaft an sich zu reißen, zu realisieren - tut er aber nicht. Stattdessen beschreitet er mit der...

Die Suche nach dem heiligen Gral

Alle Monate aufs Neue mache ich mich auf die Suche nach einer neuen, tolleren IDE, die hoffentlich alle meine Probleme lösen kann. Bisher jedoch leider vergeblich, obwohl – wie ich finde – meine Anforderungen doch eigentlich gar nicht so unrealistisch sind:

  • Syntax-Highlighting und Code-Completion für C/C++
  • Plattformunabhängigkeit: Sollte unter Linux und Windows verwendbar sein
  • Unterstützung für autoconf/automake wäre ganz nett
  • Integration von GDB inkl. Remote Debugging
  • Ich möchte gerne mehr Zeit damit verbringen, Code zu schreiben, als die IDE zu konfigurieren oder gegen deren Macken anzukämpfen

Und so fange ich an, diverse IDEs zu testen – in der Hoffnung, dass die jeweils aktuelle Version inzwischen halbwegs erträglich ist.
Zunächst einmal Eclipse CDT und NetBeans. Plattformunabhängig sind sie ja, das muss man den Java-IDEs lassen. Aber da hört es für mich leider auch schon wieder auf. Mal eben Eclipse starten, um eine Datei zu bearbeiten?: Fehlanzeige – die IDE startet so träge, dass es mich wundert, dass die Entwickler nicht gleich noch einen Lade-Screen für den Splash-Screen implementiert haben.
Auch das Indexing für die Code Completion lässt sich bei beiden IDEs gerne mal etwas mehr Zeit. Im Allgemeinen scheinen sowieso viele Hintergrund-Tasks zu laufen, die meine CPU zum Kochen bringen wollen. – Nein, danke.
Der Vollständigkeit halber will ich Visual Studio erwähnen. Was die Editor-Features und v.a. IntelliSense angeht, ist Visual Studio wirklich absolute Spitze. Leider ist es für mich nur eingeschränkt verwendbar, da ich meine Software primär unter Linux teste. Und jedes Mal meinen Quellcode zwischen einer Windows-VM und meiner Linux-Workstation hin- und herzukopieren ist mir zu aufwändig.
Nach weiteren Versuchen mit Anjuta, KDevelop, Code::Blocks und diversen anderen unbekannteren IDEs bin ich dann wieder bei meinen “klassischen” Tools gelandet: GNOME Terminal bzw. PuTTY unter Windows, vim und gdb (mit cgdb-Frontend). Nunja, zumindest habe ich wohl nun wieder für einige Monate keinen Bedarf mehr, die ideale IDE zu finden.

Weekly Snap: GDB for Debugging, ispCP for Web Server Admin, 1 New Job & 3 New Hardware

1 – 6 August started the month with blogging from across the office. First on new products from the hardware store, tips from the development and managed services teams and also a new job opening on the sales team.
Starting the week, Marcus shared a tip for web server management with isp Contol Panel Omega. A fork of the now inactive VHCS project, ispCP is an open source, multi server control and administration panel for internet service providers. He likes ispCP for its user interface and ability assign various roles to users such as ‘administrator’, ‘reseller’ and ‘user’ to apply refined user rights and principles. Installation is easy with the helpful official documentation and ispCP is available in a stable v1.0.7. However for a look at its new features Marcus recommends the v1.1.0 beta version or simply their online demos.
From the development team, Gunnar showed how to use GDB for debugging. As of v.7.0, GDB can “record” and replay program execution allowing the user to pinpoint problem areas in the source code. Handy indeed, but he cautioned that GDB significantly slows the program when “recording” and should be used for the shortest process portions possible.
Following on from Sales, Peter posted a position for a Junior Account Manager. The ideal candidate would have some experience in hosting, systems management, monitoring etc and enjoy dealing with customers. More on the position and application can be found on the jobs area of our website.
From our hardware shop, Martin announced the arrival of Kentix AlamManager, Multi Sensor LAN and the new Multi-Tech Multi Modem for SMS. The Kentis Alarm Manager Set consists of a base station and wireless multi sensor. The base station facilitates communication with the company network and sends SMS alerts through the in-built GSM modem. The sensor monitors temperature, humidity, dew point, fire/carbon monoxide and movement, communicating to the base station wirelessly via Zig Bee. For smaller environments, the Multi Sensor LAN is also available, offering a version that is integrated into the company network via a network cable (with PoE). As alway. Icinga/Nagios  plugins can be downloaded at www.netways.org
Finally, the last addition to the shop is the follower to the Multi-Tech Multi Modem MTCBA-G-EN-F4-ED-EU, known as the Multi-Tech Multi Modem MTCBA-G2-EN2-F4-ED-EU. From in-house tests, Martin noted that interceptty is no longer needed; instead communication can be set simply in the SMS server tool config.

Historisches Debuggen mit GDB

Beim Debuggen von Speicherzugriffen ist es manchmal recht schwierig, die verursachende Stelle im Quelltext zu finden, wenn das Programm an einer scheinbar zufälligen Stelle crasht oder es durch Logikfehler unerwartete Ergebnisse liefert.
Hilfsmittel wie Valgrind oder Watchpoints (“help watch” und “help rwatch” in GDB) erleichtern hierbei die Fehlersuche, können aber nicht immer den Fehler finden. Gerade bei komplexeren Bugs wünscht man sich oft, in der Programmausführung zurückgehen zu können, um Variablen vor einem bestimmten Funktionsaufruf untersuchen zu können, oder um weitere Breakpoints zu setzen.
Seit Version 7.0 ist genau das mit GDB möglich. Mit Hilfe des “record”-Targets kann die Programmausführung aufgenommen werden und schrittweise zurück- und auch wieder vorgespult werden.
Um dieses Feature zu demonstrieren, kompilieren wir folgendes Beispiel-Programm mit “gcc -ggdb -o test test.c”:

int main(int argc, char **argv) {
    int a, b;
    a = 7;
    b = a;
    return 0;
}

Danach können wir wie gewohnt gdb aufrufen:

$ gdb ./test

Zunächst müssen wir einen Breakpoint setzen, an dem wir mit der Aufnahme der Programmausführung starten wollen. Im einfachsten Falle wäre das die “main”-Funktion. Bei komplexeren Programmen kann hier eine andere Stelle im Programm verwendet werden, wo der zu untersuchende Bug noch nicht aufgetreten ist:

(gdb) break main
Breakpoint 1 at 0x4004bf: file test.c, line 4.

Danach können wir noch einen zweiten Breakpoint setzen, wenn wir wissen, an welcher Stelle der Bug schon aufgetreten ist (z.B. beim Speichern einer Datei, wenn die zu speichernden Daten zu diesem Zeitpunkt bereits fehlerhaft sind) – dies ist jedoch optional:

(gdb) break test.c:8
Breakpoint 2 at 0x4004cc: file test.c, line 8.

Nachdem wir die Breakpoints gesetzt haben, können wir das Programm starten:

(gdb) run
Starting program: /home/gunnar/test
Breakpoint 1, main (argc=1, argv=0x7fffffffe288) at test.c:4
4		a = 7;

GDB stoppt unseren Prozess an dem ersten Breakpoint. Mit dem “record”-Befehl können wir nun GDB anweisen, die weitere Programmausführung aufzuzeichnen:

(gdb) record

Wenn wir den Prozess nun weiterlaufen lassen, sollte er den zweiten Breakpoint erreichen. (Falls wir keinen gesetzt haben, fragt GDB uns nach Ausführung des Programms, ob wir den Prozess anhalten möchten – dies sollte mit “y” beantwortet werden, da GDB sonst den Prozess beendet):

(gdb) continue
Continuing.
Breakpoint 2, main (argc=1, argv=0x7fffffffe288) at test.c:8
8		return 0;

Um nun in der Aufnahme zurückspringen zu können, bietet GDB zusätzlich zu den normalen Ausführungsbefehlen (continue, step, next, usw.) entsprechende Befehle, die in umgekehrter Richtung funktionieren:

  • reverse-continue
  • reverse-finish
  • reverse-next
  • reverse-nexti
  • reverse-step
  • reverse-stepi

Mit reverse-continue können wir z.B. zum Anfang der Aufnahme zurückspringen:

(gdb) reverse-continue
Continuing.
No more reverse-execution history.
main (argc=1, argv=0x7fffffffe288) at test.c:4
4		a = 7;

An dieser Stelle können wir z.B. weitere Breakpoints und Watchpoints setzen, oder mit “step” das Programm zeilenweise durchlaufen lassen und mit “print” Variablen untersuchen.
Abschließend wäre noch zu beachten, dass “record” das auszuführende Programm deutlich verlangsamt. Idealerweise sollten dabei die Breakpoints so gewählt werden, dass ein möglichst kleiner Teil des Prozesses aufgezeichnet werden muss.