Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
1 Einleitung
TEIL I: Einstieg in Linux
2 Die Installation
3 Erste Schritte
4 Linux als Workstation für Einsteiger
TEIL II: Grundlagen
5 Kernel
6 Grundlagen aus Anwendersicht
TEIL III: Die Shell
7 Die Shell
8 Reguläre Ausdrücke
9 Konsolentools
10 Die Editoren
11 Shellskriptprogrammierung mit der bash
12 Die C-Shell
TEIL IV: System- & Netzwerkadministration
13 Benutzerverwaltung
14 Grundlegende Verwaltungsaufgaben
15 Netzwerkgrundlagen
16 Anwendersoftware für das Netzwerk
17 Netzwerkdienste
18 Mailserver unter Linux
19 LAMP & Co.
20 DNS-Server
21 Secure Shell
TEIL V: Die grafische Oberfläche
22 Die grafische Oberfläche
23 Window-Manager und Desktops
24 X11-Programme
25 Multimedia und Spiele
TEIL VI: Systeminterna
26 Prozesse und IPC
27 Bootstrap und Shutdown
28 Dateisysteme
29 Virtualisierung und Emulatoren
TEIL VII: Programmierung und Sicherheit
30 Softwareentwicklung
31 Crashkurs in C und Perl
32 Einführung in Computersicherheit
33 Netzwerksicherheit überwachen
TEIL VIII: Anhang
A Lösungen zu den einzelnen Aufgaben
B Kommandoreferenz
C X11-InputDevices
D MBR
E Buch-DVDs
F Glossar
G Literatur
Stichwort
Ihre Meinung?

Spacer
Linux von Johannes Plötner, Steffen Wendzel
Das umfassende Handbuch
Buch: Linux

Linux
Rheinwerk Computing
1282 S., 5., aktualisierte Auflage 2012, geb., mit 2 DVDs
49,90 Euro, ISBN 978-3-8362-1822-1
Pfeil 30 Softwareentwicklung
Pfeil 30.1 Interpreter und Compiler
Pfeil 30.1.1 C und C++
Pfeil 30.1.2 Perl
Pfeil 30.1.3 Java
Pfeil 30.1.4 Tcl
Pfeil 30.1.5 Was es sonst noch gibt
Pfeil 30.2 Shared Libraries
Pfeil 30.2.1 Vorteile der Shared Libraries
Pfeil 30.2.2 Statisches Linken
Pfeil 30.2.3 Dateien
Pfeil 30.3 Debugging
Pfeil 30.3.1 Vorbereitung
Pfeil 30.3.2 Konsolenarbeit
Pfeil 30.3.3 DDD
Pfeil 30.4 Profiling
Pfeil 30.4.1 Compiler-Option
Pfeil 30.4.2 gprof verwenden
Pfeil 30.4.3 Profiling-Daten lesen
Pfeil 30.5 Tracing
Pfeil 30.6 Hilfe beim Finden von Bugs
Pfeil 30.6.1 ProPolice
Pfeil 30.6.2 Flawfinder und RATS
Pfeil 30.6.3 Electric Fence
Pfeil 30.7 Integrierte Entwicklungsumgebungen
Pfeil 30.8 Make
Pfeil 30.8.1 Makefile
Pfeil 30.8.2 Makros
Pfeil 30.8.3 Shellvariablen in Makefiles
Pfeil 30.8.4 Einzelne Targets übersetzen
Pfeil 30.8.5 Spezielle Targets
Pfeil 30.8.6 Tipps im Umgang mit Make
Pfeil 30.9 Die GNU Autotools
Pfeil 30.10 lex/flex und yacc/bison
Pfeil 30.10.1 flex grundlegend anwenden
Pfeil 30.10.2 bison/yacc grundlegend anwenden
Pfeil 30.11 Unix-Software veröffentlichen
Pfeil 30.12 Manpages erstellen
Pfeil 30.12.1 groff nutzen
Pfeil 30.12.2 Manpages installieren
Pfeil 30.13 Versionsmanagement
Pfeil 30.13.1 CVS
Pfeil 30.13.2 Subversion
Pfeil 30.13.3 Git
Pfeil 30.14 Wichtige Bibliotheken
Pfeil 30.14.1 Entwicklung grafischer Oberflächen
Pfeil 30.14.2 Weitere Bibliotheken
Pfeil 30.15 Zusammenfassung
Pfeil 30.16 Aufgaben

Rheinwerk Computing - Zum Seitenanfang

30.6 Hilfe beim Finden von BugsZur nächsten Überschrift

Dieser Abschnitt erläutert, wie Sie mithilfe verschiedener Programme Bugs in Softwareprojekten finden können. Zu diesem Zweck werden wir das folgende C-Programm analysieren, das ich absichtlich mit diversen Fehlern versehen habe.

Listing 30.28 bug1.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <err.h>

int
main(int argc, char *argv[])
{
char buf[16] = { '\0' };
char *p;

if (argc > 1)
strcpy(buf, argv[1]);

p = (char *) calloc(15, 1);
if (p) {
int i;
for (i = 0; i <= 16; i++)
p[i] = buf[i];
printf("%s\n", p);
} else
err(1, "calloc");

return 0;
}

Dieses Programm ist anfällig für einen typischen Buffer-Overflow. Das bedeutet, dass ein statischer Puffer (hier mit einer Größe von 16 Byte [0xf]) überschrieben wird. Überschrieben werden kann der Puffer, falls das erste Argument, das dem Programm übergeben wurde, größer als 15 Bytes ist. In diesem Fall wird nämlich das sechzehnte Zeichen, das eigentlich eine abschließende Null sein sollte, überschrieben. Werden noch mehr Bytes kopiert, so werden andere Variablen der Stackframes oder auch auf dem Stack gesicherte Registerwerte überschrieben. Dieses Problem haben wir bereits in unserem Buch »Praxisbuch Netzwerksicherheit« im Detail beschrieben.

Das zweite große Problem besteht darin, dass sich an der Adresse, auf die der Pointer p zeigt, weniger Speicher befindet, als im Puffer buf vorhanden ist. Da in p allerdings der gesamte Puffer sowie zwei zusätzliche Bytes kopiert werden, wird auch dieser Heap-Puffer überschrieben. [Fn. Auch zum Thema Heap-Overflows finden Sie weitere Informationen in unserem »Praxisbuch Netzwerksicherheit«.] Man bezeichnet ein solches Problem, bei dem ein Puffer um ein Byte überschrieben wird, als Off-by-One-Overflow. In unserem Fall liegt ein zweifacher Off-by-One-Bug vor, da die Schleife erstens nur bis 15 (und nicht 16) durchlaufen werden sollte und zweitens ein < anstelle von <= verwendet werden müsste.


Rheinwerk Computing - Zum Seitenanfang

30.6.1 ProPoliceZur nächsten ÜberschriftZur vorigen Überschrift

Seit der Version 3.4 ist der sogenannte ProPolice-Patch – eine Entwicklung von IBM – für den GNU C Compiler verfügbar. [Fn. Seit gcc-4.1 ist sie fester Bestandteil des gcc.] Mit dieser Erweiterung können Buffer- Overflows innerhalb eines Stackframes verhindert werden. Zu diesem Zweck wird der Stack etwas modifiziert: Lokale Stack-Variablen, die keine Puffer sind, werden vor diesen plaziert, so dass Puffer (deren Elemente in die entgegengesetzte Richtung aufsteigen) nur andere Buffer überschreiben können. Hinter den Puffern wird zudem ein spezieller Canary-Wert eingefügt. Dieser Zufallswert wird bei einem Overflow überschrieben, wodurch eine Veränderung des Werts entdeckt werden kann. In diesem Fall wird das Programm abgebrochen.

Ein Test

Versuchen wir nun, das obige Programm zu einem Overflow zu führen. Anschließend werden wir es mit ProPolice schützen (-fstack-protector) und sehen, dass das Programm gekillt wird.

[»]Achtung: Bei Ubuntu muss zur Übersetzung ohne Stack Protection explizit der gcc-Parameter -fno-stack-protector gesetzt werden, da die Stack Protection automatisch aktiv ist.

Listing 30.29 ProPolice Protection

$ gcc -o bug1 bug1.c
$ ./bug1 123
123
$ ./bug1 `perl -e 'print "A"x99'`
AAAAAAAAAAAAAAAA

Segmentation fault (core dumped)
$ gcc -o bug1 bug1.c -fstack-protector
$ ./bug1 `perl -e 'print "A"x99'`
AAAAAAAAAAAAAAAAA
*** stack smashing detected ***
: ./bug1 terminated
Abort (core dumped)

Mit ProPolice steht dem Programmierer also eine Erweiterung zur Verfügung, die oft in der Lage ist, Schlimmeres zu verhindern. [Fn. Es gibt Möglichkeiten, ProPolice zu umgehen, aber diese hier zu besprechen, würde zu weit gehen.]


Rheinwerk Computing - Zum Seitenanfang

30.6.2 Flawfinder und RATSZur nächsten ÜberschriftZur vorigen Überschrift

Besser noch ist es, wenn man in der Lage ist, solche Bugs während der Entwicklung zu finden, um die gezielte Programmbeendigung durch die ProPolice gar nicht erst stattfinden zu lassen. Hierbei helfen Programme wie Flawfinder sowie das mittlerweile nicht mehr weiterentwickelte pscan oder RATS.

Für all diese Tools gilt allerdings, dass ihre Ausgaben von Hand überprüft werden müssen. Es handelt sich bei allen Angaben immer nur um mögliche Bugs und Sicherheitsprobleme.

Flawfinder

Der Flawfinder wurde von David Wheeler entwickelt und wird zur Analyse von C/C++-Code eingesetzt. Das Programm untersucht den Quellcode nach bestimmten tückischen Funktionen, die zu Problemen führen können. Zudem erkennt es einige häufige Fehlerquellen.

Listing 30.30 Flawfinder untersucht bug.cc

$ flawfinder bug1.c
Flawfinder version 1.26, (C) 2001-2004 David A. Wheeler.
Number of dangerous functions in C/C++ ruleset: 158
Examining bug1.c
bug1.c:13:
[4] (buffer) strcpy:
Does not check for buffer overflows when copying to
destination. Consider using strncpy or strlcpy
(warning, strncpy is easily misused).
bug1.c:9:
[2] (buffer) char:
Statically-sized arrays can be overflowed. Perform
bounds checking, use functions that limit length,
or ensure that the size is larger than the maximum
possible length.

Hits = 2
Lines analyzed = 26 in 0.54 seconds (678 lines/second)
Physical Source Lines of Code (SLOC) = 21
Hits@level = [0] 0 [1] 0 [2] 1 [3] 0 [4] 1
[5] 0
Hits@level+ = [0+] 2 [1+] 2 [2+] 2 [3+] 1 [4+]
1 [5+] 0
Hits/KSLOC@level+ = [0+] 95.2381 [1+] 95.2381 [2+]
95.2381 [3+] 47.619 [4+] 47.619 [5+] 0
Minimum risk level = 1
Not every hit is necessarily a security vulnerability.
There may be other security vulnerabilities; review
your code!

Wie Sie sehen, weist Flawfinder auf zwei Probleme hin: Zum einen wird die unsichere Funktion strcpy() verwendet, die einen Puffer ohne Längenüberprüfung in einen anderen kopiert. Dies kann durch entsprechende Verwendung von strncpy oder auch strlcpy() verhindert werden, aber auch diese Funktionen müssen fehlerfrei verwendet werden, damit sie nicht zu Bugs führen.

Zum anderen wird auf die statische Größe des Puffers hingewiesen, was oftmals zu Overflow-Problemen führen kann. Den Off-by-One Bug hat Flawfinder also nicht entdeckt.

RATS

Das Programm RATS funktioniert ähnlich wie Flawfinder, unterstützt aber auch PHP-, Python- und Perl-Code. Wie Sie sehen, findet RATS in unserem Fall keine weiteren Fehler und liefert ein gleichwertiges Ergebnis wie Flawfinder.

Listing 30.31 RATS scannt bug1.c.

$ rats bug1.c
Entries in perl database: 33
Entries in python database: 62
Entries in c database: 336
Entries in php database: 55
Analyzing bug1.c
bug1.c:9: High: fixed size local buffer

Extra care should be taken to ensure that character
arrays that are allocated on the stack are used
safely. They are prime targets for buffer overflow
attacks.

bug1.c:13: High: strcpy

Check to be sure that argument 2 passed to this
function call will not copy more data than can be
handled, resulting in a buffer overflow.

Total lines analyzed: 27
Total time 0.019469 seconds
1386 lines per second

Rheinwerk Computing - Zum Seitenanfang

30.6.3 Electric FenceZur vorigen Überschrift

Um den Heap-Overflow in bug1.c zu finden, brauchen wir ein weiteres Tool namens Electric Fence, eine Bibliothek, die Zugriffe auf nicht reservierten Speicher findet. Oftmals gehört ein Speicher, der überschrieben wurde, noch zum Kontext des Programms, wodurch dieses weiterläuft und der Bug nicht aufgedeckt wird. Electric Fence sorgt hingegen dafür, dass das Programm in einem solchen Fall sofort abstürzt. Wie Sie sehen, stürzt das Programm in unserem Fall tatsächlich nicht ab, auch wenn wir ihm ganze 16 Bytes übergeben. Beachten Sie zudem, dass die Anzahl der übergebenen Bytes auf den Heap-Puffer keinen Einfluss hat, da immer so viel Bytes in den Puffer kopiert werden, wie es Schleifendurchläufe gibt.

[»]Achtung: Auch hier gilt, dass bei Distributionen wie Ubuntu, die standardmäßig Stack Protection aktiviert haben, diese explizit abgestellt werden muss.

Listing 30.32 Das Programm stürzt nicht ab.

$ gcc -o bug1 bug1.c
$ ./bug1 `perl -e 'print "A"x16;'`
AAAAAAAAAAAAAAAA

Nun übersetzen wir das Programm mit der Electrice-Fence-Library. Um es im GNU Debugger analysieren zu können, übergeben wir zudem den Parameter -g. Da die Anzahl der Bytes für den Overflow im Heap-Buffer nicht relevant ist, können wir das Programm ohne Parameter starten.

Listing 30.33 Electrice Fence

$ gcc -g -o bug1 bug1.c -fno-stack-protector -lefence
$ ./bug1

Electric Fence 2.1 Copyright (C) 1987-1998 Bruce Perens.
Segmentation fault (core dumped)

Wie Sie sehen, lässt Electric Fence das Programm tatsächlich abstürzen. Nun führen wir eine Analyse

im GNU Debugger durch.

Listing 30.34 bug1 im gdb

$ gdb bug1
GNU gdb 6.6-debian
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General
Public License, and you are welcome to change it
and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type
"show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
Using host libthread_db library
"/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) run
Starting program:
/home/swendzel/books/kompendium2/examples/bugs/bug1
[Thread debugging using libthread_db enabled]
[New Thread –1210296640 (LWP 6405)]

Electric Fence 2.1 Copyright (C) 1987-1998
Bruce Perens.

Program received signal SIGSEGV, Segmentation fault.

[Switching to Thread –1210296640 (LWP 6405)]
0x0804857c in main (argc=1, argv=0xbfb06284) at bug1.c:19
19
p[i] = buf[i];
(gdb) list 19
14
15 p = (char *) calloc(15, 1);
16 if (p) {
17 int i;
18 for (i = 0; i <= 16; i++)
19 p[i] = buf[i];
20 printf("%s\n", p);
21 } else
22 err(1, "calloc");
23
(gdb) quit
The program is running. Exit anyway? (y or n) y

Fazit

Electric Fence hat unseren Speicherzugriffsfehler gefunden. In Kombination mit einem anderen Programm wie Flawfinder oder RATS verfügen Sie also über eine sehr effektive Toolchain zur Analyse von Code.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.

>> Zum Feedback-Formular
<< zurück
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Linux Handbuch






 Linux Handbuch


Zum Katalog: Linux Server






 Linux Server


Zum Katalog: Raspberry Pi






 Raspberry Pi


Zum Katalog: Ubuntu 14.04 LTS






 Ubuntu 14.04 LTS


Zum Katalog: Roboter bauen mit Arduino






 Roboter bauen
 mit Arduino


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2012
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de