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

Perfekter Login

thescream92

Neues Mitglied
Hiho, ich versuche gerade einen perfekten Login zu schreiben, bei dem SQL-Injections nichts tun können und so... Falls ihr einen Trick findet die Seite zu überlisten oder irgendein weiteres Sicherheitsloch, dann schreibt das bitte ;)

index.php
PHP:
<?php
if (!include('./cfg.php')) {
    echo "<center>Die Server sind zurzeit überlastet!<br /> Bitte versuchen Sie es später erneut. <br /><br />Vielen Dank für ihr Verständnis!</center>";
    exit;
}
?>

<html>
    <head>
        <title>Godrax Webinterface</title>
        <style>
            .headline {
                font-family: Verdana;
                font-size: 15;
            }
            .text {
                font-family: Verdana;
                font-size: 12;
            }
            .input {
                border: 1px solid #949494;
                font-family: Verdana;
            }
            .copyright {
                font-family: Verdana;
                font-size: 10;
            }
        </style>
        <meta http-equiv="Content-Script-Type" content="text/javascript">
        <meta http-equiv="Content-Style-Type" content="text/css">
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    </head>
    <body>
<?
if (!isset($_SESSION['login_fail'])) {
    $_SESSION['login_fail'] = 0;
}
if ($_SESSION['login_fail'] >= 5) {
    echo '<center>Sie haben jetzt fünf mal erfolglos versucht sich einzuloggen. Ihr Computer wurde deswegen aus Sicherheitsgründen für 20 Minuten für den Login gesperrt.</center>';
    exit;
}

if (!isset($_GET['go'])) {
    echo '<table border="0" width="100%" height="100%"><tr><td valign="middle">
    <form name="login" action="./index.php?content=login&go" method="post">
        
        
        <table width="450" height="250" style="border: 1px solid #bababa" align="center" cellspacing="0" cellpadding="0">
        <tr height="30">
            <td style="background-color: #bababa" class="headline">Webinterface</td>
        </tr>
        <tr height="220">
            <td valign="middle" style="background-color: #white">
            
                    <table align="center" cellspacing="2" cellpadding="2" class="text">';
                    if (isset($_GET['fail'])) {
                        echo '<tr><td></td><td><font color="red">-Login fehlgeschlagen</font><br><br></td></tr>';
                    }
                        echo'<tr>
                            <td>E-Mail</td><td><input class="input" type="text" name="mail"></td>
                        </tr>
                        <tr>
                            <td>Passwort</td><td><input class="input" type="password" name="passwort"></td>
                        </tr>
                        <tr>
                            <td>Optionen</td><td><input type="submit" value="Login" class="input"> <input type="reset" value="Reset" class="input"></td>
                        </tr>
                        <tr>
                            <td>Verfügbare Versuche</td><td>';
                            if (isset ($_SESSION['login_fail'])){ echo 5-$_SESSION['login_fail']; }
                            else { echo '5'; }
                            echo'</td>
                        </tr>
                    </table>
            
            </td>
        </tr>
        </table>
        <table width="450" align="center" cellspacing="0" cellpadding="0" class="copyright"><tr><td>Copyright by mir</td></tr></table>
        
    </form>
    </td></tr></table>';
}
else {
    if (!empty($_POST['passwort']) && isstandardusername($_POST['passwort']) && !empty($_POST['mail']) && isstandardusername($_POST['mail'])) {
        $post_mail = $_POST['mail'];
        $post_pass = md5($_POST['passwort']);
        $gefunden = select("SELECT COUNT(*) AS anzahl FROM user WHERE mail='$post_mail' and password='$post_pass'");
        if ($gefunden['anzahl'] == 1) {
            echo "<br /><br /><br /><br /><center>Erfolgreich eingeloggt!</center>";
            $_SESSION['login_fail'] = 0;
            weiterleitung ('./logged/');
        }
        else {
            $_SESSION['login_fail'] = $_SESSION['login_fail']+1;
            header('location:./index.php?fail');
        }
    }
    else {
        $_SESSION['login_fail'] = $_SESSION['login_fail']+1;
        header('location:./index.php?fail');
    }
}


?>

    </body>
</html>

cfg.php
PHP:
<?php


// ---------------------------- MySQL
$host_sql = "localhost";
$user_sql = "XXXX";
$pass_sql = "XXXX";

if (!$link = mysql_connect($host_sql, $user_sql, $pass_sql)){
  echo ("MySQL Connection Error");
  die;
}
if (!mysql_select_db("godrax_interface")){
  echo ("MySQL DB selection Error");
  die;
}

function querry ($query){
  if(empty($query)) return 0;
  if (!mysql_query($query)){
    return 0;
  }
  return 1;
}

function select ($query){
  if(empty($query)) return false;
  $result = mysql_query($query) or die('Query failed!');
  $result = mysql_fetch_assoc($result);
  return $result;
}
// ---------------------------- MySQL ENDE

function isstandardusername ($string){
    if (preg_match("/^[A-Z0-9a-z-_]*$/", $string)){
        return 1;
    }
    else {
        return 0;
    }
}


function weiterleitung ($seite, $dauer_func='1500') {
    echo "
    <script type='text/javascript'>
        window.setTimeout('set()',".$dauer_func.");
        function set() {
            location.href='".$seite."';
            return true;
        }
    </script>
    ";
    return 1;
}

session_start();

?>
 
du hast keinen schutz gegen brute force atacken. php sessions brauchen die zusammenarbeit mit dem client. das cookie muss im header oder in der url vermerkt sein. ist das nicht der fall erkennt der server den client nicht wieder und vergisst die, in der session gespeicherten, variablen.

sql injection ist möglich, abhilfe schafft: PHP: mysql_real_escape_string - Manual

ip sperre, proxyserver aussperren, ssl usw. wären ansätze für ein wirklich sicheres einloggen.

if(!include...) exit; sollte man besser durch require(); ersetzten.
 
Zuletzt bearbeitet von einem Moderator:
Um Sql injection zu vermeiden solltes du PDO verwenden! Die alte zugriffs Metode die du für die Datenbank verwendest ist nicht sicher auch nicht wenn du mysql_real_escape_string verwendest.

Desweiteren nutz es dir nix nur den Login vorgang sicher zu machen du mußt auch alle nachfolgenden seiten ausreichend schützen sonst wird dein Login einfach umgangen.

Dein Script ist ein normales Login script wie man es aus den Tutorials her kennt sicherheit ist dabei minimal.

SELECT COUNT(*) AS anzahl FROM user WHERE mail='$post_mail' and password='$post_pass'
Weiteres wenn du dich 100% vor Sql injection schützen willst dann verwende bei der Sql abfrage keine Werte von aussen!

$post_mail und $post_pass haben sollten nicht im Sql befehl vorkommen.

Weiters solltes dich gegen cross side Angriffe schützen.

Mfg Splasch
 
du hast keinen schutz gegen brute force atacken. php sessions brauchen die zusammenarbeit mit dem client. das cookie muss im header oder in der url vermerkt sein.
Sorry, aber ich weiß nicht genau, wie ich das machen soll ... kannst du da ein Beispiel geben ?

sql injection ist möglich, abhilfe schafft: PHP: mysql_real_escape_string - Manual
Hmmm aber ich überprüfe doch ob es nur Standardzeichen sind und ohne ' bzw. " kann man doch keine injection machen oder ?
PHP:
if (preg_match("/^[A-Z0-9a-z-_]*$/", $string)){

ip sperre, proxyserver aussperren, ssl usw. wären ansätze für ein wirklich sicheres einloggen.
Welche IPs sperren ? Wie kann ich rausfinden ob ein Proxy verwendet wird und SSL werd ich noch machen.

Um Sql injection zu vermeiden solltes du PDO verwenden!
Was ist das ?

Weiteres wenn du dich 100% vor Sql injection schützen willst dann verwende bei der Sql abfrage keine Werte von aussen!
Wie soll ich denn das SQL bilden und den Nutzer mit der DB vergleichen ???

Weiters solltes dich gegen cross side Angriffe schützen.
Werd ich mich mal drüber schlau machen.

Danke für die schnellen Antworten !
 
Code:
[COLOR=#000000][COLOR=#007700]if ([/COLOR][COLOR=#0000bb]preg_match[/COLOR][COLOR=#007700]([/COLOR][COLOR=#dd0000]"/^[A-Z0-9a-z-_]*$/"[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000bb]$string[/COLOR][COLOR=#007700]))[/COLOR][/COLOR]
reicht nicht aus. mysql_real_escape_string ist standart und sollte min. verwendet werden.

mir ist vor allem diese stelle aufgefallen. hier packst du eine post variable ohne sie zu überpfüfen in das SQL:
Code:
[COLOR=#000000][COLOR=#0000bb]$post_mail [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000bb]$_POST[/COLOR][COLOR=#007700][[/COLOR][COLOR=#dd0000]'mail'[/COLOR][COLOR=#007700]];[/COLOR][/COLOR]
[COLOR=#000000][COLOR=#0000bb]$post_pass [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000bb]md5[/COLOR][COLOR=#007700]([/COLOR][COLOR=#0000bb]$_POST[/COLOR][COLOR=#007700][[/COLOR][COLOR=#dd0000]'passwort'[/COLOR][COLOR=#007700]]);
        [/COLOR][COLOR=#0000bb]$gefunden [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000bb]select[/COLOR][COLOR=#007700]([/COLOR][COLOR=#dd0000]"SELECT COUNT(*) AS anzahl FROM user WHERE mail='$post_mail' and password='$post_pass'"[/COLOR][COLOR=#007700]);[/COLOR][/COLOR]
zu den php cookies:

der server braucht die php session id um die session zuordnen zu können.

diese wird automatisch vom browser im header übergeben. dort steht dann sowas wie:
Code:
PHPSESSID=g9gt8g0t6ivmchosvatsh3vtv6
man kann sie auch per post oder get übergeben:
Code:
<input type="hidden" name="PHPSESSID" value="g9gt8g0t6ivmchosvatsh3vtv6" />
wenn du diese id nicht sendest, behandelt dich das php script jedes mal wie einen neuen besucher mit 5 versuchen.

eine ip sperre speichert die client ip ab und sperrt das formular eine zeit für diese ip.
wenn du proxy server sperren möchtest google einfach mal ein bisschen. das thema wird öfters heiß diskutiert.
ein gängiger ansatz ist es zu prüfen ob $_SERVER['HTTP_CLIENT_IP'] oder $_SERVER['HTTP_X_FORWARDED_FOR'] gesetzt sind.

ich habe noch nicht mit PDO gearbeitet, aber es ist eine, noch sehr junge, erweiterung zum arbeiten mit datenbanken: PHP: PDO - Manual
ist aber keine gängie methode (soweit ich weiß).
 
Ich hab dann mal auf eure Tipps aufbauend etwas weiter gemacht ... Was fehlt noch ?

PHP:
<?php
if (!require('./cfg.php')) {
    echo "<center>Die Server sind zurzeit überlastet!<br /> Bitte versuchen Sie es später erneut. <br /><br />Vielen Dank für ihr Verständnis!</center>";
    exit;
}
?>

<html>
    <head>
        <title>Godrax Webinterface</title>
        <style>
            .headline {
                font-family: Verdana;
                font-size: 15;
            }
            .text {
                font-family: Verdana;
                font-size: 12;
            }
            .input {
                border: 1px solid #949494;
                font-family: Verdana;
            }
            .copyright {
                font-family: Verdana;
                font-size: 10;
            }
        </style>
        <meta http-equiv="Content-Script-Type" content="text/javascript">
        <meta http-equiv="Content-Style-Type" content="text/css">
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    </head>
    <body>
<?
if (!isset($_SESSION['login_fail'])) {
    $_SESSION['login_fail'] = 0;
}
$zeit = time()-1200;
$sql = select("SELECT COUNT(*) As anzahl FROM bad_ips WHERE ip = '".getenv('REMOTE_ADDR')."' and zeit > '".$zeit."'");
if (($_SESSION['login_fail'] >= 5) || $sql['anzahl'] > 5) {
    echo '<center>Sie haben jetzt fünf mal erfolglos versucht sich einzuloggen. Ihr Computer wurde deswegen aus Sicherheitsgründen für 20 Minuten für den Login gesperrt.</center>';
    session_destroy();
    exit;
}

if (!isset($_GET['go'])) {
    echo '<table border="0" width="100%" height="100%"><tr><td valign="middle">
    <form name="login" action="./index.php?content=login&go" method="post">
        
        
        <table width="450" height="250" style="border: 1px solid #bababa" align="center" cellspacing="0" cellpadding="0">
        <tr height="30">
            <td style="background-color: #bababa" class="headline">Webinterface</td>
        </tr>
        <tr height="220">
            <td valign="middle" style="background-color: #white">
            
                    <table align="center" cellspacing="2" cellpadding="2" class="text">';
                    if (isset($_GET['fail'])) {
                        echo '<tr><td></td><td><font color="red">-Login fehlgeschlagen</font><br><br></td></tr>';
                    }
                        echo'<tr>
                            <td>E-Mail</td><td><input class="input" type="text" name="mail"></td>
                        </tr>
                        <tr>
                            <td>Passwort</td><td><input class="input" type="password" name="passwort"></td>
                        </tr>
                        <tr>
                            <td>Optionen</td><td><input type="submit" value="Login" class="input"> <input type="reset" value="Reset" class="input"></td>
                        </tr>
                        <tr>
                            <td>Verfügbare Versuche</td><td>';
                            if (isset ($_SESSION['login_fail'])){ echo 5-$_SESSION['login_fail']; }
                            else { echo '5'; }
                            echo'</td>
                        </tr>
                    </table>
            
            </td>
        </tr>
        </table>
        <table width="450" align="center" cellspacing="0" cellpadding="0" class="copyright"><tr><td>Copyright by Godrax</td></tr></table>
        
    </form>
    </td></tr></table>';
}
else {
    // Nur wenn alles angegeben ist und dem standard entspricht - weiter
    if (!empty($_POST['passwort']) && isstandardpass($_POST['passwort']) && !empty($_POST['mail']) && isstandardmail($_POST['mail'])) {
        
        $post_mail = $_POST['mail'];
        $post_pass = md5($_POST['passwort']);
        
        // immer 1 User aus DB laden und mit eingegebenen Daten vergleichen.
        $resource = mysql_query("SELECT * FROM user");
        $fertig = 0;
        while(($row = mysql_fetch_array($resource)) && $fertig == 0){
            if (($row["mail"] == $post_mail) && ($row["password"] == $post_pass)){
                $fertig = 1;
            }
            else {
                $fertig = 0;
            }
        }
        
        // Wenn ein User gefunden wurde
        if ($fertig == 1) {
            $post_mail = mysql_real_escape_string ($post_mail);
            $post_pass = mysql_real_escape_string ($post_pass);
            // SQL mit eingegebenen Daten, die ja sicher stimmen und keine Sonderzeichen haben und noch mit real_esc ... getestet sind
            $ruckgabe = select("SELECT * FROM user WHERE mail='$post_mail' and password='$post_pass'");
                echo "<br /><br /><br /><br /><center>Erfolgreich eingeloggt!</center>";
                $_SESSION['ID'] = $ruckgabe['ID'];
                $_SESSION['nick'] = $ruckgabe['nick'];
                $_SESSION['customer_id'] = $ruckgabe['customer_id'];
                $_SESSION['main'] = $ruckgabe['main'];
                
                $_SESSION['login_fail'] = 0;
                querry ("DELETE FROM bad_ips WHERE ip='".getenv('REMOTE_ADDR')."'");
                
                weiterleitung ('./logged/');
        }
        else {
            $_SESSION['login_fail'] = $_SESSION['login_fail']+1;
            header('location:./index.php?fail');
            add_ip (getenv('REMOTE_ADDR'));
        }
    }
    else {
        $_SESSION['login_fail'] = $_SESSION['login_fail']+1;
        add_ip (getenv('REMOTE_ADDR'));
        header('location:./index.php?fail');
    }
}


?>

    </body>
</html>
PHP:
<?php

// ---------------------------- MySQL
$host_sql = "localhost";
$user_sql = "XXXXX";
$pass_sql = "XXXXX";

if (!$link = mysql_connect($host_sql, $user_sql, $pass_sql)){
  echo ("MySQL Connection Error");
  die;
}
if (!mysql_select_db("godrax_interface")){
  echo ("MySQL DB selection Error");
  die;
}

function querry ($query){
  if(empty($query)) return 0;
  if (!mysql_query($query)){
    return 0;
  }
  return 1;
}

function select ($query){
  if(empty($query)) return false;
  $result = mysql_query($query) or die('Query failed!');
  $result = mysql_fetch_assoc($result);
  return $result;
}
// ---------------------------- MySQL ENDE

function isstandardpass ($string){
    if (preg_match("/^[A-Z0-9a-z-_]*$/", $string)){
        return 1;
    }
    else {
        return 0;
    }
}
function isstandardmail ($string){
    if (preg_match("/^[A-Z0-9a-z-_]*@[A-Z0-9a-z-_]*\.[A-Z0-9a-z-_]*$/", $string)){
        return 1;
    }
    else {
        return 0;
    }
}

function add_ip ($ip){
    if (querry ('INSERT INTO bad_ips VALUES ("'.$ip.'", "'.time().'")')){
        return 1;
    }
    else {
        return 0;
    }
}


function weiterleitung ($seite, $dauer_func='1500') {
    echo "
    <script type='text/javascript'>
        window.setTimeout('set()',".$dauer_func.");
        function set() {
            location.href='".$seite."';
            return true;
        }
    </script>
    ";
    return 1;
}

session_start();

?>
 
Zuletzt bearbeitet:
Code:
if (!require('./cfg.php')) {
    echo "<center>Die Server sind zurzeit überlastet!<br /> Bitte versuchen Sie es später erneut. <br /><br />Vielen Dank für ihr Verständnis!</center>";
    exit;
}
require erzeugt einen fehler und bricht das script ab, wenn es die datei nicht laden kann. das echo und exit danach sind überflüssig. sie befehle würde im fehlerfall nicht mehr ausgeführt.
nachlasen kann man es auf: PHP: require - Manual
 
Jap ich weiß aber ich möchte eine individuelle Ausgabe ;)

Und meine Frage war eher: Wo sind da noch Sicherheitslücken ?
 
wenn du fehler abfangen willst die aus der datei kommen solltest du das mit try {} catch(); machen und wenn du wissen willst ob die datei existiert bevor du sie einbindest dann solltest du das mit file_exists machen.

für dein aktuelles konstrukt sehe ich absolut keine notwendigkeit.
 
Ja das passt schon so ...
Noch eine Frage: Ich habe jetzt noch einen Security Code eingebunden ... ist es jetzt wiiirklich sicher ?
-SQL-Injection geht net, da ich die Daten nicht ins SQL tu.
-brute force atacken gehen auch net wegen dem Security Code, wie praktisch alle anderen automatischen Scripte auch.
 
Mal eine Frage, weil hier gerade das Thema Login ist. Habe jetzt mein Login mit md5 Verschlüsselt, doch leider erfolgt keine Anmeldung. Habe ich mir die Passwörter aus DB und Formular ausgeben lassen, beiom Formular werden grundsätzlich 2 Zeichen angehängt, wo liegt das Problem?

Code:
[B]DB[/B] 4e04ed7f0949e21482e7ddfd21782d [B]Form [/B]4e04ed7f0949e21482e7ddfd21782d[B][I][U][COLOR=black]75[/COLOR][/U][/I][/B]
 
Zähl doch mal: Ein MD5 Hash ist 32 Zeichen lang ... in deiner DB allerdings ist der Hash 30 Zeichen lang - zu kurz, was dir sagt, dass der Hash in die DB entweder nicht richtig eingetragen wird oder das Feld maximal 30 Zeichen zulässt, was ich denke ;)

Jetzt bitte wieder zu meeeeinem Problem, ob der login jetzt sicher ist xD
 
nebenbei, dir ist schon klar das auf deiner seite nur benutzer mit aktiviertem javascript weitergeleitet werden ne? es gibt viele nutzer deren browser nichtmal javascript unterstützt, man sollte da nicht nur die leute beachten die es in ihrem browser ausgeschaltet haben. wie währe es denn für dich wenn du 60% der internetseiten die du besuchst dich nicht durch lassen weil die nicht weiter geleitet werden oder weil sie kein menü sehen? ;)
 
Hmm mal wa shierzu...^^
Ich denke der PHP Interpreter erzeugt Dynamisches HTML und das is ja nur HTML mit Javascript, also wenn er JS net kann wird er die php seiten auch nicht verstehen^^ Also ist es kacke und Wurst ob er JS benutzt oder nicht...

60% der Leute sollten sich wohl dann mal aktualliesieren :smile:. IE is müll wie wärs mit Firefox oder Google Chrome? Opera is doch au toll. Außerdem die einzigsten die den IE5 oder 6 noch benutzen sind PC in Schulen oder Büros, der Moderne Bürger hat sowas net mehr^^

Mfg Wikinger75!
 
Ich denke der PHP Interpreter erzeugt Dynamisches HTML und das is ja nur HTML mit Javascript, also wenn er JS net kann wird er die php seiten auch nicht verstehen^^ Also ist es kacke und Wurst ob er JS benutzt oder nicht...
Das ist schwachsinn - PHP wird auf dem Server ausgeführt und dieser sendet die fertige Page an den Browser ... der macht nichts als das anzuzeigen und JS zu interpretieren ... was heißt, dass PHP und JS nciths miteinander zu tun haben. :mrgreen:
60% der Leute sollten sich wohl dann mal aktualliesieren :smile:. IE is müll wie wärs mit Firefox oder Google Chrome? Opera is doch au toll. Außerdem die einzigsten die den IE5 oder 6 noch benutzen sind PC in Schulen oder Büros, der Moderne Bürger hat sowas net mehr
Riiiiichtig ! Und außerdem: Der Logi ist für eine Seite, wo man Gameserver steuern und kaufen und so kann ... Leute die eigene Server haben, haben meinstens auch Opera oder fast immer Firefox. Ich habe auf meiner privaten Webseite einen Counter, der auch die Browser zählt programmiert ... 754 firefox und 0 IEs seit dem 27. April ... :wink:
Jeder der ein wenig verantwortungsvoll ist, und nicht will, dass Google einem alles ausspioniert, nutzt den Dreck nicht :-P
 
chrome ist ein sehr guter browser. wie der ie8 startet er einen neuen prozess für jeden tab und ist das performanz monster nr1.
ob es fair ist google infos über verhalten als gegenleistung zu schicken ist bedenklich. an 1. stelle sehe ich da die gefahr des monopols auf solche daten.

ansonsten hast du völlig recht. es macht keinen sinn sich eine gameservervewalltung für unrelevante programme zu optimieren!

je nachdem wie komplex deine anwendung werden soll kann zusätzlich PHPIDS » Web Application Security 2.0 o.ä. für dich hilfreich sein.
 
chrome ist ein sehr guter browser. wie der ie8 startet er einen neuen prozess für jeden tab und ist das performanz monster nr1.
Das auf jeeeden Fall - Stürzt ein Tab ab läufts weiter ... nutzt mehrkerner aus ... das Ding hat uper Funktionen ... AAABER ^^ :lol:
ob es fair ist google infos über verhalten als gegenleistung zu schicken ist bedenklich. an 1. stelle sehe ich da die gefahr des monopols auf solche daten.
Gaz deiner Meinung! Ich finde das total dreist :razz:
je nachdem wie komplex deine anwendung werden soll kann zusätzlich PHPIDS » Web Application Security 2.0 o.ä. für dich hilfreich sein.
Ich werds mir mal anschauen ... was ist das denn genau ? :D

Und zum Thread: Verucht mal den Login zu übergehen:
Godrax Webinterface
Ihr habt meine Erlaubnis und mein Versprechen, keine Anzeige wegen 'Hackens' zu bekommen. Aber nur bis zum 15. Mai ;)
 
Zurück
Oben