# SQL-Injection verhindern OHNE PreparedStatements



## Natac (11. Jan 2013)

Liebe Community,

folgende Problemstellung: Ich habe eine Datenbank-Schnittstelle, die auf verschiedene Datenbank-Typen (MySql, Access, etc...) zugreifen können soll. 

Nun ist es natürlich so, dass ich bei Nutzung der Schnittstelle eine Sql-Injection verhindern möchte. Die Lösung, auf die ich hier und im Internet für Java immer wieder stoße ist: PrepraredStatements. 

Aber leider unterstüzen nicht alle Datenbank-Typen (bspw. MS Access) PreparedStatements und ich kann folglich nicht damit arbeiten, wenn die Schnittstelle allgemein bleiben soll.

Daher benötige ich eine Lösung einen String von einer möglichen Sql-Injection zu "befreien" OHNE PreparedStatements zu nutzen.

Irgendwelche Ideen?


----------



## SlaterB (11. Jan 2013)

"befreien", also ändern musst du die Eingabe ja wohl nicht,
wenn ein böswilliger Angriff vorliegt, dann lohnt sich kaum, einen womöglich legalen Anteil herauszufiltern, vielleicht eh nur Dummy-Daten,

wenn ein nicht bedachtes Problem vorliegt, dann die Daten auch nicht willkürlich (automatisch) kürzen, dann muss die Eingabe überdacht werden

deine Aufgabe besteht doch eher im Erkennen eines Problems,
hast du schon ausführliche Problem-Seiten wie
SQL Injection Attacks by Example
angesehen?

auf gewisse Schlüsselwörter, Semikolon usw. kann man prüfen,
freilich vielleicht im Text selber erlaubt, dann muss man auf korrekte Anführungszeichen und keine im Text selber achten usw.

man kann natürlich auch und sollte wahrscheinlichen einen String-Parameter einfach so als unbehandelten Text nehmen,
dann alle Anführungszeichen darin maskieren wie immer nötig und gesamten Text in Anführungszeichen setzen

PreparedStatement wird letztlich auch nur solche einfachen Schritte ausführen


----------



## maki (11. Jan 2013)

MS-Access unterstützt PreparedStatement IME, allerdings wird der SQL Standard nicht so wirklich ganz unterstützt.. abgesehen davon sollte die JDBC-ODBC Brücke nie produktiv eingesetzt werden.

Alles in allem kann ich dir von MS-Access nur abraten, genauso wie zu versuchen selber SQL INjections zu verhindern.

PreparedStatement arbeiten anders IMHO, da wird "typsicher" konvertiert und damit SQL Injections verhindert, nicht Strings geparst und dann gefiltert.
D.h. dass ein String komplett (eventuell maskiert) an die DB gesendet wird, die Trick mit SQL Injetion funktionieren dann nicht mehr, weil sonderzeichen/spezielle Zeichen maskiert werden.


----------



## nillehammer (11. Jan 2013)

> Daher benötige ich eine Lösung einen String von einer möglichen Sql-Injection zu "befreien" OHNE PreparedStatements zu nutzen.
> 
> Irgendwelche Ideen?


Du musst bei den eingegebenen Parametern alle Zeichen maskieren, die in dem verarbeitenden Programm (hier SQL) eine Sonderbedeutung haben. Das selbst zu implementieren, ist bestimmt sehr fehleranfällig. Deswegen lieber eine Library für sowas benutzen. In Apache commons-lang gibt es die Klasse StringEscapeUtils (StringEscapeUtils (Commons Lang 2.4 API)). Die kann das.

Ansonsten schließe ich mich den Vorrednern und Tutorials im Internet an und verweise auf PreparedStatement. In der aktuellen Version von Commons-Lang (3) ist aus genau dem Grund auch die Methode escapeSql rausgeflogen.


----------



## fastjack (11. Jan 2013)

Ich würde vorsichtig sein, bei SQL-Injection auf PreparedStatements zu vertrauen, besonders wenn es DB unabhängig sein soll. Die Implementierung kommt doch vom jeweiligen DB-Provider und das Interface PreparedStatement verpflichtet zu nichts bezüglich SQL-Injections.


----------



## Natac (11. Jan 2013)

Okay, "befreien" war vielleicht nicht der richtige Ausdruck. Erstmal möchte ich es erkennen können. Wie ich dann damit umgehe oder ob man es "escapen" kann, ist dann die eher unkritische Frage.



maki hat gesagt.:


> Alles in allem kann ich dir von MS-Access nur abraten, genauso wie zu versuchen selber SQL INjections zu verhindern.



Tja, wie das Leben so spielt:
a) Es gibt vorhandene Access-Datenbanken, die ich auslesen und beschreiben können muss (btw: suche dazu noch einen möglichs unabhängigen (ohne ODBC?) Treiber für MS Access, der auch Sql versteht)

b) Bin ich ja auch gerne bereit eine Bibliothek zu nutzen, die das übernimmt. Aber wenn selbst die apache.common das rausgenommen hat


----------



## maki (11. Jan 2013)

a) Es gibt kommerzielle JDBC Treiber für MS-Access, die sollen besser sein, aber machen auch aus Access keine echte DB.


----------



## fastjack (11. Jan 2013)

escapeSql aus den Commons hat lediglich die Hochkommata escaped, mehr nicht. Darum ist es weg.


----------



## Lumaraf (11. Jan 2013)

fastjack hat gesagt.:


> escapeSql aus den Commons hat lediglich die Hochkommata escaped, mehr nicht. Darum ist es weg.



Sich auf escapeSql zu verlassen wäre z.b. bei MySQL sehr schlecht da MySQL zum escapen \' verwendet. Wenn man mit Escaping SQL-Injections verhindern will muß man für jede Datenbank eine eigene Methode verwenden.


----------



## Natac (11. Jan 2013)

@Sql + access: Hm... freeware wäre schon schöner. Könnte man nicht einfach über eine MS-Access-Api (bspw. jackcess) eine HSQLDB füllen und diese dann mit Sql abfragen? Wäre zumindest ein Workaround, ohne einen neuen Treiber schreiben zu müssen...


Gibts da echt nirgends eine lib oder eine RegEx, der mir hilft Sql-Injections zu finden? Kann doch nicht sein, dass sich alle Welt auf die PreparedStatements verlässt ???:L 
Am Ende muss ich doch ne eigene Methode schreiben, wa!?


----------



## Bernd Hohmann (11. Jan 2013)

nillehammer hat gesagt.:


> Deswegen lieber eine Library für sowas benutzen. In Apache commons-lang gibt es die Klasse StringEscapeUtils (StringEscapeUtils (Commons Lang 2.4 API)). Die kann das.



Die kann was?


```
public static String escapeSql(String str) {
           if (str == null) {
               return null;
           }
           return StringUtils.replace(str, "'", "''");
       }
```

Ob das ausreicht eine SQL-Injection zu verhindern, da habe ich etwas Zweifel dran.

Bernd


----------



## Bernd Hohmann (11. Jan 2013)

maki hat gesagt.:


> PreparedStatement arbeiten anders IMHO, da wird "typsicher" konvertiert und damit SQL Injections verhindert, [...]



Nicht mal das. Der Trick besteht einfach darin, dass bei PreparedStatements der SQL-Befehl separat von den Variablen behandelt werden kann. Das eigentliche Statement läuft also durch den SQL-Interpreter, die Variablen jedoch nicht -- und schwupp ist man das Problem mit den Injections los.

PreparedStatements haben noch weitere Vorteile: Die Query kann vorkompiliert und auf Syntax geprüft werden. Weiterhin können "bessere" Datenbanken damit auch den Zugriffpfad auf die Daten besser optimieren (access plan) bzw. der Admin seinen eigenen access plan an die Query binden.

Im OWASP Projekt gibt es Filter um für Legacy-Applikationen Eingabestrings von SQL-Kommandos zu befreien, die Filter gibts aber auch nur für Oracle und MySQL. Keine Chance da was mit MS-Access zu machen.

https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet

Bernd


----------

