LogIn-Skript Sicherheit

Die Sessiondaten sollten nur am Server sein, also kein Problem, die UserID direkt zu speichern.

Aber das Accountsperren wegen mehrfacher Logins würd ich mir noch einmal überlegen.
zB. ein Nutzer mit mehreren Geräten, die er abwechselnd verwendet.
Oder Login, Computer stürzt ab bevor das Cookie auf der Platte ist, Neustart, wieder Login.
oder...
 
Hi,

anstatt den Account zu sperren könntest du aber alle anderen Sessions ungültig machen. Somit kann es pro User immer nur eine aktive geben.

Grüsse,
BK
 
Du kannst es auch mit zwei Cookies lösen: einem Hash, der für jeden offenen Browser/PC nur einmal vorhanden ist und den Du in der Datenbank speicherst und dazugehörig in einem zweiten Cookie die Nutzerkennung (ID). Somit hast Du mehr Sicherheit, was die Fälschung von Daten betrifft. Vom Speichern der IP-Adresse rate ich Dir ab, da sich diese einmal pro Tag ändert, also wenn Dein Provider Dich neu im Netz anmeldet.
 
[...]Vom Speichern der IP-Adresse rate ich Dir ab, da sich diese einmal pro Tag ändert, also wenn Dein Provider Dich neu im Netz anmeldet.
Normalerweise, ja. Ich habe bei KD allerdings schon seit Monaten die gleiche IP. Anders sieht es allerdings mobil aus. Mit meinem Handy bekomme ich teilweise im Halbstunden-Takt eine neue IP.
Von daher würde ich auch von der IP-Prüfung abraten, oder diese zumindest auf das B-Netz beschränken (erste beiden Blöcke).

Grüsse,
BK
 
Wie Bratkartoffel gerade erwähnt hat, kann es sein, dass die IP-Adresse gleich bleibt. Da es allerdings keine Verpflichtung dazu gibt, sollte man sich nicht darauf verlassen.
 
ini_set(session.cookie_httponly,1);
ini_set(session.use_trans_sid,0);
ini_set(session.use_only_cookies,1);

Die Zeilen tun gar nichts. (Anführungszeichen um die Strings vergessen.) Ruhig mal das Error-Reporting aktivieren. Entweder in der php.ini oder per:

PHP:
ini_set('display_errors', 1);
error_reporting(E_ALL); // Vor PHP 5.4: E_ALL|E_STRICT schreiben

$fehler[] = "Bitte Nutzereingaben überprüfen!";

Sortier deine Charsets. ;) Es gibt praktisch keinen Grund, Umlaute als Entities zu schreiben.

In der Regel beste Lösung: Editor auf UTF-8 (NFC, ohne BOM) einstellen und in PHP den UTF-8-Charset-Header setzen:

PHP:
header('Content-Type: text/html; charset=UTF-8');

Hinter header-Zeilen mit Location tendenziell immer ein exit; setzen, weil das PHP-Skript sonst erst mal weiterläuft. (Ist im Einzelfall bei Codeausschnitten schwierig zu beurteilen, ob das beabsichtigt ist oder nicht.)

htmlentities($string, ENT_QUOTES, "UTF-8");

Besser: htmlspecialchars($string, ENT_QUOTES, 'UTF-8'); Der Grund ist der gleiche wie bei &uuml; oben: Es müssen lediglich die syntaktisch relevanten Zeichen (<, >, ", ', &) maskiert werden. Bei anderen Zeichen erfüllt eine Maskierung keinen wirklichen Zweck.

Dann vielleicht noch mal zu der Sache mit dem Schutz gegen JavaScript. Das ist eigentlich überhaupt kein Sonderfall und ist ganz normal mit dem erwähnten htmlspecialchars (mit ENT_QUOTES) auch erledigt. Kontextwechsel nach HTML: htmlspecialchars und fertig. Ob in den Daten nun JavaScript-Code steht oder HTML oder PHP-Code oder sonst was, ist völlig egal.

Der „Sonderfall“ bei JavaScript ist der, dass JavaScript-Code über manche HTML-Attribute ausgeführt werden kann.

<div onclick="alert('foo');">click</div>
<a href="javascript:alert('foo')">click</a>

Für so was gibt es keine Escaping-Funktion. Das ist kein Kontextwechselproblem, sondern ein anwendungslogisches Problem.

Bei der ersten Zeile ist es wohl einsehbar, dass es keine gute Idee ist, Nutzereingaben überhaupt – oder zumindest ungefiltert – in derlei Event-Handler zu schreiben. Wie eine Filterung aussehen könnte, ist Sache der Anwendungslogik. Das sollte schon korrekt dort ankommen, wo die Ausgabe zusammengebaut wird.

Bei der zweiten Zeile ist es genauso. Es fällt in die Zuständigkeit der Anwendung, erst gar keine „javascript:“-URIs zu akzeptieren oder an den Ausgabeteil durchzureichen. Das sollte nicht erst beim Generieren der Ausgabe auffallen, weil der Code dort nicht die Befugnisse hat, zu entscheiden, ob JavaScript-Code an der Stelle gewollt ist oder nicht. Es gibt halt auch zig andere Fälle, in denen der Ausgabeteil darauf vertraut, dass die Restanwendung richtige Daten liefert. Wieso sollte er es hier nicht tun?

Edit: Der Ausgabeteil hat sich in Sachen Escaping und dergleichen mit dem Kontextwechsel zum Zielformat zu befassen. Das ist seine Aufgabe.

Das war jetzt zumindest die Theorie. Aber werden wir mal praktisch. :D Es ist zufällig simpel, auf „javascript:“-URIs zu prüfen, und man kann recht sicher sagen, dass die Dinger quasi nie gewollt sind, und es ist bekannt, dass genau dieses Einschleusen von JS-Code einer der prominentesten Angriffsvektoren ist. Deshalb tue ich mich schwer, ernsthaft zu sagen, dass entsprechende Checks im Ausgabecode nichts zu suchen haben – ungeachtet der Tatsache, dass sie dort meines Erachtens an der falschen Stelle stehen.

Die Funktion, von der ich spreche, würde ungefähr so aussehen (ungetestet):

PHP:
function blockXss($uri)
{
    if (0 === strpos(strtolower(trim($uri)), 'javascript:')) {
        throw new Exception('JavaScript URI slipped through');
    }

    return $uri;
}

Anwendung (escape() ist die normale htmlspecialchars-ENT_QUOTES-Funktion):

PHP:
<a href="<?=escape(blockXss($uri))?>">click</a>

Aber man sieht an dem Code meiner Meinung nach schon ganz schön, dass das so ein wenig was von „Ich vertraue meiner eigenen Anwendung nicht“ hat. Das ist etwas schizophren. Dann wiederum ist Vertrauen gut, aber Kontrolle besser.
 
Zuletzt bearbeitet:
Zwei, drei andere Sachen:

Vorher wende ich noch strip_tags() an, da ich keine HTML- und PHP-Tags zulasse.

Das ist weitestgehend sinnlos beziehungsweise eine unnötige Einschränkung des möglichen Contents, die mit der Sicherheit – wenn man es richtig macht – nichts zu tun hat. Die Kontextwechsel (vor allem nach HTML) musst du sowieso beachten (wegen Ampersands, Anführungszeichen und Größer-/Kleiner-Zeichen außerhalb von Tags). Und wenn du die beachtest, dann kann dir auch korrekter HTML- und PHP-Code nichts.

Mit strip_tags sorgst du dann mehr oder weniger lediglich dafür, dass niemand auf deiner Seite komfortabel über HTML oder PHP schreiben kann.

function sanitize_from_javascript [Variante von einfach nur crack]

Löst das falsche Problem auf die falsche Weise, sorry. :) Du kannst sowieso schon mal nicht alle Doppelpunkte durch &#65306; ersetzen. Da kommen die Typographen mit Heugabeln und Fackeln an.

function sanitize_from_javascript [Variante von schiese]

Ne. Gleiche Probleme wie die andere Variante und schwammigerer Fokus, der überraschend exakt mit verschlimmbessert beschrieben werden kann. :)

anstatt den Account zu sperren könntest du aber alle anderen Sessions ungültig machen. Somit kann es pro User immer nur eine aktive geben.

Kann man machen, halte ich aber für ein Anti-Feature, weil Leute heutzutage halt verschiedene Geräte haben, mit denen sie auch zeitgleich eingeloggt sein wollen. Ich mache das ständig bei etwa Twitter.

Es gibt die Option, irgendwo dezent eine Funktion anzubieten, alle anderen Accounts auszuloggen oder zumindest auf weitere Logins hinzuweisen. Ich glaube, so macht Gmail das oder hat das zumindest mal so gemacht. Ich wäre mir aber nicht sicher, dass die Umsetzung vom ersten Fall (mit Auslog-Möglichkeit) trivial ist, weil man ja auch nicht will, dass ein Angreifer die regulären Sessions ausloggt. Aber keine Ahnung. Dazu müsste ich auch erst recherchieren.

Ich glaube, an simplen Lösungen hast du „nur einen Login zulassen“ und „beliebig viele Logins zulassen“. Davon würde ich zu letzterer Variante raten.
 
Zurück