Anzeige
Tutorialbeschreibung

Javascript und Ajax - Top Secret: Passwortschutz

Javascript und Ajax - Top Secret: Passwortschutz

[Javascript und Ajax] Top Secret: Passwortschutz 28

Dieses Kapitel erläutert klärt, wie sie ein möglichst sicheren Zugansschutz mit JavaScript erstellen können.


Das nun folgende Tutorial ist ein Auszug aus der 7. Auflage des Buches: JavaScript und Ajax von Christian Wenz.

Top-secret siehe topsecret Ew: streng geheim – Die aktuelle deutsche Rechtschreibung, Naumann & Göbel 1997

Kapitel 28 Top Secret: Passwortschutz

Eines der Ziele, auf dem die Idee des Internet fußt, ist der freie und unbeschränkte Zugriff auf Informationen. Mit der Kommerzialisierung des Webs entstand jedoch die Notwendigkeit, nur einem begrenzten Personenkreis den Zugriff auf bestimmte Bereiche einer Website zu gewähren.

Doch nicht nur merkantile Absichten erfordern einen geschützten Bereich, auch persönliche Informationen wie beispielsweise Bewerbungsunterlagen, die online übertragen werden, sollten nicht für jedermann und -frau einsehbar sein.

Mit serverseitigen Mitteln ist das kein größeres Problem: Ein Benutzername und ein Passwort können als Teil der HTTP-Anforderung an den Webserver übertragen werden, und der Webserver kann diese Daten mit den gespeicherten Informationen auf dem lokalen System überprüfen. Passen der Benutzername und das Passwort zusammen, wird das angeforderte Dokument übertragen, andernfalls wird ein Error-Code 401 zurückgegeben – Authorization required (siehe Abbildung 25.1).


Bilder

Abbildung 28.1     Fehlermeldung bei keinem (oder falschem) Passwort

Eine der häufigsten Fragen lautet nun, ob dies auch mit JavaScript möglich sei. Um die Antwort gleich vorwegzunehmen: nein, leider nicht. Egal, was die Leute Ihnen erzählen mögen, ein hundertprozentiger Schutz besteht bei clientseitigen Methoden nicht, denn der Code kann mit ein wenig krimineller Energie eingesehen, analysiert und letztendlich geknackt werden. Serverseitige Mittel sind jedoch gleichzeitig teuer und mühsamer zu implementieren, weswegen sich JavaScript unter Umständen als Alternative anbietet. Im Folgenden werden Sie einige Möglichkeiten kennenlernen, um den subversiven Elementen, die unerlaubten Zugriff erhalten möchten, das Leben möglichst schwer zu machen. Die PIN Ihrer EC-Karte sollten Sie dennoch nicht auf diese Art und Weise schützen – und sie sowieso am besten nicht online verwalten. Denn das wäre eine genauso kluge Idee, wie die Nummer direkt auf die Karte zu schreiben und sie an einem Geldautomaten liegen zu lassen.


28.1 URL aus Passwort

Die wohl einfachste Methode, einen Bereich per Passwort zu schützen, besteht darin, die eigentliche URL dieses Bereichs einfach nicht zu verraten.


28.1.1 Passwort == URL 

Das »Passwort«, das in diesem Fall eingegeben werden muss, entspricht dann meistens der eigentlichen, geheimen URL:

<html>

<head>

<title>Top Secret</title>

<script type="text/javascript"><!--

function check(f) {

   var pwd = f.elements["pass"].value;

   location.href = pwd;

}

//--></script>

</head>

<body>

<h1>Passwortabfrage</h1>

<form onsubmit="check(this); return false;">

   <input type="password" name="pass" />

   <input type="submit" value="Login" />

</form>

</body>

</html>

Bilder

Abbildung 28.2     Die Passwortabfrage im Browser

Das Passwort hat in diesem Fall oftmals die Form »xlbrmf.html« oder »geheimesverzeichnis/geheimedatei.html«, und die eigentlichen geheimen Daten sind nicht weiter geschützt. Kennt der Feind die URL, kennt er deren Inhalte, denn diese URL kann auch direkt durch Eingabe im Webbrowser aufgerufen werden.

Ganz nebenbei deutet das Passwort schon auf die Art des verwendeten Zugriffsschutzes hin, und auch Leute, die berechtigt Zugriff auf die geheimen Inhalte haben, werden das System durchschauen und die Passwort-abfrage schlichtweg umgehen, indem sie die URL von Hand zusammensetzen. Diese Situation kann man aber noch ein wenig verbessern.

 

28.1.2 Passwort » URL 

Es stellt nur eine Verbesserung dar, die URL aus dem Passwort zusammenzusetzen, beispielsweise indem ein weiteres Verzeichnis vorangestellt und ein spezielles Zeichen angefügt wird. Auch, wenn das nicht mehr ganz so durchsichtig ist, das eigentliche (schwache) Schutzprinzip bleibt dasselbe: Die URL selbst ist ungeschützt.

<html>

<head>

<title>Top Secret</title>

<script type="text/javascript">

function check(f){

   var pwd = f.elements["pass"].value;

   var url = "geheimverzeichnis/";

   url += pwd;

   url += "-geheim.html";

   location.href = url;

}

//--></script>

</head>

<body>

<h1>Passwortabfrage</h1>

<form onsubmit="check(this); return false;">

   <input type="password" name="pass" />

   <input type="submit" value="Login" />

</form>

</body>

</html>

Lautet das Passwort nun beispielsweise »galileo«, so würde die (relative) URL geheimesverzeichnis/galileo-geheim.html aufgerufen werden.

 

28.1.3 f : Passwort ® URL

Eine weitere Idee besteht darin, die URL zwar aus dem Passwort zu erzeugen, den Zusammenhang aber nicht so offensichtlich wie oben darzustellen.

In Kapitel 27 haben Sie die Funktionen codeschutz_encode() und codeschutz_decode() kennen gelernt, die eine Zeichenkette durch die Verschiebung von Buchstaben verschlüsseln (z.  B. wird aus einem a ein b, aus b wird c und so weiter; aus z wird a). Ihnen stehen nun zwei Varianten zu Verfügung:

>

Sie geben dem geheimen Verzeichnis (oder der geheimen Datei) einen sprechenden Namen (zum Beispiel »geheim«). Das Passwort muss nun derart beschaffen sein, dass die Anwendung von codeschutz_decode() (oder wahlweise codeschutz_encode()) »geheim« zurückliefert.

 

>

Sie geben dem Passwort einen sprechenden Namen (zum Beispiel »geheim«). Der Name des versteckten Verzeichnisses oder der versteckten Datei muss das Ergebnis der Anwendung von codeschutz_decode() oder codeschutz_encode() auf das Passwort sein.

Bei der Verwendung einer Schrittweite von 1 bei der Verschlüsselung würde aus »geheim« der String »hfifjn« werden (denn codeschutz_ encode("geheim", 1) ergibt "hfifjn"). Sie haben also zwei Möglichkeiten:

>

Das Passwort ist »hfifjn« (oder, bei der Verwendung von codeschutz_decode(), »fdgdhl«), und der Verzeichnisname lautet »geheim«.

 

>

Das Passwort ist »geheim«, und der Verzeichnisname ist – je nachdem, ob codeschutz_decode() oder codeschutz_encode() verwendet wird – »hfifjn« oder »fdgdhl«.

Je nach Art Ihrer Website und Ihrer Zielgruppe sollten Sie sich überlegen, ob Sie Ihren Besuchern ein schwer zu merkendes Passwort zumuten können oder ob Sie dann doch lieber dem geheimen Verzeichnis einen kryptischen Namen geben.

Im Folgenden sehen Sie Code, der das Passwort decodiert (oder codiert) und dann die entsprechende URL aufruft:

<html>

<head>

<title>Top Secret</title>

<script type="text/javascript"><!--

function codeschutz_encode(s, delta) {

   var temp = "";

   var alt, neu;

   for (var i=0; i<s.length; i++) {

      alt = s.charCodeAt(i);

      if (alt>=65 && alt<=90) {

         neu = alt + delta;

         if (neu > 90) {

            neu -= 26;

         }

      } else if (alt>=97 && alt<=122) {

         neu = alt + delta;

         if (neu > 122) {

            neu -= 26;

         }

      } else {

         neu = alt;

      }

      temp += String.fromCharCode(neu);

      }

   return temp;

}

 

function check(f) {

   var pwd = f.elements["pass"].value;

 

   url = codeschutz_encode(pwd, 13);

   location.href = url;

}

//--></script>

</head>

<body>

<h1>Passwortabfrage</h1>

<form onsubmit="check(this); return false;">

   <input type="password" name="pass" />

   <input type="submit" value="Login" />

</form>

</body>

</html>

Die hier vorgestellten Methoden haben alle eines gemeinsam: Sie bauen darauf, dass die URL der geheimen Inhalte tatsächlich geheim ist. Sobald die URL bekannt ist, kann sie auch direkt aufgerufen werden, es gibt keinen Schutz. Im nächsten Abschnitt lernen Sie Methoden kennen, um die eigentlichen Seiten ebenfalls zu schützen – mit JavaScript natürlich.

28.2 Seiten mit Cookies schützen  

Um eine Seite mit JavaScript-Mitteln vor unbefugtem Zugriff zu schützen, gibt es prinzipiell zwei Möglichkeiten:

>

Die Seite wird vollständig von JavaScript erzeugt.

 

>

Irgendeine Form der Authentifizierung wird ausgeführt; schlägt diese fehl, wird der Benutzer auf eine Fehlerseite weitergeleitet.

All diese Methoden haben eines gemeinsam: Sie funktionieren ohne JavaScript entweder gar nicht, oder sie können durch das Abschalten von JavaScript ausgehebelt werden (weil dann beispielsweise die Weiterleitung nicht mehr funktioniert).

Wir werfen in diesem Abschnitt nur einen Blick auf diejenigen Möglichkeiten, die eine Seite direkt mit JavaScript schützen. Um einen eingeloggten Benutzer festzustellen, verwenden wir Cookies.


 

 

28.2.1 Passwort im Quelltext 

Cookies können dazu verwendet werden, Textdaten lokal auf dem Rechner des Benutzers zu speichern. Mehr dazu erfahren Sie in Kapitel 12. In den folgenden Listings werden wir einige der Hilfsfunktionen verwenden, die in diesem Kapitel erstellt worden sind – unter anderem Funktionen zum Setzen und Auslesen von Cookies:

>

Mit cookie_lesen() lesen Sie den Wert eines Cookies aus.

 

>

Mit cookie_setzen() setzen Sie einen Cookie.

Der entsprechende Cookie darf nur dann gesetzt werden, wenn das Passwort korrekt eingegeben worden ist. Dies ist eine weitere Schwäche des Algorithmus, denn wie Sie in Kapitel 27 gesehen haben, lässt sich der eigentliche Quellcode nicht schützen, weswegen ein finsterer Geselle mit ein wenig Mühe das Passwort herausfinden kann.

Für das folgende Beispiel verwenden wir wieder die Funktion codeschutz_encode(). Das Passwort steht dann verschlüsselt, aber mit ein wenig Aufwand knackbar, im Quelltext:

<html>

<head>

<title>Top Secret</title>

<script type="text/javascript"><!--

function cookie_setzen() {

   var anzParameter = cookie_setzen.arguments.length;

   var parameter = cookie_setzen.arguments;

   var name = parameter[0];

   var value = (anzParameter >= 2) ? parameter[1] : "";

   value = escape(value); // URL-Codierung

   var expires = (anzParameter >= 3) ? parameter[2] : null;

   if (expires != null) {

      if (expires.toGMTString) {

         expires = expires.toGMTString();

      }

   }

   var domain = (anzParameter >= 4) ? parameter[3] : null;

   var path = (anzParameter >= 5) ? parameter[4] : null;

   if (path != null) {

      path = escape(path); // Sonderzeichen umwandeln

   }

   var secure = (anzParameter >= 6) ? parameter[5] : null;

   var c = name + "=" + escape(value);

   if (expires != null) {

      c += "; expires=" + expires;

   }

   if (domain != null) {

      c += "; domain=" + domain;

   }

   if (path != null) {

      c += "; path=" + path;

   }

   if (secure) {

      c += "; secure";

   }

   document.cookie = c;

}

 

function codeschutz_encode(s, delta) {

   var temp = "";

   var alt, neu;

   for (var i=0; i<s.length; i++) {

      alt = s.charCodeAt(i);

      if (alt>=65 && alt<=90) {

         neu = alt + delta;

         if (neu > 90) {

            neu -= 26;

         }

      } else if (alt>=97 && alt<=122) {

         neu = alt + delta;

         if (neu > 122) {

            neu -= 26;

         }

      } else {

         neu = alt;

      }

      temp += String.fromCharCode(neu);

      }

   return temp;

}

 

function check(f){

   var pwd = f.elements["pass"].value;

   if (codeschutz_encode(pwd, 1) == "hfifjn") {

      //"geheim"

      cookie_setzen("Login", "ok");

      location.href = "geheim.html";

   }

}

//--></script>

</head>

<body>

<h1>Passwortabfrage</h1>

 

<form onsubmit="check(this); return false;">

   <input type="password" name="pass" />

   <input type="submit" value="Login" />

</form>

</body>

</html>

Die Datei geheim.html (und alle anderen, geschützten Seiten) müssen dann den folgenden Code enthalten, der überprüft, ob der Cookie gesetzt ist. Falls nicht, wird der Benutzer auf eine Fehlerseite geschickt:

<html>

<head>

<title>Top Secret</title>

<script type="text/javascript"><!--

function cookie_lesen(name) {

   var i = document.cookie.indexOf(name + "=");

   var c = "";

   if (i > –1) {

      var ende = document.cookie.indexOf("; ",

                 i+name.length+1);

      if (ende == –1) {

         ende = document.cookie.length;

      }

      c = document.cookie.substring(i+name.length+1, ende);

   }

   return unescape(c);

}

 

if (cookie_lesen("Login") != "ok") {

   location.href = "fehler.html";

}

//--></script>

</head>

<body>

Geheime Inhalte ...

</body>

</html>

Die Datei fehler.html enthält eine Fehlermeldung. Sie ist hier nicht angeführt, da sie aus dem JavaScript-Blickwinkel nichts Neues bringt. Sie müssen die Datei also selbst erstellen und mit einer aussagekräftigen Fehlermeldung versehen.


28.2.2 Mit Java

Wenn Sie das Passwort nicht im Klartext (oder nur schwach verschlüsselt, wie oben gesehen) im Quelltext unterbringen möchten, steht Ihnen eine (zugegebenermaßen etwas extravagante) Alternative zur Verfügung. Das Passwort wird in einem (unsichtbaren) Java-Applet gespeichert.

Wie Sie vielleicht wissen (etwa nach Lektüre von Kapitel 24), können Sie von JavaScript aus alle als public deklarierten Methoden eines Java-Applets aufrufen.

Sie benötigen also ein Java-Applet, das Folgendes erledigt:

>

Es speichert das Passwort in einer Variablen.

 

>

s bietet eine Methode an, die eine Zeichenkette mit dem Passwort vergleicht und dementsprechend true oder false zurückliefert.

Die letztgenannte Methode wird dann vom JavaScript-Code aus aufgerufen. Liefert sie true zurück, wird der Cookie gesetzt (ansonsten nicht).

Beginnen wir mit dem Java-Applet. Wir werden es nicht en detail erläutern, schließlich halten Sie ein JavaScript-Buch in den Händen, kein Java-Buch. Mit Ihren JavaScript-Kenntnissen werden Sie aber nicht allzu viele Probleme haben, das Listing zu verstehen.

import java.applet.*;

import java.awt.*;

public class login extends Applet {

  private String passwort = "geheim"; // das Passwort

   public void paint(Graphics g) {

   }

   public boolean checkLogin(String versuch) {

      return (versuch.equals(passwort));

   }

}

Kompilieren Sie diese Java-Datei mit javac login.java, um die Datei login.class zu erhalten. Binden Sie dann das Applet in eine HTML-Seite ein. Mit JavaScript können Sie dann die Funktion checkLogin() aufrufen:

<html>

<head>

<title>Top Secret</title>

<script language="JavaScript"><!--

function cookie_setzen() {

   var anzParameter = cookie_setzen.arguments.length;

   var parameter = cookie_setzen.arguments;

   var name = parameter[0];

   var value = (anzParameter >= 2) ? parameter[1] : "";

   value = escape(value); // URL-Codierung

   var expires = (anzParameter >= 3) ? parameter[2] : null;

   if (expires != null) {

      if (expires.toGMTString) {

         expires = expires.toGMTString();

      }

   }

   var domain = (anzParameter >= 4) ? parameter[3] : null;

   var path = (anzParameter >= 5) ? parameter[4] : null;

   if (path != null) {

      path = escape(path); // Sonderzeichen umwandeln

   }

   var secure = (anzParameter >= 6) ? parameter[5] : null;

   var c = name + "=" + escape(value);

   if (expires != null) {

      c += "; expires=" + expires;

   }

   if (domain != null) {

      c += "; domain=" + domain;

   }

   if (path != null) {

      c += "; path=" + path;

   }

   if (secure) {

      c += "; secure";

   }

   document.cookie = c;

}

function check(f){

   var pwd = f.elements["pass"].value;

   var applet = document.loginApplet;

   if (applet && applet.checkLogin

              && applet.checkLogin(pwd)) {  // Passwort ok?!

      cookie_setzen("Login", "ok");

      location.href = "geheim.html";

   }

}

//--></script>

</head>

<body>

<h1>Passwortabfrage</h1>

<form onsubmit="check(this); return false;">

   <input type="password" name="pass" />

   <input type="submit" value="Login" />

</form>

<applet code="login.class" name="loginApplet"

        width="1" height="1"></applet>

</body>

</html>

Die Überprüfung, ob ein Cookie vorliegt, nehmen Sie dann auf den geschützten Seiten wie gehabt vor.

Damit haben Sie einen geschützten Bereich mit JavaScript erstellt, der aber wie folgt ausgehebelt werden kann:

gpBilder
 

durch Deaktivierung von JavaScript

 

gpBilder
 

durch manuelles Setzen des Cookies (was leider einfacher ist als man denkt)

 

28.3 Ein Blick über den Tellerrand

Wenn serverseitige Mittel zur Verfügung stehen, ist das Problem mit den geschützten Seiten schon etwas anderes; auf der Serverseite lässt sich der Zugriffsschutz viel einfacher und auch besser realisieren.

Wir werden im Folgenden Lösungen für die Skriptsprache PHP sowie eine Lösung für den Apache Web Server betrachten. Damit müssten Sie auf fast jedem besseren Server einen einfachen Zugriffsschutz realisieren können. Wenn Ihr Hoster keine Möglichkeit bietet, serverseitige Skriptsprachen einzusetzen, können Sie diesen Abschnitt getrost überspringen.


28.3.1 PHP

PHP bietet ein so genanntes eingebautes Session-Management. Damit ist es möglich, einen Benutzer auch während mehrerer Sitzungen zu behalten. Rein technisch geschieht das so, dass bei jedem Seitenaufruf in der URL eine eindeutige, standardmäßig 32 Zeichen lange Session-ID übergeben wird, die den aktuellen Benutzer identifiziert. Wenn der Client Cookies unterstützt, umso besser: Dann wird die Session-ID in einem Cookie übergeben.

Auf der Serverseite können Sie abspeichern, ob sich der Benutzer korrekt eingeloggt hat oder nicht. Der Benutzer selbst sieht nur die Session-ID, aber nicht die entsprechende Variable. Er kann es also nicht mit ein wenig Aufwand erreichen, dass er die Variable »eingeloggt ja/nein« von Hand setzen kann, wie das bei der Cookie-Lösung in Abschnitt 28.2 noch der Fall war.

Die Loginmaske sieht folgendermaßen aus: Der Benutzer muss ein Passwort in das Formular eingeben, das dann auf der Serverseite mit dem korrekten Passwort verglichen wird. Da der serverseitige Code nicht an den Benutzer übermittelt wird, können Sie hier das Passwort direkt hineinschreiben.

Wenn das Passwort korrekt ist, wird in der aktuellen Session (Sitzung) abgespeichert, dass der Loginversuch erfolgreich war.

<?php
session_start();
if (isset($_POST['Submit']) &&
    $_POST['Submit'] == 'Login') {
   if (isset($_POST['pass']) &&
      $_POST['pass'] == 'geheim') {
      $_SESSION['Login'] = 'ok';
   }
   header("Location: geheim.php?" . session_name()
                                  . "=" . session_id());
}
?>
<html>
<head>
<title>Top Secret</title>
</head>
<body>
<h1>Passwortabfrage</h1>
<form method="post">
   <input type="password" name="pass" />
   <input type="submit" value="Login" name="Submit" />
</form>
</body>
</html>

Auf den Unterseiten müssen Sie nur noch sicherstellen, dass Benutzer, die noch nicht eingeloggt sind, wieder hinausgeworfen werden.

<?php
session_start();
if (!isset($_SESSION['Login']) ||
    $_SESSION['Login'] != 'ok') {
   header('Location: login.php');
}
?>
<html>
<head>
<title>Top Secret</title>
</head>
<body>
Geheime Informationen ...
</body>
</html>

28.3.2 .htaccess 

Der am weitesten verbreitete Webserver, der Apache, sucht unter UNIX und Linux in jedem Verzeichnis nach einer Datei namens .htaccess (unter Windows ist der Dateiname nicht gültig, dort müssen Sie einen anderen Dateinamen konfigurieren und einsetzen). In dieser Datei kann der Webmaster Zugriffsbeschränkungen für eine Website einrichten.

Eine solche Datei sieht folgendermaßen aus:

AuthUserFile /usr/home/apache/www/htaccess/.htpasswd
AuthName Top Secret
<Limit GET POST>
require valid-user
</Limit>

Damit wird Folgendes festgelegt:

> Das aktuelle Verzeichnis ist geschützt.
> Es dürfen nur autorisierte Benutzer auf Dateien in diesem Verzeichnis zugreifen (require valid-user).
> Der Name des Bereichs, der auch in den Dialogfenstern zur Passworteingabe steht, ist »Top Secret« (AuthName Top Secret).
> Die autorisierten Benutzer und deren Passwörter (natürlich verschlüsselt) stehen in der Datei /usr/home/www/htaccess/.htpasswd.

Nun fehlt Ihnen nur noch das Wissen, wie Sie die Benutzernamen und Passwörter in die Datei .htpasswd schreiben können. Auf Konsolenebene geht das ganz einfach:

htpasswd .htpasswd Benutzername

So können Sie einen neuen Benutzer anlegen oder einen bestehenden Nutzer modifizieren. Die Informationen werden dann zeilenweise in die Datei .htpasswd geschrieben. Die Passwörter werden dabei verschlüsselt, so dass auch das Auslesen der Datei noch keinen Zugriff auf den geschützten Bereich ermöglicht.




Beim erstmaligen Erstellen der Passwortdatei müssen Sie noch den Schalter –c angeben, damit die Datei erzeugt wird.


Das Tutorial ist ein Auszug aus der 7. Auflage des Buches von Christian Wenz:

JavaScript und Ajax - Das umfassende Handbuch
Galileo Computing, 853 Seiten, 8. aktualisierte Auflage

Die Veröffentlichung des Kapitels erfolgt mit freundlicher Genehmigung von Galileo Press.

Mehr Informationen zum aktualisierten Fachbuch für Webentwickler gibt es hier: JavaScript und Ajax
 
Alle Kapitel des Buches:
1 Grundlagen
2 JavaScript-Praxis
3 Professionelles JavaScript
4 Web 2.0 und Ajax
5 Kommunikation
6 Serverseitige Programmierung
7 Sicherheit
8 Praxis
9 Anhang
Bilder


 

DVD-Werbung
Kommentare
Achtung: Du kannst den Inhalt erst nach dem Login kommentieren.
Portrait von Monkeyman26
  • 11.01.2018 - 15:21

Danke für das Tutorial.

Portrait von paufk
  • 07.04.2010 - 01:28

Genial :)
Danke geiles Tutorial mach weiter so

Portrait von sallal
  • 08.10.2009 - 22:48

SUUUPER! Genau das was ich gesucht hab!

Alternative Portrait

-versteckt-(Autor hat Seite verlassen)

  • 24.09.2009 - 11:03

Sehr gutes Tutorial hat mir weiter geholfen.

Portrait von maikl91
  • 16.09.2008 - 15:31

nice...schönes tut, danke...wo gibts des buch?

x
×
×