Cross Site Scripting und APEX Berichte. Das sollten Sie wissen.
Stand |
APEX-Version |
Datenbankversion |
Mai 2016 |
ab APEX 5.0 |
ab 11.1 |
Sicherheit ist für alle Web-Anwendungen ein wichtiges Thema - so auch für Application Express.
In diesem Tipp geht es um das Thema Cross Site Scripting (XSS) im Zusammenspiel mit
Berichten (Reports). In der Praxis werden Berichte vielfältig eingesetzt, und oft werden
die Darstellungsmöglichkeiten des Browsers voll ausgenutzt. Wie sicherheitsrelevant das
ist, schauen wir uns in diesem Tipp an.
Wir beginnen mit einem einfachen Bericht auf die wohlbekannt Tabelle EMP - der
sieht dann wie in Abbildung 1 aus.
Abbildung 1: "Ein einfacher, interaktiver Bericht"
Eine typische Anforderung ist dann, die Spalte EMP_COMMENT rot einzufärben. Oft wird das
mit einer veränderten SQL-Abfrage realisiert ...
... was zunächst zu einer Ausgabe wie in Abbildung 2 führt.
Abbildung 2: Versuch, die Spalte SAL rot einzufärben
Nun wird noch die Einstellung Escape Special Characters
für die Spalte auf No
gestellt und das Ergebnis ist erreicht (Abbildung 3).
Abbildung 3: Das Ergebnis
Allerdings hat die Anwendung nun schon eine mögliche Cross Site Scripting Lücke. Diese entstehen,
wenn der Browser Javascript zur Ausführung bringt, welches der Anwendungsentwickler
gar nicht vorgesehen hatte. In unserem Beispiel gehen wir davon aus, dass die Spalte
EMP_COMMENT nur einfachen Text enthält - aber angenommen, ein
anderer (bösartiger) Anwender macht folgenden Eintrag - das könnte sogar über ein völlig anderes Tool
erfolgen.
Der nächste Aufrufer der Seite würde dann die folgende Ausgabe sehen.
Abbildung 4: Cross Site Scripting in Aktion
Dieses Beispiel ist zwar lästig, aber noch harmlos. Viel gefährlicher wird es, wenn
mit dem <script> Tag externer Code von fremden Servern heruntergeladen wird.
Solcher Code könnte Inhalte (Daten) der Seite auslesen und
über das Internet an den Server des Angreifers schicken - oder andere, gefährliche Dinge tun.
Die Art und Weise, wie die Spalte EMP_COMMENT rot eingefärbt wurde, ist also
nicht zu empfehlen. Bedeutet das nun, dass man Daten in Berichten nicht mehr dynamisch formatieren
darf oder kann ...? Nein, mitnichten. Es gibt allerdings einen wesentlich sichereren Weg, dies
umzusetzen.
- Stellen die die Einstellung Escape Special Characters in der Berichtsspalte auf Yes zurück - damit ist der Bericht wieder sicher.
- Nehmen Sie das HTML-Markup aus der SQL-Abfrage heraus und selektieren Sie die Spalte ganz normal
- Navigieren Sie im Page Designer zur Berichtsspalte, im Property Editor zum Attribut HTML Expression und hinterlegen Sie dort folgendes.
Wenn Sie die Berichtsspalte nun ansehen, ist die Spalte Comments immer noch rot eingefärbt,
die Nutzereingabe wird aber maskiert und bleibt damit ungefährlich: Dieser Bericht ist sicher
vor Cross-Seite-Scripting Attacken.
Abbildung 5: Dieser Bericht ist sicher
Doch mit solch einfachen Anforderungen ist es oft nicht getan - denken wir also ein wenig
weiter: Die Kommentare werden rot eingefärbt, wenn das Gehalt größer als 3000 ist,
orange zwischen 2000 und 3000 und grün unter 1000. Das ist ein komplexer Ausdruck,
den man mit der HTML-Formatmaske so nicht abbilden kann - ein SQL CASE Ausdruck muss
her. Bevor Sie jedoch nun jedoch wieder HTML-Markup in der SQL-Query generieren, denken
Sie nochmals nach: Es braucht doch kein dynamisches HTML-Markup; nur die Farben selbst (!)
müssen generiert werden. Schauen Sie sich die folgende Abfrage an.
Die neue Spalte COMMENT_COLOR stellen Sie auf Hidden, so dass man sie im Bericht nicht
sehen kann. Als HTML Expression für die Spalte EMP_COMMENT nehmen Sie nun folgendes:
Das Ergebnis sieht dann wie in Abbildung 6 aus - sie sehen: Auch verschiedene Farben bzw.
CSS-Direktiven sind kein Problem - in den Tabellenspalten enthaltene HTML-Sonderzeichen werden
weiterhin maskiert - der Bericht bleibt sicher.
Abbildung 6: Bericht mit konditionaler Darstellung - immer noch sicher
Mit diesem Ansatz kommt man bei der Berichtsformatierung wirklich sehr weit - versuchen Sie am besten,
Ihre Anforderungen immer so umzusetzen. Allerdings
gibt es auch Situationen, wo die HTML Expression alleine nicht mehr ausreicht. Das ist
dann der Fall, wenn die zu erzeugenden HTML-Tags selbst dynamisch generiert werden müssen. Angenommen,
die Spalte EMP_COMMENT soll, wenn das Gehalt größer als 4500 ist, eine deutlich sichtbare Nachricht
enthalten - außerdem soll der Kommentar dann eingerahmt werden. Das ist zugegebenermaßen
eine etwas konstruierte Anforderung, dennoch wollen wir sie umsetzen.
Versuchen wir es zuerst, wie gerade gelernt: In der SQL-Query
wird allein die Warnung generiert.
Im Attribut HTML Expression machen wir die Formatierung:
Die Spalte COMMENT_WARN machen wir wiederum unsichtbar (Hidden). Starten Sie die
Seite und schauen Sie das Ergebnis an.
Abbildung 7: Weiterer Bericht mit konditionaler Darstellung - es ercheinen auch leere Rahmen
Dieses Ergebnis ist nicht ganz so, wie wir es erhofft haben. Alle Kommentare sind
nun eingerahmt, außerdem sieht man in den Zeilen ohne Warnung deutlich den freien Platz
für dieselbe.
Grund ist, dass das HTML der Formatmaske immer dargestellt wird - auch ohne Nachricht
ist das HTML-Tag <h1> enthalten; es ist nur leer. In diesem Fall braucht es
dynamisches HTML-Markup, welches in der SQL Abfrage erzeugt werden muss.
Um jedoch nicht wieder
eine Cross-Site-Scripting Lücke einzuführen, werden die eigentlichen Inhalte der Tabellenspalten
mit der Funktion APEX_ESCAPE.HTML "behandelt". Danach kann die Einstellung Escape Special Characters
gefahrlos auf No gestellt werden. Hinterlegen Sie also die folgende SQL-Abfrage.
Das Ergebnis ist wiederum sicher (erkennbar an der Ausgabe <script> ...), obwohl Escape Special Characters auf No gestellt wurde. Grund ist,
dass die Inhalte aus der Tabelle mit APEX_ESCAPE.HTML esplizit maskiert wurden. Das übrige HTML-Markup
besteht aus statischen, in der Query kodierten HTML-Tags. Wann immer Sie in SQL-Abfragen oder PL/SQL Code
dynamisches HTML-Markup generieren und Escape Special Characters auf No stellen, behandeln Sie die unsichere Eingaben des Endbenutzers mit den
Prozeduren von APEX_ESCAPE .
Abbildung 8: Sichere Berichtsausgabe trotz komplett dynamischem HTML
Bleibt noch die letzte Variante: Angenommen, die Spalte EMP_COMMENT wird von einem Rich Text Editor
mit HTML-Code befüllt - HTML-Tags wie <b> oder <i> sollen also entsprechend dargestellt
werden. Mit unserem aktuellen Setup werden die Tags maskiert - aus Sicherheitsgründen wollten wir
das ja auch genau so haben.
Abbildung 9: Alle HTML-Tags werden maskiert - auch ungefährliche
Nicht nur das Tag
<script> gefährtlich, sondern auch <iframe>; denn auch dieses
lädt Inhalte von einer URL, beispielsweise von der eines fremden Servers. <img> ist ebenfalls
sicherheitsrelevant; es lädt ein externes
Bild - und mit der Bild-URL lassen sich Daten zu einem Server übertragen. Tags wie
<b> oder <i> sind aber definitiv ungefährlich.
APEX_ESCAPE.HTML_WHITELIST arbeitet wie APEX_ESCAPE.HTML, maskiert die HTML-Tags,
die in der Whitelist enthalten sind (also ungefährliche Tags), aber nicht. Standardmäßig sind das:
Mit dem Parameter p_whitelist_tags lässt sich eine eigene Tag-Whitelist
anwenden - seien Sie hier aber entsprechend vorsichtig. Probieren wir dies für unsere obige SQL-Abfrage aus.
Das Ergebnis sieht wie in Abbildung 10 aus.
Abbildung 10: Sichere Berichtsausgabe bei gleichzeitiger Berücksichtigung von HTML-Markup
Abbildung 10 zeigt sicherlich das komplexeste Beispiel, welches aber immer noch sicher
gegenüber Cross-Site Scripting Attacken ist. Ein genereller Leitfaden zur Implementierung
sicherer Berichte lässt sich sehr leicht herleiten.
- Belasse Escape Special Characters, wo immer möglich, auf Yes.
- Realisiere HTML-Markup in der Berichtsausgabe mit dem Spaltenattribut HTML Expression.
- Führe bei Bedarf zusätzliche, versteckte Spalten ein.
- Stelle Escape Special Characters nur dann auf No, wenn Deine Anforderung mit
HTML Expression absolut nicht realisierbar ist.
- Stelle sicher, dass alle Tabellenspalten mit APEX_ESCAPE behandelt werden.
- Nimm APEX_ESCAPE.HTML, wenn keinerlei Markup in der Ausgabe erwünscht ist.
- Nimm APEX_ESCAPE.HTML_WHITELIST, wenn bestimmtes Markup (Fett, Kursiv) in der Ausgabe erwünscht ist.
- Nimm APEX_ESCAPE.HTML_ATTRIBUTE, wenn die Tabellenspalte ein HTML-Attribut sein soll.
- Stelle auf gar keinen Fall Escape Special Characters auf No, ohne gleichzeitig in der Abfrage APEX_ESCAPE zu verwenden.
Beachtet man diese einfachen Regeln, so lässt sich jeder Bericht gegen Cross-Site-Scripting
sichern - und das, ohne das man auch nur den kleinsten Abstrich bei der Formatierung machen
muss. Dieses Thema ist in jeder APEX-Anwendung auf fast jeder Seite relevant - probieren Sie
es aus und machen Sie Ihre Berichte sicher.
Zurück zur Community-Seite
|