2012-05-09 13 views
5

Antecedentes:Escapar SQL cadenas en Java

Actualmente estoy desarrollando una interfaz Java para una base de datos de CMS Empresa (Business Objects). Por el momento, estoy creando una función para permitir al usuario crear una consulta de base de datos personalizada. Ya he implementado medidas para garantizar que el usuario solo pueda seleccionar utilizando un subconjunto de columnas disponibles y operadores que han sido aprobados para el acceso de los usuarios (por ejemplo, SI_EMAIL_ADDRESS puede seleccionarse mientras que campos más potentes como SI_CUID no pueden ser). Hasta el momento las cosas han estado sucediendo a la perfección, pero ahora es el momento de asegurar esta característica contra los potenciales ataques de inyección SQL.

La Pregunta:

Busco a un método para escapar de las cadenas de entrada de usuario. Ya he visto PerparedStatement, sin embargo, estoy obligado a utilizar API de terceros para acceder a la base de datos. Estas API son inmutables para mí y el acceso directo a la base de datos está fuera de cuestión. Los métodos individuales toman cadenas que representan las consultas que se ejecutarán, invalidando así PreparedStatement (que, que yo sepa, debe ejecutarse contra una conexión de base de datos directa).

He considerado utilizar String.replace(), pero no quiero reinventar la rueda si es posible. Además, estoy muy lejos de los expertos en seguridad que desarrollaron PerparedStatement.

También había mirado la referencia de API de Java para PerparedStatement, con la esperanza de encontrar algún tipo de método toString(). Por desgracia, no he podido encontrar nada por el estilo.

Cualquier ayuda es muy apreciada. Gracias de antemano.

Referencias:

Java - escape string to prevent SQL injection

Java equivalent for PHP's mysql_real_escape_string()

Respuesta

2

Por supuesto, sería más fácil y más seguro usar PreparedStatement.

ANSI SQL requiere una cadena literal para comenzar y terminar con una comilla simple, y el único mecanismo de escape para una comilla simple es utilizar dos comillas simples:

'Joe''s Caffee' 

tanto, en teoría, sólo se necesitan reemplace una comilla simple con dos comillas simples. Sin embargo, hay algunos problemas. En primer lugar, algunas bases de datos (MySQL, por ejemplo) también (o solo) admiten una barra diagonal inversa como mecanismo de escape. En ese caso, necesitaría duplicar las barras diagonales inversas (también).

Para MySQL, sugiero usar el MySQLUtils. Si no usa MySQL, entonces necesita verificar cuáles son los mecanismos de escape exactos para usar.

2

aún puede ser capaz de usa una declaración preparada. Ver esta publicación: get query from java sql preparedstatement. Además, según esa publicación, puede usar Log4JDBC para manejar esto.

Cualquiera de estas opciones debería evitar que deba preocuparse por evitar las cadenas para evitar la inyección de SQL, ya que la declaración preparada lo hace por usted.

+0

Ese primer eslabón de la suya es poderoso interesante. Me preocupa el comportamiento potencialmente indefinido del método toString() definido implícitamente. Los arquitectos de la empresa han realizado esfuerzos impresionantes para garantizar que la base de datos en sí esté bien oculta (como deberían). Ni siquiera sé qué DBMS se está ejecutando o si se cambiará en el futuro. – phobos51594

+0

En realidad, pensándolo bien, no parece que PreparedStatement tenga incluso un constructor de acceso público. Como no tengo un objeto de conexión JDBC, no estoy seguro de cómo podría obtener un objeto PreparedStatment para empezar. Hm. – phobos51594

+0

Sí, puedo ver cómo eso sería un enigma. No he usado Log4JDBC, pero parece que podría generar el SQL para usted según la declaración preparada. – ametren

0

Aunque no existe una forma estándar de manejar la mysql_real_escape_string() de PHP en Java, lo que hice fue encadenar todo el método de reemplazo para manejar todos los aspectos que pudieran ser necesarios para evitar cualquier excepción. Aquí está mi código de ejemplo:

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

}