易受 SQL 注入攻击?
Vulnerable to SQL Injection?
我目前正在创建一个 Java 应用程序,它使用 MySQL。
我了解到在某些情况下您应该使用准备好的语句来防止 SQL 注入。
到目前为止,我不使用准备好的语句,实际上我有点担心我的代码可能容易受到 SQL 注入的攻击。
执行MySQL个查询的情况:
- 从应用程序内部直接查询(所有使用的变量都在应用程序中定义)
- API 调用(另一个应用程序进行 MySQL 查询 --> 使用的所有变量都在进行调用的应用程序内部定义)
MySQL代码:
public static void Update(final String qry) {
try {
Statement stnt = connection.createStatement();
stnt.executeUpdate(qry);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static ResultSet Query(String qry) {
final ResultSet rs;
try {
Statement stnt = connection.createStatement();
rs = stnt.executeQuery(qry);
} catch (Exception e) {
e.printStackTrace();
}
return rs;
}
你能post举个例子String qry
吗?
一般来说,如果您使用不是在程序内部定义但从外部定义的值执行查询,则可能容易受到攻击。
例如:
如果您有 String name = null;
并且 name
是用户定义的,并且您将 name
推入数据库,这可能是一个漏洞。
您可以避免使用 preparedStatement
注入,因为您使用将值处理为字符串的方法设置参数。
示例:
try (Connection con = DriverManager.getConnection(JDBC_URL, JDBC_USERNAME, JDBC_PASSWORD)){
try (PreparedStatement pst = con.prepareStatement(
"INSERT INTO " + TABLE_NAME
+ "(id, date, ip, name) "
+ "VALUES (?,?,?,?)")) {
pst.clearParameters();
pst.setInt(1, objectID);
pst.setDate(2, (Date) objectDate);
pst.setString(3, objectIP.getHostAddress());
pst.setString(4, object.getName());
int n = pst.executeUpdate();
System.out.println("Inserted " + n + " rows.");
} catch (SQLException e) {
System.out.println("Error in insertion: " + e.getMessage());
}
} catch (SQLException e){
System.out.println("Problem with connection to db:" + e.getMessage());
}
用TABLE_NAME
作为静态字符串变量。
例如,对名称的 SQL 注入尝试将通过 pst.setString
,因此数据库不会将其视为查询,而只是将其视为要插入数据库的值。
根据其他因素,您的应用程序可能仍然容易受到来自有权访问您应用程序环境的人的 SQL 注入攻击。
例如,如果您的代码中定义的变量从配置文件中获取它们的值,并且随后成为 SQL 查询的一部分,则有权访问您的配置文件的攻击者可以执行 SQL 通过更改配置文件的内容进行注入攻击。其他应用程序也是如此:如果有一种方法可以更改进入 SQL 查询构造的变量的内容,则很可能会执行成功的 SQL 注入攻击。
使用准备好的语句可以全面防御注入。不过,增加的复杂性是值得的,因为您可以通过相对简单的修复来填补一个巨大的安全漏洞。
不确定你的问题是什么,但是是的,你可能容易受到 sql 注入的攻击,因为你有查询参数来自应用程序外部的场景(如你所解释的)。
如果您在构建查询字符串时(或之前)已经在进行检查以防止这种情况发生,即使您没有使用准备好的语句,您也可能不会受到攻击。
但我强烈建议使用准备好的语句和绑定变量
我目前正在创建一个 Java 应用程序,它使用 MySQL。
我了解到在某些情况下您应该使用准备好的语句来防止 SQL 注入。
到目前为止,我不使用准备好的语句,实际上我有点担心我的代码可能容易受到 SQL 注入的攻击。
执行MySQL个查询的情况:
- 从应用程序内部直接查询(所有使用的变量都在应用程序中定义)
- API 调用(另一个应用程序进行 MySQL 查询 --> 使用的所有变量都在进行调用的应用程序内部定义)
MySQL代码:
public static void Update(final String qry) {
try {
Statement stnt = connection.createStatement();
stnt.executeUpdate(qry);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static ResultSet Query(String qry) {
final ResultSet rs;
try {
Statement stnt = connection.createStatement();
rs = stnt.executeQuery(qry);
} catch (Exception e) {
e.printStackTrace();
}
return rs;
}
你能post举个例子String qry
吗?
一般来说,如果您使用不是在程序内部定义但从外部定义的值执行查询,则可能容易受到攻击。
例如:
如果您有 String name = null;
并且 name
是用户定义的,并且您将 name
推入数据库,这可能是一个漏洞。
您可以避免使用 preparedStatement
注入,因为您使用将值处理为字符串的方法设置参数。
示例:
try (Connection con = DriverManager.getConnection(JDBC_URL, JDBC_USERNAME, JDBC_PASSWORD)){
try (PreparedStatement pst = con.prepareStatement(
"INSERT INTO " + TABLE_NAME
+ "(id, date, ip, name) "
+ "VALUES (?,?,?,?)")) {
pst.clearParameters();
pst.setInt(1, objectID);
pst.setDate(2, (Date) objectDate);
pst.setString(3, objectIP.getHostAddress());
pst.setString(4, object.getName());
int n = pst.executeUpdate();
System.out.println("Inserted " + n + " rows.");
} catch (SQLException e) {
System.out.println("Error in insertion: " + e.getMessage());
}
} catch (SQLException e){
System.out.println("Problem with connection to db:" + e.getMessage());
}
用TABLE_NAME
作为静态字符串变量。
对名称的 SQL 注入尝试将通过 pst.setString
,因此数据库不会将其视为查询,而只是将其视为要插入数据库的值。
根据其他因素,您的应用程序可能仍然容易受到来自有权访问您应用程序环境的人的 SQL 注入攻击。
例如,如果您的代码中定义的变量从配置文件中获取它们的值,并且随后成为 SQL 查询的一部分,则有权访问您的配置文件的攻击者可以执行 SQL 通过更改配置文件的内容进行注入攻击。其他应用程序也是如此:如果有一种方法可以更改进入 SQL 查询构造的变量的内容,则很可能会执行成功的 SQL 注入攻击。
使用准备好的语句可以全面防御注入。不过,增加的复杂性是值得的,因为您可以通过相对简单的修复来填补一个巨大的安全漏洞。
不确定你的问题是什么,但是是的,你可能容易受到 sql 注入的攻击,因为你有查询参数来自应用程序外部的场景(如你所解释的)。
如果您在构建查询字符串时(或之前)已经在进行检查以防止这种情况发生,即使您没有使用准备好的语句,您也可能不会受到攻击。
但我强烈建议使用准备好的语句和绑定变量