Biete einfache (webbasierte) Stempeluhr mit Exportfunktion
Hallo liebe Kollegen,
2016 stellte ein Forumskollege eine Suchanfrage:
Suche einfache (webbasierte) Stempeluhr mit Exportfunktion
Aus diesem Thread heraus ergab es sich, dass ich eine solches Zeiterfassungssystem schrieb und in dem Thread zur Verfügung stellte.
Es ist im Wesentlichen eine Sammlung von PHP-Scripten, die aber auf einer veralteten php-Version basiert.
Ich habe jetzt die alten Skripte umgeschrieben, sodass sie auch mit aktuellen Apache/MySQL/php-Kombinationen (Windows und Linux) kompatibel sind.
Die Datenbankanbindung erfolgt jetzt per PDO-Treiber.
Es kamen in dem Zuge auch ein paar kleine, neue Funktionen und Bugfixes hinzu.
Es gibt auch ein Demosystem, damit man sehen kann, um was es sich eigentlich handelt.
http://zeiterfassung.pedant.de
Die Zugangsdaten zum Demosystem, alle Informationen und ein Downloadlink sind auf meiner Webseite zu finden:
https://www.pedant.de/html/tools_zeiterfassung.php
Wer das alte System schon nutzt und umsteigen möchte, der kann seine alte Datenbank weiter nutzen.
Es muss nur eine neue, zusätzliche Tabelle eingefügt werden.
Dazu gibt es im neuen System, im Unterordner "sicherungen" eine SQL-Datei namens
"Tabelle_status_hinzufuegen.sql", die einfach importiert werden kann.
Ich freue mich auf Eure Kommentare.
Gruß Frank
2016 stellte ein Forumskollege eine Suchanfrage:
Suche einfache (webbasierte) Stempeluhr mit Exportfunktion
Aus diesem Thread heraus ergab es sich, dass ich eine solches Zeiterfassungssystem schrieb und in dem Thread zur Verfügung stellte.
Es ist im Wesentlichen eine Sammlung von PHP-Scripten, die aber auf einer veralteten php-Version basiert.
Ich habe jetzt die alten Skripte umgeschrieben, sodass sie auch mit aktuellen Apache/MySQL/php-Kombinationen (Windows und Linux) kompatibel sind.
Die Datenbankanbindung erfolgt jetzt per PDO-Treiber.
Es kamen in dem Zuge auch ein paar kleine, neue Funktionen und Bugfixes hinzu.
Es gibt auch ein Demosystem, damit man sehen kann, um was es sich eigentlich handelt.
http://zeiterfassung.pedant.de
Die Zugangsdaten zum Demosystem, alle Informationen und ein Downloadlink sind auf meiner Webseite zu finden:
https://www.pedant.de/html/tools_zeiterfassung.php
Wer das alte System schon nutzt und umsteigen möchte, der kann seine alte Datenbank weiter nutzen.
Es muss nur eine neue, zusätzliche Tabelle eingefügt werden.
Dazu gibt es im neuen System, im Unterordner "sicherungen" eine SQL-Datei namens
"Tabelle_status_hinzufuegen.sql", die einfach importiert werden kann.
Ich freue mich auf Eure Kommentare.
Gruß Frank
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 5898588752
Url: https://administrator.de/contentid/5898588752
Ausgedruckt am: 21.11.2024 um 16:11 Uhr
25 Kommentare
Neuester Kommentar
Einen? Da werden jegliche Kontextwechsel ignoriert, ich würde dringend davon abraten das Script einzusetzen!
Wenn es der einzige wäre
Nach kurzem Überfliegen der Quelle sehe ich noch eine Menge potentieller SQLi-Lücken, da Variablen ungesehen in SQL-Queries übernommen werden. Anstatt es mit Prepared Statements der PDO zu machen.
Alles in allem ist das eine nette Idee, allerdings ist (leider) allzu offensichtlich, dass grundlegende Kenntnisse in PHP und objektorientierter Entwicklung fehlen
Nicht nur wegen der Sicherheitslücken sondern auch wie der Code insgesamt aussieht.
Wenn du zart besaitet bist, bitte hier aufhören zu lesen. Wenn du an aufrichtigter, wenn auch harter Kritik interessiert bist:
Mal als unvollständige Liste dessen, was mir sofort ins Auge springt:
Das würde ich meinem aktuellen Azubi so nicht durchgehen lassen
Nach kurzem Überfliegen der Quelle sehe ich noch eine Menge potentieller SQLi-Lücken, da Variablen ungesehen in SQL-Queries übernommen werden. Anstatt es mit Prepared Statements der PDO zu machen.
Alles in allem ist das eine nette Idee, allerdings ist (leider) allzu offensichtlich, dass grundlegende Kenntnisse in PHP und objektorientierter Entwicklung fehlen
Nicht nur wegen der Sicherheitslücken sondern auch wie der Code insgesamt aussieht.
Wenn du zart besaitet bist, bitte hier aufhören zu lesen. Wenn du an aufrichtigter, wenn auch harter Kritik interessiert bist:
Mal als unvollständige Liste dessen, was mir sofort ins Auge springt:
- Englisch + Deutsch wild gemischt
- Die Einrückung im Code ist auch eher nach Zufall als nach einer festen Regel
- Die wild versprengten Tabs in den echo-Blöcken (Tabs hätten dem Code an sich gut getan). Einrückung im ausgegebenen HTML-Code ist eigentlich nicht wichtig, wenn man mit den Browser-Tools debugged, macht aber den PHP-Code lesbarer. Das fällt extrem in html/login.php auf, wo mit über 50 aufeinanderfolgenden "echo()"-Zeilen und ohne Ende Tab-Zeichen irgendwelcher HTML- und Javascript-Code ausgegeben wird. Dafür hat uns PHP die HEREDOC-Marker gegeben. Oder Template-Systeme.
- Dass dort ein Kennwort vorausgefüllt im Input-Feld mitgeliefert wird, ist ziemlich unschön.
- Die Art und Weise, wie du Eingabevariablen in der common/get_post_session.php behandelst, lässt darauf schließen, dass du die Funktionsweise des dankenswerterweise schon lange verstorbenen "register_globals"-Verhaltens nachbilden willst. Es hat einen Grund, warum man keine Variablen von außen akzeptiert, die im Code eine Funktion abbilden können. Ich kann dir mit entsprechenden GET-Parametern einfach eine Session zusammenknuppern, wie ich sie benötige. Einfach an die URL anhängen müsste genügen, ist aber ungetestet.
?_SESSION[angemeldet]=1
- Die Stempelzeiten in der Tabelle werden separat als Datum und Uhrzeit gespeichert, das macht eigentlich aus Programmsicht wenig Sinn - denn Nachtschichten mit Datumswechsel sind damit prinzipbedingt nicht möglich
- Charset "latin1" zerfällt dir mit Nicht-Lateinischen Zeichen (kyrillisch, griechisch,...)
- Kennwörter werden als SHA1-Hash gespeichert, das ist mittlerweile auch nicht mehr State Of The Art
- Btw: SQL-Injection-Lücke beim Login: Gib mal als Benutzername ein, dann hat jeder User ab dem Moment das Kennwort "apfelsine"
x"; UPDATE users SET user_password="2e0a7cbdc90eb7a866e23e4125b37b6b293126a0"; --
- Das inhärente Problem der SQL-Injections im Code würde theoretisch mit der PDO sehr gut abgefangen, wenn du denn Prepared Statements verwenden würdest. Allerdings sehe ich auch überall dass du explizit "$dbdatenbank.tabellenname" in den SQL-Queries benutzt, was auch unnötig ist, wenn man denn mit PDO einmal nach der Verbindung die Datenbank auswählt.
Das würde ich meinem aktuellen Azubi so nicht durchgehen lassen
Nun - man sollte eben mal schauen: Es wird was für umsonst angeboten - es steht ja jedem frei das zu nutzen oder nicht. Und da sind sicher einige "unschöne" Dinge drin - andersrum steht es ja jedem Frei den Code entsprechend (ggf. auch nur für sich selbst) zu verbessern... Man sollte lediglich da dazu erwähnen das man solchen Code natürlich _NICHT_ einfach so irgendwo auf nem öffentlichen Webserver ballern sollte u. hoffen das nix passiert. Für ne 3-Personen-Bude die jetzt eben grad von der Zeiterfassungspflicht überrollt wurde und wo es nur intern aufm Server läuft kanns aber ja interessant sein.
WAS man da aber natürlcih primär sehen muss wäre für mich nen ganz anderer Punkt der gegen sowas spricht: Wer ist für die WARTUNG der Software da, wer kann im Zweifel auch Support leisten? Ich stelle mir das schon eher schwer vor wenn man da jetzt fröhlich munter 1-2 Jahre Daten reinklöppelt und dann bei ner "Buchprüfung" plötzlich rauskommt das leider irgendwo nen Fehler war u. die Daten im Nirvana sind... und den Prüfer wird da dann schon interessieren was da los ist u. ich denke "ich habe mal nen Freeware-Script genommen, auf meinen Server gehauen und naja,... doof gelaufen halt" ist da keine valide Antwort :D
WAS man da aber natürlcih primär sehen muss wäre für mich nen ganz anderer Punkt der gegen sowas spricht: Wer ist für die WARTUNG der Software da, wer kann im Zweifel auch Support leisten? Ich stelle mir das schon eher schwer vor wenn man da jetzt fröhlich munter 1-2 Jahre Daten reinklöppelt und dann bei ner "Buchprüfung" plötzlich rauskommt das leider irgendwo nen Fehler war u. die Daten im Nirvana sind... und den Prüfer wird da dann schon interessieren was da los ist u. ich denke "ich habe mal nen Freeware-Script genommen, auf meinen Server gehauen und naja,... doof gelaufen halt" ist da keine valide Antwort :D
Zitat von @evgnbz:
kann mir jemand sagen wo ich etwas über sowas wie sql injection lesen kann wie man das macht und wie man sich davon schützt
kann mir jemand sagen wo ich etwas über sowas wie sql injection lesen kann wie man das macht und wie man sich davon schützt
SQL injection how to
Und dann an den Informationen entlanghangeln.
lks
Zitat von @maretz:
nen Fehler war u. die Daten im Nirvana sind... und den Prüfer wird da dann schon interessieren was da los ist u. ich denke "ich habe mal nen Freeware-Script genommen, auf meinen Server gehauen und naja,... doof gelaufen halt" ist da keine valide Antwort :D
nen Fehler war u. die Daten im Nirvana sind... und den Prüfer wird da dann schon interessieren was da los ist u. ich denke "ich habe mal nen Freeware-Script genommen, auf meinen Server gehauen und naja,... doof gelaufen halt" ist da keine valide Antwort :D
deswegen gibt es backups
100%
Zitat von @Pedant:
Geht es tatsächlich um diese PHPSESSID oder darum, dass man der log.php Javascript unterjubeln könnte, das dann aber doch nur im aufrufenden Browser ausgeführt wird?
Geht es tatsächlich um diese PHPSESSID oder darum, dass man der log.php Javascript unterjubeln könnte, das dann aber doch nur im aufrufenden Browser ausgeführt wird?
Oder. Es lässt sich aber auch ein script-Element einbauen welches ein externes Script nachlädt - und damit lässt sich dann allerhand Unfug anstellen wie das Ausführen von irgendwelchen Schädlingen oder dem Verschicken von Daten.
Ich schreib mir mal auf die ToDo-Liste $meldung etwas zu filtern/bereinigen bevor es zum echo kommt.
Du musst einfach nur die Kontextwechsel richtig behandeln, dann kann dem Benutzer auch kein Javascript-Code untergejubelt werden.
Hast Du ein konkretes Beispiel, das zeigt was Du damit meinst?
Deinen Link habe ich verfolgt aber noch nicht durchgelesen.
Deinen Link habe ich verfolgt aber noch nicht durchgelesen.
Dann mach das mal, dort ist das Problem beschrieben, auch mit Beispielen. Das Prinzip ist aber eigentlich ganz einfach: wenn man bei dir z.B. beim Login ein Anführungszeichen im Namen verwendet wird das 1:1 im Query eingebaut und die Datenbank haut dir eine Fehlermeldung um die Ohren (bzw. die genaue Fehlermeldung sollte ein Benutzer garnicht zu sehen bekommen!). Wenn der Kontextwechsel nach SQL richtig behandelt worden wäre, wäre das Anführungszeichen maskiert worden und der Query würde keinen Fehler mehr werfen.
Dass dort ein Kennwort vorausgefüllt im Input-Feld mitgeliefert wird, ist ziemlich unschön.
Ich vermute Du meinst login.php, Zeile 146echo "\t\t\t\t\t<td class=blank><input name=\"passwort\" type=\"password\" value=\"".$passwort."\" ...
Vorausgefüllt werden sie nur, wenn dort zum Login eine ungültige Kombinationen eingegeben wurde.
Vorausgefüllt werden sie dann mit den Werten, die der User soeben selbst eingegeben hatte.
Da sehe ich weiter kein Problem.
Wer sich also nur bei Benutzername oder Passwort vertippt hatte, muss nur eins korrigieren statt beides neu einzutippen.
Ein Passwort sollte niemals irgendwo im Klartext ausgegeben werden (auch nicht im Quelltext als Wert des value-Attributs) - welches Zeichen falsch war sieht der Benutzer ohnehin nicht und das Passwort ganz neu einzugeben geht dann ohnehin schneller.
Was an der Stelle auch noch auffällt: du verwendest Layouttabellen - die sind seit vielen Jahren nicht mehr notwendig. Tabellen sind nur für tabellarische Daten gedacht was das Login-Formular nicht ist (das könnte man als Definitionsliste (dl usw.) auszeichnen, zum Formatieren gibt es grid- und flex-Layouts).
Was ist die Alternative zu den lange verstorbenen "register_globals"?
Direkt mit $_GET/$_POST arbeiten. So ist der Code unles- bzw. unwartbar da ständig irgendwelche Variablen auftauchen bei denen nicht klar ist woher die eigentlich kommen. Wenn Variablen nicht anständig initialisiert werden wird das ganze (wie schon geschrieben wurde) auch noch potentiell gefährlich.
Zitat von @LordGurke
Charset "latin1" zerfällt dir mit Nicht-Lateinischen Zeichen (kyrillisch, griechisch,...)
Auf meinen Rechner und im Demosystem zerfällt es nicht, daher war mir das nicht aufgefallen, aber die Datenbank sollte ich auch auf utf8 umstellen.Charset "latin1" zerfällt dir mit Nicht-Lateinischen Zeichen (kyrillisch, griechisch,...)
Verwende als Charset utf8mb4, nicht utf8 (das ist ein Alias für utf8mb3 und veraltet). Denk daran dass du nicht nur die Datenbank (Datenbank selbst, Tabellen und Spalten!) umstellen musst sondern auch die Verbindung zur Datenbank und auch alle PHP-Dateien!
Zitat von @LordGurke
Kennwörter werden als SHA1-Hash gespeichert, das ist mittlerweile auch nicht mehr State Of The Art
Soll es lieber SHA256 sein oder etwas anderes?Kennwörter werden als SHA1-Hash gespeichert, das ist mittlerweile auch nicht mehr State Of The Art
Verwende zum Speichern bzw. Überprüfen von Passwörtern password_hash() bzw. passwort_verify().
Wenn ich Dich richtig verstehe, schlägst Du vor am Ende meiner connect.php ein
USE database;
als Abfrage auszuführen.Nein. Im DSN (erster Parameter bei new PDO(…)) einfach den Datenbanknamen angeben, siehe Handbuch.
Hi,
ich bekomme immer diesen Fehler beim klick auf "Zeiten ansehen"
Der Fehler wird auch hier in der Demo angezeigt.
ich bekomme immer diesen Fehler beim klick auf "Zeiten ansehen"
Meldung: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
SQLState: HY093
Error-Code: 0
Datei: /mnt/web413/a3/38/5201438/htdocs/zeiterfassung/common/connect.php
Zeile: 8
Der Fehler wird auch hier in der Demo angezeigt.
Zitat von @Wolfsblut76:
Bei mir ist der Fehler nicht replizierbar.
Was mir aufgefallen ist, wenn der Mitarbeiter sein Passwort ändert, dass der Name und das Bild gelöscht wird.
Bei mir ist der Fehler nicht replizierbar.
Was mir aufgefallen ist, wenn der Mitarbeiter sein Passwort ändert, dass der Name und das Bild gelöscht wird.
Wie gesagt, das wird unabhängig vom Browser selbst bei der Demo so ausgespielt: http://zeiterfassung.pedant.de/index.php
Also muss es ja was Grundsätzliches sein.
Schade, die ganze Zeit lief es durch und nach ein Update auf phpMyAdmin 5.2.1.0 kommt nun der gleiche Fehler.
Meldung: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
SQLState: HY093
Error-Code: 0
Datei: /share/CACHEDEV1_DATA/Web/zeiterfassung/common/connect.php
Zeile: 81
Meldung: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
SQLState: HY093
Error-Code: 0
Datei: /share/CACHEDEV1_DATA/Web/zeiterfassung/common/connect.php
Zeile: 81
<?php
include_once('fehlerbehandlung.php');
/* Verbindung zur Datenbank */
$dbbenutzer = "XXXXXXXXX"; // Hier sollte ein minderpreviligierter MySQL-User angegeben werden, der nur auf die Datenbank "zeiterfassung" Zugriffrechte hat.
$dbkennwort = "XXXXXXXX";
$dbserver = "localhost";
$dbport = "3306";
$dbdatenbank = "zeiterfassung";
$serverundportunddatenbank = "mysql:host=".$dbserver."; port=".$dbport."; dbname=".$dbdatenbank;
$pdo = new PDO($serverundportunddatenbank, $dbbenutzer, $dbkennwort);
$pdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
/* Aufrufbare Funktion für Datenbankabfragen */
/*
Anwendungsbeispiel:
$abfrage = "SELECT * FROM users WHERE user_id = :user_id AND user_alias = :user_alias";
$parameter = array(':user_id' => $user_id, ':user_alias' => $user_alias);
$pdostatement = abfragen($pdo, $abfrage, $parameter);
$anzahl = $pdostatement -> rowCount();
$ergebnis = $pdostatement -> fetchAll(PDO::FETCH_ASSOC);
abfragen($pdo, "standsetzen", "");
*/
function abfragen($pdo, $abfrage, $parameter)
{
//echo "abfrage: ".$abfrage."<br>\n";
if ($abfrage == "") {return ("");};
//if ($parameter == "" || $parameter == "manuellessql") {echo "parameter = \"".$parameter."\"<br>\n";} else {foreach ($parameter as $var => $wert) {echo $var." = ".$wert."<br>\n";};};
if ($abfrage == "standsetzen")
{
$abfrage = "UPDATE status SET stand = NOW() WHERE status_id = :status_id;";
$parameter = array(':status_id' => 1);
};
// Abfragen, die keine Variablen enthalten werden nicht mit "prepare" durchgeführt sondern mit "query" oder "exec" oder gar nicht.
if ($parameter == "" || $parameter == "manuellessql")
{
// Das erste Wort der Abfrage ($abfrage) ermitteln und auswerten
$anweisungsart = explode (" ", $abfrage);
$anweisungsart = strtolower($anweisungsart[0]);
//echo "anweisungsart: ".$anweisungsart."<br>\n";
switch ($anweisungsart)
{
case "select":
case "show":
$methode = "query";
break;
case "insert":
case "update":
case "replace":
case "delete":
$methode = "exec";
break;
default:
if ($parameter == "manuellessql") {$methode = "query";}
else {$methode = "keine";};
};
}
else {$methode = "prepare";};
//echo "methode: ".$methode."<br>\n";
if ($methode == "prepare")
{
$pdostatement = $pdo -> prepare($abfrage);
$pdostatement -> execute($parameter);
return ($pdostatement);
};
if ($methode == "query")
{
$pdostatement = $pdo -> query($abfrage);
return ($pdostatement);
};
if ($methode == "exec")
{
$anzahl = $pdo -> exec($abfrage);
return ($anzahl);
};
if ($methode == "keine")
{
// keine Abfrage
return ("");
};
return ("");
}
function testfehler($pdo)
{
$jetzt = date("H:m:s");
$abfrage = "SELECT ".$jetzt; // ungültige Abfrage
abfragen($pdo, $abfrage, "");
return ("");
}
?>
Hallo Frank,
ich kann das Problem mit dem Bild nachvollziehen,
Ich habe als Benutzer nur das Kennwort geändert und bekomme folgende Hinweise in Grün:
"Der Vorname wurde geändert.
Der Nachname wurde geändert.
Das Passwort wurde geändert.
Die E-Mail-Adresse wurde geändert.
Ein anderes Bild wurde zugeordnet,"
Mein Setup:
Apple Rechner mit
MAMP 6.8
PHP 7.4.33
MySql 5.7.39
Zusätzliches Problem:
1. Wenn ich auf "Zeiten ansehen" klicke, kommt folgende Meldung:
"SQLState: 42000
Error-Code: 1055
Meldung: Expression"
2. Auf Deiner Website als admin angemeldet und auf "Zeiten verwalten" geklickt, bekomme ich nur den Text und die Buttons angezeigt.
Unterhalb der Eintragsfilter kommt nichts und nur der Button "Alle Angezeigten löschen" bewirkt ein Hinweis PopUp, sonst aber nichts,
Die andere Meldung vom VorPoster ist jedenfalls weg,
Vielen Dank für Deine Arbeit und die zur Verfügungstellung
Grüße vom Klaus
ich kann das Problem mit dem Bild nachvollziehen,
Ich habe als Benutzer nur das Kennwort geändert und bekomme folgende Hinweise in Grün:
"Der Vorname wurde geändert.
Der Nachname wurde geändert.
Das Passwort wurde geändert.
Die E-Mail-Adresse wurde geändert.
Ein anderes Bild wurde zugeordnet,"
Mein Setup:
Apple Rechner mit
MAMP 6.8
PHP 7.4.33
MySql 5.7.39
Zusätzliches Problem:
1. Wenn ich auf "Zeiten ansehen" klicke, kommt folgende Meldung:
"SQLState: 42000
Error-Code: 1055
Meldung: Expression"
2. Auf Deiner Website als admin angemeldet und auf "Zeiten verwalten" geklickt, bekomme ich nur den Text und die Buttons angezeigt.
Unterhalb der Eintragsfilter kommt nichts und nur der Button "Alle Angezeigten löschen" bewirkt ein Hinweis PopUp, sonst aber nichts,
Die andere Meldung vom VorPoster ist jedenfalls weg,
Vielen Dank für Deine Arbeit und die zur Verfügungstellung
Grüße vom Klaus