Mailinglist Archive: opensuse-de (4731 mails)

< Previous Next >
Re: Mit sed Zeilenende loeschen
  • From: David Haller <david@xxxxxxxxxx>
  • Date: Thu, 19 Jul 2001 11:53:53 +0200
  • Message-id: <20010719115353.F28814@xxxxxxxxxx>
On Don, 19 Jul 2001, Bernd Brodesser wrote:
>* David Haller schrieb am 18.Jul.2001:
>> On Mit, 18 Jul 2001, Bernd Brodesser wrote:
>> >* David Haller schrieb am 18.Jul.2001:
[..]
>> >> $ mktemp /root/${prg}.$$.XXXXXX
>> >> Cannot create temp file /root/.12760.YTRUBd
>
>> >Ich mache meine Fehlermeldung lieber selber. Was soll der
>> >Endanwender mit obiger Meldung anfangen?
>
>> Du weisst ja auch nix genaues (Rechte, Disk voll, uebergeordnetes
>> Verz. existiert nicht)... Du weisst du dass es nicht geklappt hat
>> (mkstemp liefert nur 1 als exit-status).
>
>Das ist richtig. Aber wenn ich mktemp in einer Anwendung benutze,
>die wiederum von einem anderen Skript benutzt wird, dann kann der
>Endanwender nichts damit anfangen, daß mktemp nicht funktioniert.
>Welches mktemp?

mktemp(1).

Sollte via

  foo=`mktemp ...` || exit $?

klappen, wenn denn mktemp(1) mit exit(errno) aussteigen wuerde...
(was es leider nicht tut, aber IMO meist auch nicht noetig ist).

Und ein

Cannot create temp file /root/test.YTRUBd: Permission denied

waere IMO relativ aussagekraeftig, wenn das "Permission denied"
in der SuSE Version (und anderen) nicht weggepatcht waere...
(wobei das "Permission denied" dank strerror auf deutsch kaeme).

>Klar, allerdings, wenn es sich nur um so ein Miniwegwerfskript
>handelt, dann benutze ich erst gar nicht mktemp. Wenn es sich aber
>um ein Skript für den ständigen Gebrauch handelt, dann werde ich
>auch selber in einem Jahr nicht mehr wissen, wie und wo da mktemp
>benutzt wurde. Geschweige ein Anderer.

Ack. Mach ich ja auch ;)

>Ich meinte den XXXXX-Teil. Das mit der VORLAGE habe ich auch so in
>Erinnerung.

Siehe man 3 mkstemp. Da ist der Mechanismus mit dem XXXXXX erklaert.

>> >Wichtig ist doch, daß mktemp überprüft, ob der
>> >vorgeschlagene Dateiname schon existiert oder nicht. Wenn es das
>> >nicht tut, dann ist es nicht zu gebrauchen. 
>
>> Tut es. Es scheitert dann (bzw. mkstemp(3) scheitert und gibt
>> in errno EEXIST ("File exists" bzw. "Die Datei existiert bereits")
>> zurueck. Leider gibt die gepatchte Version von mktemp diese Fehler-
>> ursachen weder aus noch weiter (z.B. mittels 'exit(errno);')...
>
>Ägypten?

Kairo? (*nixblick*)

>Ich erwarte von mktemp, daß wenn es feststellt, daß der von
>ihm gewählten Namen schon existiert, einfach einen anderen nimmt.
>Solange bis es einen gefunden hat.

Genau _das_, das alternativen testen, macht keine der Funktionen
(bzw. mktemp(1)). Darum muss man sich selbst kuemmern. z.B. in
der bash mit:

while ! tmpfile=`mktemp vorlage.XXXXXX`; do : ; done

(ggfs. noch mit nem schleifenzaehler um irgendwann abzubrechen).

>> >> Kryptographisch "sicher" ist das IMO nicht.
>
>> >Was hat das mit Kryptographie zu tun? Auch wenn es echte
>> >Zufallszahlen sind, wird Gleichheit nicht ausgeschlossen. 
>
>> Naja, um die Gleichheit geht es auch nicht (es gibt fuer das
>> Muster immerhin 62^6 = 56.800.235.584 Moeglichkeiten). Das
>> Problem ist, wie das Muster erzeugt wird (d.h. mit welchem
>> Aufwand es zu vorherzusagen ist...) Und da ist das "clevere"
>> Schema das in __gen_tempname verwendet wird nicht sonderlich,
[schnippel]
>> Das "sicher" bezieht auf die Vorhersagbarkeit...
>
>Was ist schlimm an Vorhersagbarkeit? Was ich will ist
>Einzigartigkeit. Das ist wichtig. Wenn ich eine Datei temp1 nenne,
>die nächste temp2 usw. so ist das absolut vorhersehbar, aber es ist
>Einzigartig, genau das was ich will. Allerdings müßten alle
>Programme, die temporäre Dateien benutzen dieses Schema benutzen.

Das hat mir Wolfgang mal erklaert hat (IIRC im Zusammenhang mit meine
"toggle-a-attr", das IIRC anfangs auch ueber die Liste ging)... (s.u.)

>> Wolfgang koennte zu den Folgen der (von mir vermuteten Vorhersagbarkeit)
>> noch einiges mehr sagen...
>
>> Aber wie gesagt, ich denke, dass die (Nicht-)Vorhersagbarkeit von
>> __gen_tempname (und somit von mkstemp(3) und mktemp(1)) fuer die
>> meisten Faelle ausreicht (also schwierig genug ist)...
>
>Ich verstehe immer noch nicht, was da so schlimm dran sein soll. Was
>kann der Angreifer machen, wenn er weiß, wie die nächste temporäre
>Datei heißt? Er darf natürlich von Anfang an keine Schreibrechte
>darauf haben. Am Besten auch keine Leserechte. Wenn diese Datei
>schon existiert, wird sie nicht angelegt, sondern ein anderen Namen
>gewählt. Also kann der Angreifer da auch keine Fallen aufbauen. Habe
>ich da was übersehen?

Ja. Reingefallen. Wie ich auch... :)

Ein Szenario folgt (das aber, wie ich schrieb, fuer die meisten
Faelle wenig bis nicht relevant ist, aber wir reden hier ja inzwischen
um's Prinzip, oder? Darueber, dass mktemp in der Praxis (fast)
immer ausreicht sind wie uns glaub einig...)

Ach ja, ob und wie man das genannte Problem "remote" ausnuezten
koennte weiss ich nicht, Wolfgang wuesste da mehr, aber es waere
AFAIK moeglich sich als lokaler user (und somit ggfs. via einem
solchen auch remote) mit root-Rechten zu agieren (oder sogar diese
zu erlangen?)

>Vielleicht den kurzen Moment, der vom Test auf
>Existenz bis zur tatsächlichen Anlegung vergeht? Aber das Problem
>habe ich immer.

Ja. So in etwa....

- Angreifer erlangt "user-Rechte" auf einer Kiste (egal wie).

- A macht einen benchmark auf die Verzoegerung zwischen Aufruf
  von mktemp(1) und dem __gettimeofday [1] in __gen_tempname.
  Je ungenauer die tatsaechliche "Zeitaufloesung" auf der HW
  ist (in Bezug zu den Mikrosekunden die in __gen_tempname
  verwendet werde), umso einfacher wird IMO der Angriff.

- A schreibt einen exploit, der anhand der Voraussage der Latenz
  zwischen dem mktemp Aufruf und dem __gettimeofday sehr vereinfacht
  wird, und der (millonenfach) versucht die Ausgabe des __gettimeofday
  vorherzusagen.

- hat A einen "Treffer" erzielt ist die PID (via dem __getpid [2])
  trivial. Aus diesen Daten kann die Ausgabe von __gen_tempname
  vorhergesagt werden.

(Wobei die laenger dauernden Funktionen wie evtl. getpid natuerlich
passen vorverlagert werden muessen)

- A kann also mit einer hinreichenden Genauigkeit "voraussagen" was
  mktemp generieren wird (beim naechsten Aufruf generieren wuerde).

- A "weiss" den Namen der tempdatei bevor es der legitime Nutzer
  weiss.

- Zwei Moeglichkeiten:

  a) mktemp kann von A mit dem Parameter -u aufgerufen werden,
     der die tempdatei unlinkt (man 2 unlink).
     => ln -sf /etc/passwd tempfile
        und mktemp loescht fuer A /etc/passwd, dass A dann ganz
        nach Geschmack neu anlegen kann, oder wenn /etc/ passende
        Rechte hat, ist /etc/passwd auch nur einfach weg.
  b) A klinkt sich mit einem aehnlichen Angriff "mittenrein"
     in mktemp(1)/mkstemp(3)/__gen_tempname und kann ebenfalls
     beliebige Dateien so verlinken, dass er die Rechte daran
     hat (die Details weiss ich leider nicht mehr, bin mir aber
     recht sicher, dass das gehen wuerde).

Insgesamt ergibt sich, dass __gen_tempname (und somit mkstemp(3),
mktemp(1), und mehr noch mktemp(3)) nicht wirklich "sicher" sind,
auch wenn diese Sicherheit wohl fuer die meisten Faelle in der
Praxis ausreicht.

Aus man 3 mktemp:
BUGS
       Never use mktemp(). Some implementations  follow  BSD  4.3
       and  replace XXXXXX by the current process id and a single
       letter,  so  that  at  most  26  different  names  can  be
                                    ^^^^^^^^^^^^^
       returned.   Since  on  the  one hand the names are easy to
       guess, and on the other hand there is a race between test­
       ing  whether  the  name exists and opening the file, every
       use of mktemp() is a security risk.  The race  is  avoided
       by mkstemp(3).

Das ist eben nicht wirklich richtig, denn die "Race Condition" wird
nicht umgangen (avoided), sondern es wird nur um deutlich schwerer,
aber eben IMO laengst nicht unmoeglich, die Namen vorherzusagen.

Einmal dadurch, dass es potentiell 62^6 namen gibt (aber die PID
wird zur Erzeugung verwendet, wie genau hab ich nicht analysiert,
und die PID ist sozusagen "vorhanden", d.h. die eigentlichen
Moeglichkeiten werden um ein paar Groessenordnungen verringert).

Kurz und gut: Die Sicherheit von __gen_tempname (und abegeleitete)
beruht auf der Vorhersagbarkeit von __gettimeofday(), und die _ist_
vorherzusagen...

Wenn du das mit den Kommentaren am Anfang von
/usr/src/linux/drivers/char/random.c vergleichst, insbesondere, welche
wesentlich zufaelligeren Datenquellen im Vergleich zu __gettimeofday
verwendet werden, wirst du sehen, dass das _vergleichsweise_ unsicher
ist (auch wenn es fuer die meisten _praktischen_ Faelle ausreichen
sollte.

Ein "sicheres" __gen_tempname wuerde also nicht 64 bit aus
__gettimeofday + PID sondern 64 bit aus /dev/random verwenden,
das u.a. Tastatur(Taste, Zeitpunkt), Maus (Position, Klicks, Zeitpunkt),
HD (Zeit von IO ops), IRQs (Zeitpunkt) allgemein verwendet und mit
(wenn nicht) der beste Zufallsgenerator auf PCs ist.

Und nur, damit keine Missverstaendnisse aufkommen: Fuer (fast) alle
praktischen Anwendungen ist __gen_tempname (also auch mkstemp und
mktemp) sicher genug! Und auch die zeitliche Aufloesung von
__gettimeofday sollte fuer (fast) alle Anwendungen "reichen" um
zusaetzliche Sicherheit zu gewaehrleisten.

Leider bin ich weder in C noch in der Kryptographie bewandert
genung um auch nur eine Abschaetzung der Sicherheit (d.h. des
Aufwandes, um z.B. oben skizzierten Angriff durchzufuehren) zu
wagen...

Um nochmal zusammenzufassen:

Die (pauschale(!!!)) Aussage __gen_tempname (und somit mkstemp(3)
und somit mktemp(1)) sei "sicher" ist falsch!

Die Aussage __gen_tempname sei sicher _genug_ fuer *fast* alle
Anwendungen ist IMO richtig!

Und nochmal: Die "Eindeutigkeit" des erzeugten Muster ist mit
62^6 IMO gut genug, die "Schwaeche" ist die Vorhersagbarkeit des
Ergebnisses (egal in welcher Stufe, sei's noch innerhalb
von __gen_tempname, sei's in mkstemp(3) oder sei's in mktemp(1)).

Die "Guete" von 62^6 ist aber nur gleichzusetzen mit einer "Schluessel-
laenge" x von 35 bit < x < 36 Bit... Und das ist heutzutage kein Problem.
Und da gettimeofday quasi fuer jeden beliebigen Zeitpunkt im Voraus(!)[3]
berechnet werden kann (und die PID ein "piece of cake" ist)...

Hmm. Sowenig das ganze mit der Praxis zu tun haben mag (das kann und
will ich nicht beurteilen, ich bin kein Hacker und erst recht kein
Cracker), so hoffe ich doch, das "blinde" Vertrauen erschuettert
zu haben und, wie Wolfgang es bei mir in Sachen Race-Conditions etc.
generell tat, auch bei dir (und anderen?) ein gewisses, gesundes
Misstrauen und vielleicht auch Interesse an der Problematik geweckt
zu haben.

Ja, klar fuer die 08/15 Kiste ist sogar mktemp vielleicht schon
overkill, aber fuer Rechner, die sicher sein muessen, ist IMO
eine bessere Version von mkstemp (s.o., mit /dev/random) zu
verwenden...

Und ja, auf solchen Kisten, sollte man wohl die GNU libc sowieso nicht
verwenden ;)

-dnh

P.S: Ja, das "clever" in __gen_tempname hat mich stutzig gemacht...

PPS: Nein, ich bin kein Sicherheitsfetischist, ich hab weder eine
     Firewall am laufen noch einen aktuellen PGP/GPG Key...
     ABER: Ich denke ich habe eine gewisse Idee, wie unsicher meine
     Kiste ist... Und darauf kommt's IMO an, sich der Problematik
     bewusst zu sein.
     Da faellt mir ein Spruch ein, den ich leider noch nicht gesiggt
     habe und daher einfach mal sinngemaess auf deutsch statt auf
     englisch wiedergebe:

     "Das einzige sichere System, ist in einem Safe, in einem 10m^3
      Betonblock und versenkt im Marianengraben"

     Und ne "echte" sig, die dazu passt *eg*:

     The only truly safe "embedded system" is the system that has
     an axe embedded in it...                           -- Tanuki

[1] siehe man 2 gettimeofday, das __ kommt innerhalb der libc dazu
[2] man 2 getpid
[3] also mit "beliebigem" Aufwand

-- 
no amount of Zen contemplation will ever make you at one
with a 3c905B ethernet card.                 -- Alan Cox

< Previous Next >
Follow Ups