[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [FYI] Bin?res XML -




Florian Weimer wrote:
> Kristian Koehntopp <kris@koehntopp.de> writes:
> > On Sun, Sep 21, 2003 at 04:47:44PM +0200, Florian Weimer wrote:
> >> Bei ASN.1 und den Encoding Rules hat man *eigentlich* die Chance, dass
> >> der Encoder solche Fehler nicht produziert.
> >
> > Äh. Ja.
> 
> Ich erwähnte schon, daß es an brauchbaren Implementierungen mangelt.
> Deswegen muß aber nicht das Konzept an sich unbrauchbar sein, nur
> etwas unpraktikabel.

Als Seitenlinie unserer Diskussion über ASN.1 bzw. binäres XML
und "die Folgen":

-----
http://www.heise.de/newsticker/data/pab-30.09.03-000/
Sicherheitslöcher in OpenSSL

"...
Diese Zertifikate sind nach der Abstract Syntax Notation (ASN.1)
aufgebaut und enthalten unter anderem die Namen des Austellers
(Issuer) und der Eigentümers (Common Name, CN). Manipuliert ein
Angreifer bestimmte ASN.1-Elemente, kann er damit den Dienst zum
Absturz bringen oder beliebigen Code auf den Stack schreiben und
ausführen.
..."

-----

Disclaimer: Ich habe mir die Patches nicht angesehen und kenne
die Natur der Fehler nicht. Die folgenden Gedanken sind
unabhängig von diesem konkrekten Problem.



Das Problem sind nie die korrekten Daten, sondern die defekten.

In ASN.1-Anwendungen kommt neben dem Binärformat noch was
anderes dazu: Widersprichlichkeit durch Überspezifikation. Wie
bereits erklärt, bestehen einige ASN.1-Codierungen im Prinzip
aus (Typkennung, Länge, Nutzdaten)-Tupeln. Auf diese Weise kann
ein lesendes Programm, das Typkennung nicht kennt, Länge Bytes
überspringen und hinter den Daten wieder aufsetzen.

ASN.1 kennt jedoch auch Containertypen, etwa Arrays oder
Structe. Hier sind die Nutzdaten selber wieder (Typkennung,
Länge, Nutzdaten)-Sequenzen. Es ist nun möglich, defekte
ASN.1-Pakete zu konstruieren, in denen die Summe der Längen der
Daten in einem Array nicht mit der angegebenen Gesamtlänge des
Containers übereinstimmt.

Das geht nur, weil ASN.1 an alles und jedes Längen dranschreibt,
anstatt Längen wie nicht-binäres XML implizit klar zu machen.

Array
12 Byte <- hier 10 oder 14 Byte angeben
 Integer
 4 Byte
 3

 Integer
 4 Byte
 0

 Integer
 4 Byte
 2


Stimmt die Längenangabe im Array nicht, könnte ein Reader, der
den Array-Typ nicht erkennt ("unwissender Reader", der ohne DTD
auf wohlgeformten ASN.1 arbeitet), auf der Längenangabe oder dem
Inhalt des letzten Integer wiederaufsetzen, während ein Reader,
der den Array-Typ kennt, die Integer einzeln parsed.

In XML ist die Länge wissenden und unwissenden Lesern sofort
und gleichermaßen klar:

<array>
 <integer>3</integer>
 <integer>0</integer>
 <integer>2</integer>
</array>


Ein wissender ASN.1-Reader kann sich auch nicht auf die
Längenangabe im ASN.1-Record verlassen, um Speicher zu
bestellen. Stünde dort "10 Byte" und er würde dann 3 Integer a 4
Byte lesen, hätte er zu wenig Speicher bestellt und würde
Strukturen überschreiben. Stünde dort eine sehr große Zahl oder
eine negative Zahl bestellt er entweder zu viel Speicher oder
haut sich wegen Vorzeichenüberlaufs mit negativen Offsets
sonstwo in die Pampa.

Auch dieses Problem tritt mit nicht-binärem XML prinzipbedingt
nicht auf, weil die Codierung wiederspruchsfrei ist (Beachte
jedoch, daß <array len="3" /> uns zu demselben Problem in XML
führt wie in ASN.1 - len="3" ist beim Parsen keine Angabe, der
ein Parser vertrauen könnte. Es interessiert nur, wie viele
Elemente das <array/> tatsächlich enthält, alles andere ist
Überspezifikation und ein Quell von Widersprüchen!)



Der "Vorteil" bei ASN.1 ist, falls man den Längenangaben
vertraut, daß man das Array vorallozieren und dann einmalig
durchlesen kann: Bestelle 12 Byte und haue dann dreimal ein
Integer da rein, es wird schon stimmen (Das kann man jedoch
billiger haben, siehe unten).

Vertraut man den Längenangaben nicht, ist ASN.1 schwieriger zu
parsen als nicht-binäres XML: Auch hier muß man bei Containern
sich den Anfang merken, den Container durchlesen um die Größe zu
bestimmen, Speicher bestellen, den Container tatsächlich
einlesen und dann weiter machen. Anders als bei nicht-binärem
XML muß man jedoch noch damit rechnen, daß die Offsets bei
verschachtelten Containern defekt sind und ggf. Backtracken.

Ein embedded Endgerät gewinnt mit keiner Datenstruktur. Hier
will man

00 00 00 17 00 00 00 03 00 00 00 00 00 00 00 02

übertragen. "17" ist eine "Message Type 17", von der das
Endgerät dann implizit weiß "12 Byte Nutzdaten" oder "kenn ich
nicht, gib auf, signalisiere Error", es dann statisch 12 Byte
Speicher bereitstellt und die Daten da ohne Parsen reinmapped.

Das hat aber mit ASN.1 noch mit XML was zu tun, sondern ist so
primitiv wie irgend möglich. Es ist auch am wenigsten
fehleranfällig, weil qmail-like die Datensätze genau gar nicht
geparsed werden. Mithin genau das, was man im Bereich embedded
eigentlich will.


Andere Protokolle haben diese Problemfamilie auch geerbt - im
Prinzip ist jedes Tunnelprotokoll für solche
Überspezifikationsprobleme anfällig. Wir haben solche Probleme
in der Vergangenheut an so unwahrscheinlichen Stellen wie in SMB
beobachten können. Hier werden DCE RPC Parameter in SMB Blöcken
in TCP/IP Paketen eingepackt und jede Kapselungsebene hat ihre
eigene Längenangabe mitgebracht. Es widersprechen sich
unterschiedliche SMB-Implementierungen (read: Windows-Dialekte
und Samba) darin, ob und wo Padding mit in die Länge eingeht
oder nicht. Dies kann im Zusammenhang mit Memoryallokatoren,
die Längenbytes aus den eingelesenen Daten glauben, zu
interessanten Effekten führen...


Hat sich jemand den OpenSSL-Patch einmal angesehen und kann
erklären, welche Problemklasse hier getriggert worden ist?

Kristian

-- 
To unsubscribe, e-mail: debate-unsubscribe@lists.fitug.de
For additional commands, e-mail: debate-help@lists.fitug.de