• Hallo Besucher!

    Du bist neu im Forum? Dann registriere dich hier, um Diskussionen beizutreten oder eigene Themen zu erstellen. Für die Registrierung ist es erforderlich, dass du einen Spielaccount bei Die Stämme hast.

    Andernfalls kannst du dich hier direkt einloggen.

    Falls du dein Passwort vergessen hast, kannst du hier ein neues Passwort anfordern.

[PHP] Views zählen, Pushen verhindern

DeletedUser92786

Gast
Hallo ihr Programmierer

Ich arbeite momentan an einer Webseite, auf der man Bilder hochladen kann und und und, alles so plattform-mäßig
und jetzt gerade bin ich bei de Problem, dass ich doch gerne die Views eines einzelnden Bilds zählen würde (alles mit Datenbank usw)

mein bisheriger Ansatz war es, dass beim Aufrufen der url der counter des jeweiligen bilds um eins nach oben zählt.

PHP:
$id = $_GET["id"];
$aendern = "UPDATE tabellenname Set spalte=spalte + 1 WHERE id = '$id'";
$update = mysql_query($aendern);

ja, das ganze funktioniert - aber nicht gut
läd man die seite mit F5 oder einfach anders neu, wird der zähler sofort weitergezählt..damit ist es auch möglich ein einzelndes Bild ohne nennensewrten Aufwand massiv zu pushen...mag ich nicht.

http://www.scribbit.de


dann dachte ich mir..ja, lass ich doch irgendne zeitmethode von php nebenbei mitlaufen und das script wird erst nach 10 sekunden oderso aufgerufen, das würde notorische seiten-reloader ja wenigstens etwas abhalten..

ich finde aber kein entsprechendes script
meistens kommt nur etwas mit cronjobs oder sleep(), was aber den kompletten seitenaufbau lahmlegt.

kann mir wer helfen oder hat jemand andere ideen diese pushen zu verhindern?
 

DeletedUser

Gast
In der Session speichern, dass bereits gevoted wurde... Das dann vor dem SQL-Befehl abfragen und gegebnfalls den Befehl nicht ausführen. Wär jetz so ne Lösung auf die schnelle^^
 

DeletedUser24674

Gast
Die SQL-Query ist so fatal, offenes Tor für SQL-Injections...

Dein Problem kannst du lösen, indem du Datum+Uhrzeit und die IP des Benutzers (bzw. einen Hash davon) speicherst und dann halt vergleichst ob der Benutzer heute/in der letzten stunde/... das Bild schonmal angesehen hat oder nicht. Und je nach dem machst du dann ein +1 oder nicht :)

btw: Cooles Design!
 
Zuletzt bearbeitet von einem Moderator:

DeletedUser86143

Gast
wie mein Vorgänger schon sagte, der oben gezeigte Code ist sehr unsicher. Das ist bald so als wenn du zu Hause deine Haustür offen lässt und nen Schild vorhängst "bitte ausrauben"

http://php.net/manual/en/function.mysql-real-escape-string.php sollte schon ein wenig weiterhelfen, zusätzlich kannst du aber auch noch sagen wenn es sich um eine id handelt (int)$variable und dadurch gleich einen Integer erzwingen

ja und ansonsten halt die IP oder ein hash dessen in einer extra tabelle ablegen und abfragen ob das in den letzten 24 Stunden schon aufgerufen wurde. Alternativ wären auch noch cookies möglich (die kann man aber löschen und unterdrücken, wäre also nur eine zusatzoption um zu sagen, zähle nur einmal in der woche für eine person, oder sowas in der art)
bei eingeloggten Besuchern könnte man auch 2 einträg einfügen, einmal dessen ip (falls er sich ausloggt) und einmal dessen benutzername.

Übrigens: Mit einem Cronjob könntest du die Tabelle dan nauch immer bereinigen. (so nach dem Motto: wenn Datum länger her als 24 Stunden dann löschen) Für einen cronjob kannst du zum Beispiel http://www.cron-job.org nutzen.
 
Zuletzt bearbeitet von einem Moderator:

DeletedUser92786

Gast
@thecain
hm, es gibt ja mehr als ein bild, das würden dann doch relativ..viele sesssion werden, oder ich weiß grad nicht genau wie du dir das vorstellst..

@Alexander der Große III, das klingt gut, ich glaub da setz ich mich gleich ran, erstmal ab in die mensa frühstücken :Ddanke
 

DeletedUser24674

Gast
@Alexander der Große III, das klingt gut, ich glaub da setz ich mich gleich ran, erstmal ab in die mensa frühstücken :Ddanke

Alright ;) Aber denk unbedingt daran die ganzen Sicherheitslücken rauszumachen (ich gehe jetzt mal davon aus es gibt noch weitere dieser Art...), wäre schade um die Seite!
 

Vidirat

Gast
Wo gerade von Sicherheitslücken in MySQL geredet wird:

exploits_of_a_mom.png


Zufällig gefunden und dachte das passt... :)
 
Zuletzt bearbeitet:

DeletedUser

Gast
In der Session speichern, dass bereits gevoted wurde... Das dann vor dem SQL-Befehl abfragen und gegebnfalls den Befehl nicht ausführen. Wär jetz so ne Lösung auf die schnelle^^

oww.. thread vergessen^^ Nochmal wegen den Sessions^^ Ich hätt einfach so ne Session à la $_SESSION['lastPic'] gemacht. Dann da die ID vom zuletzt angeschauten bild reingemacht. dann das geprüft... F5 klicker vertrieben.

Aber wie gesagt, maximal einfache Lösung. Aber ohne Änderung an der DB und eine Zeile im Code^^
 

DeletedUser

Gast
maximal einfach ist selten effektiv^^

Ich wollte nur nicht grad, dass man meint ich will x hundert session variablen anlegen :D
 

DeletedUser92786

Gast
ja also ich hab das freitag noch so gelöst wie Alexander der Große III es vorgeschlagen hat. Danke dafür :)
und dann wird einfach geprüft ob ein nutzer ein bestimmtes scribb in den letzten 2 minuten angeschaut hat (zukleiner wert?)
- könnt ihr ja auch ausprobieren, sollte alles soweit klappen

und dann..zum wohl größeren problem :D SQL Injections
damit hab ich ehrlich gesagt NULL ahnung, ich hatte PHP und generell datenbanken vorher auch nie ind er schule oder in der Uni und das ganze
basiert jetzt eher auf php wissen, welches man sich leicht selbstständig im internet aneignen und zusammen suchen kann, wenn man nebenbei noch so ein grobes grundverständnis von programmieren hat..

also SQL injections sind also nun solche Sicherheitslücken bei denen Eingaben des Nutzers nicht auf Korrektheit geprüft werden, wodurch jeder mögliche Internet benutzer quasi seinen Code auf unserem Server laufen lassen könnte? hm

also bei dem beispiel von mir im ersten post kann der Nutzer ja selber die $id variable ändern, da das ja nur ein Parameter in der url ist..
gut, das macht er, dann wäre $id anders und dann würde das php zeug in
PHP:
$aendern = "UPDATE tabellenname Set spalte=spalte + 1 WHERE id = '$id'";
nach anderen eingaben suchen/sortieren.. spontan würde ich sagen, wenn man da einfach willkürlich für $id was nimmt, kommt nur mumpitz raus, ausser der wert ist zufällig in der datenbank vorhanden..sonst gibt es einfach keine ergebnisse..
aaaaber :D ich nehm an, da dies eine viel eklatantere sicherheitslücke ist...klärt mich auf, ein beispiel hierdran würde mir wohl helfen, im internet finde ich überwiegend..schmock, zumindest kann ich das mit meinem wissen grad nicht so ganz toll auf diese situation übertragen
 

DeletedUser24674

Gast
ja also ich hab das freitag noch so gelöst wie Alexander der Große III es vorgeschlagen hat. Danke dafür :)
und dann wird einfach geprüft ob ein nutzer ein bestimmtes scribb in den letzten 2 minuten angeschaut hat (zukleiner wert?)
- könnt ihr ja auch ausprobieren, sollte alles soweit klappen

Du musst selbst ausprobieren, was für dich ein guter Wert ist. 2 Minuten halten aufjedenfall F5 drücker erstmal ab - und da die anderen "Scribb"s ja genau die gleiche 2 Minuten sperre haben hat man immer eine faire Referenz. Wäre halt gut wenn du den Wert nachträglich nicht änderst, denn sonst kann man mit den "Views" nichts anfangen.

und dann..zum wohl größeren problem :D SQL Injections
damit hab ich ehrlich gesagt NULL ahnung, ich hatte PHP und generell datenbanken vorher auch nie ind er schule oder in der Uni und das ganze
basiert jetzt eher auf php wissen, welches man sich leicht selbstständig im internet aneignen und zusammen suchen kann, wenn man nebenbei noch so ein grobes grundverständnis von programmieren hat..

Und genau da liegt die Gefahr - schnell was zusammenprogrammiert, nicht wirklich gewusst wo und was Sicherheitslücken sind und Zack die erste Enttäuschung: Seite gehackt. Ich frage mich: Behandeln die ganzen "PHP-Tutorials" dieses Thema nicht, oder überlesen die Leute es einfach nach dem Motto "SQL Injections? Wasn das. Kenn ich nicht, brauch ich nicht!" ??!

also SQL injections sind also nun solche Sicherheitslücken bei denen Eingaben des Nutzers nicht auf Korrektheit geprüft werden, wodurch jeder mögliche Internet benutzer quasi seinen Code auf unserem Server laufen lassen könnte? hm

...und noch viel mehr, der "Hacker" kann Daten ausspionieren, manipulieren, auf deiner Seite ein Virus einbauen, ...

also bei dem beispiel von mir im ersten post kann der Nutzer ja selber die $id variable ändern, da das ja nur ein Parameter in der url ist..
gut, das macht er, dann wäre $id anders und dann würde das php zeug in
PHP:
$aendern = "UPDATE tabellenname Set spalte=spalte + 1 WHERE id = '$id'";
nach anderen eingaben suchen/sortieren.. spontan würde ich sagen, wenn man da einfach willkürlich für $id was nimmt, kommt nur mumpitz raus, ausser der wert ist zufällig in der datenbank vorhanden..sonst gibt es einfach keine ergebnisse..

Man könnte via dem ID-Parameter ganz einfach die komplette SQL-Query ändern. Beispiel:
Ich übergebe als ID folgendes:
Code:
' OR 1 = 1 /*
Die Query wäre dann:
Code:
UPDATE tabellenname SET spalte = spalte + 1 WHERE id = '' OR 1 = 1 /*'

Das würde dann den Counter bei allen "Scribbs" um 1 erhöhen. Das ist jetzt zwar nicht weiter schlimm, aber auf diese Art und Weise sind noch viel mehr Sachen möglich, wie zum Beispiel Passwörter der Benutzer auslesen, und eben Code auf deinem Server auszuführen.

aaaaber :D ich nehm an, da dies eine viel eklatantere sicherheitslücke ist...klärt mich auf, ein beispiel hierdran würde mir wohl helfen, im internet finde ich überwiegend..schmock, zumindest kann ich das mit meinem wissen grad nicht so ganz toll auf diese situation übertragen

Du kannst dich ganz einfach dagegen schützen. Entweder du verwendest Prepared Statements, oder du lässt jede Variable Bevor du sie in der DB verwendest durch mysql_real_escape_string laufen. Wichtig hierbei ist, dass du immer alle Werte die in deiner Query sind in '' fasst. Beispiel:
SCHLECHT:
PHP:
$id = mysql_real_escape_string($_GET['id']);
mysql_query("UPDATE bla SET bla = $id");

GUT:
PHP:
$id = mysql_real_escape_string($_GET['id']);
mysql_query("UPDATE bla SET bla = '$id'");

Man beachte den kleinen, aber feinen und WICHTIGEN unterschied um die Variable $id in der Query!!

Zu Prepared Statements gibts ne menge Tutorials, google mal nach PHP-PDO.

Achja, auch noch sehr wichtig: Beim Lesen aus der Datenbank solltest du Benutzereingaben aufjedenfall einmal durch htmlspecialchars vor der Ausgabe jagen, sonst kann man deine Seite durch Cross-Site-Scripting missbrauchen.

Wenn du das hast, hast du dich gegen das gröbste Abgesichert. Danach kannst du dann noch deine Benutzer gegen CSRF-Attacken schützen (ist sehr empfehlenswert!), dazu kann ich dir dann auch ne kleine Erklärung bei Bedarf schreiben (sollte aber auch alle Infos dazu bei Google geben!) :p

- Alex
 

DeletedUser

Gast
mysql_real_escape_string() ist also gut und schlecht? Interessant.

Ich empfehle: Anstatt mysql_real_escape_string() intval(), aber auch nur bei Zahlen.
 

DeletedUser92786

Gast
so, ich bin auch mal zurück
also, ich überprüfe jetzt auf allen seiten alle nutzereingaben und alle GET-Variablen und url parameter mit mysql_real_escape_string() und htmlspecialchars($string,ENT_QUOTES) und behandle sonderzeichen dann noch mit str_replace() bei den kommentaren

noch eine frage..wenn jetzt jemand versucht mit so einer eingabe irgendwas auf der seite zu machen

"/galerie.php?sort=kommentare DESC,user ASC--"

was bedeuten dann das ASC und die beiden minusse am ende des strings?? und verhindert mysql_real_escape_string() oder eine der anderen funktionen sowas? ich wurde vor ein paar wochen bevor ich das in den code eingebaut habe darauf hingewiesen..das das wohl noch möglich sei mit diesem string estwas ausgeben zu lassen was wohl nciht ganz korrekt ist
 

DeletedUser

Gast
"/galerie.php?sort=kommentare DESC,user ASC--"
Nochmal, falls du hier noch liest:
Das würde deine Query nach kommentare und anschließend nach user sortieren und das -- macht, dass alles danach ignoriert wird, weil es dann als kommentar gesehen wird.

Was die ID angeht würde ich ein einfaches int-Cast einfügen:

$id = (int) $_GET['id'];
$query = 'UPDATE ... WHERE id = ' . $id . ' && ...';

Ansonsten: Statt mysql empfehle ich dir mysqli und dann für Strings:
$sql = new mysqli('localhost', 'name', 'pass', 'db');
$result = $sql->query('...' . $sql->real_escape_string('...') . '...');

Zum eigentlichen Problem nochmal:
Einfach zu jeder IP den letzten Timestamp für jedes Bild speichern und wenn der vorhanden ist und nicht länger als xx zurück liegt, dann wird der Counter des Bildes erhöht.

Gruß, Cembon
 
Oben