Lieber Besucher, herzlich willkommen bei: OS X Entwicklerforum. Falls dies dein erster Besuch auf dieser Seite ist, lies bitte die Hilfe durch. Dort wird dir die Bedienung dieser Seite näher erläutert. Darüber hinaus solltest du dich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutze das Registrierungsformular, um dich zu registrieren oder informiere dich ausführlich über den Registrierungsvorgang. Falls du dich bereits zu einem früheren Zeitpunkt registriert hast, kannst du dich hier anmelden.
|
|
Quellcode |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
<?php
error_reporting(E_ALL);
$dbname="q_db0";
$dbhost="localhost";
$dbuser="USER";
$dbpass="PASSWORD";
mysql_connect($dbhost,$dbuser,$dbpass);
mysql_select_db($dbname);
$username = $_GET[username];
$password = $_GET[password];
$getToken = $_GET[token];
$ergebnis = mysql_query("SELECT * FROM accounts WHERE mail='$username'");
$all = mysql_fetch_array($ergebnis);
$asdf = $all[pushTokens];
$teile = explode(";", $asdf);
if ($password == $all[passwort]){
$vorhanden = FALSE;
// Gucken ob der Token wirklich in der DB drin ist…
for($x = 0; $x < count($teile); $x++) {
if ($teile[$x] == $getToken){
$vorhanden = TRUE;
}
}
// Wenn er drin ist, dann ein neuen String für DB schreiben, aber OHNE den aktuellen Token
if ($vorhanden == TRUE){
echo "Vorher: $asdf<br>";
// Alle Token durchlaufen
for($x = 0; $x < count($teile); $x++) {
if ($teile[$x] == $getToken){
}else{
// Nur hinzufügen, wenn der Token nicht der Aktuelle ist
$doof .= ";$teile[$x]";
}
}
echo "Nachher: $doof<br>";
// Den Rest nachher OHNE den aktuellen Token in die DB updaten.
$sql = "UPDATE accounts SET pushTokens = '$doof' WHERE mail='$username'";
$db_erg = mysql_query($sql)
or die(mysql_error());
}
echo "login,0";
}else{
echo "login,1";
}
?>
|
Wenn Du wirklich mit E_ALL arbeiten würdest, würde PHP Dir (zurecht) einen Haufen Warnings um die Ohren werfen. Nicht-numerische Keys von Arrays gehören in Anführungszeichen oder Hochkommata.
![]()
Quellcode
1 2 3 4 5 6 <?php error_reporting(E_ALL); … $username = $_GET[username]; $password = $_GET[password]; $getToken = $_GET[token];
Bitte informier Dich dringend mal über den Begriff »SQL Injection«.
![]()
Quellcode
1$ergebnis = mysql_query("SELECT * FROM accounts WHERE mail='$username'");
Ich glaube, Du solltest Dir mal die Funktion in_array() ansehen.
![]()
Quellcode
1 2 3 4 5 6// Gucken ob der Token wirklich in der DB drin ist… for($x = 0; $x < count($teile); $x++) { if ($teile[$x] == $getToken){ $vorhanden = TRUE; } }
SQL Injektion ist mir ein Begriff, dabei kann man z.B. ja über die GET URL Code in die DB einschleusen, aber wie sollte ich bei einem NSURL-Request sonst noch Daten übermitteln? GET ist das Einfachste, aber POST geht doch sicher auch, ist das denn 'sicherer'?
Da ich wirklich nur mal eine Woche mir neulich PHP angeschaut habe, weiss ich wirklich nicht genau, was ich alles beachten muss.
Dann ergänze mal das hier zu Beginn des Skripts:Zum Thema Error-Report: Entweder ich habe das Teil nicht ganz verstanden, oder ich hab was vergessen. Denn Warnings gibt er keine.
|
|
Quellcode |
1 |
ini_set('display_errors', 1);
|
Die HTTP-Methode ist egal – die Angreifbarkeit liegt nicht in der Methode, sondern in falscher oder fehlender Vorbereitung von Strings, die Du an die Datenbank schickst. BTW geht es nicht nur ums Einschleusen, sondern auch um das Umgehen von Authentifizierung oder das Löschen oder Ändern von Daten.SQL Injektion ist mir ein Begriff, dabei kann man z.B. ja über die GET URL Code in die DB einschleusen, aber wie sollte ich bei einem NSURL-Request sonst noch Daten übermitteln? GET ist das Einfachste, aber POST geht doch sicher auch, ist das denn 'sicherer'?
Dann wäre es m.E. dringendst angeraten, dass Du Dir ein Buch wie »PHP-Sicherheit« von Kunz/Esser durchzulesen, bevor Du Dich als leichte Beute von Script Kiddies exponierst.Da ich wirklich nur mal eine Woche mir neulich PHP angeschaut habe, weiss ich wirklich nicht genau, was ich alles beachten muss.
Ob es »richtig« ist, kann ich nicht beurteilen. Von dem, was Du schreibst, würde ich sagen: Dein Vorgehen ist zumindest nicht lehrbuchmäßig, weil Du nicht normalisierst, aber in Zeiten von NoSQL-Datenbanken wirst Du sicher nicht mehr schief deswegen angesehen, wenn die Normalisierung nur Bloat, aber sonst keinen Nutzen mit sich brächte.Aber warum serialisiert speichern? Ich weiss nicht wirklich, wie ich dynamisch Felder erzeugen lassen soll und wie ich sie wieder lösche, durchlaufe.
Daher war eben meine Annahme, dass es richtiger wäre, alles in ein Feld zu schreiben.
Das ist beim konkreten Beispielcode falsch, denn die alte mysql_*-API aus dem Beispiel kann in einem Funktionsaufruf nicht mehrere Queries ausführen.3. Ändert das um in register.php?username='; drop table accounts;--
4. Deine PHP Anwendung führt dann (sofern magic quotes nicht an ist -- ist jetzt zu illustrationszweckene) folgendes aus
SELECT * FROM accounts WHERE mail=''; drop table accounts;--'
5. Schon hat irgendein Typ mit Langerweile Deine ganze DB gelöscht.
Ich werde mal ganz deutlich: es ist scheißegal, was für kryptographische Geschütze Du auffährst, solange sie sich umgehen lassen.Ehm die Mail und Passwort sind mit 16000bit RSA verschluesselt in der DB. Also wer da einen SQL Code in den kodierten RSA String bekommt ist schon gut.
|
|
Quellcode |
1 |
SELECT userid FROM usertable WHERE password = 'gehashtes-Passwort-mit-Salt' AND username = 'name-des-users'; |
|
|
Quellcode |
1 |
SELECT userid FROM usertable WHERE password = 'gehashtes-Passwort-mit-Salt' AND username = '' OR '1'='1'; |
Das ist beim konkreten Beispielcode falsch, denn die alte mysql_*-API aus dem Beispiel kann in einem Funktionsaufruf nicht mehrere Queries ausführen.
Mail und Passwort sind mit 16000bit RSA verschluesselt in der DB
Es geht nur um eine userfreundliche eindeutige Authentifizierung. Ich brauche den private Key nicht. Ich möchte damit nur zum
Ausdruck bringen, dass es rein Mathematisch ja nicht mal mehr möglich ist, dass ein 'Einbrecher' in die DB oder ich an die Userdaten komme. Die DeviceToken habe ich momentan da noch nicht bei. Mal sehen, wie sich das in der Benutzung zeigt beim DeviceToken. Natürlich dauert es beim
erstmaligen Login ein wenig, aber es geht um Sicherheit und das möchte ich auch zeigen.
Zur Injection: Wenn die Ubergabe von Daten so dramatisch unsicher ist, muss es ja einen anderen, sichereren, Weg geben. Sonst würde es ja niemand nutzen. Da ich aber nur einen Shell/PHP/SQL Server habe, muss ich aber mit PHP wohl arbeiten. Denn eine SSH Verbindung und das Eintragen via Shell ist dann ja genauso unsicher.
Aber ich hab noch nicht alle Antworten gelesen, bis heute Abend aber natürlich.
Okay das heisst ich muss von Hand hingehen, um sicher zu stellen, dass es kein PHP/SQL Kommando ist?
Das Problem ist wohl also, dass ich eine öffentliche URL habe?
Wenn ich diese URL schützen würde in irgendeiner Weise (wie weiss ich grade nicht), kann ich doch trotzdem wie geplant verfahren? Also ich könnte dann meinen kodierten Stuff schreiben/lesen lassen?
Es geht bei meiner Anwendung von RSA in dem Fall nur um Sicherheit. Ich mache das doch nur, damit sich ein User identifizieren kann, aber auch nichts zwei Mal in der DB steht an Nutzernamen. Ich kodiere alles, aber ich will es gar nicht wieder dekodieren. Also brauche ich den Privatekey nicht und kann somit sagen, dass die Daten nicht entschlüsselbar sind. (Also natürlich könnte man, wenn man mehrere 100 Jahre Langeweile hat).
Also Fazit: Ich muss von Hand gucken, dass kein SQL/PHP Kommando mitkommt?
Benutzerinformationen überspringen
Wohnort: Herdecke
Beruf: Selbständig
Hobbys: Gleitschirmfliegen, RC-Helikopter, Faustball
Ist natürlich prinzipiell korrekt, aber im Fall der in der Frage verwendeten Anno-Dazumal-MySQL-API nicht zielführend, weil die nicht weiß, was Prepared Statements sind.Um sich vor SQL-Injections zu schützen hatte ich Dir schon prepared statements genannt.