2012-05-09 11 views
5

Background:Fuggi-fuggi SQL stringhe in Java

Attualmente sto sviluppando un front-end Java per un database di Enterprise CMS (Business Objects). Al momento, sto costruendo una funzionalità per consentire all'utente di creare una query di database personalizzata. Ho già implementato misure per garantire che l'utente sia in grado di selezionare solo un sottoinsieme di colonne disponibili e operatori approvati per l'accesso utente (ad esempio SI_EMAIL_ADDRESS può essere selezionato mentre non possono essere più potenti campi come SI_CUID). Finora le cose sono andate avanti bene, ma è giunto il momento di proteggere questa funzionalità da potenziali attacchi di SQL injection.

la domanda:

Sto cercando un metodo per sfuggire stringhe di input dell'utente. Ho già visto PerparedStatement, tuttavia sono costretto a utilizzare API di terze parti per accedere al database. Queste API sono per me immutabili e l'accesso diretto al database è fuori questione. I singoli metodi accettano stringhe che rappresentano le query da eseguire, invalidando quindi PreparedStatement (che, a mia conoscenza, deve essere eseguito su una connessione diretta al database).

Ho pensato di utilizzare String.replace(), ma non voglio reinventare la ruota se possibile. Inoltre, sono molto diverso dagli esperti di sicurezza che hanno sviluppato PerparedStatement.

Avevo anche esaminato il riferimento API Java per PerparedStatement, sperando di trovare una sorta di metodo toString(). Ahimè, non sono riuscito a trovare nulla del genere.

Qualsiasi aiuto è molto apprezzato. Grazie in anticipo.

Riferimenti:

Java - escape string to prevent SQL injection

Java equivalent for PHP's mysql_real_escape_string()

risposta

2

Ovviamente sarebbe più semplice e sicuro utilizzare PreparedStatement.

ANSI SQL richiede una stringa letterale per iniziare e terminare con una sola citazione, e l'unico meccanismo di fuga per una singola citazione è quello di utilizzare due apici:

'Joe''s Caffee' 

Quindi, in teoria, è solo bisogno di sostituire una singola citazione con due virgolette singole. Tuttavia, ci sono alcuni problemi. In primo luogo, alcuni database (MySQL ad esempio) anche (o solo) supportano un backslash come meccanismo di escape. In tal caso, sarà necessario raddoppiare anche i backslash.

Per MySQL, suggerisco di utilizzare lo MySQLUtils. Se non si utilizza MySQL, è necessario verificare quali sono i meccanismi di escape esatti da utilizzare.

2

Si può ancora essere in grado di utilizzare una dichiarazione preparata. Vedi questo post: get query from java sql preparedstatement. Inoltre, in base a quel post, potresti essere in grado di utilizzare Log4JDBC per gestirlo.

Una di queste opzioni dovrebbe impedire all'utente di preoccuparsi di eseguire il escape delle stringhe per impedire l'iniezione SQL, poiché l'istruzione preparata lo fa per voi.

+0

Quel primo link del tuo è possente interessante. Mi interessa il comportamento potenzialmente indefinito del metodo toString() implicitamente definito. Gli architetti aziendali hanno compiuto sforzi notevoli per garantire che il database stesso sia ben nascosto (come dovrebbero). Non so nemmeno cosa DBMS sia in esecuzione o se verrà modificato in futuro. – phobos51594

+0

In realtà, vieni a pensarci, non sembra che PreparedStatement abbia anche un costruttore accessibile pubblicamente. Dal momento che non ho un oggetto di connessione JDBC, non sono sicuro di come potrei anche ottenere un oggetto PreparedStatment con cui iniziare. Hm. – phobos51594

+0

Sì, posso vedere come sarebbe un enigma. Non ho usato Log4JDBC ma sembra che potrebbe essere in grado di generare l'SQL per te in base alla dichiarazione preparata. – ametren

0

Sebbene non ci sia un modo standard per gestire mysql_real_escape_string() di PHP in Java Quello che ho fatto è stato quello di sostituire il metodo chainAll per gestire ogni aspetto che potrebbe essere necessario per evitare qualsiasi eccezione. Qui è il mio codice di esempio:

public void saveExtractedText(String group,String content) { try { content = content.replaceAll("\", "\\") .replaceAll("\n","\n") .replaceAll("\r", "\r") .replaceAll("\t", "\t") .replaceAll("\00", "\0") .replaceAll("'", "\'") .replaceAll("\"", "\\"");

state.execute("insert into extractiontext(extractedtext,extractedgroup) values('"+content+"','"+group+"')"); 
} catch (Exception e) { 
    e.printStackTrace(); 

}