PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [PHP] Mysql-Anweisung fehlerhaft...



sniper.de
24.06.2004, 15:11
hi!

Ich habe da gestern Ewigkeiten drangesessen und versucht, den fehler zu finden.

Aber irgednwioe bin ich zu verpeilt.
Habe es soagr schon neugeschrieben.

Es geht NUR um die mysql Anweisung, er bringt mir immer einen Syntaxfehler in der SQL Anweisung.


// Daten erzeugen
$username = trim($_POST['username']);
$name = trim($_POST['name']);
$email = trim($_POST['email']);
$art = trim($_POST['art']);
$faecher = trim($_POST['faecher']);
$schulzeit = trim($_POST['schulzeit']);
$anschuleseit = trim($_POST['anschuleseit']);
$abi = trim($_POST['abi']);
$homepage = trim($_POST['homepage']);
$icq = trim($_POST['icq']);
$msn = trim($_POST['msn']);
$besleistungen = trim($_POST['besleistungen']);
$datum = date("d.m.Y");
$password = generate_password();
$showperpage = 25;

if ($_POST['hide_email'] == 'yes')
$hide_mail = 1;
else
$hide_mail = 0;


// Daten nun in die Datenbank eintragen

$db->query("INSERT INTO user (user, password, email, name, abi, schulzeit, homepage, icq, joined, hide_email, msn, lehrer, faecher, art, schuleseit, showperpage)
VALUES (

$username,
".md5($password).",
'$email',
$name,
$abi,
'$schulzeit',
$homepage,
$icq,
$datum,
$hide_mail,
$msn,
1,
$faecher,
$art,
$anschuleseit,
25)
");

vor dem user in der Tabelle kommt noch ein AutoIncrementfeld id.

ALT255@Seti
24.06.2004, 15:32
Also auf den ersten Blick sehe ich auch nichts aber normalerweise ist die Fehler Meldung doch etwas Aussagekräftiger, ich meine er sagt doch immer sowas wie Syntax error near ?, kannst du das nicht mal untersuchen, oder ist das nur beim mssql-server so.

MfG

ALT255

sniper.de
24.06.2004, 15:49
hier die fehlermeldung:



-> Database Error: Invalid SQL: INSERT INTO user (user, password, email, name, abi, schulzeit, homepage, icq, joined, hide_email, msn, lehrer, faecher, art, schuleseit, showperpage)
VALUES (

dirk-alive,
b814da6b4d445c64590dfceaada5db38,
'test@test2.de',
Testlehrer,
2005,
'2004 - 2006',
http://www.vwar.de,
'',
24.06.2004,
0,
,
1,
Mathematik, Englisch,
testrat,
2004,
25)

-> MySQL Error: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '://www.vwar.de,
'',
24.06.2004,
0,

-> MySQL Error Number: 1064
-> Date: 24.06.2004 @ 15:50
-> Script: /ehemaligenliste/admin/lehrer.php?action=add
-> Referer:

Das nicht alles vollständig ausgefüllt ist ist egal, auch da bringt er diesen Fehler.

SKar
24.06.2004, 19:31
Hi,

versuchs mal mit ' ':


$db->query("INSERT INTO user (id, user, password, email, name, abi, schulzeit, homepage, icq, joined, hide_email, msn, lehrer, faecher, art, schuleseit, showperpage)
VALUES (
'',
'$username',
'".md5($password)."',
'$email',
'$name',
'$abi',
'$schulzeit',
'$homepage',
'$icq',
'$datum',
'$hide_mail',
'$msn',
1,
'$faecher',
'$art',
'$anschuleseit',
25)
");

vor dem user in der Tabelle kommt noch ein AutoIncrementfeld id. [/php]

Bei solchen Problemen stell ich mir die Query immer zuerst in einer Variablen $query zusammen und falls es Probleme gibt, mach ich ein print $query; ... erleichert das debuggen (kannst deine Query ja dann z.B. phpMyAdmin testen und verbessern bis es geht..

ALT255@Seti
24.06.2004, 20:06
Ja denn Weg mit der Query in einer Variablen nehme ich auch, und du solltest grundsätzlich alle Werte die du in deine DB schreiben willst in '' setzen egal ob als Variable oder String im Script übergeben.

MfG ALT255

PS.: Leider scheint MySQL nicht so informativ wie MSSQL zu sein, denn da bekommt man immer noch die Stelle angezeigt an der der Fehler in der Query ist.

sniper.de
24.06.2004, 20:19
Also ich teste es gleich mal.

Danke für den Debugging Tip @ SKar

Wie meinst du das, ALT255@Seti ?

Wie alles in " setzen?

meinst du mit
".$var." oder wie?

sniper.de
24.06.2004, 21:44
FUNZT 1a !!!

Danke euch :)

Procyon
25.06.2004, 17:08
Tach erstmal

nein, so wie du das programmiert hast ist das dingen offen für sql-injections!

SQL-Injection heißt, dass man ungewollte sql-anweisungen mit einschleusen & ausführen kannst.

Das passiert weil du die einzelnen Werte der Eingaben nicht begrenzt! Wenn in dem eingegebenen Benutzernamen ein Komma drin wäre, dann würde das mit übergeben und es gäbe einen Wert mehr als spalten zum einfügen ausgewählt wurden ...



<?php
// Beispiel:
$username="Procyon, theEvil";
$password="123456";
$email="test@test.com";

// gekürzt:

$db->query
( 'INSERT INTO user (user, password, email)
VALUES
( $username,
'.md5($password).',
$email
)'
);
?>

würde in dieser Query resultieren:

INSERT INTO user (user, password, email)
VALUES
( Procyon, theEvil,
e10adc3949ba59abbe56e057f20f883e,
test@test.com
)
In dem Values-Teil gibt es 4 Werte, alle mit einem Komma separiert, es wurden aber nur die 3 Spalten user, password und email ausgewählt um Daten einzutragen. Dieses Beispiel erzeugt nur eine Fehlermeldung der MySQL-Datenbank, es ist aber möglich das noch anderweitig auszunutzen.

Um solche Sachen zu verhindern solltest du alle Benutzereingaben separieren und escapen. Separieren heißt dass die Eingaben von den restlichen Sachen der SQL-Query abgegrenzt werden.

Tabellen- und Spaltennamen werden bei MySQL mit so genannten "Backticks" ` eingeschlossen (Shift und die französischen Accents gleichzeitig drücken, dann die Leertaste). Dann musst du nur noch alle Backticks aus den Tabellen- und Spaltennamen entfernen, damit evtl. eingeschleuste Teile in den Tabellen- und Spaltennamen nicht aus der Backtick-Begrenzung ausbrechen können.

Bei Strings verwendet MySQL einfache Anführungszeichen ' (Apostrophe, Shift und die Raute # gleichzeitig drücken) um die Eingaben von der MySQL-Query zu separieren.

Bei den Strings kann man aber nicht so einfach die Apostrophe rauslöschen denn die sind in der Regel ja gewollt. Statt dessen entwertet man sie (escapen), indem man ihnen einen Backslash \ voranstellt. Bei so etwas wie
mysql_query
( "INSERT INTO
`user` (`text`)
VALUES
('ich hab\\' hier ein Apostroph gemacht')"
); zählt das Apostroph nach dem Backslash nicht als Steuerzeichen (das bedeuten würde dass der String zu ende ist), sondern MySQL entfernt den Backslash wieder und in der Datenbank steht dann der Text "ich hab' hier ein Apostroph gemacht" ...

hier 2 Funktionen die ich fast immer verwende:


<?php
function mysqlsafetblcolname($name)
{
global $db;
settype($name,'string');
$name=str_replace('`','',$name);
return('`'.mysql_real_escape_string($name,$db).'`');
} // end function mysqlsafetblcolname

function mysqlsafestringvalue($value)
{
global $db;
settype($value,'string');
return("'".mysql_real_escape_string($value,$db)."'");
} // end function mysqlsafestringvalue
?>


Guck dir auch mal die Funktionsweise von magic_quotes an, denn es ist möglich die Sachen doppelt zu entwerten (escapen).

Weitere Infos:

http://dclp-faq.de/ch/ch-security.html (auch der Rest der FAQ)
http://php.net/mysql_escape_string
http://php.net/addslashes
http://php.net/stripslashes
http://de3.php.net/manual/de/faq.using.php (Fragen 2 und 3)
http://de3.php.net/manual/de/faq.html.php (Frage 1. Ist nicht das gleiche, aber ein ähnliches Problem)

Ich hoffe dir geholfen zu haben ;)

sniper.de
25.06.2004, 20:53
ophhh...

Ist mir so noch gar nicht bewusst geworden!
ich habe es glücklicherweise nicht überall so, das ist ja ne Sicherheitslücke groß wie ein Scheunentor!

DANKE DANKE DANKE.
Du hast mir seeehhhrrr geholfen!

Werde mir die Funktionen mal vornehmen.
Also diese Funktionen entwer´ten die ' in Strings, sodass ich bei Mysql mit ' arbeiten kann!?

Procyon
25.06.2004, 22:55
Tach erstmal


Original geschrieben von sniper.de
Also diese Funktionen entwerten die ' in Strings, sodass ich bei Mysql mit ' arbeiten kann!?

Ja. Du brauchst eigentlich nur mysqlsafestringvalue, da du die Tabellen- und Spaltennamen ja schon beim Programmieren festlegst (und dabei dann eben keine Sonderzeichen nimmst). Dann musst du die auch nicht in Backticks setzen.

Wenn du eine Benutzereingabe vorher durch mysqlsafestringvalue jagst kannst du sicher sein dass evtl. bösartiger Code darin nicht aus der Begrenzung durch die Apostrophe ausbrechen kann.

Zur Erklärung von der magic_quotes:
Wenn die angeschaltet sind (=> php.ini) dann entwertet PHP alle Benutzereingaben automatisch (so wie es addslashes() (http://php.net/addslashes)) tun würde. Ich persönlich mag es aber nicht, wenn so was vorher gemacht wird ... denn evtl. werden die Eingaben zweimal entwertet, nämlich am Anfang durch PHP und dann durch mysql_(real_)escape_string. D.h. aus einem einfachen Apostroph wird durch PHP ein Backslash + Apostroph und dann erhält man durch mysql_(real_)escape_string drei Backslashes + ein Apostroph, was ja nicht gewollt ist und dann durch MySQL nur zu einem Backslash mit Apostroph danach umgewandelt wird, ergo hat man einen Backslash da den der Benutzer gar nicht eingegeben hat.

Falls du bei deinem Provider magic_quotes nicht ausschalten kannst:


<?php
/*
** MAGIC QUOTES
**
** I don't like magic quotes, if they're on, remove them again
*/
/*
** recursive_stripslashes
**
** removes the slashes from strings & arrays recursively.
** only works on strings & arrays, all other types are not changed.
*/
function recursive_stripslashes($with_slashes)
{
// the type of $with_slashes decides what to do
if(is_string($with_slashes))
// just remove the slashes and we're finished
return(stripslashes($with_slashes));
elseif(is_array($with_slashes))
{ // work on every element of the array recursively
foreach($with_slashes as $index=>$value)
$with_slashes[$index]=recursive_stripslashes($value);
return($with_slashes); // return it ... even now the varname is wrong
}
else
// don't know what to do, do nothing
return($with_slashes);
} // end function recursive_stripslashes

/*
** do this before the call of recursive_stripslashes, because the returned
** value from recursive_stripslashes would probably be sent through addslashes
** again if magic_quotes_runtime is 1 !!!
*/
set_magic_quotes_runtime(0);

if(get_magic_quotes_gpc())
$GLOBALS=recursive_stripslashes($GLOBALS);
?>


Dieses entfernen der hinzugefügten Slashes ist wichtig (finde ich), weil PHP ja nicht weiß wie ich die Eingaben weiterverwenden will. Als Parameter an einer URL muss ich sie ja anders behandeln als bei einer SQL-Query und anders als in einem Formular etc. (Wie muss ich enkodieren / dekodieren, wenn ich einen Wert über ein Formular / einen URL weitergeben möchte? (http://de3.php.net/manual/de/faq.html.php#faq.html.encoding)) Außerdem mag ich es nicht wenn mir jemand in meine Sachen reinpfuscht :D


Wenn du Integer in die Datenbank einträgst, dann mach sie mit settype($var,'integer'); auch zu Integern und setz sie in die Query, ohne sie in Apostrophe einzuschließen oder mit mysqlsafestringvalue zu entwerten. Da Integer ja nur Ganzzahlen sind, können sie gar nicht ausbrechen ;)


[EDIT 2]
falls du mit NULL-Werten arbeitest, sind diese Funktionen von Wie kann ich bösartigen Code in SQL-Abfragen unterbinden? (http://dclp-faq.de/q/q-sql-injection.html) besser weil sie NULL-Werte beachten:


<?php
function sqlSafeString($param) {
// Hier wird wg. der grossen Verbreitung auf MySQL eingegangen
return (NULL === $param ? "NULL" : '"'.mysql_escape_string ($param).'"');
}

function sqlSafeInt($param) {
return (NULL === $param ? "NULL" : intVal ($param));
}
?>

[/EDIT 2]

Viel Spaß noch beim Programmieren! :D

sniper.de
26.06.2004, 00:21
Original geschrieben von Procyon_theEvil
....
Viel Spaß noch beim Programmieren! :D

jo den werde ich dank dir nun erst recht haben :)

Nun durchsuche ich alles mal nach "Schwachstellen" :)

Hier kannsu meine "phpkünste" bewundern (ich lerne erst seit März PHP):

http://web10.isis88.plusserver.de/