• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

PHP Login Script so okay und sicher?

aJunkie

Mitglied
Hallo Forum,

bezüglich diesen Threads möchte ich Euch fragen, was ihr von diesem Script und dessen Sicherheit haltet.
Es handelt sich eigentlich nur um einen Script, womit ich mich als einziger Admin einloggen, aber Schaulustige fernhalten möchte.

login:
PHP:
<?php 
### Loginscript
session_start();

if(isset($_POST['submit'])) {                            // wenn Formular abgeschickt
    if(isset($_POST['user']) && !empty($_POST['user']) && isset($_POST['passwort']) && !empty($_POST['passwort'])) {    // wenn User und Passwort eingegeben und nicht leer sind
    
    include('mysqlconnect.php');                        // Datenbankverbindung
    $dbSelect     = mysql_select_db('datenbank',$connect);    // Datenbankauswahl
    $abfrage    = mysql_query("SELECT user, passwort FROM tabelle WHERE user = '".mysql_real_escape_string($_POST['user'])."' LIMIT 1");
    $row         = mysql_fetch_array($abfrage);
    
        if($_POST['user'] == $row['user'] && md5($_POST['passwort']) == $row['passwort']) {
            $_SESSION['eingeloggt'] = TRUE;                // eingeloggt
            $_SESSION['user']        = $row['user'];
            session_regenerate_id();                    // neue Session-ID, um Session-Hijacking zu vermeiden
            $meldung = 'Erfolgreich eingeloggt!';
            header('Location: http://'.$_SERVER['SERVER_NAME'].'/admin');
        } else {                                        // Login fehlgeschlagen
            // Administrator Benachrichtigung vorbereiten
            $meldung = 'Falsches Login! Der Administrator wurde über Fehlversuch informiert!';
            
            $benachrichtigung = "
            <h1>Login-Fehlversuch</h1>\n
            Soeben hat jemand versucht, sich in den ACP einzuloggen und schlug fehl.<br /><br />\n
            <strong>IP-Adresse</strong>: ".$_SERVER['REMOTE_ADDR']."<br />\n
            <strong>Datum | Uhrzeit</strong>: ".date('d.m.Y - H:i:s')."<br /><br />\n
            <strong>Eingegebene Logindaten waren:</strong><br />\n
            <strong>ID-Kennung</strong>: ".htmlspecialchars($_POST['idkennung'])."<br />\n
            <strong>User</strong>: ".htmlspecialchars($_POST['user'])."<br />\n
            <strong>Passwort</strong>: ".htmlspecialchars($_POST['passwort'])."<br />\n";
            
            $header  = "MIME-Version: 1.0\n";
            $header .= "Content-type: text/html; charset=iso-8859-1\n";
            $header .= "From: [email protected] (mein Name)\n";
            
            // Administrator über Login-Fehlversuch benachrichtigen
            @mail('[email protected]', 'Login-Fehlversuch', $benachrichtigung, $header);    // Das @ vor dem mail unterdrückt Fehlermeldungen
            // # Idee: eventuell noch in Datenbank speichern
        }
                
    } else {                                            // User und Passwort nicht eingegeben
            $meldung = 'Logindaten nicht vollständig!';
    }
}
?>
<!-- PROVOSORISCH !-->
<link href="../style.css" rel="stylesheet" type="text/css" />
<div id="container">
<h1>Login</h1>
<?php if(!empty($meldung)) { ?>
<p class="red strong"><?php echo $meldung; ?></p>
<?php 
}
?>
<form action="" method="post">
<table>
<tr><td><strong>ID-Kennung:</strong></td><td><input type="password" name="idkennung" /></td></tr>
<tr><td><strong>User:</strong></td><td><input type="text" name="user" value="<?php if(isset($_POST['user'])) echo $_POST['user']; ?>" /></td></tr>
<tr><td><strong>Passwort:</strong></td><td><input type="password" name="passwort" /></td></tr>
<tr><td><input type="submit" name="submit" value="Einloggen" /></td></tr>
</table>
</form>
</div>
mysqlconnect.php enthät die Datenbankvariablen.

logout.php:
PHP:
<?php
// Logout
session_start();

include('mysqlconnect.php');
mysql_select_db('datenbank',$connect);
$query = mysql_query("UPDATE tabelle SET lastLogin = NOW(), ip = '".$_SERVER['REMOTE_ADDR']."' WHERE user = '".mysql_real_escape_string($_SESSION['user'])."' LIMIT 1", $connect);    // "Letzter Login" aktualisieren

session_destroy();                    // Session zerstören/beenden
header('Location: http://'.$_SERVER['SERVER_NAME'].'/login');    // Nach Logout zur Loginseite weiterleiten
?>
check.php:
PHP:
<?php // Dieser Script wird in jede Datei includet, die geschützt werden soll
session_start();

// Wenn $_SESSION['eingeloggt'] nicht existiert, false ist oder $_SESSION['user'] nicht existiert
if(!isset($_SESSION['eingeloggt']) or !$_SESSION['eingeloggt'] or !isset($_SESSION['user'])) {
    header('Location: http://'.$_SERVER['SERVER_NAME'].'/login');        // zur Loginseite weiterleiten
    exit;    // Abbrechen. Ganz wichtig, um die geschützte Datei nicht auszugeben
}
// ansonsten, wenn also eingeloggt, alles in bester Ordnung und die Datei ist sichtbar.
?>
Beispielseite, die geschützt werden soll:
PHP:
<?php include('../login/check.php'); ?>
Eingeloggt<br />
<a href="/login/logout.php">Logout</a>
Eventuell könnte ich den Logout Script noch in check.php einbinden, um eine Datei zu sparen. Und zwar, dass der Link so gebildet wird: <a href="?logout">Logout</a>
Per Get würde ich auslesen, ob diese Variable existiert und ausloggen.
Gibt es Einwände?

Edit: Beim Logout.php habe ich nun noch die IP-Adresse des letzten Loggers eingefügt.

Weitere Frage: Was bringt md5, wenn ich das Passwort eh auf Seiten wie diesen umwandeln kann?
 
Zuletzt bearbeitet:
Werbung:
Ich würde die check.php lieber wie folgt gestalten:
PHP:
 <?php // Dieser Script wird in jede Datei includet, die geschützt werden soll
session_start();

// Wenn $_SESSION['eingeloggt'] nicht existiert, false ist oder $_SESSION['user'] nicht existiert
if(!isset($_SESSION['eingeloggt']) or !$_SESSION['eingeloggt'] or !isset($_SESSION['user'])) {
    die (header('Location: http://'.$_SERVER['SERVER_NAME'].'/login'));        // Ausführung des gasammten Scriptes beenden, und zu Login weiterleiten
}
// ansonsten, wenn also eingeloggt, alles in bester Ordnung und die Datei ist sichtbar.
?>

Solltest du vor dieser Datei bereits was ausgeben, bekommst du eine Fehlermeldung "can not modify header information...output startet in line"

Abgebrochen wird aufjedenfall.

Weitere Frage: Was bringt md5, wenn ich das Passwort eh auf Seiten wie diesen umwandeln kann?
Ließ dir in dem Link den Text unter der textbox durch, dann weißt du es^^
 
Vor dieser Datei wird nichts ausgegeben.
Das exit; habe ich reingemacht, falls header('Location: *') nicht funktionieren sollte.
Und ich "doppelt" abgesichert bin, dass wirklich nichts ausgegeben werden kann.
 
Werbung:
Deine "Doppelabsicherung" ist durchaus verständlich. Es könnte ja sein, dass wirklich besagte Fehlermeldung kommt, dann wird nicht weitergeleitet. Aus diesem Grund habe ich es in die "die()" funktion gepackt.
Um es deutlicher zu machen kannst du auch so schreiben:
PHP:
 <?php
session_start();
if(!isset($_SESSION['eingeloggt']) or !$_SESSION['eingeloggt'] or !isset($_SESSION['user'])) {
    header('Location: http://'.$_SERVER['SERVER_NAME'].'/login')
    die ('Du hättest eigentlich an http://'.$_SERVER['SERVER_NAME'].'/login geleitet werden sollen. Script wurde des wegen abgbrochen');
}
?>

edit
Habe gerade gelesen das die() äquivalent zu exit() ist. Ich dachte exit; bricht wie return; nur das include/require ab. Dem ist dann wohl nicht so.
 
Ja, das ist auch gut. =) *renommee*
Edit: Achsooo, habe die die() Funktion weiter oben gar nicht gesehen. Na klar!

Und was noch? Also ich meine, ob ihr das so nutzen würdet?
 
Zuletzt bearbeitet:
So direkt würde ich es nicht nutzen, aber man könnte es.

Ich persönlich habe mein Loginsystem so aufgebaut:
PHP:
$keine_sitzung = false;
if (isset ($_POST['username']) && isset ($_POST['password'])) {
	if (isset ($_GET['seite'])) {
		if ($_GET['seite'] == 'logout') {
			$_GET['seite'] = 'home';	
		}
	}
	$username = $_SESSION['username'] = $_POST['username'];
	$password = $_SESSION['password'] = md5 ($_POST['password']);
	setcookie ("username", $username, time() + 60*60*24*365);
	setcookie ("password", $password, time() + 60*60*24*365);
} elseif (isset ($_SESSION['username']) && isset ($_SESSION['password'])) {
	$username = $_SESSION['username'];
	$password = $_SESSION['password'];
} elseif (isset ($_COOKIE['username']) && isset ($_COOKIE['password'])) {
	$username = $_COOKIE['username'];
	$password = $_COOKIE['password'];
} else {
	$keine_sitzung = true;
}
if (isset ($_GET['seite'])) {
	if ($_GET['seite'] == 'logout') {
		$keine_sitzung = true;
		setcookie ("username", "", time() - 60*60*24*365);
		setcookie ("password", "", time() - 60*60*24*365);
		session_destroy();
	}
}
if ($keine_sitzung === false) {
	$login = $db -> select ('SELECT id FROM members WHERE username = "' . $username . '" AND passwort = "' . $password . '"', true);
	if (isset ($login -> id)) {
		$user = new user ($login -> id);
		unset ($login);
		define ('IS_MEMBER', 'TRUE');
		define ('MEMBER_RECHTE', $user -> daten -> rechte);
	} else {
		define ('MEMBER_RECHTE', 0);
	}
} else {
	define ('MEMBER_RECHTE', 0);
}
unset ($username, $password, $keine_sitzung);
Habe dann zb. eine Designdatei, und dort wird dieser Code included. Dann steht er für jede Seite zur Verfügung. Und ich habe dann die Konstanzen MEMBER_RECHTE und IS_MEMBER.

Damit lässt dich dann sehr sehr viel realisieren
 
Werbung:
Okay, danke.
Memberrechte brauche ich derzeit nicht, weil ich der einzige Admin bleiben möchte.
Aber ist dein Script nicht anfällig für Attacken, weil du die Eingaben nicht escapest?
 
Aber ist dein Script nicht anfällig für Attacken, weil du die Eingaben nicht escapest?

Nein, dafür habe ich eine extra Datei. Dort wird jede $_GET, $_POST und $_REQUEST variable durchlaufen und diverse Filter angewendet.

edit

Der Vollständigkeit halber hier noch der Code:
PHP:
<?php
//Gefahren in dem globalen Array Post entschärfen
foreach ($_POST as $var => $value) {
	$value = trim ($value);
	$value = htmlspecialchars ($value, ENT_QUOTES, 'UTF-8');	
	$value = strip_tags ($value);
	$value = stripslashes ($value);
	$value = mysql_real_escape_string ($value);
	$_POST[$var] = $value;
}
//Gefahren in dem globalen Array Get entschärfen
foreach ($_GET as $var => $value) {
	$value = trim ($value);
	$value = htmlspecialchars ($value, ENT_QUOTES, 'UTF-8');	
	$value = strip_tags ($value);
	$value = stripslashes ($value);
	$value = mysql_real_escape_string ($value);
	$_GET[$var] = $value;
}
//Gefahren in dem gloablen Array Cookie entschärfen
foreach ($_COOKIE as $var => $value) {
	$value = trim ($value);
	$value = htmlspecialchars ($value, ENT_QUOTES, 'UTF-8');	
	$value = strip_tags ($value);
	$value = stripslashes ($value);
	$value = mysql_real_escape_string ($value);
	$_COOKIE[$var] = $value;
}
//Gloabalen Array Request Löschen, um Sicherheit zu erhöhen
unset($_REQUEST);
?>
 
Zuletzt bearbeitet:
Werbung:
Zurück
Oben