I\'m trying to put some anti sql injection in place in java and am finding it very difficult to work with the the \"replaceAll\" string function. Ultimately I need a functio
Prepared Statements are the best solution, but if you really need to do it manually you could also use the StringEscapeUtils class from the Apache Commons-Lang library. It has an escapeSql(String) method, which you can use:
import org.apache.commons.lang.StringEscapeUtils;
…
String escapedSQL = StringEscapeUtils.escapeSql(unescapedSQL);
The only way to prevent SQL injection is with parameterized SQL. It simply isn't possible to build a filter that's smarter than the people who hack SQL for a living.
So use parameters for all input, updates, and where clauses. Dynamic SQL is simply an open door for hackers, and that includes dynamic SQL in stored procedures. Parameterize, parameterize, parameterize.
From:[Source]
public String MysqlRealScapeString(String str){
String data = null;
if (str != null && str.length() > 0) {
str = str.replace("\\", "\\\\");
str = str.replace("'", "\\'");
str = str.replace("\0", "\\0");
str = str.replace("\n", "\\n");
str = str.replace("\r", "\\r");
str = str.replace("\"", "\\\"");
str = str.replace("\\x1a", "\\Z");
data = str;
}
return data;
}
In case you are dealing with a legacy system, or you have too many places to switch to PreparedStatement
s in too little time - i.e. if there is an obstacle to using the best practice suggested by other answers, you can try AntiSQLFilter
PreparedStatements are the way to go, because they make SQL injection impossible. Here's a simple example taking the user's input as the parameters:
public insertUser(String name, String email) {
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = setupTheDatabaseConnectionSomehow();
stmt = conn.prepareStatement("INSERT INTO person (name, email) values (?, ?)");
stmt.setString(1, name);
stmt.setString(2, email);
stmt.executeUpdate();
}
finally {
try {
if (stmt != null) { stmt.close(); }
}
catch (Exception e) {
// log this error
}
try {
if (conn != null) { conn.close(); }
}
catch (Exception e) {
// log this error
}
}
}
No matter what characters are in name and email, those characters will be placed directly in the database. They won't affect the INSERT statement in any way.
There are different set methods for different data types -- which one you use depends on what your database fields are. For example, if you have an INTEGER column in the database, you should use a setInt
method. The PreparedStatement documentation lists all the different methods available for setting and getting data.
Using a regular expression to remove text which could cause a SQL injection sounds like the SQL statement is being sent to the database via a Statement rather than a PreparedStatement.
One of the easiest ways to prevent an SQL injection in the first place is to use a PreparedStatement
, which accepts data to substitute into a SQL statement using placeholders, which does not rely on string concatenations to create an SQL statement to send to the database.
For more information, Using Prepared Statements from The Java Tutorials would be a good place to start.