(SSL) gegen MITM absicher?

Ok, nach dem ich nun das Problem des langsamen Handshakes gelöst hab (hab dazu noch einiges im Netz gefunden nach dem ich erstmal wusste wonach ich suchen muss) kommt mir nun der Gedanke: Wie sichere ich mich gegen MITM ab?
Aktuell ist es so dass ich Cert von StartSSL nutze - da Oracle warum auch immer dieser CA nicht vertraut muss ich, wie schon mal gepostet, das CA zur Runtime laden und kann dann erst eine Verbindung herstellen. Nun ist es aber als Java-Bastler einfach einen Proxy dazwischen zu schalten und die Sicherung auszuhebeln: Das StartSSL-root-ca wird einfach gegen ein eigenes ausgetauscht und der Verbindungsaufbau dann einfach auf den Proxy umgebogen. Mein Client kann nun nicht erkennen dass die Verbindung umgebogen wurde da ihm ja ein gültiges CA vorliegt durch dass das cert des MITM akzeptiert wird.
Entweder hab ich PKI nicht verstanden oder dafür die allgemeine Schwäche: So lange ein Angreifer ein gültiges CA laden kann ist das System ausgehebelt (so scannt Kaspersky ja z.B. SSL-Verkehr in dem beim Setup das Kaspersky-CA installiert wird).
Dazu hat Java halt die allgemeine Schwäche: Jeder der mehr oder weniger Gut mit nem de-compiler umgehen und das Ergebnis verstehen kann kann daraus auch einfache Tools ableiten oder, soweit möglich, den Code halt anpassen und neu compilen.
Welche Schutzmaßnahme gibt es gegen sowas im Sinne von “den Aufwand so in die Höhe treiben dass es entweder nicht umkehrbar oder für einen Angreifer nicht lohnenswert ist”?
Ich denke auch dass Problem dürfte sein: So lange mein kein ordentliches DRM einbaut und (wenn auch für einen cent-Betrag) Lizenzen vergibt wird es bei Freeware einfach unmöglich Angreifer auszubremsen da sonst irgendwann die Blacklist-Datenbank aus allen Fugen quillt.

An der Stelle wird es aber schwierig, denn du brauchst für die Serverseite den privaten Schlüssel, den du nicht hast. Zumindest nicht von einer dem Zertifikatsspeicher des Clients bekannten CA.

Sobald du den privaten Schlüssel einer CA hast, kannst du natürlich für jede beliebige Domain ein Zertifikat ausstellen. Das ist nicht optimal, da ein Angreifer natürlich versuchen würde, sein eigenes Zertifikat „an den Mann zu bringen“. Solange dies aber nicht gelingt, ist das System sicher.

Das einzige was mir dazu einfällt, ist ein Obfuscator. Und selbst die Ergebnisse überzeugen nicht immer.

Moin,

wenn Alice und Bob via SSL kommunizieren, kann Mallory nicht dazwischen funken.

Mallory kann ohne Probleme Alice vortäuschen, das er Bob ist. Da Bob zwar einen eigenen Key erzeugt, dieser aber nicht öffentlich überprüft wird.

Mallory kann aber Bob nicht vortäuschen, das er Alice ist. Er hat zwar den öffentlichen Key und kann diesen ab Bob ausliefern. Nur hat er nicht den Privaten-Key mit dem er verschlüsseln muss. Sofern Bob nicht prüft ob mit dem richtigen Schlüssel verschlüsselt wurde, hat Bob ein Problem.

Mallory kann nur auf zwei Arten an den Schlüssel von Alice kommen. Vom Server klauen (oder ähnlichem Blödsinn) oder aus dem Public-Key berechnen.

Hmm, ich glaub ich hab mich falsch ausgedrückt oder wir reden aneinander vorbei.
Das Grundproblem ist wie gesagt dass das Root-CA von StartSSL weder im Oracle-JRE noch im OpenJDK-JRE vorhanden ist. Daher muss ich dieses zur Runtime selbst aus einem File laden. Was ich nun mit “root-ca-cert austauschen” meine ist dass jeder der sich halt einen Proxy basteln will genau dieses File einfach durch sein eigenes CA austauscht und damit mein Code dann nicht dass StartSSL-CA sondern das des Proxies läd. Somit fällt der MITM nicht auf. Und die Frage war halt nun wie ich mich genau gegen sowas sichern kann?
Bevor wer auf die Idee kommt, mir vorzuschlagen ein anderes CA zu nutzen was im JRE-keystore vorhanden ist: Man kann über einen bestimmten Parameter den TrustStore zum Start selbst bestimmen - gleiches Problem. Und hard-coden fällt auch flach - decompilen und mit anderem CA neu compilen.
Mir würde dann auch nur noch die Idee mit einem Obfuscator bleiben.

Wovon Du redest ist aber kein MITM.

Du redest vom modifizieren von Deinen Binarys durch Mallory. Das geht aber nur wenn Mallory zugriff darauf hat. Falls Bob sich Deine Files von Mallory besorgt, ist das Bob sein Problem.

Und Obfuscation hilft gegen Modifikation auch nicht. Das hilft nur gegen Script-Kiddies.

Das ist ja der Grund der Frage: Ich sehe noch nicht wirklich wie, unabhängig davon dass die eigentlichen class-Files durch de-compiling manipuliert werden können, SSL vor solchen MITM-Proxies schützen soll.

Wie @mogel schon sagte, eine manipulierte Binary ist kein MITM. Wenn die Binary kompromittiert ist, dann ist der Zug abgefahren. Da kann man nichts gegen machen. Im Zweifel wird die Überprüfung der Validität des Serverzertifikates in der Binary einfach deaktiviert. Dann kann ein beliebiger Lauscher einen MITM-Angriff durchführen.
Die Sicherheit kann man nur ein wenig erhöhen, indem man die Binary signiert. Das vermindert zumindest das Risiko, dass der Endanwender eine gefälschte Anwendung ausführt.

Hmm, soweit mir bekannt bringt es aber leider nichts ein JAR zu signieren und so vor Manipulation zu schützen. Begründung: Ein Angreifer kann den Inhalt des JAR einfach ins Dateisystem extrahieren (und ggf. in einem nicht-signierten neuen JAR wieder neu zusammenpacken) - damit ist dann auch dieser Schutz ausgehebelt.
Generell scheint mir das aber ein Grundsätzliches Problem von SSL zu sein: Wenn ich als Angreifer lokal auf meinem eigenen Rechner eine SSL-Verbindung aufbrechen will muss ich meinem System nur mein eigenes CA-cert als vertrauenswürdig installieren. Die Frage zielt halt auf die Frage ab wie genau ich sowas halt unterbinden kann. Oder vielleicht etwas konkreter ausgedrückt: Wie erhöhe ich den Aufwand mein Netzwerkprotokoll durch reverse engineering zu knacken so dass es sich für einen Angreifer nicht mehr lohnt?
Sicher, Script-Kiddies die halt “nur mal schnell cheaten wollen” kann man schon mit einigen einfachen Maßnahmen gut “aussperren”, aber für jemanden der sich etwas mehr mit der Materie befasst ist es immer noch ein leichtes.

Es sollen ja auch keine top-secret Daten übertragen werden - sondern ich will halt mit für mich möglichst geringem Aufwand verhindern dass jemand in die Kommunikation zwischen Client und Server eingreift (wobei dass auch keine all zu große Rolle spielt … der Server prüft ob die Commands des Clients überhaupt gültig sind und droppt die Verbindung bei ungültigen Daten … also alles was man durch Manipulation erreichen würde wäre ein sofortiger Disconnect).

Es muss doch möglich sein Code und Kommunikation so zu schützen dass der Aufwand diesen Schutz zu brechen für einen Angreifer unattraktiv/nicht mehr rentabel wird.

du bringst hier schon wieder SSL und MITM mit Binarys durcheinander - das sind zwei grundsätzliche Probleme. SSL ist sicher gegen MITM - Deine Binarys vor Manipulation nicht. Und gegen Letzteres gibt es keinen Schutz.

Darf ich dich mal fragen was du eigentlich machen willst?

Geht es wirklich um ein Spiel um cheaten zu erkennen und verhindern?

Denn im Normalfall reicht es wenn du in die Anwendung das RootCA von StartSSL integrierst, solange dein Anwender mit der von dir zur Verfügung gestellten Anwendung arbeitet, kann dein Anwender sicher sein, dass am anderen Ende nur du sitzt und durch SSL wird auch garantiert, dass kein MITM stattfindet.

Natürlich muss dein Anwender selbst dafür Sorge tragen, dass niemand einen Virus/Wurm auf seinem System einschleust, der deine Anwendung reverse engineered. Aber das kann dir bei einer Einfach en Client/Serveranwendung egal sein.

Solltest du aber eben z.B. ein System brauchen, das garantiert, dass deine Clientanwendung vom Anwender selbst nicht manipuliert wird (z.B. Cheat detection in Spiele) kann ich dir nicht viel raten. Denn durch revers engineering kann der Anwender eingeltich immer alles unterwandern. Siehe E-Sport bei CS oder LEague of Legends selbst die können Cheats oft nicht erkennen und haben sicher mehr Fachleute zur Hand als dieses Forum.

Schwermachen kann man es dem User aber schon durch gewisse Chellenge response verfahren zur Überprüfung ob das JAR noch immer gültig ist. z.B. Code einbauen der eine Checksumme des JARs berechnet und dieses an den Server sendet. um zu verhindern dass der User nur ein Replay einer früheren Antwort schickt, vl die checksumme nicht über das ganze JAR berechnen sondern dynamisch vom Server einen Bereich anfordern.

Wenn ich dich aber komplette falsch verstanden habe, kann ich dir gar nicht helfen

LG
AmunRa

@mogel
Es geht um folgendes: Um die Verbindung aufzubrechen würde es einem “Hacker” reichen mein ausgeliefertes JAR auszupacken - das .crt-File durch seine eigene CA zu ersetzen - wieder einzupacken und die Anwendung laufen zu lassen. Die Verbindung “umzubiegen” - also dass statt einer direkten Verbindung zu meinem Server vorher halt der SSL-Proxy durchlaufen wird - kann man mit JVM-Argumenten umsetzen.
Das Problem was sich nun ergibt: meine Anwedung hat nun keine Möglichkeit festzustellen dass es sich nicht um mein Zertifikat handelt - da es ja durch das eingeschleuste CA des Hackers dessen Zertifikat vertraut. Man muss sich also nun nicht mal die Mühe machen meine class-Files zu de-compilen und versuchen nachzuvollziehen was da abgeht - sondern kann den Traffic nun ganz einfach im Plaintext mitlesen und so einfach Replay-Attacken und ähnliches fahren. Dagegen schützt dann nur noch der Server-Code der halt prüft ob die übertragenen Daten zu diesem Zeitpunkt gültig sind.
@AmunRa
Das mit dem Challenge-Response-mäßigem Hashen über einen zufälligen Bereich des Jar ist auf jeden Fall eine sehr geniale Idee. Da ja auch vorgesehen ist in regelmäßigen Abständen die beteiligten Jar-Files immer mal wieder durch neue Versionen zu ersetzen würden auch Replay-Attacken schwer (außer irgendwer macht sich die Mühe für die Ranges ne Rainbow-Table zu basteln) - aber da kann man ja dann auch z.B. mit verschiedenen Hash-Algos variiren um da gegenzusteuern.

Wie gesagt: Es soll halt auch nicht vorrangig darum gehen “Missbrauch” des Protokolls zu entdecken oder gar zu verhindern - sondern einfach die Schwelle die es braucht um halt die Verbindung erfolgreich aufzubrechen soweit anzuheben dass es sich halt für den Angreifer schlicht nicht mehr lohnt.
Klar, wer will und über Wissen verfügt wird lediglich mehr Zeit brauchen, aber ich hoffe dass es halt einfach viele schon davon abhält die sich halt den Aufwand nicht machen wollen.

wie Dir schon von mehreren geschrieben wurde - SSL ist sicher. Was Du verhindern willst ist eine Modifikation der Binarys - dagegen gibt es keinen (erfolgreichen) Schutz. Du kannst es höchstens mit Webstart ausliefern. Aber auch das hilft nur bedingt.

@Sen-Mithrarin

[quote=Sen-Mithrarin]Wie gesagt: Es soll halt auch nicht vorrangig darum gehen “Missbrauch” des Protokolls zu entdecken oder gar zu verhindern - sondern einfach die Schwelle die es braucht um halt die Verbindung erfolgreich aufzubrechen soweit anzuheben dass es sich halt für den Angreifer schlicht nicht mehr lohnt.
Klar, wer will und über Wissen verfügt wird lediglich mehr Zeit brauchen, aber ich hoffe dass es halt einfach viele schon davon abhält die sich halt den Aufwand nicht machen wollen.[/quote]

Die Frage die für mich noch unbeantwortet bleibt ist, welchen Angreifer du meinst?
A) Der Klassische “man in the middle” der weder den Client Computer noch den Server kontrolliert, sondern nur sich in das Netzwerk zwischen beiden hängen kann (z.B. Public unencrypted WLAN):
Diesen Typ kannst du mit SSL und eben dem von dir mit ausgelieferten root-Zertifikat von StartSSL garantiert verhindern. Für dieses Szenario ist SSL garantiert sicher und nur für dieses Szenario wurde SSL konzipiert.

B) Der Hacker der deine JAR manipuliert: Wie in meinem oberen Beitrag erwähnt gibt es hiergegen keinen wirklich hundert prozentigen Schutz. In diesem Zusammenhang ist aber eben immer die Frage wovor willst du dich Schützen? (Vl kannst du die frage wirklich hier öffentlich beantworten) Geht es dir darum, daten auf deinem Server zu schützen, oder willst du verhindern, dass dein Client Anwender blödsinn baut.
Wenn ein Anwender Word umschreibt (reverse engineered) sodass immer wenn er den Buchstaben a drückt ein b ins word Dokument geschrieben wird, so ist das Microsoft ziemlich egal und sie werden sich nie dagegen wehren. Wenn es dir aber darum geht, dass keine ungültigen Daten auf deinem Server landen, dann kann diese Sicherheit nur auf dem Server selbst garantiert werden. Hier stellt sich wieder die Frage warum ist es dir so wichtig, dass die Daten die du empfängst tatsächlich von deiner Binary kommen und nicht von einer anderen?

tldr;
Bitte beschreibe nochmal warum es für dich wichtig ist, dass deine binary nicht verändert wird. Eine Allgemein gültige Antwort (z.B. Nutze diese und jene Technik dann ist das Problem behoben) gibt es nicht, aber vl. wenn wir deinen Use Case kennen, können wir dir einen geeigneten Weg für genau dein Problem geben (bzw. interessante Denkanstöße geben).

LG

Ok, vielleicht versuche ich mal auf die Frage “Wo vor schützen?” zu beantworten:
Nehmen wir eine beliebige Anwendung X die über eine mehr oder weniger einfache oder komplexe Verbindung mit einem Server kommuniziert. Nun ist es mein Bestreben die Daten nicht im Klartext zu übertragen um so einfaches Mitlesen z.B. mit Wireshark zu verhindern.

Nach einigem Hin und Her und eigenen Codes (mit teils schweren Sicherheitslücken) und Ausprobieren und dann endlich mal durch Zufall auf die Lösung kommen habe ich mich nun für die in Java-SE eingebauten SSL-Klassen entschieden.

Unabhängig davon wie ich jetzt die Verbindung aufbaue, also darauf angespielt dass ich halt das Root-CA von StartSSL zur Runtime nachladen muss da es halt nicht im Standard-KeyStore vorhanden ist, ist mir folgendes Aufgefallen: Genau wie ich kann jeder, sei es durch Start-Optionen der VM oder austausch des CA-Files, (s)ein beliebiges CA laden, so dass die Verbindung als “sicher” eingestuft und aufgebaut wird.

Das jedoch ermöglicht nun auch eine große Sicherheitslücke: das Aufbrechen der eigentlich sicheren Verbindung durch einen MITM-Proxy und so wieder plaintext-Zugriff auf die Verbindung.

Die Frage zielt nun darauf ab: Ob, und wenn ja: wie, es möglich ist sich dagegen abzusichern? Wie kann ich also meinen Code der sich um die Verbindung kümmert designen dass es einem potentiellen Angreifer im Sinne von “lokaler Hacker” nur schwer möglich ist in diesem Prozess einzugreifen. Die angesprochene Möglichkeit des obfuscaten wäre sicher drin, und ein Root-CA mal eben “hardcode als String” durch obfuscation “verstecken” geht zwar auch und dürfte die meisten “Script-Kiddies” schon mal vor eine schwere Aufgabe stellen. Aber wer genug wissen und einen guten de-compiler und de-obfuscator bedienen kann - für den dürfte es keine all zu große Hürde werden das nötige File wieder sinnvoll herzustellen und das CA auszutauschen.
Da kam dann noch der Ansatz des range-hashes über das Jar. Das dürfte schon eine gute Absicherung sein, vor allem da man mit verschiedenen Hash-Funktionen auch stark variieren und somit eine mögliche Rainbow-Table stark erschweren kann. Wobei, wer gut ist wird auch das recht schnell herausbekommen und parallel ein original-File liegen haben an das dan delegiert wird.

Ich hoffe das die Frage jetzt etwas deutlicher wird.

Hint: Ich hab noch von Jar2Exe 1.8 ne gecrackte Version rumgeistern mit der man sehr gut die eigentlichen Daten vor Zugriff schützen kann (aus dem sonst bei Launchern zusammengesteckten ZIP wird dann durch weiteres crypto-Zeugs mit passenden Loadern für den Laien ein fast nicht knackbares Stück Code erzeugt (sicher, der Key und der Algo stehen ja auch drin - aber erstmal rausbekommen)), würde mich aber auf Windows limitieren (zu mal die Nutzung auf Grund nicht rechtmäßiger “Lizenz” eh fragwürdig wäre"). Und einen anderen freien Launcher der so ein Feature anbietet kenn ich leider nicht (was bei nem opensource-Projekt auch nicht gerade sinnvoll wäre weil sonst nur der zusätzliche Schritt drin wäre sich durch den source zu wühlen um rauszufinden wo im end-“Produkt” die nötigen Infos zu finden sind).

Die Frage, warum es für dich wichtig ist, dass die Binary nicht verändert werden darf, hast du immer noch nicht beantwortet. Wo ist das Problem, wenn der Datenverkehr mitgelesen wird?
Wenn der Traffic geheim bleiben muss, dann schafft das “security by obscurity”. Und wie hinlänglich bekannt, ist das keine echte Sicherheit.

Im Normalfall ist dein Anwender selbst dafuer verantwortlich sein System durch Virenschutzsoftware und regelmäßigen Updates vor Eindringlingen zu schützen. Ich sehe das nicht als Aufgabe des Softwareanbieters. Das selbe Problem haben ja Banken mit Internetbanking auch. Sobald ein Angreifer sein eigenes Root Zertifikat im Browser installiert, kann die Bank selbst auch nicht mehr verhindern, dass der Anwender auf eine gefälschte Seite umgeleitet wird. Der Schutz dass trozdem der Bezahlvorgang nicht umgeschrieben werden kann, liegt darin dass sie zu Autorisierung des Zahlvorgang einen Out of Band channel verwenden.

Mir fällt eigentlich außer Spiele jetzt kein wirklicher Grund ein, weshalb die Anwendung selbst nicht vom Anwender selbst manipuliert werden duerfte. Wie zuvor bereits erwaehnt ist der schutz der Manipulation durch einen Außenstehenden Dritten nicht die Aufgabe der Anwendung selbst, sondern Aufgabe eines Virenschutzes bzw. ähnlichen Programmen wie rkhunter.

Bei spiele halt deshalb, weil Aimbots in CS z.B. den Spielverlauf fuer Andere derart beeinträchtigen, dass andere mögliche Spieler vergrault werden und daher Geldverlust fuer die Firma droht.

[QUOTE=cmrudolph]Die Frage, warum es für dich wichtig ist, dass die Binary nicht verändert werden darf, hast du immer noch nicht beantwortet. Wo ist das Problem, wenn der Datenverkehr mitgelesen wird?
Wenn der Traffic geheim bleiben muss, dann schafft das “security by obscurity”. Und wie hinlänglich bekannt, ist das keine echte Sicherheit.[/QUOTE]

Kurz: Um mein geistiges Eigentum vor unbefugtem Zugriff zu schützen. Der vor Manipulation des Datenverkehrs ist dabei eher zweitrangig, da wie gesagt vom Server validiert wird.

Yea, Java Obfuscator bringt nur 10 % Sicherheit. 90 % Sicherheit hättest du, wenn du eine .exe mit Java 1.3-kompatiblen GCJ erstellst, selber ein simples Programm ist dann schon ~ 5 MB groß und es gibt wirklich nicht viele, die das dann „untersuchen / unter die Lupe nehmen“ können.
Den GCJ gibt es für viele Plattformen.

Sonst kann ich nicht so viel zum Thema beitragen…

Naja, war mir schon klar, da halt, wie wir alle wissen, an irgend einem Punkt der VM verständliche Daten vorliegen müssen.
Ich hätte halt nur nicht gedacht das man SSL so dermaßen leicht knacken kann. PKI hin oder her - aber so lange ich als Hacker meinem System nur klar machen muss: “So, alles was mit Key X signiert ist ist auch ok.” und mir dann jedes Analysetool offen steht da ich mich bewusst als MITM zwischenklinken kann bringt das halt alles nichts.
Ist einfach nur krass was man so mitbekommt wie einfach viele Schutzmaßnahmen zu umgehen sind so lange es keine zweite externe Stelle gibt.
Klar: einen Kanal zu sichern damit auf dem Weg zwischen A und B keiner mitlesen kann ist zwar toll, aber es nervt dann doch wenn man bei ner Runde Monopoly damit griefen kann in dem man nicht nur ein mal einen Trade anfragt sondern zig 1000 mal, was ja ohne die Regel “Je Runde nur je ein Trade je Mitspieler.” sogar eine ligitime Aktion darstellt.

Das kann man auch nicht… Wurde im Verlaufe des Threads aber auch schon gefühlte 25x gesagt.