Simplest PHP Counter
Hallo zusammen,
gestern wurde spät in der Nacht einem Bekannten ein minimalistisches PHP Counter Script zusammengebastelt. Mein PHP und MySQL war etwas eingerostet, aber dennoch etwas (hoffentlich) brauchbares draus geworden. Vielleicht fängt ja jemand etwas mit dem Source an oder verwendet es sogar in eigenen Projekten.
Geloggt wird die aufgerufene Seite, der UserAgent, Referer und die IP des Nutzers. Im Panel werden dann die Hits und Unique Hits der letzen 24, sowie die Gesammtanzahl der Hits ausgegeben. Ein paar Statistiken zeigen, welche Seite besonders oft frequentiert wurde.
Wenn jemand XSS oder SQLi findet, so darf er mir gerne Bescheid geben!
Download: Simplest PHP Counter (38)
Greez
Ich habe mir den Quelltext angeschaut. Willst du ernsthaftes Feedback?
Warum verwendest du keine SQL-prepared statements? Der Quelltext erinnert mich an PHP4
Und wenn du schon ohne prepared statements escapst, dann würde ich mysql_real_escape_string vorschlagen und den mysqli-Treiber nehmen.
Da ich nie mit PDO gearbeitet habe, wollte ich mich für dieses kleine Projekt nicht noch extra reinarbeiten. Aber klar, Recht hast Du auf jeden Fall.
Durch htmlspecialchars in Kombination mit ENT_QUOTES kann ich halt direct XSS und SQLi Abdecken. AFAIK ist mysql_real_escape_string nicht (mehr) von allen PHP Versionen unterstützt?
MySQLi Treiber hast Du natürlich auch recht.
Also PDO hat so eine simple API, da zählt die Ausrede “da wollte ich mich nicht einarbeiten” eigentlich nicht.
Ist auf jeden Fall die sicherste Lösung und wirklich extrem einfach zu nutzen, außerdem eigentlich auch die übersichtlichste Lösung die Paramter in Queries so ganz übersichtlich zu assignen.
@wieschoo hat recht, htmlspecialchars() ist nicht ausreichend für ein escaping, wie folgende SQL-Injection zeight:
Besucher aus dem Jahr 2033: http://…/PHPCounter/hit.php?referer=1\&url=,0,FROM_UNIXTIME%282000000000%29%20-%20-
Dann zu dem iframe: Wenn du schon mit Javascript arbeitest, kannst du auch einen Ajax-Request an den Server absetzen, anstelle ein iframe zu laden. Da du aber sowieso nur den Referer und die Url speicherst, lese einfach die $_SERVER Variablen aus und binde dein PHP-Skript als transparentes 1×1 Tracking-Pixel ein:
hit.php:
$referer = $_SERVER["HTTP_REFERER"];
$url = $_SERVER['REQUEST_URI'];
/*
restlicher Code
*/
header(‘Content-Type: image/gif’);
echo base64_decode(‘R0lGODlhAQABAJAAAP8AAAAAACH5BAUQAAAALAAAAAABAAEAAAICBAEAOw==’);
include.html:
Kannst du das konkreter erklären, was du da gefunden hast. Wenn ich deine Injection probiere erhalte ich doch nur folgenden SQL Befehl??:
$query = “INSERT INTO `hits` (`IPAddr` ,`UserAgent` ,`Referer` ,`Site` ,`Time`)
VALUES (
‘$ip’, ‘$user_agent’, ’1\’, ‘,0,FROM_UNIXTIME%282000000000%29%20–%20-’, NOW( )
);”;
Beim Absenden meines Kommentares ist ein Kommentar-Strich (-) verloren gegangen, zudem werden Apostrophe hier teilweise encodiert. Korrekt ausgeführt und URL-decoded steht für VALUES dann folgender Eintrag:
VALUES (
‘$ip’, ‘$user_agent’, ’1\’, ‘,0,FROM_UNIXTIME(2000000000) –– -’, NOW( )
);
Durch das Escaping des Apostrophes (\’) wird ’1\’, ‘ als ein String gewertet. NOW() ist auskommentiert und durch FROM_UNIXTIME ersetzt worden.
Mehr dazu hier: http://stackoverflow.com/questions/22116934/is-htmlspecialchars-enough-to-prevent-an-sql-injection-on-a-variable-enclosed-in
PS: Die simple Lösung, die Request-URI aus dem $_SERVER["REQUEST_URI"]-Eintrag einzulesen ist natürlich unsinnig. Richtig muss es in etwa lauten:
$referer = $_GET["referer"];
$url = $_SERVER["HTTP_REFERER"];
Der Original-Referer des Requests an die das Tracking-Script einbindenden Seite lässt sich nur mit aktiver Javascript-Ünterstützung auslesen.