2012-05-09 15 views
5

Tło:Ucieczki SQL Ciągi w Javie

Jestem obecnie opracowanie przód Java dla bazy danych Enterprise CMS (Business Objects). W tej chwili buduję funkcję, aby umożliwić użytkownikowi zbudowanie niestandardowego zapytania do bazy danych. Mam już wdrożone środki, aby zapewnić, że użytkownik jest w stanie wybrać tylko za pomocą podzbioru dostępnych kolumn i operatorów, którzy zostali zatwierdzeni do uzyskiwania dostępu przez użytkownika (np. SI_EMAIL_ADDRESS może być wybrany, podczas gdy bardziej zaawansowane pola, takie jak SI_CUID, nie mogą być). Do tej pory sprawy toczyły się płynnie, ale nadszedł czas, aby zabezpieczyć tę funkcję przed potencjalnymi atakami typu SQL injection.

Pytanie:

szukam sposobu ucieczki ciągów wejściowych użytkownika. Widziałem już PerparedStatement, jednak jestem zmuszony korzystać z API stron trzecich w celu uzyskania dostępu do bazy danych. Te interfejsy są dla mnie niezmienne, a bezpośredni dostęp do bazy danych nie wchodzi w grę. Poszczególne metody przyjmują łańcuchy reprezentujące kwerendy, które mają być uruchamiane, unieważniając w ten sposób PreparedStatement (które, o ile wiem, musi być uruchamiane w oparciu o bezpośrednie połączenie z bazą danych).

Rozważałem użycie String.replace(), ale nie chcę na nowo odkrywać koła, jeśli to możliwe. Ponadto jestem bardzo odległy od ekspertów ds. Bezpieczeństwa, którzy opracowali PerparedStatement.

Przyjrzałem się także odnośnikowi Java API dla PerparedStatement, mając nadzieję na znalezienie metody toString(). Niestety, nie mogłem znaleźć niczego podobnego.

Każda pomoc jest bardzo doceniana. Z góry dziękuję.

Referencje:

Java - escape string to prevent SQL injection

Java equivalent for PHP's mysql_real_escape_string()

Odpowiedz

2

Oczywiście korzystanie z PreparedStatement byłoby łatwiejsze i bezpieczniejsze.

ANSI SQL wymaga ciąg dosłownego zacząć i skończyć z jednym cytatem, a jedynie mechanizm ucieczki na pojedynczy cudzysłów jest użycie dwóch apostrofów:

'Joe''s Caffee' 

Więc teoretycznie, trzeba tylko zastąp pojedynczą cytat dwiema pojedynczymi cytatami. Jednak są pewne problemy. Po pierwsze, niektóre bazy danych (na przykład MySQL) również (lub tylko) obsługują ukośnik odwrotny jako mechanizm ucieczki. W takim przypadku trzeba podwoić również ukośnik odwrotny (również).

Dla MySQL proponuję użyć MySQLUtils. Jeśli nie używasz MySQL, musisz sprawdzić, jakie dokładnie są mechanizmy ucieczki.

2

Być może nadal być w stanie stosować przygotowane oświadczenie. Zobacz ten wpis: get query from java sql preparedstatement. Ponadto, w oparciu o ten post, może być w stanie użyć Log4JDBC do obsługi tego.

Każda z tych opcji powinna zapobiegać obawom przed przechodzeniem łańcuchów znaków, aby zapobiec iniekcji SQL, ponieważ przygotowana instrukcja wykonuje to za Ciebie.

+0

To pierwsze ogniwo jest twój potężny interesujące. Obawiam się potencjalnie niezdefiniowanego zachowania niejawnie zdefiniowanej metody toString(). Architekci zajmujący się architekturą wykonali imponujący wysiłek, aby zapewnić, że sama baza danych jest dobrze ukryta (tak jak powinna). Nie wiem nawet, który system DBMS jest uruchomiony lub czy zostanie zmieniony w przyszłości. – phobos51594

+0

Właściwie, pomyśl o tym, nie wygląda na to, że PreparedStatement ma nawet publicznie dostępny konstruktor. Ponieważ nie mam obiektu połączenia JDBC, nie jestem pewien, jak mogę nawet uzyskać obiekt PreparedStatment na początek. Hm. – phobos51594

+0

Tak, widzę, jak to by było zagadką. Nie używałem Log4JDBC, ale wygląda na to, że może on wygenerować kod SQL dla ciebie na podstawie przygotowanej instrukcji. – ametren

0

Chociaż nie ma standardowego sposobu obsługi PHP w mysql_real_escape_string() w Javie To, co zrobiłem, to łańcuch metody replaceAll, aby obsłużyć każdy aspekt, który może być konieczny, aby uniknąć wyjątków. Oto mój przykładowy kod:

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(); 

}