aboutsummaryrefslogtreecommitdiff
path: root/de_DE.ISO8859-1/books/developers-handbook/secure/chapter.xml
blob: cfcee8612329fc5ee9fe8b0c6c6b2e3938ebc72c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
     The FreeBSD Documentation Project
     The FreeBSD German Documentation Project

     $FreeBSD$
     $FreeBSDde: de-docproj/books/developers-handbook/secure/chapter.xml,v 1.16 2010/12/18 13:28:29 jkois Exp $
     basiert auf: 1.30
-->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="secure">
  <info><title>Sicheres Programmieren</title>
    <authorgroup>
      <author><personname><firstname>Murray</firstname><surname>Stokely</surname></personname><contrib>Contributed by </contrib></author>
    </authorgroup>
    <authorgroup>
      <author><personname><firstname>Hagen</firstname><surname>Kühl</surname></personname><contrib>Übersetzt von </contrib></author>
    </authorgroup>
  </info>

  

  <sect1 xml:id="secure-synopsis">
    <title>Zusammenfassung</title>

    <para>Dieses Kapitel beschreibt einige Sicherheitsprobleme, die
      &unix;-Programmierer seit Jahrzehnten quälen, und
      inzwischen verfügbare Werkzeuge, die Programmierern helfen,
      Sicherheitslücken in ihrem Quelltext zu vermeiden.</para>
  </sect1>

  <sect1 xml:id="secure-philosophy">
    <title>Methoden des sicheren Entwurfs</title>

    <para>Sichere Anwendungen zu schreiben erfordert eine sehr
      skeptische und pessimistische Lebenseinstellung. Anwendungen
      sollten nach dem Prinzip der <quote>geringsten
      Privilegien</quote> ausgeführt werden, sodass kein Prozess
      mit mehr als dem absoluten Minimum an Zugriffsrechten arbeitet,
      die er zum Erfüllen seiner Aufgabe benötigt. Wo es
      möglich ist, sollte Quelltext, der bereits
      überprüft wurde, wiederverwendet werden, um
      häufige Fehler, die andere schon korrigiert haben, zu
      vermeiden.</para>

    <para>Eine der Stolperfallen der &unix;-Umgebung ist, dass es
      sehr einfach ist Annahmen über die Konsistenz der Umgebung
      zu machen. Anwendungen sollten Nutzereingaben (in allen Formen)
      niemals trauen, genauso wenig wie den System-Ressourcen,
      der Inter-Prozess-Kommunikation oder dem zeitlichen Ablauf von
      Ereignissen. &unix;-Prozesse arbeiten nicht synchron. Daher sind
      logische Operationen selten atomar.</para>
  </sect1>

  <sect1 xml:id="secure-bufferov">
    <title>Puffer-Überläufe</title>

    <para>Puffer-Überläufe gibt es schon seit den
      Anfängen der Von-Neuman-Architektur <xref linkend="COD"/>.

      <indexterm><primary>Puffer-Überlauf</primary></indexterm>
      <indexterm><primary>Von-Neuman</primary></indexterm>

      Sie erlangten zum ersten Mal durch den Internetwurm Morris im
      Jahre 1988 öffentliche Bekanntheit. Unglücklicherweise

      <indexterm><primary>Morris Internetwurm</primary></indexterm>

      funktioniert der gleiche grundlegende Angriff noch heute.  Die bei weitem
      häufigste Form eines Puffer-Überlauf-Angriffs basiert darauf,
      den Stack zu korrumpieren.</para>

    <indexterm><primary>Stack</primary></indexterm>
    <indexterm><primary>Arguments</primary></indexterm>

    <para>Die meisten modernen Computer-Systeme verwenden einen
      Stack, um Argumente an Prozeduren zu übergeben und
      lokale Variablen zu speichern. Ein Stack ist ein
      last-in-first-out-Puffer (LIFO) im hohen Speicherbereich
      eines Prozesses. Wenn ein Programm eine Funktion

      <indexterm><primary>LIFO</primary></indexterm>
      <indexterm>
	<primary>Prozessabbild</primary>
	<secondary>Stack-Pointer</secondary>
      </indexterm>

      aufruft wird ein neuer "Stackframe" erzeugt. Dieser besteht aus
      den Argumenten, die der Funktion übergeben wurden und
      einem variabel grossem Bereich für lokale Variablen. Der
      "Stack-Pointer" ist ein Register, dass die

      <indexterm><primary>Stack-Frame</primary></indexterm>
      <indexterm><primary>Stack-Pointer</primary></indexterm>

      aktuelle Adresse der Stack-Spitze enthält.
      Da sich dieser Wert oft ändert, wenn neue Werte
      auf dem Stack abgelegt werden, bieten viele Implementierungen
      einen "Frame-Pointer", der nahe am Anfang des Stack-Frames
      liegt und es so leichter macht lokale Variablen relativ zum
      aktuellen Stackframe zu adressieren. <xref linkend="COD"/>
      Die Rücksprungadresse

      <indexterm><primary>Frame-Pointer</primary></indexterm>
      <indexterm>
	<primary>Prozessabbild</primary>
	<secondary>Frame-Pointer</secondary>
      </indexterm>
      <indexterm><primary>Rücksprungadresse</primary></indexterm>
      <indexterm><primary>Stack-Überlauf</primary></indexterm>

      der Funktionen werden ebenfalls auf dem Stack
      gespeichert und das ist der Grund für
      Stack-Überlauf-Exploits. Denn ein böswilliger Nutzer
      kann die Rücksprungadresse der Funktion überschreiben
      indem er eine lokale Variable in der Funktion
      überlaufen lässt, wodurch es ihm möglich ist
      beliebigen Code auszuführen.</para>

    <para>Obwohl Stack-basierte Angriffe bei weitem die
      Häufigsten sind, ist es auch möglich den Stack mit
      einem Heap-basierten (malloc/free) Angriff zu
      überschreiben.</para>

    <para>Die C-Programmiersprache führt keine automatischen
      Bereichsüberprüfungen bei Feldern oder Zeigern durch, wie
      viele andere Sprachen das tun. Außerdem enthält
      die C-Standardbibliothek eine Handvoll sehr
      gefährlicher Funktionen.</para>

    <informaltable frame="none" pgwide="1">
      <tgroup cols="2">
	<tbody>
	  <row>
	    <entry><function>strcpy</function>(char *dest, const
	      char *src)</entry>
	    <entry><simpara>Kann den Puffer dest überlaufen
	      lassen</simpara></entry>
	  </row>

	  <row>
	    <entry><function>strcat</function>(char *dest, const
	      char *src)</entry>
	    <entry><simpara>Kann den Puffer dest überlaufen
	      lassen</simpara></entry>
	  </row>

	  <row>
	    <entry><function>getwd</function>(char *buf)</entry>
	    <entry><simpara>Kann den Puffer buf überlaufen
	      lassen</simpara></entry>
	  </row>

	  <row>
	    <entry><function>gets</function>(char *s)</entry>
	    <entry><simpara>Kann den Puffer s überlaufen
	      lassen</simpara></entry>
	  </row>

	  <row>
	    <entry><function>[vf]scanf</function>(const char
	      *format, ...)</entry>
	    <entry><simpara>Kann sein Argument überlaufen
	      lassen</simpara></entry>
	  </row>

	  <row>
	    <entry><function>realpath</function>(char *path,
	      char resolved_path[])</entry>
	    <entry><simpara>Kann den Puffer path überlaufen
	      lassen</simpara></entry>
	  </row>

	  <row>
	    <entry><function>[v]sprintf</function>(char *str,
	      const char *format, ...)</entry>
	    <entry><simpara>Kann den Puffer str überlaufen
	      lassen</simpara></entry>
	  </row>
	</tbody>
      </tgroup>
    </informaltable>

    <sect2>
      <title>Puffer-Überlauf Beispiel</title>

      <para>Das folgende Quellcode-Beispiel enthält einen
	Puffer-Überlauf, der darauf ausgelegt ist die
	Rücksprungadresse zu überschreiben und die
	Anweisung direkt nach dem Funktionsaufruf zu
	überspringen. (Inspiriert durch
	<xref linkend="Phrack"/>)</para>

      <programlisting>#include &lt;stdio.h&gt;

void manipulate(char *buffer) {
char newbuffer[80];
strcpy(newbuffer,buffer);
}

int main() {
char ch,buffer[4096];
int i=0;

while ((buffer[i++] = getchar()) != '\n') {};

i=1;
manipulate(buffer);
i=2;
printf("The value of i is : %d\n",i);
return 0;
}</programlisting>

      <para>Betrachten wir nun, wie das Speicherabbild dieses
	Prozesses aussehen würde, wenn wir 160 Leerzeichen
	in unser kleines Programm eingeben, bevor wir Enter
	drücken.</para>

      <para>[XXX figure here!]</para>

      <para>Offensichtlich kann man durch böswilligere Eingaben
	bereits kompilierten Programmtext ausführen (wie z.B.
	exec(/bin/sh)).</para>
    </sect2>

    <sect2>
      <title>Puffer-Überläufe vermeiden</title>

      <para>Die direkteste Lösung, um
	Stack-Überläufe zu vermeiden, ist immer
	grössenbegrenzten Speicher und String-Copy-Funktionen
	zu verwenden.
	<function>strncpy</function> und <function>strncat</function>
	sind Teil der C-Standardbibliothek.

	<indexterm>
	  <primary>Zeichenketten-Kopierfunktioen</primary>
	  <secondary>strncpy</secondary>
	</indexterm>
	<indexterm>
	  <primary>Zeichenketten-Kopierfunktionen</primary>
	  <secondary>strncat</secondary>
	</indexterm>

	Diese Funktionen akzeptieren einen Längen-Parameter. Dieser
	Wert sollte nicht größer sein als die Länge
	des Zielpuffers. Die Funktionen kopieren dann bis zu
	`length' Bytes von der Quelle zum Ziel. Allerdings gibt es
	einige Probleme. Keine der Funktionen garantiert, dass
	die Zeichenkette NUL-terminiert ist, wenn die
	Größe

	<indexterm><primary>NUL-Terminierung</primary></indexterm>

	des Eingabepuffers so groß ist wie das Ziel.
	Außerdem wird der Parameter length zwischen strncpy
	und strncat inkonsistent definiert, weshalb Programmierer
	leicht bezüglich der korrekten Verwendung durcheinander
	kommen können. Weiterhin gibt es einen spürbaren
	Leistungsverlust im Vergleich zu
	<function>strcpy</function>, wenn eine kurze Zeichenkette in
	einen großen Puffer kopiert wird. Denn
	<function>strncpy</function> fült den Puffer bis zur
	angegebenen Länge mit NUL auf.
      </para>

      <para>In OpenBSD wurde eine weitere Möglichkeit zum

	<indexterm><primary>OpenBSD</primary></indexterm>

	kopieren von Speicherbereichen implementiert, die dieses
	Problem umgeht. Die Funktionen <function>strlcpy</function>
	und <function>strlcat</function> garantieren, dass das Ziel
	immer NUL-terminiert wird, wenn das Argument length ungleich
	null ist. Für weitere Informationen über diese
	Funktionen lesen Sie bitte <xref linkend="OpenBSD"/>. Die
	OpenBSD-Funktionen <function>strlcpy</function> und
	<function>strlcat</function> sind seit Version 3.3 auch in
	FreeBSD verfügbar.</para>

      <indexterm>
	<primary>Zeichenketten-Kopierfunktionen</primary>
	<secondary>strlcpy</secondary>
      </indexterm>

      <indexterm>
	<primary>Zeichenketten-Kopierfunktionen</primary>
	<secondary>strlcat</secondary>
      </indexterm>

      <sect3>
	<title>Compiler-basierte Laufzeitüberprüfung
	  von Grenzen</title>

	<indexterm>
	  <primary>Prüfung von Grenzen</primary>
	  <secondary>Compiler-basiert</secondary>
	</indexterm>

	<para>Unglücklicherweise gibt es immer noch sehr viel
	  Quelltext, der allgemein verwendet wird und blind Speicher
	  umherkopiert, ohne eine der gerade besprochenen Funktionen,
	  die Begrenzungen unterstützen, zu verwenden.
	  Glücklicherweise gibt es einen Weg, um solche Angriffe zu
	  verhindern -  Überprüfung der Grenzen zur Laufzeit, die in
	  verschiedenen C/C++ Compilern eingebaut ist.</para>

	<indexterm><primary>ProPolice</primary></indexterm>
	<indexterm><primary>StackGuard</primary></indexterm>
	<indexterm><primary>GCC</primary></indexterm>

	<para>ProPolice ist eine solche Compiler-Eigenschaft und ist in den
	  &man.gcc.1; Versionen 4.1 und höher integriert.  Es ersetzt und
	  erweitert die &man.gcc.1; StackGuard-Erweiterung von
	  früher.</para>

	<para>ProPolice schützt gegen stackbasierte
	  Pufferüberläufe und andere Angriffe durch das Ablegen von
	  Pseudo-Zufallszahlen in Schlüsselbereichen des Stacks bevor es
	  irgendwelche Funktionen aufruft.  Wenn eine Funktion beendet wird,
	  werden diese <quote>Kanarienvögel</quote> überprüft
	  und wenn festgestellt wird, dass diese verändert wurden wird das
	  Programm sofort abgebrochen.  Dadurch wird jeglicher Versuch, die
	  Rücksprungadresse oder andere Variablen, die auf dem Stack
	  gespeichert werden, durch die Ausführung von Schadcode zu
	  manipulieren, nicht funktionieren, da der Angreifer auch die
	  Pseudo-Zufallszahlen unberührt lassen müsste.</para>

	<indexterm><primary>Puffer-Überlauf</primary></indexterm>

	<para>Ihre Anwendungen mit ProPolice neu zu kompilieren ist
	  eine effektive Maßnahme, um sie vor den meisten
	  Puffer-Überlauf-Angriffen zu schützen, aber die
	  Programme können noch immer kompromittiert werden.</para>
      </sect3>

      <sect3>
	<title>Bibliotheks-basierte Laufzeitüberprüfung
	  von Grenzen</title>

	<indexterm>
	  <primary>Prüfung von Grenzen</primary>
	  <secondary>Bibliotheks-basiert</secondary>
	</indexterm>

	<para>Compiler-basierte Mechanismen sind bei Software,
	  die nur im Binärformat vertrieben wird, und die somit
	  nicht neu kompiliert werden kann völlig nutzlos.
	  Für diesen Fall gibt es einige Bibliotheken, welche
	  die unsicheren Funktionen der C-Bibliothek
	  (<function>strcpy</function>, <function>fscanf</function>,
	  <function>getwd</function>, etc..) neu implementieren und
	  sicherstellen, dass nicht hinter den Stack-Pointer
	  geschrieben werden kann.</para>

	<itemizedlist>
	  <listitem><simpara>libsafe</simpara></listitem>
	  <listitem><simpara>libverify</simpara></listitem>
	  <listitem><simpara>libparanoia</simpara></listitem>
	</itemizedlist>

	<para>Leider haben diese Bibliotheks-basierten
	  Verteidigungen mehrere Schwächen. Diese Bibliotheken
	  schützen nur vor einer kleinen Gruppe von
	  Sicherheitslücken und sie können das
	  eigentliche Problem nicht lösen. Diese
	  Maßnahmen können versagen, wenn die Anwendung
	  mit -fomit-frame-pointer kompiliert wurde.
	  Außerdem kann der Nutzer die Umgebungsvariablen
	  LD_PRELOAD und LD_LIBRARY_PATH überschreiben oder
	  löschen.</para>
      </sect3>
    </sect2>
  </sect1>

  <sect1 xml:id="secure-setuid">
    <title>SetUID-Themen</title>

    <indexterm><primary>seteuid</primary></indexterm>

    <para>Es gibt zu jedem Prozess mindestens sechs verschiedene
      IDs, die diesem zugeordnet sind. Deshalb müssen Sie
      sehr vorsichtig mit den Zugriffsrechten sein, die Ihr Prozess
      zu jedem Zeitpunkt besitzt. Konkret bedeutet dass, das alle
      seteuid-Anwendungen ihre Privilegien abgeben sollten, sobald
      sie diese nicht mehr benötigen.</para>

    <indexterm>
      <primary>Benutzer-IDs</primary>
      <secondary>reale Benutzer-ID</secondary>
    </indexterm>
    <indexterm>
      <primary>Benutzer-IDs</primary>
      <secondary>effective Benutzer-ID</secondary>
    </indexterm>

    <para>Die reale Benutzer-ID kann nur von einem
      Superuser-Prozess geändert werden. Das Programm
      <application>login</application> setzt sie, wenn sich ein
      Benutzer am System anmeldet, und sie wird nur selten
      geändert.</para>

    <para>Die effektive Benutzer-ID wird von der Funktion
      <function>exec()</function> gesetzt, wenn ein Programm
      das seteuid-Bit gesetzt hat. Eine Anwendung kann
      <function>seteuid()</function> jederzeit aufrufen, um die
      effektive Benutzer-ID entweder auf die reale Benutzer-ID oder
      die gespeicherte set-user-ID zu setzen. Wenn eine der
      <function>exec()</function>-Funktionen die effektive
      Benutzer-ID setzt, wird der vorherige Wert als
      gespeicherte set-user-ID abgelegt.</para>
  </sect1>

  <sect1 xml:id="secure-chroot">
    <title>Die Umgebung ihrer Programme einschränken</title>

    <indexterm><primary>chroot()</primary></indexterm>

    <para>Die herkömmliche Methode, um einen Prozess
      einzuschränken, besteht in dem Systemaufruf
      <function>chroot()</function>. Dieser Aufruf
      ändert das Wurzelverzeichnis, auf das sich alle
      Pfadangaben des Prozesses und jegliche Kind-Prozesse beziehen.
      Damit dieser Systemaufruf gelingt, muss der Prozess
      Ausführungsrechte (Durchsuchungsrechte) für das
      Verzeichnis haben, auf das er sich bezieht. Die neue Umgebung
      wird erst wirksam, wenn Sie mittels
      <function>chdir()</function> in Ihre neue Umgebung wechseln.
      Es sollte erwähnt werden, dass ein Prozess recht einfach
      aus der chroot-Umgebung ausbrechen kann, wenn er root-Rechte
      besitzt. Das kann man erreichen, indem man Gerätedateien
      anlegt, um Kernel-Speicher zu lesen, oder indem man einen
      Debugger mit einem Prozess außerhalb seiner
      &man.chroot.8;-Umgebung verbindet, oder auf viele andere
      kreative Wege.</para>

    <para>Das Verhalten des Systemaufrufs
      <function>chroot()</function> kann durch die
      kern.chroot.allow_open_directories
      <command>sysctl</command>-Variable beeinflusst werden. Wenn
      diese auf 0 gesetzt ist, wird <function>chroot()</function>
      mit EPERM fehlschlagen, wenn irgendwelche Verzeichnisse
      geöffnet sind. Wenn die Variable auf den Standardwert 1
      gesetzt ist, wird <function>chroot()</function> mit EPERM
      fehlschlagen, wenn irgendwelche Verzeichnisse geöffnet
      sind und sich der Prozess bereits in einer
      <function>chroot()</function>-Umgebung befindet. Bei jedem
      anderen Wert wird die Überprüfung auf
      geöffnete Verzeichnisse komplett umgangen.</para>

    <sect2>
      <title>Die Jail-Funktionalität in FreeBSD</title>

      <indexterm><primary>Jail</primary></indexterm>

      <para>Das Konzept einer Jail (Gefängnis) erweitert
	<function>chroot()</function>, indem es die Macht des
	Superusers einschränkt, um einen echten 'virtuellen
	Server' zu erzeugen. Wenn ein solches Gefängnis einmal
	eingerichtet ist, muss die gesamte Netzwerkkommunikation
	über eine bestimmte IP-Adresse erfolgen und die
	"root-Privilegien" innerhalb der Jail sind sehr stark
	eingeschränkt.</para>

      <para>Solange Sie sich in einer Jail befinden, werden alle
	Tests auf Superuser-Rechte durch den Aufruf von
	<function>suser()</function> fehlschlagen. Allerdings wurden
	einige Aufrufe von <function>suser()</function>
	abgeändert, um die neue
	<function>suser_xxx()</function>-Schnittstelle zu
	implementieren. Diese Funktion ist dafür verantwortlich,
	festzustellen, ob bestimmte Superuser-Rechte einem
	eingesperrten Prozess zur Verfügung stehen.</para>

      <para>Ein Superuser-Prozess innerhalb einer Jail darf
	folgendes:</para>

      <itemizedlist>
	<listitem>
	  <simpara>Berechtigungen verändern mittels:
	    <function>setuid</function>,
	    <function>seteuid</function>,
	    <function>setgid</function>,
	    <function>setegid</function>,
	    <function>setgroups</function>,
	    <function>setreuid</function>,
	    <function>setregid</function>,
	    <function>setlogin</function></simpara>
	</listitem>

	<listitem>
	  <simpara>Ressourcenbegrenzungen setzen mittels
	    <function>setrlimit</function></simpara>
	</listitem>

	<listitem>
	  <simpara>Einige sysctl-Variablen (kern.hostname)
	    verändern</simpara>
	</listitem>

	<listitem>
	  <simpara><function>chroot()</function></simpara>
	</listitem>

	<listitem>
	  <simpara>Ein Flag einer vnode setzen:
	    <function>chflags</function>,
	    <function>fchflags</function></simpara>
	</listitem>

	<listitem>
	  <simpara>Attribute einer vnode setzen wie Dateiberechtigungen,
	    Eigentümer, Gruppe, Größe, Zugriffszeit
	    und Modifikationszeit</simpara>
	</listitem>

	<listitem>
	  <simpara>Binden eines Prozesses an einen öffentlichen
	    privilegierten Port (ports &lt; 1024)</simpara>
	</listitem>
      </itemizedlist>

      <para><function>Jail</function>s sind ein mächtiges
	Werkzeug, um Anwendungen in einer sicheren Umgebung
	auszuführen, aber sie haben auch ihre Nachteile.
	Derzeit wurden die IPC-Mechanismen noch nicht an
	<function>suser_xxx</function> angepasst, so dass Anwendungen
	wie MySQL nicht innerhalb einer Jail ausgeführt werden
	können. Der Superuser-Zugriff hat in einer Jail nur eine
	sehr eingeschränkte Bedeutung, aber es gibt keine
	Möglichkeit zu definieren was
	"sehr eingeschränkt" heißt.</para>
    </sect2>

    <sect2>
      <title>&posix;.1e Prozess Capabilities</title>

      <indexterm><primary>POSIX.1e Process
	Capabilities</primary></indexterm>
      <indexterm><primary>TrustedBSD</primary></indexterm>

      <para>&posix; hat einen funktionalen Entwurf (Working Draft)
	herausgegeben, der Ereignisüberprüfung,
	Zugriffskontrolllisten, feiner einstellbare Privilegien,
	Informationsmarkierung und verbindliche Zugriffskontrolle
	enthält.</para>

      <para>Dies ist im Moment in Arbeit und das Hauptziel des <link xlink:href="http://www.trustedbsd.org/">TrustedBSD</link>-Projekts.
	Ein Teil der bisherigen Arbeit wurde in &os.current;
	übernommen (cap_set_proc(3)).</para>
    </sect2>
  </sect1>

  <sect1 xml:id="secure-trust">
    <title>Vertrauen</title>

    <para>Eine Anwendung sollte niemals davon ausgehen, dass
      irgendetwas in der Nutzerumgebung vernünftig ist.
      Das beinhaltet (ist aber sicher nicht darauf
      beschränkt): Nutzereingaben, Signale,
      Umgebungsvariablen, Ressourcen, IPC, mmaps, das
      Arbeitsverzeichnis im Dateisystem, Dateideskriptoren,
      die Anzahl geöffneter Dateien, etc..</para>

    <indexterm><primary>positive Filterung</primary></indexterm>
    <indexterm><primary>Datenvalidierung</primary></indexterm>

    <para>Sie sollten niemals annehmen, dass Sie jede Art von
      inkorrekten Eingaben abfangen können, die ein Nutzer
      machen kann. Stattdessen sollte Ihre Anwendung positive
      Filterung verwenden, um nur eine bestimmte Teilmenge an
      Eingaben zuzulassen, die Sie für sicher halten.
      Ungeeignete Datenüberprüfung ist die Ursache
      vieler Exploits, besonders für CGI-Skripte im Internet.
      Bei Dateinamen müssen Sie besonders vorsichtig sein,
      wenn es sich um Pfade ("../", "/"), symbolische
      Verknüpfungen und Shell-Escape-Sequenzen handelt.</para>

    <indexterm><primary>Perl Taint-Modus</primary></indexterm>

    <para>Perl bietet eine wirklich coole Funktion, den sogenannten
      "Taint"-Modus, der verwendet werden kann, um zu verhindern,
      dass Skripte Daten, die von außerhalb des Programmes
      stammen, auf unsichere Art und Weise verwenden. Dieser
      Modus überprüft Kommandozeilenargumente,
      Umgebungsvariablen, Lokalisierungsinformationen, die
      Ergebnisse von Systemaufrufen
      (<function>readdir()</function>,
      <function>readlink()</function>,
      <function>getpwxxx()</function>)
      und alle Dateieingaben.</para>
  </sect1>

  <sect1 xml:id="secure-race-conditions">
    <title>Race-Conditions</title>

    <para>Eine Race-Condition ist ein unnormales Verhalten, das von
      einer unerwarteten Abhängigkeit beim Timing von Ereignissen
      verursacht wird. Mit anderen Worten heißt das, ein
      Programmierer nimmt irrtümlicher Weise an, dass ein
      bestimmtes Ereignis immer vor einem anderen stattfindet.</para>

    <indexterm><primary>Race-Conditions</primary>
    <secondary>Signale</secondary></indexterm>

    <indexterm><primary>Race-Conditions</primary>
    <secondary>Zugriffsprüfungen</secondary></indexterm>

    <indexterm><primary>Race-Conditions</primary>
    <secondary>Öffnen von Dateien</secondary></indexterm>

    <para>Einige der häufigsten Ursachen für
      Race-Conditions sind Signale, Zugriffsprüfungen und das
      Öffnen von Dateien. Signale sind von Natur aus
      asynchrone Ereignisse, deshalb ist besondere Vorsicht im
      Umgang damit geboten. Das Prüfen des Zugriffs mittels
      der Aufrufe <function>access(2)</function> gefolgt von
      <function>open(2)</function> ist offensichtlich nicht atomar.
      Benutzer können zwischen den beiden Aufrufen Dateien
      verschieben. Stattdessen sollten privilegierte Anwendungen
      <function>seteuid()</function> direkt gefolgt von
      <function>open()</function> aufrufen. Auf die gleiche Art
      sollte eine Anwendung immer eine korrekte Umask vor dem
      Aufruf von <function>open()</function> setzen, um
      störende Aufrufe von <function>chmod()</function> zu
      umgehen.</para>
  </sect1>
</chapter>