LogIn-Skript Sicherheit

schiese

Erfahrenes Mitglied
Hallo,
ich möchte für eine kleine Anwendung ein LogIn-Skript schreiben. Nachdem ich schon sehr viel über Session-Hijacking, XSS-Skripting, ... gelesen habe, bin ich etwas verunsichert bezüglich der Sicherheit eines Skripts. Es sollen keine wichtigen Sachen geschützt werden, jedoch möchte ich trotzdem niemandem Zugriff gewähren. Mir geht es hier auch eher ums Prinzip.

Als ersten Schutz nehme ich die folgenden Änderungen vor

PHP:
ini_set(session.cookie_httponly,1) // JavaScript hat keinen Zugriff auf das Session-Cookie!
ini_set(session.use_trans_sid,0)  // kein PHPSESSID= an die Links angehängt
ini_set(session.use_only_cookies) // Sessionverwaltung wird auf das Session-Cookie beschränkt
Ich weiß, dass ich User aussperre, die keine Cookies akzeptieren. Aber Sicherheit geht vor. Ich möchte die Session-ID nicht an die Links anhängen. Das LogIn-Skript sei wie folgt aufgebaut (Das Passwort und der Username sind nur jetzt in der Datei gespeichert):
PHP:
ini_set(session.cookie_httponly,1);
ini_set(session.use_trans_sid,0);
ini_set(session.use_only_cookies,1);

session_start();

if (isset($_POST['name']) && isset($_POST['passwort']))
{
   $ru = "user";
   $rp = "580a03af77ce5ddc2410796eb17b74293f7ffe6a283e18172f7700a1a8de6f27086ae2e6153e4bf7fc61073605d34463917882cb656fea67fc1aea0153e45d08";
   if ((hash("sha512", $_POST['passwort']) === $rp) && ($_POST['name'] === $ru))
   {
     session_regenerate_id(true); // Zusätzliche Sicherheit
     $_SESSION['user'] = "Ich";
     header("LOCATION: index.php?login=true");
   }
   else
   {
     $fehler[] = "Bitte Nutzereingaben überprüfen!";  
   }
}

Das Logout-Skript:
PHP:
session_start();
$_SESSION = array(); // Leert alle Sessionvariablen
session_destroy();
header("LOCATION: index.php?action=logout");
Die Überprüfung ob eingeloggt nehme ich mit
PHP:
if (!session_is_registered("user"))
{
   header("LOCATION: login.php");
}
else
{
   // Code
}
vor.
Die Einschleusung von JavaScript-Code auf meiner Seite schließe ich (als Laie) mal aus. Alle Datenbank-Ausgaben geschehen mit
PHP:
htmlentities($string, ENT_QUOTES, "UTF-8");
wobei JavaScript keine Schäden mehr anrichten kann (ini_set(session.cookie_httponly,1);)?!

Meiner Meinung nach hätte ich jetzt alle Sicherheitslücken geschlossen. Dem ist wohl aber nicht so. Bin über jeden Hinweis (auch Literatur) bezüglich der Sicherheit dieses Skripts dankbar.

EDIT: Das ganze wird später über HTTPS laufen. "Menschliches Versagen" (kein Ausloggen im INet-Cafe) wird durch die Lebensdauer des Session-Cookies abgefangen.

Viele Grüße
schiese
 
Zuletzt bearbeitet:
Hi

Meiner Meinung nach hätte ich jetzt alle Sicherheitslücken geschlossen. Dem ist wohl aber nicht so.
Hast du irgendein spezifisches Problem/Bedrohung im Sinn?

Sonst, fürs Erste fällt mit auf dass,
* ENT_QUOTES bei htmlentities nicht 100% gegen JS schützt,
* man den einzelnen sha512 mit zB. einem PBKDF2-System ersetzen könnte,
* session.cookie_httponly auf die Mithile vom Browser angewiesen ist, also nicht zu sehr drauf verlassen
* HTTPS gut wäre (was du ja planst, nur noch einmal als Bestätigung)
* Salts
* Ich fang grad an, deinen gezeigten Passworthash zu cracken
( :p Klartext: Bitte ändern, nachdem du es öffentlich gepostest hast )

* Deine Userdaten sind hartkodiert. Nicht gerade erweiterbar
 
Zuletzt bearbeitet:
Hallo,
vielen Dank für deine Antwort.

Eine spezielle Bedrohung habe ich nicht. Mir geht es darum, keine Sicherheitslücken im Login zu haben.
Ich dachte, dass wenn ich session.cookie_httponly auf true setze ich abgesichert bin. Ich habe es mit sämtlichen Browsern getestet und konnte nicht auf das Cookie per JS zugreifen.

ENT_QUOTES bei htmlentities nicht 100% gegen JS schützt,
Das mit den ENT_QUOTES war mir nicht bekannt. Habe da auch gleich auf php.net ein Beispiel zu gefunden
PHP:
$a = 'javascript:alert(document.cookie)';
$href = htmlEntities($a, ENT_QUOTES,"UTF-8");
echo "<a href='$href'>link</a>"; # results in: <a href='javascript:alert(document.cookie)'>link</a>
Allerdings biete ich keine Links auf der Homepage an. Dieser Fall wird bei mir nicht vorkommen. Es gibt keine dynamischen Links und keine Gästebücher, Foren, ... . Ich gebe nur Benutzereingaben aus der DB aus oder lade Variablen in ein Input-Feld aber immer mit htmlentities und ENT_QUOTES. Vorher wende ich noch strip_tags() an, da ich keine HTML- und PHP-Tags zulasse. Das müsste doch vor JS schützen?
man den einzelnen sha512 mit zB. einem PBKDF2-System ersetzen könnte,
Das wird natürlich noch verbessert. Mir ging es erst einmal um Session-Hijacking oder sonstige Übernahmemöglichkeiten eines Logins.
Ich fang grad an, deinen gezeigten Passworthash zu cracken
Nur zu. Das ist kein wichtiges oder geheimes Passwort. Extra zum testen zuhause genommen. Wenn du meinst du hast es, kannst es gerne sagen. Interessiert mich auch, wie schnell man so etwas rausbekommt :p
Kann dir auch die Anzahl der Zeichen nennen ;-)
Deine Userdaten sind hartkodiert. Nicht gerade erweiterbar
Kommt alles noch. Mir geht es jetzt erstmal darum, was beim Login zu beachten ist, um keine Sessionübernahmen zu bekommen. Also das z. B. jemand einem anderen einen Link mit einer nicht vergebenen SessionID zuschickt, er sich über die Seite anmeldet, die Session aktiviert ist und der andere ebenfalls mit seinem Account eingeloggt ist. Aber da ich ini_set(session.use_only_cookies,1) gesetzt habe dürfte der Fall bei mir ja nicht passieren.

Viele Grüße
schiese
 
Wenn Du JavaScript ineffektiv machen willst, dann solltest Du die entsprechenden Teile maskieren, die in HTML zu einer Ausführung führen: einerseits die Script-Tags (<script></script>) und andererseits für Links das JavaScript-Keyword (javascript: ). Das sollte aus meiner Sicht – spontan mal darüber nachgedacht – reichen.
 
Hallo,
das heißt, dass ich mit strip_tags() und str_replace("javascript:", "", "$ausgabe") JavaScript unschädlich mache. Gibt es denn noch andere Wege eine Session oder einen Cookie zu übernehmen und sich somit mit einem fremden Account einzuloggen?
 
So, wieder da...
Ich habe es mit sämtlichen Browsern getestet
Lynx und IE6? :p
Ernsthafter, schau dir einmal das an: https://de.wikipedia.org/wiki/Liste_von_Webbrowsern
Und als Vervielfachung gibts die ganzen Versionen pro Browser
Ich will ja nicht sagen, dass es schlecht ist oder so, aber 100% ist nichts.

[Zu ENT_QUOTES] Allerdings biete ich keine Links auf der Homepage an. Dieser Fall wird bei mir nicht vorkommen.
Dann ists in Ordnung.
(ich nehme an, auch onclick´s usw. werde nicht mit Benutzereingaben gefüllt)

Nur zu. Das ist kein wichtiges oder geheimes Passwort. Extra zum testen zuhause genommen. Wenn du meinst du hast es, kannst es gerne sagen. Interessiert mich auch, wie schnell man so etwas rausbekommt :p
Kann dir auch die Anzahl der Zeichen nennen ;-)
Eigentlich hab ichs nur als Witz gemeint, aber ich machs gern wirklich :D
Aber vllt. sagst du mir doch die Zeichenanzahl, ob es sich überhaupt lohnt anzufangen
SHA2-512 ist nach heutigem Stand der Technik praktisch unknackbar, wenn es richtig angewendet wird.
(falsche Anwendung = zB. Passwort zu kurz und keine "künstliche" Verlängerung. PBKDF ist da resistenter)

(und zur Geschwindkeit, ob es die CPU von einem 8 Jahre alten Laptop oder
OclHashcat auf 500 guten AWS-Servern ist, macht natürlich einen Unterschied.

Gibt es denn noch andere Wege eine Session oder einen Cookie zu übernehmen
Genug, aber vermutlich nicht mehr viel, was man als Seitenersteller verhindern kann :)
zB. schon bestehende Malware am Rechner vom Benutzer (unabhängig von JS, Browser oder so). Die vom Browser gespeicherten Cookies auszulesen ist von einem nativen Programm aus einfach, zB. IE hat pro Cookie eine normale Textdatei in einem bestimmten Ordner, und Firefox verwendet eine SQLite-Datenbank.
 
Die Maskierung sollte so gehen:
PHP:
function sanitize_from_javascript( $value ) {
  return str_replace( array("<", ">", ":"), array("&lt;", "&gt;", "&#65306;"), $value );
}
 
Hallo zusammen,
Die werden von mir glatt ignoriert. Der IE6 aufgrund der geringen Verbreitung und des eingestellten Supports und Lynx wegen fehlender JavaScript-Unterstützung. :rolleyes:
Eigentlich hab ichs nur als Witz gemeint, aber ich machs gern wirklich :D
Aber vllt. sagst du mir doch die Zeichenanzahl, ob es sich überhaupt lohnt anzufangen
SHA2-512 ist nach heutigem Stand der Technik praktisch unknackbar, wenn es richtig angewendet wird.
(falsche Anwendung = zB. Passwort zu kurz und keine "künstliche" Verlängerung. PBKDF ist da resistenter)
Ist ein kurzes Passwort. Sind nur 6 Zeichen. Es lautet aber nicht "geheim" :-D Ein weiterer Tip: es beinhaltet sind 3 Buchstaben ;-)
PHP:
function sanitize_from_javascript( $value ) {
 $value = htmlentities($value, ENT_QUOTES,"UTF-8");
  return str_replace(":", "&#65306;", $value );
}
Das ist natürlich besser als die Zeichenkette "Javascript:" komplett zu entfernen. Ich habe die htmlentities noch hinzugefügt.

Vielen Dank
 
Wenn Du die Funktion so definierst, solltest Du sie aber auch noch umbenennen, denn jetzt ist es keine Funktion mehr, die sich allein auf das Maskieren von JavaScript bezieht. Nenne sie lieber "sanitize_for_output" oder so etwas in der Art.
 
Hallo,
das klingt logisch :)
Mir ist jetzt eine andere grundsätzliche Frage aufgekommen. Angenommen der LogIn verlief erfolgreich. Jetzt möchte ich die Usernummer des Users speichern. Wie gehe ich da am besten vor?
Speicher ich die UserID aus der DB direkt in der Session via $_SESSION['userid'] oder erstelle ich besser einen zufälligen Hashwert aus verschiedenen Parametern, wie mit microtime und Nutzerdaten aus dem HTTP-Request (wie z. B. $_SERVER['HTTP_USER_AGENT']) und speicher diesen in der Session und zusätzlich mit der UserID in der DB ab? So könnte ich ja auf jeder Seite nach session_start() gucken, ob die UserID mehr als einmal in der Tabelle vorkommt und falls ja aus der Tabelle löschen, woraufhin ich den Account sperren kann.
 

Neue Beiträge

Zurück