Autor |
Beitrag |
mczero
Hält's aus hier
Beiträge: 1
Windows, von Zeit zu Zeit mal Linux Mint
Delphi 7, Lazarus
|
Verfasst: Fr 20.08.10 11:14
Hallo!
Ich bin neu hier und möchte mich kurz vorstellen bevor ich zum Thema komme..
Ich bin nun seit ca. 2 Monaten dabei, mir Delphi anzueignen, da ich es beruflich einsetzen werde. Zurzeit bin ich noch weit davon entfernt, ein echter Delphi-Profi zu sein, aber ich denke ich bin auf einem guten Weg. Zuvor hatte ich Kontakt mit C, PHP und JAVA. Allerdings stehe ich erst am Anfang meiner Laufbahn, und so habe ich in keiner der Programmiersprachen jahrelange Erfahrung. Darum verzeit mir bitte allzu dumme Fragen, ich verspreche die Suche zuvor zu nutzen bevor Fragen auftauchen, die vllt. jemand anderes zuvor schon beantwortet hat!
Nun zum Thema:
Sicherheit ist ja ein großes Thema. Schaut man sich an, welche Patches jeden Monat durch Microsoft ins Betriebssystem einfließt, wird einem klar, wie oft Sicherheitslücken in Form von Pufferüberläufen ausgenutzt werden.
Ich denke ich habe eine ungefähre vorstellung, was das ausnutzen eines Pufferüberlaufs bedeutet: z.B. ist dort eine Variable deklariert, die einen gewissen Rahmen hat, z.b. ein ShortInt, und jemand schafft es, einen größeren Wert in eine Komponente oder ein Programm einzuschleusen, als es ein ShortInt zulässt. Somit wird der "überstehende" Bereich in einen Speicherbereich geschrieben, der eigentlich gar nicht für die Variable vorgesehen war. Wenn der überstehende Bereich nun aus Assemblercode besteht und man es schafft, den Zeiger auf diesen Bereich zu verbiegen, dann wird der Code ausgeführt.
Ich selbst habe aber kein einziges Beispiel in Form eines Delphi-Codes. Nicht einmal eine vage Vorstellung, wie sowas Codemäßig aussieht. Ich würde einfach gerne einmal ein Beispiel sehen, ein ganz simples, und möchte mich selbst ein wenig auf "guten Programmierstil" sensibilisieren, sofern das bei Pufferüberläufen möglich ist.
Das heißt: einmal ein Beispiel wo eine Lücke vorhanden ist, und ein Gegenbeispiel, wo diese Lücke geschlossen wurde.
Hat jemand vielleicht ein solches Beispiel? Ich bin gespannt.
Ansonsten wünsche ich euch allen ein schönes Wochenende!
Gruß,
Tim
Moderiert von Narses: Überflüssige Zeilenumbrüche/Leerzeilen entfernt.
Moderiert von Narses: Topic aus Sonstiges (Delphi) verschoben am Fr 20.08.2010 um 14:25
Moderiert von Narses: Titel erweitert.
|
|
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Fr 20.08.10 11:34
Hallo und  in der Entwickler-Ecke,
Zuweisungen an ShortInt und andere einfache Typen sind kein Problem. Da kommt es dann zu einem Integerüberlauf, aber es wird kein falscher Speicher überschrieben. Das kann zwar auch doofe Auswirkungen haben, aber dürfte nicht direkt zu solchem Schweinkram führen.
Gefährlicher sind Operationen mit Arrays oder Strings, bei denen die Länge variieren kann. Ein Beispiel wäre sowas:
Du willst ein binäres Dateiformat einlesen. An einer Stelle steht ein Integer in der Datei, der die Länge des nachfolgenden Strings angibt. Laut Spezifikation des Formats darf die Länge nur 100 Zeichen sein, daher machst du sowas:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| var i: integer; s: String[100]; fs := TFileStream.Create('c:\meinedatei.abc', fmOpenread); fs.read(i, SizeOf(i)); fs.read(s[1], i); |
Wenn du eine manipulierte Datei bekommst, in der der Wert für i größer ist als 100, wird dann zuviel gelesen, und dabei Speicher überschrieben. Besser wäre dann sowas:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| var i: integer; s: String; fs := TFileStream.Create('c:\meinedatei.abc', fmOpenread); fs.read(i, SizeOf(i)); SetLength(s, i); fs.read(s[1], i); |
In der Regel stürzt das Programm bei sowas einfach ab. Wie sich das genau ausnutzen lässt, um beliebigen Code auszuführen, weiß ich nicht.
_________________ We are, we were and will not be.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 20.08.10 12:17
Zum Ausführen von beliebigen Code bedarf es ein wenig der Kenntnis der Speicherverwaltung von Programmen. Grundlegend gibt es da 3 Arten von Speicherbereichen:
1. Programmcode (read-only, executable)
2. Heap (read-write)
3. Stack (read-write)
Je nach dem, wo der Pufferüberlauf stattfindet, unterscheidet man zwischen Stack Overflows und Heap Overflows. Die Techniken, um diese auszunutzen variieren da immer ein wenig, laufen aber i.d.R. auf das Gleiche hinaus: Das Überschreiben von Rücksprungadressen.
@Gausi: Dein Code wäre nur mit extremen Heap Spraying exploitable ODER wenn Du SEHR VIELE kleine Objekte hättest. Daher nehm ich mal ein etwas anderes Beispiel.
Angenommen, du hast folgende Prozedur:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| procedure ReadSomething(File:HFILE); var I: Integer; Buffer: array[0..63] of Char; begin ReadFile(File, I, Sizeof(I)); ReadFile(File, @Buffer[0], I); end; |
(Mal kurz bei Gausi geklaut, um sein Beispiel zu nem Stack Overflow umzubauen. Bewusst schlechter Code-Stil)
DProblem ist wie gesagt auch hier der Puffer fester Größe, der, wenn I als eine Zahl größer 64 gelesen wird, garantiert überläuft.
Nun ist die Anordnung auf dem Stack etwa folgende (Low --> High): I, Buffer, Stackframe, Return Address, Variablen, Stackframe, Return Address, ...
Wenn ich nun erraten kann, wo zu diesem Zeitpunkt der Stack Pointer ist (und damit weiß, wo Buffer anfängt), kann ich beliebigen Code in die Datei schreiben.
Nehmen wir also an, in der Datei stehen 2 KB von Duke Nukem Forever. Um diese zu starten müsste der Angreifer lediglich nach den 64 Bytes der Puffer-Länge 8 Bytes präparieren: den Stackframe (der kann ignoriert werden; kann aber auch zum Initialisieren des EBP-Registers verwendet werden) und der Start-Adresse für DNF. Statt nun zurück zum Programm zu springen findet die CPU als Rücksprung-Ziel den Start von DNF ... und zockt da erstmal ne Runde
Bei Heap Overflows würde man nicht die Rücksprung-Adressen manipulieren, sondern die Einsprung-Adressen zu Methoden. Diese liegen da z.B. als Teil der Objekt-Beschreibung im Speicher und werden durch einen Zeige auf die VMT (Virtual Method Table) einer Klasse referenziert. Überschreibt man diesen Zeiger, kann man effektiv ne eigene VMT bereitstellen und beim nächsten Aufruf einer Methode eines Objektes, wird diese neue VMT angesprungen. Das ist übrigens die Technik, die man bei PHP so gern verwendet 
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Reinhard Kern
      
Beiträge: 591
Erhaltene Danke: 14
|
Verfasst: Fr 20.08.10 17:36
Hallo, ich würde eher schreiben
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| var i: integer; s: String[100]; fs := TFileStream.Create('c:\meinedatei.abc', fmOpenread); fs.read(i, SizeOf(i)); if i > 100 then i := 100; fs.read(s[1], i); |
und überhaupt einfach alles überprüfen, was von draussen kommt - Zahlen auf erlaubte Werte, aber auch Strings auf erlaubte Zeichen oder auf erlaubten Inhalt, das sind auch beliebte Angriffsmöglichkeiten, besonders in Kombination: bei Eingabe einer TCP/IP-Adresse könnte ein zu langer String eingegeben werden, der z.B. nach 192.168.178.001 noch eine Befehlssequenz enthält.
(Bei der Version mit setlength könnte man z.B. den string länger als den verfügbaren Speicher machen und so wenigstens das Programm abstürzen lassen, zumindest weiss ich nicht wieweit das zur Laufzeit abgesichert ist)
Gruss Reinhard
|
|
Boldar
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Fr 20.08.10 18:32
Reinhard Kern hat folgendes geschrieben : |
(Bei der Version mit setlength könnte man z.B. den string länger als den verfügbaren Speicher machen und so wenigstens das Programm abstürzen lassen, zumindest weiss ich nicht wieweit das zur Laufzeit abgesichert ist)
|
Dann gibts ne OutOfMemory-Exception. Na und?
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 20.08.10 19:16
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
|