Warning: PDOStatement::execute(): SQLSTATE[HY093]

Matze202

Erfahrenes Mitglied
Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: parameter was not defined in /home/www/doc/*/www/func/user.func.php on line 45

PDOStatement::errorInfo(): Array ( [0] => HY093 [1] => [2] => )

PHP:
    $stmt = $db->prepare("INSERT INTO lwp_user_log_error (ip, login-ts, login-zeitspanne, user_name, user_key, user_pass, log_error)
                            VALUES (:ip, :login-ts, :login-zs, :uname, :ukey, :pass, :ulogerror)");
    $stmt->bindValue(":ip", $_SERVER['REMOTE_ADDR'], PDO::PARAM_STR);
    $stmt->bindValue(":login-ts", $_POST['login-ts'], PDO::PARAM_INT);
    $stmt->bindValue(":login-zs", login_zs(), PDO::PARAM_INT);
    $stmt->bindValue(":uname", $_POST['user_name'], PDO::PARAM_STR);
    $stmt->bindValue(":ukey", $_POST['user_key'], PDO::PARAM_STR);
    $stmt->bindValue(":pass", md5($_POST['user_pass']), PDO::PARAM_STR);
    $stmt->bindValue(":ulogerror", user_log_error('output', NULL), PDO::PARAM_STR);
    $stmt->execute();    //Dies ist die Zeile 45
    echo "<br>\nPDOStatement::errorInfo():\n";
    $arr = $stmt->errorInfo();
    print_r($arr);

Alle dieser Einträge bekommen immer Inhalte, wenn dieses Script aufgerufen wird außer dem $_POST['user_name'], welches ich auch schon ausgeklammert hatte und aus dem Prepare entfernte, aber dies brachte leider auch keine Änderung.

Wie ich bei meiner mehrstündigen Suche mal gelesen hatte, sollte dieser Fehler häufig auftreten, wenn man mit bindValue oder bindParam einen leeren Wert einbinden würde.

Leider habe ich aber kein Beispiel gefunden, wie ich dies unterbinden kann ohne große Scripte dafür zu schreiben.

Gruß Matze202.
 
Mal am Rande:

Es ist schön, dass du PDO mit Prepared Statements nutzt, MD5 aber als Hashalgorithmus für Passwörter zu nutzen, geht gar nicht! Als sichere Alternative empfehle ich bcrypt bzw. password_hash(), da du PHP benutzt.
 
Ich vermute mal, dass login_zs() und user_log_error() eigene Funktionen sind.
Ich würde mir schon mal jedes einzelne Element ausgeben lassen, ob und wenn ja, was hier übergeben wird.
 
AFAIK ist das Minus-Zeichen auf für einen SQL-Server ein arithmetischer Operator, daher versucht das RDBMS hier eine Subtraktion. Es ist syntaktisch wohl in Ordnung, aber semantisch nicht. Das hat auch mit den Rückgabe-Werten der (User-defined-)Funktionen login_zs() oder user_log_error() nichts zu tun sondern ist ein reines SQL-Problem.

EDIT: Außerdem ist es im Falle des Einsatzes von MySQL als RDBMS sinnvoll, die Spaltennamen mit Backticks zu escapen.
 
Du darfst die Bezeichner nicht mit Minus-Zeichen definieren. Versuch mal statt :login-ts :logints.

Super danke dir, genau an dem Minus-Zeichen lag es, dafür hatte ich bestimmt so an die 10 Stunden gesucht und nix darüber mit der Fehlermeldung gefunden.

AFAIK ist das Minus-Zeichen auf für einen SQL-Server ein arithmetischer Operator, daher versucht das RDBMS hier eine Subtraktion. Es ist syntaktisch wohl in Ordnung, aber semantisch nicht. Das hat auch mit den Rückgabe-Werten der (User-defined-)Funktionen login_zs() oder user_log_error() nichts zu tun sondern ist ein reines SQL-Problem.

EDIT: Außerdem ist es im Falle des Einsatzes von MySQL als RDBMS sinnvoll, die Spaltennamen mit Backticks zu escapen.

Ja, ich muss mir angewöhnen, wenn ich schon Striche in Namen verwende, dass dies dann auch Unterstriche sein werden.

Nun noch ne Frage, der richtige Backticks ist doch das was sich auf der deutschen Tastatur zwischen dem ß und der Löschtaste befindet und mit einem Shift gedrückt wird oder? Da muss ich mich mal dran gewöhnen.

Mal am Rande:

Es ist schön, dass du PDO mit Prepared Statements nutzt, MD5 aber als Hashalgorithmus für Passwörter zu nutzen, geht gar nicht! Als sichere Alternative empfehle ich bcrypt bzw. password_hash(), da du PHP benutz

Naja das mag schon sein, aber dies ist nur unsicher, wenn man den Computern jede Zeit der Welt lässt und ihre Geschwindigkeit nicht ausbremst.

Ich habe extra eine Funktion eingebaut, welche es verhindert sich einzuloggen, wenn das Formular in weniger als von mir angegebenen Zeit abgesendet wurde und dass sind schonmal mehrere Sekunden. Somit werden in dieser Zeit auch richtige Zugangsdaten nicht akzeptiert, sondern in einer Datenbank gespeichert und wenn von der selben IP mehr als eine vorgegebene Anzahl fehlgeschlagener Logins, wegen falschen Zugangsdaten oder zu schnellem einloggen abgesendet wurden, dann wird schonmal eine IP für ne gewisse Zeit komplett gesperrt. Diese Art von Login-Unterbindung werde ich dem User natürlich auch nicht mitteilen, dass sich die, die illegal eindringen wollen, nicht darauf einstellen können. Somit ist das in meinen Augen schon absolut sicher. ;)

Gruß Matze202.
 
Zuletzt bearbeitet:
Und wie ermittelst du, wie viel Zeit vergangen ist? Evt. ist es vom User fälschbar...

Der Grund für einen Hash ist außerdem nicht die Geschwindigkeit der Einlogversuche
(je nach Länge (und Inhalt) vom richtigem Passwort beim betroffenen Account
kann ein Hash das Einbrechen auf die Art sogar leicher machen, Grund Kollisionen)

Zur Geschwindigkeit, mit der man MD5-Hashes durchprobieren kann:
zB. Ende 2012 hat ein Norweger rund 13 Milliarden pro Sekunde und GPU berechnet...

PS: "Absolut" sicher gibts nicht
 
Und wie ermittelst du, wie viel Zeit vergangen ist? Evt. ist es vom User fälschbar...
Stimmt, daran hatte ich noch nicht gedacht, daher hatte ich bisher die Aufrufzeit über das Formular übegeben, jetzt werde ich es so machen, dass zu jeder IP-Adresse, beim aufrufen der Login-Seite die IP und der entsprechende Zeitpunkt in der Datenbank gespeichert wird. Dieser Zeitpunkt ist eine gewisse Zeit gültig und kann ja nicht von User geändert werden. Das einzige was der User ändern könnte, wäre seine IP-Adresse, aber beim neuen aufrufen des Formulars wird der Zeitpunkt wieder geändert bzw. bei einer neuen IP-Adresse neu eingetragen.

Der Grund für einen Hash ist außerdem nicht die Geschwindigkeit der Einlogversuche
(je nach Länge (und Inhalt) vom richtigem Passwort beim betroffenen Account
kann ein Hash das Einbrechen auf die Art sogar leicher machen, Grund Kollisionen)
Zur Geschwindigkeit, mit der man MD5-Hashes durchprobieren kann:
zB. Ende 2012 hat ein Norweger rund 13 Milliarden pro Sekunde und GPU berechnet...
Das Streite ich ja auch nicht ab, aber ich verrate dem ja auch nicht, ob die Zugangsdaten falsch waren oder er ja halt zu schnell sich eingeloggt hat und wenn er auch 100 Milliarden pro Sekunde mir schicken würde, so werde ich ihn für ne gewisse Zeit nicht mehr auf die Seite lassen, da ich ihn bereits bei 30 Versuchen pro Minute von der Seite für mindestens 24 oder 48 Stunden und bei nochmaligem versuch dauerhaft sperren werde, weil der dann mit Sicherheit eine feste IP haben wird.

Somit unterbinde ich dann auch, dass diese Seiten von denen zu sehr überlastet würden und unterbinde auch die Gefahr einer Kollision oder nicht?

PS: "Absolut" sicher gibts nicht
Das ist mir klar, aber man kann es ja versuchen, denen nicht zu leicht zu machen und wenn die pro Tag nicht mal 1000 Versuche haben, sind das gerade mal pro Jahr keine 365.000 Versuche, da kannste dir schon mal sicher sein, wenn es jemand so langsam machen würde, viele Jahre brauchen würde um überhaupt rein zu kommen, sofern er keine Anhaltspunkte des richtigen Passworts und Usernamen hat. Zudem habe ich noch ne andere Falle drin, die ich nicht hier öffentlich verrate. ;)
 
Wie stellst du die IP fest? Bist du dir im Klaren darüber, dass man über Proxies kommen kann? Und das es Listen mit (anonymen) Proxies im Internet zur freien Verfügung gibt? Wie löst du das?

Grundsätzlich ist es keine gute Idee, sich auf die Header zu verlassen, die dir $_SERVER zur Verfügung stellt.

Mal folgender Vorschlag: beschränke die Anzahl der Fehl-Versuche auf 5, sperre für 10 Min (damit sind es max. 30 Versuche/Stunde), merke die Anzahl der Fehlversuche pro User-Account. Verwende einen sichereren Algo als MD5! Warum wehrst du dich eigentlich so verbissen dagegen? Sheel und ComFreek haben da schon absolut recht. MD5 ist ein Digest-Algo (steckt ja schon im Namen), und kein Passwort-Hash-Algo. Was bringt dir der Einsatz von MD5 im Gegentum von bspw. password_hash()? Klar, hast du jetzt in deiner DB schon die MD5-Summen für die Passwörter gespeichert, damit scheint das Kind in den Brunnen gefallen, aber es gibt eine einfach Lösung für dein Problem:

Erstelle eine weitere Spalte mit vernünftiger Breite für einen richtigen Passwort-Hash und migriere die Passwörter einfach beim nächsten Login dort rein, lösche im gleichen Zug die MD5-Summen raus und so wirst du Stück-für-Stück deine User die Migration durchführen lassen, ohne dass die was davon merken.

EDIT: Und noch was: Wenn du "ihn" für einige Zeit nicht auf die Seite lässt, wie äußert sich das dann? Bekommt das Gegenüber das mit, das es nicht auf die Seite gelassen wird? Wenn ja, teilst du dem Bot, der gegenüber arbeitet ja implizit mit, dass die Credentials falsch sind. Und noch was: verlängert sich der Verbotszeitraum bei jedem weiteren Fehlversuch?
 
Zuletzt bearbeitet:
Naja das mag schon sein, aber dies ist nur unsicher, wenn man den Computern jede Zeit der Welt lässt und ihre Geschwindigkeit nicht ausbremst.
sheel hat schon korrekt angemerkt, dass MD5 sehr, sehr schnell als ein potentieller Hashalgorithmus für Passwörter zu berechnen ist. Genau deswegen sollte man es dafür nicht nutzen.

Ich habe extra eine Funktion eingebaut, welche es verhindert sich einzuloggen, wenn das Formular in weniger als von mir angegebenen Zeit abgesendet wurde und dass sind schonmal mehrere Sekunden.
Wir reden hier aneinander vorbei.
Du redest über Bruteforce-Attacken von einer einzelnen IP-Adresse. Ich redete über das Herausfinden von Passwörter, wenn man die Hashe kennt (d. h. wenn Zugang zur DB besteht oder ein Abbild dieser).

Gegen das Blocken einzelner IP-Adressen gibt es u. a. Botznetze.


Hashalgorithmen mit Kollisionen sind nicht wirklich ein Problem, da preimage attacks der größere Schwachpunkt beim Hashen von Passwärtern sind, siehe auch hier http://security.stackexchange.com/a/61550/27234. Und genau dieser Angriffsvektor ist bei MD5 sehr leicht.


Zudem habe ich noch ne andere Falle drin, die ich nicht hier öffentlich verrate.
Mir scheint es, dass du zu sehr auf security through obscurity vertraust. Wenn das das einzige Mittel gegen Angreifer bei dir ist, dann hast du ein sehr schwaches System.
 
Zurück