Tag Javascript

  • Javascript Local Storage

    Es gibt eine große Zahl gruseliger APIs (also: „Kram, den ein Programm tun kann“) in modernem Javascript, von Sensor APIs (zur Abfrage von Beschleunigung und Orientierung des Geräts und des Umgebungslichts) bis Websocket (mit dem weitgehend beliebige Server dauernd mit dem Client reden können, und das auch noch „im Hintergrund“ in Web Workers) – gruselig ist das, weil in aktuellen und nicht weiter modifizierten Browsern jede Webseite dieses Zeug nutzen kann, wobei eingestandenermaßen ein paar besonders dramatische APIs (Mikrofon und Kamera z.B.) noch durch Rückfragen abgesichert sind. Oh: Webseiten können das nicht nur nutzen, viel zu viele brauchen Javascript und gehen nicht, wenn mensch es abdreht.

    Der breite Zugriff auf fast alles von Javascript aus ist der Grund, warum ich des Öfteren ziemlich unwillig auf „please enable Javascript“-Banner (und noch mehr auf ihre Abwesenheit trotz Abhängigkeit von Javascript) reagiere. Javascript erlauben bedeutet spätestens seit XMLHTTPRequest (mit dem Javascript an der NutzerIn vorbei mit dem Ursprungsserver kommunizieren konnte; kam in der ersten Hälfte der Nullerjahre) und CORS (was XMLHTTPRequest und jetzt fetch auf beliebige Server ausweitete, solange die kooperieren; im Firefox tauchte das 2009 auf) einen recht weitgehenden Zugriff auf die eigene Maschine zu erlauben, und das noch ganz ohne Spectre und Freunde – die übrigens ohne ubiquitäres Javascript auf privaten Rechnern weitgehend bedeutungslos wären.

    Eine API, die ziemlich gruselig ist, weil sie Webseiten ein unendlich langes Gedächtnis in eurem Browser gibt, ist Local Storage; damit können Webseiten ernsthafte Datenmengen in eurem Browser speichern und sie wiederfinden, wenn sie das nächste Mal Javascript ausführen dürfen. Dass das zunächst lokal gespeichert wird, hilft nicht viel – per Websocket oder zur Not einem fetch mit Payload ist der Kram auch (wieder) auf jedem Server, der bereit ist, sich das anzuhören. Wohlgemerkt: ohne dass NutzerInnen irgendwas mitbekommen.

    Wenn ihr mein Gruseln nachfühlen wollt, könnt ihr hier mal Javascript einschalten (ihr lasst mich doch sonst kein Javascript ausführen, oder?). Ihr bekommt dann unter diesem Absatz ein Eingabefeld, in das ihr Kram tippen könnt. Wenn ihr einen hinreichend modernen Browser habt (technisch: er muss das storage-Signal schicken; Firefox 78 tut das z.B., Webkit 4.0.37 nicht), könnt ihr eure Nachricht in der Javascript-Warnung am Fuß der Seite sehen, schockierenderweise auch in anderen Fenstern, die ihr auf blog.tfiu.de offen habt. Auf allen halbwegs aktuellen Großbrowsern erscheint der Text jedenfalls nach dem nächsten Reload. Und bleibt auch da. Aufauf, schreibt eurem künftigen Selbst eine Nachricht in den Fuß dieser Seite:

    Gut. Du hast Javascript aus.

    Nennt mich paranoid, aber lustig ist das nicht.

    Und so ärgern mich noch viel mehr als Seiten, die Javascript fordern, Seiten, die ohne Local Storage leer bleiben oder sonst irgendwie undurchschaubar kaputt gehen.

    Was tun?

    Für die großen Browser gibt es allerlei Erweiterungen, die das Management von Local Storage erlauben; im Firefox sehe ich gerade Forget Me Not oder StoragErazor (was gleich noch die IndexedDB-API mit abdeckt, die ähnlich schrecklich ist, aber noch nicht viel genutzt wird); soweit ich erkennen kann, erlaubt das unverzichtbare noscript nicht, Javascript ohne Local Storage laufen zu lassen.

    Für meinen Haupt-Browser, den Luakit (verdammt, schon wieder ein Link von hier in github rein), habe ich eine kleine Erweiterung geschrieben, mit der ich mit der Tastenkombination ,tq schnell local storage ein- und ausschalten kann; auf die Weise kann ich normalerweise ohne Local Storage browsen, wenn dann aber mal wirklich eine Seite kaputt ist (gitlab ist da derzeit so ein ganz schlechtes Beispiel), braucht es nur ein paar Anschläge. Eine Anzeige in der Fußleiste (q/Q für Storage aus/an) kommt auch mit:

    -- Web storage control
    
    -- @module webstorage_control
    -- @copyright Public Domain
    
    local _M = {}
    
    local window = require("window")
    local theme = require("theme")
    local settings = require("settings")
    local modes = require("modes")
    local add_binds = modes.add_binds
    
    function update_webstorage_disp(w)
        if settings.get_setting("webview.enable_html5_database") then
            w.sbar.r.webstorage_d.text = "Q"
        else
            w.sbar.r.webstorage_d.text = "q"
        end
    end
    
    function toggle_local_storage(w)
        local local_storage_enabled =
            settings.get_setting("webview.enable_html5_database")
    
        settings.set_setting("webview.enable_html5_database",
            not local_storage_enabled)
        settings.set_setting("webview.enable_html5_local_storage",
            not local_storage_enabled)
        update_webstorage_disp(w)
    end
    
    window.add_signal("init", function (w)
        local r = w.sbar.r
        r.webstorage_d = widget{type="label"}
        r.layout:pack(r.webstorage_d)
        r.layout:reorder(r.webstorage_d, 1)
        r.webstorage_d.font = theme.font
        update_webstorage_disp(w)
    end)
    
    add_binds("normal", {
        { "^,tq$", "Enable/disable web local storage", toggle_local_storage},
    })
    
    return _M
    
    -- vim: et:sw=4:ts=8:sts=4:tw=80
    

    Wer auch den luakit verwendet, kann das nach .config/luakit/webstorage_control.lua packen und dann:

    require("webstorage_control")
    

    an geeigneter Stelle (z.B. in .config/luakit/rc.lua) unterbringen. Wenn dermaleinst so viele Seiten ohne Local Storage kaputtgehen wie derzeit ohne Javascript, müsste das wahrscheinlich eher wie in der noscript-Erweiterung automatisiert werden.

    Auch wenn ich mal Local Storage erlaube, will ich natürlich nicht, dass der Kram persistent bleibt. Deshalb habe ich noch folgendes kleine Python-Programm geschrieben:

    #!/usr/bin/python
    """
    Clear luakit web local storage and cookies
    
    There's a whitelist applied to both.
    """
    
    
    import fnmatch
    import glob
    import os
    import re
    import sqlite3
    
    
    class Whitelist:
        """A fnmatch-based whitelist.
    
        Test as in "domain in whitelist".  It's not fast, though.
        """
        def __init__(self,
                src_path=os.path.expanduser("~/.config/luakit/cookie.whitelist")):
            with open(src_path) as f:
                self.patterns = [s.strip() for s in f.read().split("\n")]
    
        def __contains__(self, domain):
            for pattern in self.patterns:
                if fnmatch.fnmatch(domain, pattern):
                    return True
            return False
    
    
    def clear_cookies(whitelist):
        """removes cookies from domains not in whitelist from luakit's
        cookies db.
        """
        conn = sqlite3.connect(
            os.path.expanduser("~/.local/share/luakit/cookies.db"))
    
        try:
            all_hosts = list(r[0]
                for r in conn.execute("select distinct host from moz_cookies"))
            for host in all_hosts:
                if host in whitelist:
                    continue
                conn.execute("delete from moz_cookies where host=?",
                    (host,))
        finally:
            conn.commit()
            conn.execute("VACUUM")
            conn.close()
    
    
    def try_unlink(f_name):
        """removes f_name if it exists.
        """
        if os.path.exists(f_name):
            os.unlink(f_name)
    
    
    def clear_local_storage(whitelist):
        """removes luakit's local storage files unless their source
        domains are whitelisted for cookies.
        """
        for f_name in glob.glob(os.path.expanduser(
                "~/.local/share/luakit/local_storage/*.localstorage")):
            mat = re.match("https?_(.*?)_\d+.localstorage",
                os.path.basename(f_name))
            if not mat:
                print("{}???".format(f_name))
                continue
    
            if mat.group(1) in whitelist:
                continue
    
            try_unlink(f_name)
            try_unlink(f_name+"-shm")
            try_unlink(f_name+"-wal")
    
    
    def main():
        whitelist = Whitelist()
        clear_cookies(whitelist)
        clear_local_storage(whitelist)
    
    
    if __name__=="__main__":
        main()
    

    Das Programm liest eine Liste von Shell-Patterns (also etwas wie *.xkcd.com) aus einer Datei ~/.config/luakit/cookie.whitelist und löscht dann alle Cookies und Local Storage-Einträge im Luakit, die nicht von Servern kommen, die in dieser Ausnahmeliste erwähnt sind. Das Ganze läuft bei mir jeden Morgen aus meiner Crontab:

    01 09 * * * ~/mybin/clear_luakit_cookies.py
    

    Aber: Besser wärs, das wäre alles nicht da. In einem Browser, also etwas, mit dem mensch Webseiten anschauen will, hat eine API wie Local Storage mit Persistenz und Signalisierung eigentlich nichts verloren.

    Oh: Der Javascript-Quellcode für den ganzen Spaß mit euren Notizen in der Fußzeile ist erschreckend klein. Für den Fall, dass ich das mal anders schreibe und das so nicht mehr im Seiten-Quellcode zu finden sein wird, hier zunächst der Code für das Eingabefeld oben:

    <div id="textarea-container">
      <p><em>Gut.  Du hast Javascript aus.
      </em></p>
    </div>
    
    <script deferred="deferred">
      function setUp() {
        document.querySelector("#textarea-container").innerHTML =
          `<textarea id="to-store" style="width:100%; height:6cm"
          placeholder="Tippt kram, den ihr im Fuß der Seite sehen wollt."
          ></textarea>`;
        let textSource = document.querySelector("#to-store");
        if (!window.localStorage) {
          textSource.value = "Ah, gut.  Du hast local storage aus.  Dann\n"
            +"geht das hier nicht.  Wie gesagt, das ist gut.";
           return;
        }
    
        if (window.localStorage.savedText) {
          textSource.value = window.localStorage.getItem("savedText");
        }
    
        textSource.addEventListener("input", () => {
          window.localStorage.setItem("savedText", textSource.value);
        });
    
        window.addEventListener("storage", (ev) => {
          textSource.value = ev.newValue;
        });
      }
    
      setUp();
    </script>
    

    Und dann noch der fürs Management der Fußzeile (der sitzt jetzt gerade im head-Element):

    if (window.localStorage) {
      target.innerHTML +=
        `<div id="ls-warning"><p><strong>Schlimmer noch:</strong>
        Dein Browser lässt mich
        auch local storage machen.  Wenn du dir in
        <a href="/javascript-local-storage.html">diesem Artikel</a>
        eine Nachricht hinterlässt, bekommst du sie bei deinem nächsten
        Besuch unten zu sehen; du kannst da sogar dein eigenes
        HTML und Javascript unterbringen und ausführen lassen.</p>
        <p id="user-message"/></div>`;
    
      if (window.localStorage.savedText) {
        document.querySelector("#user-message").innerHTML =
          window.localStorage.savedText;
      }
    
      window.addEventListener("storage", (ev) => {
        document.querySelector("#user-message").innerHTML = ev.newValue;
      });
    }
    
  • Gehorsam macht dumm

    Eine Kuh schert aus der Herde aus, um zu fressen.

    Nicht alle Rinder sind immer brav und gefügig. Ob diese Kuh wohl ein besonders schmales Maul hat? Das würde ihr nämlich, mit der Methode des Papers, ein größeres Hirn bescheinigen.

    Die zweite Tiergeschichte, die ich neulich angekündigt habe als, nun, interessant in der Forschung aktuell-Sendung vom 9.6. (in den Meldungen ab Minute 21:55), war die, dass gezähmte Rinder ein Viertel weniger Hirn haben als wilde; ein Traditionsanarcho wie ich kann bei so einem Faktoid natürlich dem „Gehorsam macht dumm und gewalttätig“ nicht widerstehen, und so habe ich mir den zugrundeliegenden Artikel genauer angesehen.

    Es handelt sich um https://doi.org/10.1098/rspb.2021.0813, „Intensive human contact correlates with smaller brains: differential brain size reduction in cattle types“ von Ana Balcarcel und KollegInnen; die Hauptautorin arbeitet am Paläontologischen Institut und Museum der Uni Zürich, was, in memoriam Tibatong und Zwengelmann, den Urmel-Fan in mir begeistert.

    Von der Hirnschrumpfung im Rahmen der Domestikation hatte ich spätestens in einer DLF-Sendung von 2009 („Beschleunigte Evolution“) von Michael Stang gehört. Dort hatte er über schnelle Zuchterfolge bei Damhirschen[1] berichtet:

    Das Zuchtziel war klar. Der domestizierte Damhirsch musste seine natürliche Schreckhaftigkeit verlieren und die Nähe des Menschen nicht als störend empfinden. Zugleich sollte die Fleischleistung erhöht werden. Durch Probeschlachtungen konnte Helmut Hemmer feststellen, ob bereits einige Tiere ein verkleinertes Gehirn hatten - eines der entscheidenden Merkmale beim Übergang vom Wildtier zum Nutztier. [...] Heute grasen über 1000 domestizierte Damhirsche auf Wiesen in Deutschland.

    Im vorliegenden Artikel wird das deutlich quantitativer:

    Domestic cattle have 25.6% smaller brains than wild cattle, according to regressions of EV [Endocranial volume, Gehirnvolumen] versus MZW [Muzzle width, Breite des Mundes, als Stellvertreter für die Körpermasse ...]. The difference between beef and dairy breeds is also significant (ANCOVA, p = 0.010).

    Das ist natürlich weit weg von „Gehorsam macht dumm“, aber „25.4%“ weniger Hirn ist, mit drei signifikant aussehenden Stellen, schon eine Ansage.

    Eine Ansage allerdings, die ich in Summe nicht so richtig überzeugend belegt finde, nicht mal mit nur einer signifikanten Stelle. Wobei, full disclosure, ich war gleich voreingenommen, denn die Methode von Balcarcel et al waren Schädelmessungen. Nennt mich irrational, aber ich werde ernsthaft nervös, wenn jemand an Schädeln herummisst. Das war schon bei Lavater schlimm, und nach dem durch Pseudowissenschaft gestützten völligen Zivilisationsbruch der Nazi-Phrenologie kann ich auf sowas nicht mehr entspannt, sagen wir sine ira et studio, blicken.

    Aber ok, es scheint in dem Fach Konsens zu sein, die Breite des Mundes (ich vermute, der im Deutschen übliche Begriff wird Maulbreite sein, aber lasst mir mal etwas Antispeziezismus) als Maß für das Körpergewicht zu nehmen. Das Hirnvolumen hingegen schätzen die AutorInnen unter Verweis auf John Finarelli über ln(Hirnvolumen) = 1.3143 ⋅ ln(Länge der Schädelhöhle) + 0.8934 ⋅ ln(Breite der Schädelhöhle) - 5.2313. Das ist – von den fantastischen Genauigkeitsbehauptungen abgesehen – so unplausibel nicht: Proportionalität zwischen Logarithmen heißt, dass es da ein Potenzgesetz gibt, was bei der Relation zwischen linearen Größen und einem Volumen naheliegt; Fingerübung im Rechnen mit Logarithmen: bei Kugeln gilt 3 ln(r) + C = ln(V) mit einer Konstanten C.

    Dennoch: Sowohl Hirnvolumen als auch die Körpermasse als Bezugsgröße werden in der Arbeit durchweg über Proxies geschätzt. Das mag ok sein – und nein, ich habe nicht versucht, mich von den zur Unterstützung dieser Proxies angeführten Arbeiten überzeugen zu lassen –, aber wer Claims wie

    Bullfighting cattle, which are bred for fighting and aggressive temperament, have much larger brains than dairy breeds, which are intensively selected for docility.

    ins Abstract schreibt, sollte da, finde ich, schon sagen, dass für die Studie weder Rinder noch ihre Hirne gewogen wurden.

    Gesetzt jedoch, die Korrelationen zwischen den Schädelmaßen auf der einen und Körpermasse und Hirnvolumen auf der anderen Seite hauen wirklich hin[2]: Ganz laienhaft finde ich ja schon die Metrik „Hirnvolumen zu Körpermasse“ nicht ganz so überzeugend. Immerhin dürfte ja „relativ mehr Fleisch“ bei Nutzrindern auch ein Zuchtziel gewesen sein, und so kann das Verhältnis nicht nur wegen weniger Hirn, sondern genauso gut wegen mehr sonstiger Masse kleiner ausfallen. Das wäre übrigens auch plausibel im Hinblick auf größere Hirn-zu-Körper-Verhältnisse bei Kampfstieren (die Balcarcel et al finden), denn fette Kampfstiere erfüllen ihren Zweck vermutlich eher weniger gut.

    Ähnlich wenig überzeugt haben mich die Grafiken der Arbeit. Die zentralen Aussagen werden mit Punktwolken mit reingemalten Regressionsgeraden belegt. In dieser Darstellung fällt alles Mögliche in Auge (z.B. „alle Wildrinder sind rechts oben“, einfach weil diese größer sind, oder „die Geraden der Kampfrinder sind steiler“, was, wenn ich das richtig sehe, das Paper weder nutzt noch erklärt), während die eigentlich in den Tests verwendeten Achsenabschnitte (entsprechend Faktoren nach Delogarithmierung) durch eigene Rechnung bestimmt werden müssten und jedenfalls optisch unauffällig sind.

    Deshalb wollte ich probieren, mir geeignetere Plots auszudenken und habe versucht, die laut Artikel auf figshare bereitgestellten Rohdaten zu ziehen.

    Ach weh. Das ist schon wieder so ein Schmerz. Zunächst figshare: Nichts geht ohne Javascript (wie schwer kann es sein, ein paar Dateien zu verbreiten? Wozu könnte Javascript da überhaupt nur nützlich, geschweige denn notwendig sein?) und das CSS versteckt völlig unnötigerweise die Seitengröße. Dazu: Google analytics, Fonts von googleapis.com gezogen; ich bin ja kein Freund von institutional repositories, bei denen jede Uni-Bibliothek ihren eigenen Stiefel macht, aber mal ehrlich: so ein Mist muss jetzt auch nicht sein, nur um ein paar Dateien zu verteilen. Dann doch lieber Murks der lokalen Bibliothek.

    Die Datei mit den Daten sorgt nicht für Trost: Ich hatte mich schon auf so ein blödes Office Open XML-Ding („Excel“) eingestellt, aber es kam in gewisser Weise noch schlimmer: Was mensch bei figshare bekommt, ist ein PDF mit einigen formatierten Tabellen drin. An der Stelle habe ich dann aufgehört. Screen Scraping mache ich nur in Notfällen.

    Dabei will ich an der Grundaussage („Domestikation macht Hirne relativ kleiner“) nicht mal zweifeln; das mit dem „dümmer“ allerdings (was meine Sprache ist, nicht die der AutorInnen) ist natürlich gemeine Polemik, und das Paper zitiert Dritte, die vermuten, die Reduktion des Hirnvolumens gehe vor allem aufs limibische System, „a composite of brain regions responsible for the processing of fear, reactivity and aggression“. Aber das Paper hat, soweit ich als interessierter Laie das erkennen kann, keine sehr starken Argumente für diese Grundaussage.

    Dennoch habe ich nicht bereut, in das Paper reingeschaut zu haben, denn ich habe so erfahren, dass es Rinder gibt, deren Zweck es ist „to decorate the landscape“, vor allem die halbwilden Chillingham-Rinder. Die Idee, Rinder zu halten, damit der Park etwas hübscher aussieht: das finde ich hinreißend.

    [1]Hauskatzen, so hieß es irgendwo anders, haben Hirne wie ihre waldlebenden Verwandten. Damit wären sie Wildtiere, deren Habitat zufällig unsere Wohnungen sind. Das würde manches erklären…
    [2]Der Physiker in mir würde bei sowas gerne die Schätzungen für die systematischen Fehler vergrößern, und so eine ganz grobe Fehlerbetrachtung hätte diesem Paper sicher gut getan.
  • Ach, Sparda!

    Werbeschriften der Sparda-Bank

    Bin ich komisch, weil ich nicht gerne Geld geboten bekomme fürs Ausliefern von Bekannten an Banken?

    Ich bin leider Kunde der Sparda-Bank Baden-Württemberg. „Leider“ beispielsweise, weil mich die Bank dann und wann mit 75 Euro dazu bringen will, als Makler für sie tätig zu werden. Fände ich das Konzept Ehre nicht kreuzdoof, müsste ich wegen Betrag und Inhalt des Angebots Satisfaktion fordern.

    Lästiger im Alltag ist das Online-Banking, zumal es mit jedem „Relaunch“ schlimmer wird. Die utopische Hoffnung, ich könnte Kontoauszüge per PGP-verschlüsselter Mail bekommen und Überweisungen per signierter Mail in einem einfachen, maschinenlesbaren Format einreichen, habe ich dabei schon längst aufgegeben. Wahrscheinlich zwingen die diversen Zahlungsdiensterichtlinien die Bank wirklich zu (aus Sicht EDV-kompetenter Menschen) unsinnigen Schnittstellen.

    Aber wenn es schon hakelige Webseiten sein müssen, sollten sie wenigstens technisch so halbwegs in Ordnung sein. Fantastische Maximalforderung: die elementaren Funktionen sollten ohne Javascript gehen; das würde viel mehr für die Sicherheit tun als alle Zweifaktorauthentifizierungen des Universums. I have a dream.

    Die Sparda jedoch geht, wie gesagt, mit großen Schritten in die entgegengesetzte Richtung, kürzlich zu einem Laden namens TEO, mit dem sich einige Sparda-Genossenschaften, wie es aussieht, eine Art Fintech leisten wollten. Um damit nicht gleich bauchzulanden, ziehen sie ihre Kunden aus ihren alten (eingestandenermaßen auch unangenehmen) Systemen dorthin um.

    Schon, dass die KundInnen beim Umzug ein manuelles „onboarding“ samt Neueinrichtung der Konten sowie der (Nicht-) Zustellung von Kontoauszügen duchlaufen müssen, wirkt unnötig umständlich, so sehr ich verstehen kann, dass TEO nicht unbedingt die (vermutlich eher bescheidenen) Passwort-Hashes des alten Sparda-Eigenbaus übernehmen wollten. Bei den Investitionssummen, um die es hier vermutlich geht, wären jedoch elegantere Migrationspfade („bitte ändern sie jetzt ihr Passwort“) schon denkbar gewesen.

    Das um so mehr, als das onboarding richtig schlecht gemacht ist: Es erscheint erstmal ein leerer Bildschirm, und das ändert sich auch dann nicht, wenn mensch den Browser Javascript ausführen lässt. Kein Fallback, nichts, immer nur ein weißes Fenster. Das Javascript von TEO nämlich wirft eine Exception, wenn es kein local storage bekommt, und niemand fängt diese Exception. Ganz im Stil der neuen Zeit gibt es nicht mal ein minimales HTML ohne Skripting – nur weiß. Au weia.

    Zwei Zeilen Javascript würden reichen, um nicht verfügbare local storage zu diagnostizieren und das etwas weniger murksig zu machen (ordentliches HTML wäre natürlich immer noch nett). Etwas mehr Arbeit ist es, dann zu erklären, was da wie lang gespeichert wird und warum es ohne nicht gehen soll. Das jedoch würde ohnehin in die Datenschutzerklärung gehören, viel zusätzliche Arbeit wäre es also nicht. Wenn die Datenschutzerklärung etwas taugen würde, heißt das. Aber dazu gleich.

    Ich könnte jetzt weitermachen mit Punkten, an denen der Kram an allen möglichen und unmöglichen Stellen kaputt geht, ohne dass es irgendeine Sorte Fehlermeldung außerhalb der Javascript-Konsole (und welche Muggels kennen die schon?) gibt. Aber selbst wenn mensch den Browser – was bei Bank-Geschäften schon als schlechte Idee gelten kann – nach und nach immer unvorsichtiger konfiguriert, sind noch schwer verstehbare Schnitzer im Programm, etwa, dass der Flickercode die falsche Größe hat. Die meisten Clients haben inzwischen eine recht zuverlässige Idee von der physikalischen Größe der Anzeige; ein width: 6.5cm im CSS ist doch wirklich nicht zu viel verlangt.

    Ähnliche WTF-Momente ergeben sich in der Datenschutzerklärung der TEOs. Derzeit heißt es dort in 2.3:

    Zur Erhöhung der Kundensicherheit nutzen wir in TEO den Service reCAPTCHA der Google Ireland Limited, Gordon House, 4 Barrow St, Dublin, D04 E5W5, Irland. Im Rahmen der Registrierung in TEO wird das reCAPTCHA zur Erkennung und Unterscheidung zwischen missbräuchlicher Nutzung personenbezogener Daten durch Maschinen und menschliche Eingaben eingesetzt.

    Als ich das gelesen habe, habe ich erstmal mit dem „onboarding“ aufgehört, denn wer mir was verkaufen will, sollte nicht verlangen, dass ich Schaufenster oder Verkehrsschlider auf Zuruf von google abklicke, und mich schon gar nicht zum Ausführen von googles Code nötigen (ebay, hörst du mich?). Sparda beruft sich für diese Frechheit auf Art. 6 1(f) DSGVO, also berechtigte Interessen des Betreibers. Das ist offensichtlich Quatsch; Textchas oder selbst hostbare Tests funktionieren besser und unter weniger Kundenverprellung.

    Am Ende musste ich aber dringend überweisen und war entschlossen, den reCaptcha-Mist zur Not doch durchzustehen. Musste ich am Ende nicht nicht, google hielt meinen Browser offenbar wirklich für menschengesteuert – wer weiß, warum. Aber TEO lädt tatsächlich eine Datei recaptcha__de.js von google-Servern, und zwar dort aus einem Pfad wie /recaptcha/releases/CdDdhZfPbLLrfYLBdThNS0-Y/recaptcha__de.js – da könnte ich schon allein bei der URL ins Grübeln kommen, was für Informationen google da wohl aus dem Banking ausleiten mag (ok: ja, ich vermute in Wirklichkeit auch, dass die Buchstabensuppe eher etwas wie einen git-Commit auf google-Seite identifiziert – aber wenn die googles wollten, könnten sie über Pfade dieser Art fast beliebige Mengen an Information exfiltrieren, was erst dann auffallen würde, wenn mal wer Pfade verschiedener Clients vergliche).

    Was denken sich Leute, wenn sie ohne Not reCaptcha auf ihre Seiten packen? Diese Frage stellt sich fast noch mehr beim nächsten Punkt:

    2.4 Google Web Fonts

    Um Inhalte browserübergreifend korrekt und grafisch ansprechend darzustellen, werden in TEO Web Schriften von Google Fonts verwendet. Die Einbindung dieser Web Fonts erfolgt nicht über Google. Die Schriften liegen lokal auf Servern. Es erfolgt kein externer Serveraufruf bei Google. Es findet keine Informationsübermittlung an Google statt.

    Wenn ich recht verstehe, was die da sagen wollen, dann wäre das: Wir nehmen Fonts von google, aber ziehen sie nicht von google. Dann stellt sich die Frage, was diese Information hier soll – wenn die anfangen, aufzuzählen, wer alles irgendwie an der Software beteiligt war, die auf ihren Servern läuft, sind sie lang beschäftigt.

    Um das noch absurder zu machen: sie lügen (jedenfalls im Effekt). Zumindest gestern und heute versucht die Seite für mich, die URL https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu4mxP.ttf (und noch zwei weitere; ich hoffe, die Buchstabensuppe erhält nicht allzu viel Kompromittierendes über mich) zu dereferenzieren. Damit hat google die IP, via Referrer den Umstand, dass gerade wer überweist, und vermutlich auch die Muggel-Identität, da mich wundern würde, wenn nicht normal der google-Cookie auch an gstatic gehen würde (ich muss gestehen, das nicht näher untersucht zu haben, zumal fonts.gstatic.com auf meinen Maschinen zu localhost auflöst).

    Was soll das? Wenn TEO schon Geld in die Hand nimmt und meint, mir die Wahl des Fonts vorschreiben zu müssen (was ich übrigens lästig finde), dann sollen sie wenigstens irgendwas kaufen statt die vergifteten Geschenke von google zu nehmen und dann noch in ihrer Datenschutzerklärung zu lügen.

    Für eine teilweise Erklärung für die, na ja, Lüge (ich will gnädig sein: „das Versehen“) mit den google-Fonts hilft ein Blick auf die 107 (!) Requests, die mein Browser macht, um die Wurzelseite des Online-Bankings aufzubauen. Dabei zeigt sich, dass immerhin die meisten Daten von TEO-Servern kommen. Es bleiben aber, nach der Vorrede kaum überraschend, doch einige Cross-Site-Requests.

    • die erwähnten Google-Fonts
    • ein CSS, ein Logo, das Captcha-Javascript (von www.gstatic.com)
    • eine bizarre Datei „anchor“, die offenbar im Zusammenhang mit Captcha steht (und die den Browser vermutlich dazu bringt, die Fonts von fonts.gstatic.com zu ziehen)
    • Und dann noch Ressourcen list und logoutWeb von prod-teo.itmr.de, beides JSON, ersteres mit Zeug, was erstmal nach Werbequatsch aussieht, aber vermutlich Identitäsinformation ist.

    Die Suche nach ITMR in der Datenschutzerklärung ist vergeblich, www.itmr.de zeigt ohne Javascript nur einen Spinner:

    Ein Warte-Spinner

    Wenn dieses Ding genug Schöpfungshöhe für Copyright hat, liegt dieses vermutlich bei itmr. Hier verwendet unter der, klar, Satireklausel.

    Der Spinner ist schon mal deutlich mehr als die leere Seite von TEO. Mit Javascript kommt sogar ein Titel: „ITM Research GmbH – Smart Cloud Computing”, ansonsten bleibt es beim Spinner. ITM Research… nichts, was Wikipedia kennen würde. Smart? Na ja. Zieht auch erstmal fünf Pfund Zeug von Google, Fonts und eine Familienpackung Javascript von maps.googleapis.com, einen Haufen PNGs von www.google.com. Ziemlich viel Kram für einen rotierenden Spinner.

    Wenn ich der Seite obendrauf local storage erlaube, kommt endlich das heiß erwartete Cookie-Banner, und zwar so:

    Cookie-Banner mit vor-abgeklickten Trackingcookies

    Echt jetzt? Per default angeklickte Tracking-Cookies? Wie smart muss mensch wohl sein, um für so ein bisschen Überwachungsmehrwert ein fettes Bußgeld zu riskieren?

    Zurück zur Ausgangsfrage: Was für Daten tauscht die Sparda eigentlich mit diesen etwas anrüchigen Gesellen aus? „ITM-ation – unser Synonym für digitale Transformation und Innovation“ schreiben sie, wenn ihnen der Browser gut genug ist. Diese Leute bekommen mit, wenn ich mit der Sparda-Bank rede? Uh.

    Ich klicke auf „Mehr Erfahren”. Beim Bullshit Bingo hätte ich gleich gewonnen:

    Wir realisieren Projekte der digitalen Transformation und Innovation, um Ihnen durch die Digitalisierung von Geschäftsmodellen, Wertschöpfungsketten und Prozessen mehr Wachstum in einem immer stärkeren Wettbewerbsumfeld zu ermöglichen. [...] Wir entwickeln Apps und Web-Apps, um Geschäftsprozesse in digitale Ökosysteme zu transferieren. Wir entwickeln dabei Ihre Datenveredelungsstrategie, setzen aber auch externe Echtzeit-Dienste der künstlichen Intelligenz (KI) wie zum Beispiel Cognitive Services und Watson ein. [...] Eine positive User Experience ist unabdingbar in der Digitalisierung Ihrer Prozesse. Um das jederzeit und von überall zu erzielen, brauchen Sie zwischen Ihrer Anwendung und Ihren Kunden über alle Kanäle und Anwendungsoptionen hinweg funktionale und ansprechende Benutzeroberflächen und Schnittstellen.

    Der Bullshit gegen Ende suggeriert (ebenso wie der konsistente Totalausfall ohne …

  • Fürchten lernen 2: Ihre Reputation ist nicht verfügbar

    In Teil 2 der Saga von einem, der Mails verschicken will geht es um mailbox.org – an sich ja einer eher sympatische Firma, gerade im Vergleich zu Telekom und Vodafone. Aber, beim Einliefern:

    2021-02-08 05:52:09 1l8yWu-0006Ry-EM ** (Adresse tut nichts zur Sache)
    R=dnslookup T=remote_smtp H=mxext2.mailbox.org [80.241.60.215]
    X=TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256 CV=yes DN="C=DE,ST=Berlin,
    L=Berlin,O=Heinlein Support GmbH,OU=MBO,CN=*.mailbox.org": SMTP error
    from remote mail server after RCPT TO:<Adresse tut nichts zur Sache>:
    554 5.7.1 Service unavailable; Client host [116.203.206.117] blocked
    by RBL; http://www.barracudanetworks.com/reputation/?pr=1&ip=116.203.206.117
    

    Mit anderen Worten: Eine „Real Time Black List“ RBL fand, dass die IP nach Spam riecht, und drum darf ich nicht einliefern.

    Hu? Von dieser IP kam seit mindestens einem Jahr (also seit ich sie habe) nicht eine Mail an öffentliche SMTP-Server (von meinem Smarthost abgesehen), und schon gar nichts, was auch nur entfernt nach Spam aussah. Wie kommt die Kiste dann auf diese Blacklist? Schaun wir mal und dereferenzieren die URL. Resultat: Weiße Seite. Ach nee, soll ich denen Javascript erlauben? Gibt immer noch eine weiße Seite. Local Storage? Weiße Seite. Curl anwerfen. Nach kurzer Wartezeit kommen genau null Bytes zurück.

    Echte Profis, die barracudas. Vertrauenswürdige Treuhänder unserer Mail-Infrastruktur.

    Also gut, tippe ich halt mal barracudanetworks.com in den Browser ein (na gut, in Wirklichkeit habe ich in luakit 2gu gesagt; so viel nerd cred muss an der Stelle sein). Kommt ein animierter Security-Salespitch (yikes! Habe ich denen gerade Javascript erlaubt?), den sich niemand antun müssen sollte – „It's time to protect your business“ my ass. Und klar, google analytics ist auch gleich mit drauf.

    Wie finde ich denn jetzt raus, warum der Laden mich für einen Spammer hält? Auch mit etwas Rumklicken: nichts außer dämlichen Testimonials („The intuitive interface makes deployment simple and the bundled features combine to create a comprehensive email security solution.“).

    Und das alles nur, damit ich Mail einliefern darf?

    Tatsächlich kann mensch sich irgendwie zu barracudacentral.org durchklicken. Und da gibts dann einen Removal Request, der eigentlich aussieht wie ein Phishing-Versuch:

    Screenshot Formular

    Wozu wollen die jetzt eine Telefonnummer haben? Wozu eigentlich eine Mailadresse? Wie kann das bei der Prüfung eine Rolle spielen? Rufen die wirklich zurück? Und wenn ja: wärs nicht freundlich, wenigstens nach der Zeitzone zu fragen?

    Wenn ich den mailbox.org-Leuten nicht ziemlich arg trauen würde, wäre ich jetzt weg. Aber ich probiers mal. „Removal requests are typically investigated and processed within 12 hours of submission“ sagen die. Ich bin ja mal neugierig.

« Seite 2 / 2

Letzte Ergänzungen