Sonntag, 31. Mai 2020

Clickjacking - Schutz mit Hilfe von Content Security Policy (CSP) oder X-Frame-Options

Bei Clickjacking versucht eine böswillige dritte Website die eigentliche Website des Nutzers in einem unsichtbaren Rahmen zu laden bzw. zu überlagern (z.B. per iframe). Der Benutzer wird dann dazu verleitet, Aktionen auf der ursprünglichen (böswilligen) Website auszulösen ohne dass er sich dessen bewusst ist.


Hintergrund: Clickjacking ist ein konzeptionelles Problem von JavaScript und Webanwendungssicherheit. (Quelle: https://de.wikipedia.org/wiki/Clickjacking)
 

Welche Gegenmaßnahmen gibt es?


Um so einen Angriff zu verhindern, sollte man eine explizite Whitelist von Seiten definieren, die die aktuelle Seite über die Direktive für Frame-Vorfahren in die Content Security Policy (CSP) einbetten können.

Damit auch ältere Browser unterstützt werden, kann der (veraltete) Header X-Frame-Optionen zusätzlich auf DENY oder SAMEORIGIN gesetzt werden. Die Option DENY verhindert, dass Browser die Website in einem iframe anzeigt.

Header set X-Frame-Options "DENY"

Wird der Header auf SAMEORIGIN gesetzt, kann die Website in iframes auf anderen Seiten derselben Domain eingebettet werden, verhindert jedoch das Einbetten in Websites von dritten.

Header always set X-Frame-Options "SAMEORIGIN"

Wichtig: X-Frame-Options funktioniert nur durch den HTTP-Header, und NICHT per meta-tag! Daher muss die Einstellung direkt im Apache vorgenommen oder per .htaccess gesetzt werden.

Dienstag, 26. Mai 2020

Leaflet.js - draggable marker und Ausgabe der Koordinaten (lat, lng)

In dem Beitrag "Webseite mit interaktiver Karte ohne Google Maps? Leaflet.js" hatte ich beschrieben, wie man Leaflet.js auf seiner Webseite als gute Alternative zu Google Maps einbindet. 


In diesem Beispiel geht es darum einen "ziehbaren" Marker zu erstellen und die Koordinaten in zwei Feldern (lat, lng) anzuzeigen.


Es wird die Dragend-Methode für den Marker verwendet um lat und lng abzufangen:

<script type="text/javascript">
    function showMap() {
      
        var map = L.map('map_leaflet').setView([50.9033081, 9.5924615], 14);
        var my_divicon = L.divIcon({
            className: 'arrow_box'
        });
        var marker = L.marker([50.9033081, 9.5924615], {
            draggable:true
        });
        function addToTextBox(lt,ln){
            document.getElementById('lat').innerHTML = lt;
            document.getElementById('lng').innerHTML = ln;
          
        }
        marker.on('dragend', function(event){
            //alert('drag ended');
            var marker = event.target;
            var location = marker.getLatLng();
            var lat = location.lat;
            var lon = location.lng;
            addToTextBox(lat,lon);
            //alert(lat);
            //retrieved the position
          });
       
        // load a tile layer
        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
            {
                attribution: 'Map data © OpenStreetMap and contributors CC-BY-SA',
                maxZoom: 18,
                minZoom: 9
            }).addTo(map);
          
        // initialize the map
        //var map = L.map('map_leaflet', { layers: osm, tap: false } );
        L.control.scale({imperial:false}).addTo(map); // metrisch

        marker.addTo(map);
    }
</script>



Samstag, 23. Mai 2020

JavaScript - Fetch API File Upload: Apache 403 Forbidden error SecFilterEngine

Für eine Erweiterung meiner Webcamseiten, benötigte ich ein Formular mit Bild-Upload-Funktion. Das Hochladen von Dateien ist eine der häufigsten Funktionen für eine Webanwendung. Ich verwende in meinem Beispiel KEINE der vielen JavaScript-Bibliotheken, sondern die Fetch-API (eine native JavaScript Funktion).


Als erstes benötigt man auf der Webseite ein HTML Formular mit einem Eingabeelement:

...
    <form action="xyz.php" name="melderForm" method="post" enctype="multipart/form-data">
...
        <input id="formMelderImage-file" class="form-control" type="file">
...
    </form>


Mit dem folgenden JavaScript Code wird ein Event-Listener hinzugefügt, wenn der Benutzer eine Datei auswählt. Mit der Methode fileUpload () wird ein Dateiobjekt als Eingabe empfangen und es mit fetch () auf den Server hochgeladen (inklusive einer Überprüfung des Dateityps (nur Bilder) und der Dateigröße (< 10MB).

<script>
    // Datei vom Formular
    const fileInput = document.getElementById('formMelderImage-file');

    // event listener
    fileInput.addEventListener('change', () => {
        fileUpload(fileInput.files[0]);
    });
   
    const fileUpload = (file) => {
        // Check des Dateityps
        if(!['image/jpeg', 'image/gif', 'image/png', 'image/svg+xml'].includes(file.type)) {
            console.log('Es sind nur Bilder erlaubt!');
            return;
        } else if(file.size > 10 * 1024 * 1024) { // Check der Groesse (< 10MB)
            console.log('Die Datei muss kleiner 10MB sein!');
            return;
        } else {
            // Datei zum FormData object hinzufügen
            const fd = new FormData();
            fd.append('formMelderImage-file', file);

            // `POST` request senden
            fetch('/upload/image', {
                method: 'POST',
                body: fd
            })
            // Abfangen von Fehlern
            .then(res => res.json())
            .then(json => console.log(json))
            .catch(err => console.error(err));
        }
    }
</script>

SyntaxError: "JSON.parse: unexpected character at line 1 column 1 of the JSON data" - 403 Forbidden


404- oder 403-Fehlern nach dem Senden eines Formulars können an der mod_security-Einstellung in Apache auf dem Server liegen. Das Apaches-Modul mod_security hat standardmäßig ein Upload-Limit von 60 KB, sodass bei jedem größeren Upload ein 403-Fehlercode ausgegeben wird.

Man kann versuchen diese zu deaktivieren, und folgendes zu der .htaccess-Datei hinzuzufügen, man wird aber vermutlich keinen Erfolg mehr haben (support for .htaccess files was discontinued in 2.x as it raised too many security issues https://stackoverflow.com/questions/19093542/how-to-disable-mod-security-and-mod-security2-in-htaccess/19196856#19196856)

<IfModule mod_security.c>
  SecFilterEngine Off
</IfModule>

Oder wenn man direkten Zugriff auf die Apache Einstellungen hat, geht dies auch direkt unter nano  /etc/httpd/conf.d/mod_security.conf .

<IfModule mod_security.c>

    # Turn the filtering engine On or Off
    SecFilterEngine Off