Daten verschlüsseln

OnDemand

Top Contributor
Hallo zusammen,

ich muss in meiner DB Daten speichern die ich nicht gern im Klartext haben will. Ich könnte im Code was einbauen um das zu verschlüsseln, soweit so gut.

Gibt es vielleicht noch eine SQL Variante wo ich sogar nachträglich bereits abgelegte Daten verschlüsseln kann ohne, dass ich im Code was machen muss? Bin der Meinung da mal was gelesen zu haben, dass es da eine Mysql Funktion gibt, aber bin mir nicht mehr sicher und finde dazu auch nix mehr.

Edit: das hier meinte ich
INSERT INTO secrets (content) VALUES (AES_ENCRYPT('das ist mein geheimnis', 'mCgCizeXzYrXXTvxrNmrIsKO8vdaFs3ZzTo7UcQ8mr+Q/6KIpJDMdgeKH57weCqLH5vJ6aquAuI='));

AES ist jetzt nicht soooo der bringer (aber besser als Klartext) jemand ne gescheitere Idee? BTW nutzte Spring boot, vielleicht gibts da ja schon was onboard, dass man daten verschlüsselt speichert und beim select automatisch entschlüsselt
 
Hab es jetzt so gelöst, dass die entsprechende Spalte ein LONGBLOB wird und die Attribute in der Entity wie folgt:
Java:
 @ColumnTransformer(
            read = "AES_DECRYPT(data_value, 'secret-......')",
            write = "AES_ENCRYPT (?, 'secret-......')"
    )
    private String dataValue;

Wer kennt sich aus? Würde so ggf. API Keys zu anderen System abspeichern, ist das halbwegs sicher? 100% Sicher ist wohl nur, die Daten nicht zu speichern. Aber wenn man wie API Keys, die Daten wieder decrypten muss find ich keine andere Lösung. Hash geht ja nur in eine Richtung.
 
Fragen:

1) Warum must du die Keys in der Datenbank speichern? Sind die dynamisch? Ansonsten gehören die in eine config Datei.
2) Was willst du damit erreichen wenn Du die Daten AES verschlüsselst? Wer soll es nicht lesen können? Wenn jemand Zugriff auf deine DB hat kann er sie so auch entschlüsseln da für AES kein Salt benutzt wird
3) Normalerweise sollte jede moderne Hardware ihre Dateien auf der Festplatte automatisch verschlüsseln. Ein Auslesen aus den Datenbank Dateien ist damit eh nicht möglich wenn der User nicht ordnungsgemäß als User auf der Maschine angemeldet ist. Welches Szenario schwebt dir also vor wo jemand ohne Zugriffsrechte die Schlüssel lesen kann?
 
Ich gehe mal davon aus, dass jemand irgendwie Zugriff auf die DB bekommt. Die API Keys sind dynamisch.

Szenarien:
1. Jemand kommt über phpMyAdmin und will die API keys haben ( aktuell API Key nicht lesbar da als LONGBLOB gespeichert)
3. Jemand kommt über Konsole an die DB und kommt an die API Keys

Der Key für das AES decrypten ist im Code und wird benötigt um die Longblobs zu entschlüsseln. Ok im Code ist vielleicht auch nicht sonderlich sinnvoll. (Muss ich mal schauen ob Spring Boot / JPA die irgendwo anders hinstecken kann).
Es erschwert aber definitiv schon mal das auslesen der Daten "mit normalem Wissen"
 
Generell kannst du nur versuchen, einem möglichen Angreifer möglichst viele Hürden in den Weg zu legen.

Die Dinge verschlüsseln (AES ist da btw. völlig ausreichend) hilft schon mal gegen einige Angriffe. Wenn jemand Zugriff auf den Web-Service hat, hat er natürlich dann auch Zugriff auf den Schlüssel oder die entschlüsselten Daten.

Dagegen hilft z. B., den Teil der den Schlüssel kennt, auszulagern, extra zu sichern, und nur "indirekt" zugreifbar zu machen, z. B. in dem der keine HTTP-Schnittstelle anbietet.
 
Vielleicht mal ein kleiner Einblick , etwas umfänglicher.

DB Server:
Externer Zugriff nur auf 2 IPs und localhost
SSH mit starkem PW geschützt (wollen wir noch auf IP beschränken, geht aber nicht so einfach weil der Provider wechselnde IPs hat mit denen er den Server managed)

"Haupt-Server"
Hier liegt eine zentrale Applikation drauf die auf die DB zugreift (dessen IP ist freigegeben). Diese nutzt JPA und kennt den AES-Key. (JPA und SQL Injection - geht das überhaupt wenn man die Repositories nutzt?

Die Haupt-App hat eine API nach aussen (mit Basic Auth abgesichert). Hier werde ich noch einbauen, dass ebenfalls nur unsere internen IPs drauf dürfen, da die API für Fremde nach außen nicht offen sein muss.

Um an die Daten zu kommen, müsste also jemand den DB Server hacken (vermutlich SSH oder über eine Lücke im OS?) und dann noch das mysql Passwort herausfinden.

Oder die Mysql Files abreifen. Die Sql Files dürften verschlüsselt sein, sehe ich das richtig? 1624716421309.png

Oder aber er kennt unsere API Endpoints und verbindet sich, dann müsste er stand jetzt das User + PW kennen (später noch durch IP gesichert) wirds ja nicht mehr möglich sein von aussen auf die API zu kommen.

Die Daten die ich mit AES sichern will, sind hauptsächer Userdaten wie deren Keys zu externen Systemen. Persönliche Daten wie Name, IBAN. Firmendaten (Adresse, Tel) stehen unverschlüsselt im Telefonbuch...das macht mE wenig Sinn.
GGF noch Email adressen der User ?
 
Moment mal, haben wir glaube ich. Ich hab die Keydatei gespeichert daher ist mir das gar nicht mehr so bewusst.
Login mit PW geht aber dennoch. Das lass ich gleich mal abschalten, danke für den Tipp 🙂
 
Alles in Allem ist das doch aber ein guter Plan oder gibts noch Verbesserungsvorschläge?
Hab da noch was gefunden, die anderen (internen) Services holen sich von der Haupt-App Daten und würden ohne https bekommen via API. Wenn die API aber nur auf 1 hört, halte ich das für ausreichend, was sagt ihr?!
 
Also ohne HTTPS finde ich eigentlich immer ein NoGo.

Für externe Zugriffe auf die API würde ich auf jeden Fall oAuth2 nehmen und nicht Basic-Auth auch wenn es deutlich mehr aufwand ist
 
Für externe Zugriffe auf die API würde ich auf jeden Fall oAuth2 nehmen und nicht Basic-Auth auch wenn es deutlich mehr aufwand ist
merk ich mir für unsere neue App vor, die wo wir grad verbessern ist eh nicht mehr so irre lange online. Da muss Basic noch reichen. Aber was glaubst du, wie viele andere Systeme Basic nehmen. Wir haben 6 fremde Systeme angebunden, alle nutzen Basic
 
Vielleicht eine Spinnerei, aber der Vorschlag von @mrBrown war ja ein separater Dienst für das Passwort. Vielleicht gibt es da ja auch was Fertiges, z. B. so wie KeePass.
Ich meinte nicht nur einen Service für das Passwort selbst, sondern ein vom Rest getrennter Service, der die Dinge, für die das Passwort nötig ist selbst macht, und das Passwort nie nach außen gibt 🙂

Wenn der Service von außen nur über SSH erreichbar ist, hat man nahezu alle Angriffsmöglichkeiten ausgeschlossen.

merk ich mir für unsere neue App vor, die wo wir grad verbessern ist eh nicht mehr so irre lange online. Da muss Basic noch reichen. Aber was glaubst du, wie viele andere Systeme Basic nehmen. Wir haben 6 fremde Systeme angebunden, alle nutzen Basic
Basic schützt auch nur die Client-Daten, deine eigenen Daten kann man damit nicht schützen – für reine M2M Kommunikation über HTTPS reicht Basic meist aus, Angriffsmöglichkeiten gibts da wenige.
 
Hm wie genau meinst du. Mein Main Service ist im prinzip nicht zu erreichen ausser jemand kommt per SSH und kopiert sich die jar Datei und reversed sie. Dann kommt er an den AES key, hat dann aber noch keine Info was er damit macht. Die DB Verbindungdaten liegen in Dateien da kommt nur der root User ran (der sich mit dem KeyFile per SSH einloggen muss)
 
Hm wie genau meinst du. Mein Main Service ist im prinzip nicht zu erreichen ausser jemand kommt per SSH und kopiert sich die jar Datei und reversed sie. Dann kommt er an den AES key, hat dann aber noch keine Info was er damit macht. Die DB Verbindungdaten liegen in Dateien da kommt nur der root User ran (der sich mit dem KeyFile per SSH einloggen muss)

"nicht erreichbar" heißt genau das - es gibt keine Möglichkeit den Service irgendwie direkt von außen anzusprechen, insbesondere nicht über HTTP.

Wenn SSH per public-key die einzige Zugriffsmöglichkeit ist, hat ein Angreifer keine realistische Möglichkeit.
 
über HTTP nur über unsere API (die ja aber nur an 2 IP antwortet) Dann müsste er den anderen Server oder meinen lokalen Rechner kapern.
 
Moment mal, haben wir glaube ich. Ich hab die Keydatei gespeichert daher ist mir das gar nicht mehr so bewusst.
Login mit PW geht aber dennoch. Das lass ich gleich mal abschalten, danke für den Tipp 🙂
BTW: wir haben alles abgeschaltet, was nicht benötigt wird. Man verliert zwar ggf. die Kompatibilität zu Clients und ist auch nicht mehr ganz SSH-konform, das ist aber dann Problem der Clients 🙂 Bei der Einrichtung orientieren wir uns an den Empfehlungen des BSI, ergänzen diese aber um weitere (z. B. Curve 22519 statt ECDH), setzen größere Schlüssel ein, nur DH-Gruppen 16 und 18 (4096, 8192 Bits) usw.
 
Hat jemand ne Idee, wie ich an der Stelle meine IP ausspucken kann? Scheint ne andere als localhost zu sein

Java:
@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .csrf().disable()
            .authorizeRequests().antMatchers("/**").hasIpAddress("127.0.0.1")
            .anyRequest().authenticated()
            .and()
            .httpBasic();
}

BTW: wir haben alles abgeschaltet, was nicht benötigt wird. Man verliert zwar ggf. die Kompatibilität zu Clients und ist auch nicht mehr ganz SSH-konform, das ist aber dann Problem der Clients 🙂 Bei der Einrichtung orientieren wir uns an den Empfehlungen des BSI, ergänzen diese aber um weitere (z. B. Curve 22519 statt ECDH), setzen größere Schlüssel ein, nur DH-Gruppen 16 und 18 (4096, 8192 Bits) usw.
ooookay das ist zu technisch, das interessiert bestimmt meinen Servermenschen 😀
 
Ich teste den API Zugriff auf eine Whitelisted IP zu beschränken (im og Code meine lokale IP). Auf einem Testserver klappts, bekomme nur Zugriff wenn ich von einer dort angegebenen IP komme. Lokal klappts nicht, hab scheibar keine 127.0.0.1 auf meinem lokalen Rechner.
 
Das ist klar, aber wenn ich von localhost auf localhost zugreife schon (App läuft zum test auf lokalhost) aber irgendwie macht meine Fritzbox/Mac einen hostnamen davor / dahinter wie auch immer.
 
Das hat mit deine fritzbox nichts zu tun.
Die ist da rarn nicht beteiligt.


Wenn du das brauchst willst musst du eine Weiterleitung bridge auf deinem Rechner erstellen.
 
hmm mein rechnername wird mir aber als mbp-fritzbox angezeigt zb in eureka (wo sich die services registrieren) in der hosts steht das auch drin.
merkwürdig
 
127.0.0.1 ist der lokale Rechner mit der Top-Level-Domain "localhost". Die Pakete laufen durch einen virtuellen Netzwerk-Adapter (Loopback-Adapter) und werden an den Rechner zurückgeschleift. Dein WLAN/LAN-Adapter hat eine andere Adresse z. B. 192.168.172.25 (wird ggf. per DHCP zugewiesen). In diesem Netz ist dann Dein Rechner als z. B. rechner.fritz.box bekannt. Der Host rechner.fritz.box hat die IP 192.168.172.25, während localhost 127.0.0.1 hat. Wenn eine Anwendung derart konfiguriert wird, dass sie nur auf 127.0.0.1 lauscht, dann werden Pakete aus dem FritzBox-Netzwerk nicht beantwortet.
 
Ja, wobei das nix mit der Namensauflösung zu tun hat. Die ist lokal konfiguriert. Ich weiß nicht, wie das beim Mac ist, unter Linux gibts unter /etc/nsswitch.conf eine Datei, in der die Reihenfolge festgelegt wird, z. B., dass zuerst in den Dateien gesucht, dann erst der DNS verwendet wird (Konfiguration in /etc/resolv.conf). In der Datei /etc/hosts finden sich dann z. B. die Einträge für localhost.
 
Hallo zusammen,

zum Thema nochmal eine Frage.

Ich speichere mit Hibernate AES verschlüsselt Daten ab. Wo könnte ich den Schlüssel hinterlegen ausser in der Annotation? Das könnte jemand reverseengeneeren vorausgesetzt er hat Zugriff auf die jar datei?

Java:
ColumnTransformer(
            read = "AES_DECRYPT(data_value, 'secret-......')",
            write = "AES_ENCRYPT (?, 'secret-......')"
    )
    private String dataValue;
 
Wo könnte ich den Schlüssel hinterlegen ausser in der Annotation?
Der Schlüssel ist auch im GIT-Repo sichtbar, "reverseengeneeren" ist also evtl. gar nicht notwendig. Solange der Schlüssel im Code steht gewinnt man leider keinerlei Sicherheit dazu wenn die Anwendung auf eine nicht gewollte Art und Weise benutzt wird. Ich denke vorteilhafter wäre es den Tablespace zu verschlüsseln oder die DB auf einem verschlüsseltem Storage zu betreiben. Die Berechtigungen zum Datenzugriff kann man z.B.: auf User-, Gruppen-, Rollen- oder API-Key-Ebene vergeben. Bei EE-DB's funktioniert das auch auf Spaltenebene. Es macht imho keinen Sinn für alle Daten den selben Schlüssel zu verwenden. Wenn ein Nutzer einmal Zugang zur Tabelle hat, dann kann er ja alle Daten entschlüsseln, nicht nur die, für die er auch berechtigt ist.
 
Ja stimmt :/

Es ist aber schon mal sicherer als die Daten unverschlüsselt zu speichern. Wenn jemand an die DB kommen sollte, kann er die Daten schon mal nicht auslesen.

Zugang wird ein User nicht bekommen, die DB ist von den eigentlichen Usern nicht zugänglich. Möchten es nur vor Datenklau schützen

An die DB kommen ist nur über folgende Wege möglich:
- SSH nur von 2 IP zugelassen
- DB Verbdindung nur von Localhost erlaubt
 

Zurück
Oben