Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs
ASP German Homepage Homepage
 

Liste

.NET 2.0 (1)
.NET Allgemein (16)
.NET Fu (5)
ADO.NET (11)
Aprilscherz (3)
ASP Grundlagen (44)
ASP Tricks (83)
ASP.NET (44)
ASPIntranet.de (5)
C# (28)
Datenbank (44)
Dokumentation (4)
IIS 6.0 (1)
Komponenten (29)
Optimierung (10)
Server (21)
Sicherheit (34)
Tee Off (6)
VB.NET (6)
WAP (8)
Web Services (11)
XML (9)

RSS 2.0 - Die neuesten fünf Artikel auf AspHeute.com


 

Suchen





 

English Articles
Chinese Articles
Unsere Autoren
 
Link zu AspHeute
Impressum
Werben
Anfragen

Passwörter mit SHA1 absichern

Geschrieben von: Christoph Wille
Kategorie: Sicherheit

Daß man bestimmte Teile einer Website nur für authentifizierte Benutzer zugänglich macht, ist mittlerweile bereits ein üblicher Vorgang. Das Einloggen der Benutzer findet (meist) über ein ASP Formular statt, das nicht über SSL abgesichert ist - und dabei wird das Passwort im Klartext über das Netzwerk übertragen - zur freien Entnahme sozusagen. Der heutige Artikel zeigt, wie man den potentiellen Mitlesern die Arbeit erschweren kann.

Ich möchte gleich vorweg sagen, daß die heute vorgestellte Methode - das Verwenden eines Hash-Algorithmus - nach wie vor Sicherheitsprobleme in sich birgt. Das "einzige", das man gewinnt ist, daß das Passwort nicht mehr geknackt werden kann, wenn man den Netzwerktraffic mitprotokolliert. Technisch ist es aber dennoch möglich, sich als der jeweilige Benutzer auszugeben. Um auch das zu verhindern, müßte man ein zu NT ähnliches Challenge-Response System aufbauen. Dies ist zwar aufwendiger, aber durchführbar.

Für heute bleiben wir aber beim Secure Hash Algorithmus SHA1 (spricht sich wie der ebensolche von Persien aus). Dieser generiert aus einem String einen 160 Bit langen Hash, der eindeutig ist - und zweitens nur in eine Richtung funktioniert: hat man den Hash, kann man daraus das Passwort nicht mehr errechnen. Wenn man also am Client das Passwort durch den Algorithmus schickt, kann jeder, der den Netzwerktraffic protokolliert, nichts mehr damit anfangen.

SHA1 verwenden

Jetzt widmen wir uns der Frage, wie man diesen Algorithmus implementieren muß - gar nicht! Es gibt nämlich die Website JavaScript MD5, auf der man eine JavaScript Implementierung zur Gratis-Verwendung downloaden kann. Obwohl dort immer nur von Client-Side Anwendungen geredet wird, kann man diese ohne Umwege sofort am Server einsetzen (simpletest.asp):

<html>
<head>
<title>SHA1 Simple Test</title>
</head>
<body bgcolor="#ffffff">

<form method="post" action="<%=Request.ServerVariables("SCRIPT_NAME")%>">
<input type="text" name="txtText2Scramble" value="SHA1 ist 160 Bit">&nbsp;
<input type="submit">
</form>

<!-- #include file="serversidesha1.asp"-->
<%
str2Scramble = Trim(Request.Form("txtText2Scramble"))
If "" <> str2Scramble Then
  Response.Write "<pre>" & calcSHA1(str2Scramble) & "</pre>"
End If
%>

</body>
</html>

Ich habe mir erlaubt, eine kleine Includedatei zu erstellen, die auf die sha1.js verweist, die man von JavaScript MD5 downgeloadet hat. Es ist nur ein server-side Wrapper der einfachsten Art:

<script language="JScript" runat="server" src="sha1.js">
</script>

In sha1.js findet sich auch die Implementierung der Funktion calcSHA1, die ich in meinem bescheiden kurzen server-side Code aufrufe. Als Ausgabe erhalte ich einen 40 Zeichen langen String, der die hexadezimale Repräsentation des Hashes darstellt.

Die Login Seite

Der Algorithmus funktioniert also, Zeit ihn bei einem Login Formular einzubauen. Um ein realitätsnahes Beispiel zu erstellen, enthält der heutige Download auch eine Demodatenbank, mit einer Tabelle Logins. Diese hat zwei Spalten: Username und Password. Der Praxisbezug? Auch in der Datenbank speichere ich nur den Hash des Passwortes - dadurch kann ein Hacker nirgends an das Passwort herankommen. Nachteil? Wenn ein Benutzer sein Passwort vergisst, kann man ihm nur ein neues zuweisen - was eigentlich auch deutlich sicherer ist (siehe Windows 2000 Benutzeraccounts).

Ich habe die Seite zweigeteilt - eine Datei enthält das Formular, das angezeigt wird. Die andere enthält die Logik, um den Account zu überprüfen. Diese letztere Datei inkludiert das Formular, sodaß alles wie eine einzige Seite funktioniert - es läßt sich aber leichter verstehen, wenn man die Teile getrennt betrachtet.

Das Formular

Unser "Hauptproblem" ist das Formular, in dem der Benutzer den Benutzernamen und das Passwort eingibt. Ich muß nämlich bevor er das Formular abschickt, das Passwort mit SHA1 hashen. Und der einzige Weg dazu ist, client-seitiges JavaScript zu verwenden.

Ja, ich kenne die Einwände, die jetzt kommen, aber: wer Zutritt zu einem gesperrten Bereich möchte, muß leiden, ergo JavaScript einschalten.

Bevor ich Sie jetzt auf den Code von logonform.asp loslasse, noch ein Hinweis: der Validierungscode plus das Hashen des Passwortes passieren in der JavaScript Funktion Validate.

<html>
<head>
<title>Login</title>
<!--#include file="clientsidesha1.asp"-->
<script language="JavaScript">
var errfound = false;

function Validate() 
{
   errfound = false;
   myForm = document.frmLogon;

   if (!ValidLength(myForm.txtUsername.value,6)) 
      error(myForm.txtUsername,"Bitte geben Sie einen Benutzernamen ein!");
   if (!ValidLength(myForm.txtPassword.value,6)) 
      error(myForm.txtPassword,"Bitte geben Sie Ihr Passwort ein (> 6 ...");

   if (!errfound)
   {
      myForm.txtPassword.value = calcSHA1(myForm.txtPassword.value);
   }

   return !errfound;
}

//function to validate by length
function ValidLength(item, len) 
{
   return (item.length >= len);
}

// display an error alert
function error(elem, text) 
{
// abort if we already found an error
   if (errfound) return;
   window.alert(text);
   elem.select();
   elem.focus();
   errfound = true;
}
</script>
</head>
<body bgcolor="#ffffff">

<table width="100%">
<tr><td align="center">
<table border=1>
<tr><td bgcolor="#33ccff" valign="center" align="center" width="350">
<H1>Login</H1>

<% if bValidationFailed Then %>
<p><strong>Login fehlgeschlagen. Bitte erneut versuchen</strong></p>
<% End If %>
<p>
<form method="post" action="<%=Request.ServerVariables("SCRIPT_NAME")%>" 
       id=frmLogon name=frmLogon LANGUAGE="JAVASCRIPT" onsubmit="return Validate();">
<table>
<tr>
  <td>Username:</td><td><input type=text name="txtUsername" size="20"></td>
</tr>
<tr>
  <td>Password:</td><td><input type=password name="txtPassword" size ="20"></td>
</tr>
<tr>
  <td colspan=2>&nbsp;<br><center>
      <input type="submit" value="Enter secured area"></center></td>
</tr>
</table>
</form>
</p>

</td></tr></table>
</td></tr></table>

</BODY>
</HTML>

Der HTML Code für das Formular ist nichts besonderes, nur aus Sicherheitsgründen müßte man das ACTION Tag herausnehmen, daß niemand, der JavaScript ausgeschaltet hat, das Formular ohne Passwort-Hashing abschickt. Apropos Hash: SHA1 wird über die Datei clientsidesha1.asp eingebunden, die den gleichen Zweck wie sein server-seitiger Bruder erfüllt:

<script language="JavaScript" src="sha1.js"></script> 

Die Validate Funktion ist eigentlich keineswegs "Rocket Science". Es werden die Felder überprüft (willkürlich, hier kann der Leser die Überprüfung nach eigenen Gesichtspunkten gestalten), und danach das Passwort gehasht, und wieder zurück in das Passwortfeld geschrieben. Per POST-Back geht es dann zurück an den Server, an unsere Überprüfungslogik.

Überprüfung des Accounts

Wir bekommen einen Benutzernamen und ein gehashtes Passwort geliefert, und da in unserer Datenbank genau die gleichen Informationen gespeichert sind, brauchen wir nur eine einfache SELECT Abfrage. Der notwendige Code ist in der Datei logon.asp zu finden:

<% @ Language=VBScript %>
<%
bValidationFailed = False
If Request.ServerVariables("CONTENT_LENGTH") > 0 Then
  strUsername = Trim(Request.Form("txtUsername"))
  strPassword = Trim(Request.Form("txtPassword"))
  
  Set conn = Server.CreateObject("ADODB.Connection")
  Set rs = Server.CreateObject("ADODB.Recordset")
  strPath = Server.MapPath("logindb.mdb")
  strConnection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strPath
  conn.Open strConnection
  rs.Open "select * from Logins where Username='" & strUsername & _
       "' AND Password='" & strPassword & "'", conn

  If not rs.EOF and not rs.BOF then
   ' beliebige Daten aus der Tabelle auslesen...
   Session("AccessGranted") = True
   rs.Close
   conn.Close
   Response.Redirect "ok.asp"
   Response.End
  End if

  Response.AppendToLog " Logon failed: " & strUsername & " " & strPassword
  bValidationFailed = True
End If
%>
<!--#include file="logonform.asp"-->

Dieser Code ist selbsterklärend, und einfach zu erweitern: zB mehr Daten aus der Logins Tabelle auslesen, andere Session Variablen setzen, oder ein anderes Redirect-Ziel vorgeben. Ich habe sogar daran gedacht, fehlgeschlagene Logins in das Log mitzuprotokollieren.

Ach ja, beinahe hätte ich es vergessen - die letzte Zeile inkludiert das Login-Formular, das ich in der vorangegangenen Sektion vorgestellt habe. Damit wäre unser sicherer Login realisiert.

Schlußbemerkung

Der SHA1 Algorithmus eignet sich nicht nur für dieses Szenario - was ist, wenn man bei einem Shop keine Cookies verwenden will, und eine Art SessionID im Querystring mitgibt? Hier kann der SHA1 Algorithmus ebenfalls helfen, denn minimalste Änderungen am Inputstring ergeben einen beinahe völlig anderen Hashwert. Andere Kundenwarenkörbe zu "erraten" wird damit beinahe unmöglich.

Download des Codes

Klicken Sie hier, um den Download zu starten.

Verwandte Artikel

Aber bitte mit Rijndael
ASP-basierte Basic Authentication
Benutzerverwaltung leicht gemacht: Teil 1
CAPICOM One
Ein einfacher Eventkalender für Projektteams
Formular-basierte Basic Authentication
Gegengifte für SQL Injection
On Demand Zugriffsrechte für Web Sites vergeben
Passwörter speichern - aber richtig!
PGP-Verschlüsselung bei Dateien
Sicherheitsaspekte bei der Gestaltung von ASP Sites ohne Cookies
Unknackbare Verschlüsselung mit Onetime Pads
Ver- und entschlüsseln von Texten mit PGP
Verwendung von SSL Test-Certificates
Verzeichnissicherheit mit NTFS und IIS Authentifizierung

Links zu anderen Sites

JavaScript MD5

Wenn Sie jetzt Fragen haben...

Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten.

Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.

 

Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.

Bewerten Sie diesen Artikel
 Sehr gut   Nicht genügend  
   1  2  3  4  5  
 

  
   Für Ausdruck optimierte Seite

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.