Logo Oracle Deutschland   Application Express Community
Escaping für Fortgeschrittene: APEX_ESCAPE

Erscheinungsmonat APEX-Version Datenbankversion
Januar 2013 ab 4.2 ab 10.2

Mit dem Thema HTML Escaping hat sich wahrscheinlich fast jeder APEX-Entwickler schon mal auseinandergesetzt. Es geht dabei um die Behandlung von Sonderzeichen bei der Ausgabe von HTML-Code. So findet bei einem APEX-Bericht per Default immer ein Escaping der HTML-Sonderzeichen <, > und & statt. Ein Bericht mit der SQL-Abfrage ...

select '<strong>'||ename||'</strong>' as ename_bold
from emp

... sieht dann normalerweise so aus:

HTML-Sonderzeichen werden standardmäßig maskiert

Abbildung 1: HTML-Sonderzeichen werden standardmäßig maskiert

Weithin bekannt ist, dass sich dieses Verhalten einfach umstellen lässt: Dazu einfach zu den Berichtsattributen navigieren, dort zu den Spaltenattributen der Spalte (hier: ENAME_BOLD) und die Darstellung auf Standardberichtsspalte umstellen. Fertig.

Einstellung: Die HTML-Sonderzeichen sollen *nicht* mehr maskiert werden

Abbildung 2: Einstellung: Die HTML-Sonderzeichen sollen *nicht* mehr maskiert werden

Allerdings könnte es nun sein, dass hier eine Cross-Site-Scripting-Lücke entstanden ist. Denn wenn die Tabelle mit Eingaben von Endbenutzern gefüllt wird, könnte anstelle des HTML-Tags <strong> auch ein <script>-Tag enthalten sein. Der JavaScript-Code wird dann auf dem Browser zur Ausführung gebracht - was sicher nicht gewünscht ist. Auch dazu ein Beispiel: wir erstellen eine Tabelle KOMMENTARE; wir nehmen an, dass diese mit den Einträgen von Web-Nutzern eines Onlineforums gefüllt und in einer APEX-Anwendung zur Anzeige gebracht. Zuerst also die Tabelle mit ein paar Einträgen erstellen ...

create table kommentare (
  datum     date,
  username  varchar2(200),
  kommentar varchar2(4000)
);

insert into kommentare values (DATE'2012-12-10', 'PlainIsGood', 'Habe heute mit APEX experimentiert. Alles super.');
insert into kommentare values (DATE'2012-12-11', 'FormattingIsCool', 'APEX <i>mobile Applications</i> sind genial.');
insert into kommentare values (DATE'2012-12-12', 'BadGuy', 'APEX macht <b>wirklich Spaß</b><script type="text/javascript">alert("nun startet wirklich schädlicher Code!");</script>.');

commit;

Danach erzeugen wir, wie immer, einen Bericht. Standardmäßig werden alle HTML-Tags maskiert, die Anwendungsseite ist zwar sicher, sieht aber nicht besonders gut aus - es werden eben keine Formatierungen umgesetzt.

Kommentartabelle: Alle HTML-Sonderzeichen sind maskiert

Abbildung 3: Kommentartabelle: Alle HTML-Sonderzeichen sind maskiert

Nun könnte man die Darstellung auf Standardberichtsspalte umstellen; womit die HTML-Tags <b> und <i> wieder umgesetzt werden. Erwartet wird eine Ausgabe mit in Abbildung 4.

Umstellung auf Standardberichtsspalte: Erwartete Ausgabe

Abbildung 4: Umstellung auf Standardberichtsspalte: Erwartete Ausgabe

... tatsächlich bekommt man aber die Ausgabe in Abbildung 5.

Umstellung auf Standardberichtsspalte: Tatsächliche Ausgabe

Abbildung 5: Umstellung auf Standardberichtsspalte: Tatsächliche Ausgabe

Ein aufpoppendes JavaScript-Fenster ist hierbei harmlos - gefährlicher JavaScript-Code könnte nun den Browser dagegen auf eine verseuchte Webseite umleiten oder Code zum "Stehlen" der APEX-Session ausführen. Man kann also festhalten, dass es "gute" und "böse" HTML-Tags in der Ausgabe von Berichtsdaten gibt. Die Einstellung in den Spaltenattributen eines Berichts erlaubt aber nur das Ein- oder Ausschalten des Escapings.

Aber zum Glück gibt es seit APEX 4.2 das neue PL/SQL Paket APEX_ESCAPE. Und auch wer bislang schon SQL und PL/SQL mit HTF.ESCAPE_SC gearbeitet hat, sollte sich APEX_ESCAPE unbedingt näher ansehen - denn dieses Paket leistet wesentlich mehr.

APEX_ESCAPE erlaubt das Escaping mit Hilfe eines PL/SQL Funktionsaufrufs. Ein Aufruf von APEX_ESCAPE.HTML arbeitet wie die Standardeinstellung in einem APEX-Bericht - alles wird maskiert ...

SQL> select apex_escape.html('APEX <i>mobile Applications</i> sind genial.') from dual;

APEX_ESCAPE.HTML('APEX<I>MOBILEAPPLICATIONS</I>SINDGENIAL.')
--------------------------------------------------------------------------------
APEX &lt;i&gt;mobile Applications&lt;&#x2F;i&gt; sind genial.

Daneben gibt es aber noch die Funktion APEX_ESCAPE.HTML_WHITELIST, welche bestimmte HTML-Tags (eben die der Whitelist) intakt lässt.

SQL> select apex_escape.html_whitelist('APEX <i>mobile Applications</i> sind genial.') from dual;

APEX_ESCAPE.HTML_WHITELIST('APEX<I>MOBILEAPPLICATIONS</I>SINDGENIAL.')
--------------------------------------------------------------------------------
APEX <i>mobile Applications</i> sind genial.



SQL> select apex_escape.html_whitelist('APEX macht <b>wirklich Spaß</b><script type="text/javascript">alert("nun startet
 wirklich schädlicher Code!");</script>') from dual;

APEX_ESCAPE.HTML_WHITELIST('APEXMACHT<B>WIRKLICHSPAß</B><SCRIPTTYPE="TEXT/JAVASC
--------------------------------------------------------------------------------
APEX macht <b>wirklich Spaß</b>&lt;script type=&quot;text&#x2F;javascript&quot;&gt;alert(&quot;nun startet wirklich schädlicher Code!&quot;);&lt;&#x2F;script&gt;

Standardmäßig sind folgende HTML-Tags in der Whitelist:

  • <h1>
  • </h1>
  • <h2>
  • </h2>
  • <h3>
  • </h3>
  • <h4>
  • </h4>
  • <p>
  • </p>
  • <b>
  • </b>
  • <strong>
  • </strong>
  • <i>
  • </i>
  • <ul>
  • </ul>
  • <ol>
  • </ol>
  • <li>
  • </li>
  • <br />
  • <hr/>

Die Tags werden nur dann von der Maskierung ausgenommen, wenn sie im Text so vorkommen, wie sie in der Liste enthalten sind. Das Tag <i> muss also genau so vorhanden sein. Ist es zusätzlich mit einem HTML-Attribut versehen (<i style="color: red">), dann wird es nicht mehr erkannt, also maskiert. Die Funktion ist also vor allem zur Berücksichtigung einfachen HTML-Markups, wie es oft von Endanwendern verwendet wird, vorgesehen.

Es ist auch möglich, beim Aufruf von APEX_ESCAPE.HTML_WHITELIST eine eigene Whitelist mitzugeben. Wenn zum Beispiel bekannt ist, dass das HTML-Tag <em> verwendet wird oder wenn man oben genannten Ausdruck <i style="color: red"> dennoch unterstützen möchte, so kann man APEX_ESCAPE.HTML_WHITELIST wie folgt aufrufen.

SQL> select apex_escape.html_whitelist('APEX <i style="color: red">mobile Applications</i> sind genial.','<i>,<i style="
color: red">,</i>,<em>,</em>') from dual;

APEX_ESCAPE.HTML_WHITELIST('APEX<ISTYLE="COLOR:RED">MOBILEAPPLICATIONS</I>SINDGE
--------------------------------------------------------------------------------
APEX <i style="color: red">mobile Applications</i> sind genial.

Dies lässt sich nun für unseren Bericht auf die Tabelle KOMMENTARE nutzen. Dazu müssen wir die SQL-Abfrage wie folgt ändern ...

select 
  datum, 
  username, 
  apex_escape.html_whitelist(
    kommentar, 
    '<h1>,</h1>,<h2>,</h2>,<h3>,</h3>,<h4>,</h4>,
     <p>,</p>,<b>,</b>,<strong>,</strong>,<i>,</i>,
     <ul>,</ul>, <ol>,</ol>,<li>,</li>,<br />,<hr/>,
     <em>,</em>'
  ) kommentar
from kommentare

Die Darstellung der Berichtsspalte kann danach auf Standardberichtsspalte geändert werden, denn die SQL-Abfrage erledigt nun das Escaping. Der Bericht sieht dann wie folgt aus.

Selektives HTML-Escaping mit APEX_ESCAPE.HTML_WHITELIST

Abbildung 6: Selektives HTML-Escaping mit APEX_ESCAPE.HTML_WHITELIST

Auch wenn es daran geht, den Inhalt für HTML Attribute korrekt zu erzeugen, kann APEX_ESCAPE sehr hilfreich sein. Hier muss das Escaping etwas anders arbeiten als bei HTML-Tags, denn der Inhalt eines HTML-Attributs steht innerhalb von Anführungszeichen. APEX_ESCAPE.HTML_ATTRIBUTE arbeitet wie folgt:

SQL> select apex_escape.html_attribute('text"<<') from dual;

APEX_ESCAPE.HTML_ATTRIBUTE('TEXT"<<')
--------------------------------------------------------------
text&#x22;&#x3C;&#x3C;

Sobald man als Entwickler also dabei ist, in SQL-Abfragen oder im PL/SQL Code, HTML-Tags mit Attributen zu generieren, sollte man hier stets APEX_ESCAPE.HTML_ATTRIBUTE nutzen.

Wenn JavaScript-Code in einer SQL-Abfrage generiert wird, müssen anhand der Tabelleninhalte häufig JavaScript-Parameter generiert werden. Hierfür bietet sich die Funktion APEX_ESCAPE.JS_LITERAL an - es sorgt dafür, dass der generierte Code nicht "zerstört" wird, wenn sich spezielle Zeichen wie doppelte oder einfache Anführungszeichen in den Tabellen befinden. Das sieht am Beispiel dann wie folgt aus:

SQL> select 'javascript:alert('||apex_escape.js_literal('''#"&<>')||');' js_code from dual;

JS_CODE
--------------------------------------------------------------------------------
javascript:alert('\u0027#\u0022\u0026\u003C\u003E');

Die Rückgabe der Funktion enthält zum einen bereits die in JavaScript üblichen einfachen Anführungszeichen, zum anderen sind alle Sonderzeichen so maskiert, dass der Code wie gewünscht ausgeführt wird. Soll komplexerer JavaScript-Code zusammengestellt werden, dann bietet das PL/SQL Paket APEX_JAVASCRIPT noch weitere, hilfreiche Funktionen an.

Mit dem PL/SQL-Paket APEX_ESCAPE bieten sich dem Entwickler völlig neue Möglichkeiten, das Escaping selektiv und passend zu den Bedürfnissen der Anwendung einzusetzen. Anforderungen wie "Wir wollen HTML-Markup in der Berichtsausgabe erlauben, aber die Anwendung soll sicher vor Cross-Site-Scripting-Attacken sein" sind nun kein Problem mehr ...

Zurück zur Community-Seite