A.16 SQL Injection
Sofern Sie Anwendungen mit Datenbankzugriffe schreiben, sollten Sie sich auch gegen SQL Injection Angriffe verteidigen. Meistens handelt es sich dabei um eine Eingabe, die von einem User gemacht wird. Ein einfaches Beispiel sei mit folgendem Konstrukt gegeben:
SELECT * FROM user WHERE name="Wolf"
Hier wird davon ausgegangen, der Wert »Wolf« direkt von der Eingabe des Users (bspw. via Webinterface) gemacht wurde. Ein Angreifer könnte hier jetzt eine geschlossene »Double Quote« und ein Semikolon einfügen um so weitere Kommandos anzuhängen und auszuführen. Ein fieses Beispiel wäre:
SELECT * FROM user WHERE name="Wolf"; DROP TABLE user;
Hiermit wird die Tabelle »user« gelöscht. Die sicherste Alternative hierbei ist natürlich, erst gar keine Eingabe eines Users zu lassen. Aber es gibt eben immer »Gründe« dies trotzdem zu verwenden. In diesem Fall sollten Sie gefährliche Zeichen über ein Backslash entschärfen. Einige Datenbanken bieten mittlerweile hierzu schon Funktionen an, die das Problem entschärfen können, aber da nicht jede Datenbank eine solche Funktion anbietet, sei hierzu eine einfache Lösung des Problems an die Hand gegeben.
/*
* eingabe= die Zeichenkette die geschützt (escaped) werden soll
* quote = das "Quote"-Zeichen - entweder Singe Quote oder
* Double Quote, ansonsten wird ein Fehler
* zurückgegeben
* wc = wird hier 0 angegeben, werden Wildcardzeichen
* nicht "escaped".
*/
char *escape_sql(const char *eingabe, char quote, int wc) {
char *out, *ptr;
const char *c;
if (quote != '\'' && quote != '\"')
return NULL;
/* Theoretisch könnte jedes Zeichen "escaped" werden,
* daher wird zunächst das doppelte an Speicher reserviert */
if (!(out = ptr = (char *)malloc(strlen(eingabe) * 2 + 2 + 1)))
return NULL;
*ptr++ = quote;
for (c = eingabe; *c; c++) {
switch (*c) {
case '\'': /* Single Quote */
case '\"': /* Double Quote */
if (quote == *c) *ptr++ = *c;
*ptr++ = *c;
break;
/* Wildcards */
case '%':
case '_':
case '[':
case ']':
if (wc) *ptr++ = '\\';
*ptr++ = *c;
break;
/* Sonderzeichen - Escape-Sequenzen */
case '\\': *ptr++ = '\\'; *ptr++ = '\\'; break;
case '\b': *ptr++ = '\\'; *ptr++ = 'b'; break;
case '\n': *ptr++ = '\\'; *ptr++ = 'n'; break;
case '\r': *ptr++ = '\\'; *ptr++ = 'r'; break;
case '\t': *ptr++ = '\\'; *ptr++ = 't'; break;
default:
*ptr++ = *c;
break;
}
}
*ptr++ = quote;
*ptr = '\0'; /* Terminieren */
return out;
}
|