Sicherheit von C/C++



  • ~fricky schrieb:

    ja, aber es gibt noch viele andere fallstricke, wie z.b. integer-überläufe und dadurch ungewollte vorzeichenwechsel, usw. usw. die einem programm seltsame angewohnheiten entlocken können.

    Aber auch in Java und .NET. Hier drauf wurde ich durch "Beautiful Code" gestoßen:
    http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html

    @hustbaer: Was hat denn ein GC mit Sicherheit zu tun?



  • Bashar schrieb:

    @hustbaer: Was hat denn ein GC mit Sicherheit zu tun?

    Er kann bei Sicherheitsrelevanten Systemen verhindern, dass die Software aufgrund einen Speicherlecks den Dienst verweigert. Allerdings fragt sich wer auf solchen Systemen überhaupt dynamische Speicherverwaltung will. Mit "Hacker"-Sicherheit hat das aber auch nichts zu tun.



  • safety vs. security 🙂



  • Tim schrieb:

    Bashar schrieb:

    @hustbaer: Was hat denn ein GC mit Sicherheit zu tun?

    Er kann bei Sicherheitsrelevanten Systemen verhindern, dass die Software aufgrund einen Speicherlecks den Dienst verweigert. Allerdings fragt sich wer auf solchen Systemen überhaupt dynamische Speicherverwaltung will. Mit "Hacker"-Sicherheit hat das aber auch nichts zu tun.

    Ein GC (also im Grunde eine automatische, bzw. eine ueberwachte Speicherverwaltung) schliest schonmal den Hack-Angriff eines Buffer-Overflows aus. Bei einem Buffer-Overflow wird ja die Schwachstelle genutzt um Code einzuschleusen, der dann von der CPU ausgefuehrt wird. Wenn die Speicherverwaltung aber ueberwacht wird (wie es bei einem GC der Fall ist), dann kann man in einen Speicherbereich keinen Code injezieren.

    Aus Wiki:

    Durch letzteres kann die Rücksprungadresse eines Unterprogramms mit beliebigen Daten überschrieben werden, wodurch ein Angreifer durch Übermittlung von beliebigem Maschinencode beliebiege Befehle mit den Privilegien des für den Pufferüberlauf anfälligen Prozesses ausführen kann.

    Ausserdem, ein Programm das durch eine virtuelle Maschine ueberwacht wird kann auch weniger Schaden anrichten. Das ist im Grunde der gleiche Schutz (nur natuerlich um einiges schwaecher) wenn du z.B. Windows in VirtualBox laufen laesst. Das gleiche Prinzip verfolgt z.B. auch SELinux. Eine VM kann z.B. sicherstellen das ein Programm nicht auf die Festplatte schreiben darf oder das es systemkritische Funktionen ausfuehren kann.



  • DEvent schrieb:

    Ein GC (also im Grunde eine automatische, bzw. eine ueberwachte Speicherverwaltung) schliest schonmal den Hack-Angriff eines Buffer-Overflows aus. Bei einem Buffer-Overflow wird ja die Schwachstelle genutzt um Code einzuschleusen, der dann von der CPU ausgefuehrt wird. Wenn die Speicherverwaltung aber ueberwacht wird (wie es bei einem GC der Fall ist), dann kann man in einen Speicherbereich keinen Code injezieren.

    Bei einem Buffer-Overflow wird über die Grenzen eines Arrays hinaus geschrieben, das ist kein Speicherverwaltungsakt.

    Ausserdem, ein Programm das durch eine virtuelle Maschine ueberwacht wird kann auch weniger Schaden anrichten.

    Korrekt, aber VM != GC.



  • Bashar schrieb:

    safety vs. security 🙂

    😃



  • Hier ist auch was ganz interessantes dazu:
    http://www.sans.org/top25errors/
    Und hier ist "Failure to Constrain Operations within the Bounds of a Memory Buffer" aka Buffer Overflow
    http://cwe.mitre.org/top25/#CWE-119

    Das wuerde wohl Material fuer ein ganzes Semester liefern.



  • Tim schrieb:

    Bashar schrieb:

    @hustbaer: Was hat denn ein GC mit Sicherheit zu tun?

    Er kann bei Sicherheitsrelevanten Systemen verhindern, dass die Software aufgrund einen Speicherlecks den Dienst verweigert.

    Kann er leider nicht, da man auch mit GC wunderbare Leaks zaubern kann (ich sag' nur statische Maps/Listen, "unbeabsichtigte" GC-Roots etc.)

    Mit "Hacker"-Sicherheit hat das aber auch nichts zu tun.

    Doch, ein wenig.
    Wenn man von rein Funktionalen Sprachen mal absieht, ist ein GC die einzige Möglichkeit (*), garantieren zu können, dass ein Objekt, auf welches man zugreift, auch den Typ hat, den man erwartet.
    Das klingt jetzt komisch, aber wenn man genauer drüber nachdenkt, wird vielleicht klar wieso.
    Wenn ein nicht-GC Programm sagt "das brauch ich jetzt nimmer" (delete p;), dann wird der Speicher als frei markiert. Ganz egal, ob man noch woanders Zeiger/Referenzen auf diesen Speicher hat.
    Das System wird den Speicher also alsbald wieder hergeben, und das Programm wird munter andere Dinge damit anstellen. Wenn nun die "alten" Zeiger auf diesen Speicherbereich wieder verwendet werden, passieren Dinge, von denen man vermutlich nicht möchte, dass sie passieren.
    Gezielt ausnutzen lassen sich solche Bugs wohl schwer, aber ein System zumindest dazu zu bringen gröber Mist zu bauen, könnte durchaus manchmal drinnen sein, wenn man mal so einen Bug gefunden hat.

    Für die "Sicherheit" im Sinn von "Robustheit" hat ein GC dadurch allerdings einen dramatischen Einfluss.

    ----

    So, nun zum *: natürlich braucht man keinen GC in dem Sinn, aber man braucht ein System, welches sämtliche Referenzen "trackt", und verhindert, dass Speicher "mehrfach verwendet" wird. Wenn man sowas allerdings schonmal hat, ist der Schritt, einen GC draus zu basteln, nichtmehr weit.



  • ~fricky schrieb:

    hustbaer schrieb:

    Was Hack-Sicherheit angeht: in C und C++ kann man sehr leicht Programme schreiben die Sicherheitslöcher haben, z.B. "unchecked buffer".

    ja, aber es gibt noch viele andere fallstricke, wie z.b. integer-überläufe und dadurch ungewollte vorzeichenwechsel, usw. usw. die einem programm seltsame angewohnheiten entlocken können.

    Jo, klar gibt's noch haufenweise andere Dinge die man falsch machen/ausnutzen kann. Da steht ja auch "z.B." 😉



  • DEvent schrieb:

    Tim schrieb:

    Bashar schrieb:

    @hustbaer: Was hat denn ein GC mit Sicherheit zu tun?

    Er kann bei Sicherheitsrelevanten Systemen verhindern, dass die Software aufgrund einen Speicherlecks den Dienst verweigert. Allerdings fragt sich wer auf solchen Systemen überhaupt dynamische Speicherverwaltung will. Mit "Hacker"-Sicherheit hat das aber auch nichts zu tun.

    Ein GC (also im Grunde eine automatische, bzw. eine ueberwachte Speicherverwaltung) schliest schonmal den Hack-Angriff eines Buffer-Overflows aus. Bei einem Buffer-Overflow wird ja die Schwachstelle genutzt um Code einzuschleusen, der dann von der CPU ausgefuehrt wird. Wenn die Speicherverwaltung aber ueberwacht wird (wie es bei einem GC der Fall ist), dann kann man in einen Speicherbereich keinen Code injezieren.

    Nope, stimmt so nicht. Es gibt auch Systeme wo man einen GC hat, aber trotzdem Zeigerarithmetik. z.B. sämtliche Systeme die auf C oder C++ einen GC draufsetzen. Die meisten Sprachen mit GC kennen allerdings keine Zeigerarithmetik, und verwenden "bounds-checking" bei Array-Zugriffen. Solche Systeme verhindern dann den klassischen "unchecked stack based buffer" Exploit.

    Was immer noch nicht verhindert wird sind allerdings Fehler, wo man das System zwar nicht dazu bringt beliebigen Code auszuführen, aber immerhin dazu bringt irgendwas gröber falsch zu machen. Man kann ja z.B. auch innerhalb eines Puffers irgendwelche Grenzen haben, und vergessen, diese zu checken.



  • hustbaer schrieb:

    Tim schrieb:

    Bashar schrieb:

    @hustbaer: Was hat denn ein GC mit Sicherheit zu tun?

    Er kann bei Sicherheitsrelevanten Systemen verhindern, dass die Software aufgrund einen Speicherlecks den Dienst verweigert.

    Kann er leider nicht, da man auch mit GC wunderbare Leaks zaubern kann (ich sag' nur statische Maps/Listen, "unbeabsichtigte" GC-Roots etc.)

    Kann ich mir ehrlich gesagt gerade nichts drunter vorstellen. Magst mal ein konkretes Beispiel geben?



  • Bashar schrieb:

    ~fricky schrieb:

    ja, aber es gibt noch viele andere fallstricke, wie z.b. integer-überläufe und dadurch ungewollte vorzeichenwechsel, usw. usw. die einem programm seltsame angewohnheiten entlocken können.

    Aber auch in Java und .NET.

    das schon, aber da sind sie weitaus ungefährlicher. ein übergelaufener int als array-index oder pointer offset ergibt ein prima sicherheitsloch. ausserdem nehmen c++ progger auch gern mal 'int' obwohl sie eigentlich 'int32_t' meinen.
    🙂



  • hustbaer schrieb:

    Doch, ein wenig.
    Wenn man von rein Funktionalen Sprachen mal absieht, ist ein GC die einzige Möglichkeit (*), garantieren zu können, dass ein Objekt, auf welches man zugreift, auch den Typ hat, den man erwartet.

    Das reicht nicht aus, man muss auch wildes Casten a la C verhindern können. Aber du scheinst insofern recht zu haben, als dass ein GC eine notwendige Voraussetzung für (Typ-)Sicherheit darstellt.



  • Bashar schrieb:

    hustbaer schrieb:

    Doch, ein wenig.
    Wenn man von rein Funktionalen Sprachen mal absieht, ist ein GC die einzige Möglichkeit (*), garantieren zu können, dass ein Objekt, auf welches man zugreift, auch den Typ hat, den man erwartet.

    Das reicht nicht aus, man muss auch wildes Casten a la C verhindern können. Aber du scheinst insofern recht zu haben, als dass ein GC eine notwendige Voraussetzung für (Typ-)Sicherheit darstellt.

    Das denke ich nicht. Der springende Punkt ist nicht der GC sondern eine Laufzeitumgebung bzw. virtuelle Maschine.



  • buzz_lightzyear schrieb:

    Hallo,

    ich habe bis mittwoch einen Text über die Sicherheit von der Programmiersprache C/C++ zu schreiben. Mit Sicherheit ist denk ich mal "Hack-Sicherheit" gemeint.

    Leider habe ich keinen Plan was ich darüber schreiben soll. Hat irgendjemand einen Link zu besonderer Literatur was dieses Thema betrifft? die Uni-Bibliothek hilft hier auch nicht wirklich. Was würdet ihr über dieses thema schreiben? Bin für jeden Anhaltspunkt dankbar 🙂

    Lg
    b

    ES GIBT KEINE PROGRAMMIERSPRACHE MIT DEM NAMEN C/C++. ES GIBT EINE PROGRAMMIERSPRACHE MIT DEM NAMEN "C" UND EINE ANDERE MIT DEM NAMEN "C++".

    Und nun zum Thema: Keine der beiden Sprachen sind unsicher. Es sind höchstens die Programme, die ich mit der Sprache schreibe unsicher. Dann sind es aber Programmierfehler in dem Programm, aber nicht in der Sprache. Und Programmierfehler, die Sicherheitslücken verursachen sind in jeder Sprache möglich.

    Die Sprache C ist recht rudimentär und ist dadurch recht aufwändig, sichere Programme zu schreiben. Oft ist man beispielsweise bestrebt, feste Puffergrössen zu verwenden, die unter Umständen zu Pufferüberläufen führen. Eine solche Sicherheitslücke entsteht aber durch Bequemlichkeit und nicht durch die Sprache C.

    In anderen höheren Sprachen, wie beispielsweise C++ ist es einfacher, beispielsweise std::string oder std::vector zu nutzen. Sicher sind auch hier Pufferüberläufe und andere Programmierfehler möglich, aber einfacher zu verhindern.



  • tntnet schrieb:

    In anderen höheren Sprachen, wie beispielsweise C++ ist es einfacher, beispielsweise std::string oder std::vector zu nutzen.

    dumm ist nur, dass du in c++ auch alle fehler machen kannst, die in C möglich sind. was das angeht, kann der OP beide ruhig in einen topf werfen.
    🙂



  • hustbaer schrieb:

    Nope, stimmt so nicht. Es gibt auch Systeme wo man einen GC hat, aber trotzdem Zeigerarithmetik. z.B. sämtliche Systeme die auf C oder C++ einen GC draufsetzen. Die meisten Sprachen mit GC kennen allerdings keine Zeigerarithmetik, und verwenden "bounds-checking" bei Array-Zugriffen. Solche Systeme verhindern dann den klassischen "unchecked stack based buffer" Exploit.

    Du willst zum einen die Sicherheit einer Speicherverwaltung (GC), aber dann umgehst du diese mit Zeigerarithmetik? Natuerklich darfst du keine eigene Speicherverwaltung neben dem GC haben.

    hustbaer schrieb:

    Was immer noch nicht verhindert wird sind allerdings Fehler, wo man das System zwar nicht dazu bringt beliebigen Code auszuführen, aber immerhin dazu bringt irgendwas gröber falsch zu machen. Man kann ja z.B. auch innerhalb eines Puffers irgendwelche Grenzen haben, und vergessen, diese zu checken.

    Im schlimmsten Fall stuertzt also das Programm ab. Das ist um Dimensionen weniger Schaden als was mit injeziertem Code machen kann. Das Ziel eines Hackers ist es nicht deine Programme zum Absturz zu bringen, sondern die Kontrolle ueber deinen Computer zu erlangen.



  • tfa schrieb:

    Bashar schrieb:

    ein GC eine notwendige Voraussetzung für (Typ-)Sicherheit darstellt.

    Das denke ich nicht. Der springende Punkt ist nicht der GC sondern eine Laufzeitumgebung bzw. virtuelle Maschine.

    Angenommen, wir hätten eine VM ohne GC, und folgenden Code:

    SomeObject o = new SomeObject();
    o.machwas();
    delete o;
    // ... mehr Code
    o.machwas()
    

    Woher weiß die VM ohne GC, dass o nicht mehr auf dasselbe Objekt wie am Anfang verweist? Es könnte sein, dass das neue Objekt an der Stelle, auf die o verweist, vom Typ SomeObject ist, dann erkennt man das auch nicht durch Laufzeit-Typprüfung.



  • DEvent schrieb:

    Du willst zum einen die Sicherheit einer Speicherverwaltung (GC), aber dann umgehst du diese mit Zeigerarithmetik? Natuerklich darfst du keine eigene Speicherverwaltung neben dem GC haben.

    Zeigerarithmetik != Speicherverwaltung *gebetsmühle*

    Im schlimmsten Fall stuertzt also das Programm ab. Das ist um Dimensionen weniger Schaden als was mit injeziertem Code machen kann. Das Ziel eines Hackers ist es nicht deine Programme zum Absturz zu bringen, sondern die Kontrolle ueber deinen Computer zu erlangen.

    man DOS-Attacke

    Angriff etwa nach dem Schema: Ein für die Sicherheit einer Website notwendiges System wird zum Absturz gebracht. Anstatt dann aber das ganze Angebot einzustellen, wird (aufgrund Manager-Entscheidung) das System mit verringerter Sicherheit weitergefahren, bis die IT-ler das wieder zum Laufen gebracht haben.



  • ~fricky schrieb:

    dumm ist nur, dass du in c++ auch alle fehler machen kannst, die in C möglich sind. was das angeht, kann der OP beide ruhig in einen topf werfen.
    🙂

    Können ja, aber ich würde dennoch C und C++ nicht auf eine Stufe setzen (und auch als Sprache trennen). Wenn man C++ im Sinne der C++ Standardbibliothek etc. verwendet, kann man einige Fallstricke von C umgehen. Das man die gleichen Fehler machen kann, gerade wenn man meint C++ wie C zu programmieren, steht aber außer Frage...


Anmelden zum Antworten