Java 我易受SQL注入攻击吗?

Java 我易受SQL注入攻击吗?,java,sql,sql-injection,liquibase,Java,Sql,Sql Injection,Liquibase,我有一个类,它扩展了一个实现CustomTaskChange的类。由于一些类属性(如列名和类型)是通过XML文件传递给它的,因此我需要进行字符串连接。我确实使用PreparedStatement,但我想知道是否因为它我仍然容易受到SQL注入的攻击,如果是这种情况,我如何才能使它安全? XML是一个Liquibase变更集(我将在下面留下一个示例) XML文件 它是否是SQL注入漏洞取决于XML文件的来源 如果程序员正在编写这样的文件,那么就不会有SQL注入问题。是的,连接危险的东西是可能的,但这

我有一个类,它扩展了一个实现CustomTaskChange的类。由于一些类属性(如列名和类型)是通过XML文件传递给它的,因此我需要进行字符串连接。我确实使用PreparedStatement,但我想知道是否因为它我仍然容易受到SQL注入的攻击,如果是这种情况,我如何才能使它安全? XML是一个Liquibase变更集(我将在下面留下一个示例)

XML文件
它是否是SQL注入漏洞取决于XML文件的来源

如果程序员正在编写这样的文件,那么就不会有SQL注入问题。是的,连接危险的东西是可能的,但这并不比开发人员直接在代码中编写危险的东西更危险

但是,如果XML文件来自最终用户或其他服务,或者来自允许其他人或服务修改的文件,则应将其视为潜在危险,并且您的代码将面临SQL注入攻击的风险

由于所有连接的值实际上都是标识符(列名和数据类型),而不是值,因此如果您检查它们是否仅由字母数字字符组成,则可能是安全的:

if (!getColumnName().matches("\\p{AlNum}+")) {
    throw new CustomChangeException(
        "Invalid column name: \"" + getColumnName() + "\"");
}
if (!after.matches("\\p{AlNum}+")) {
    throw new CustomChangeException(
        "Invalid 'after' column name: \"" + after + "\"");
}
if (!getColumnType().matches("\\p{AlNum}+")) {
    throw new CustomChangeException(
        "Invalid column type: \"" + getColumnType() + "\"");
}

对您在不进行清理的情况下手动构造SQL,因此在调用prepareStatement时,为时已晚。如果
this.getColumnName()
返回
'',该怎么办;DROP TABLE blahblah…
我有什么办法可以阻止它吗?我确实需要XML文件传递参数。在这种情况下,我真的不需要PreparedStatement,而是可以使用语句?我不知道这是否可行,但对于您给出的示例,如果我验证变量的值是否为单个单词,是否安全?当然。编写自己功能完善的SQL注入保护当然是可能的,但也有风险。如果检查字符串是否包含a-Z字符就足够了,那么这就足够简单,我不会在代码审查中拒绝它。自定义验证越复杂,它包含破坏整个保护的错误的可能性就越高。字母数字排除空格,对吗?这样,用户不能发送多个单词。这是我对protectionCorrect的基本想法,{AlNum}只是A-Z、A-Z和0-9。请参阅。由于PreparedStatement非常无用,因为我正在从文件接收值,所以我应该切换到语句吗?这样,我就不必总是实例化一个新对象。使用PreparedStatement没有害处。另外,我是否也应该在defaultValue中进行验证?因为如果发送的值可以是例如“ABC;DROP TABLE asdds”
@Override
    public void execute(Database database) throws CustomChangeException {

        try {
            //check if there are any errors in the changelog file
            checkArgumentsNumber();

            boolean tablesFound = false;
            boolean columnsAdded = false;
            String sqlStatement = "ALTER TABLE NAME ADD COLUMN " +this.getColumnName()+" "+this.getColumnType();

            if(notNull){
                sqlStatement+=" NOT NULL";
            }

            if(defaultValue!=null){
                sqlStatement+=" DEFAULT ?";
            }

            if (this.after != null) {
                sqlStatement += " AFTER " +this.after;
            }

            System.out.println("The statement is: "+sqlStatement);

            //get tables in the database
            JdbcConnection connection = (JdbcConnection) database.getConnection();
            DatabaseMetaData metadata;
            metadata = connection.getMetaData();
            String[] types = {"TABLE"};
            ResultSet rs = metadata.getTables(connection.getCatalog(), null, "%", types);

            //if the user chose to use a regex
            if (this.getRegex() != null) {
                Pattern pattern = Pattern.compile(this.getRegex());

                while (rs.next()) {
                    String tableName = rs.getString(3);
                    Matcher matcher = pattern.matcher(tableName);
                    boolean matches = matcher.matches();
                    if (matches) {
                        tablesFound = true;
                        String addStatement=sqlStatement.replaceAll("NAME",tableName);
                        PreparedStatement s = connection.prepareStatement(addStatement);
                        if (!checkColumnsExists(s, tableName)) {
                            if(this.defaultValue!=null){
                                s.setString(1,this.defaultValue);
                            }
                            System.out.println("REGEX:"+s.toString());
                            s.executeUpdate();
                            columnsAdded = true;
                        }
                    }
                }
            }

            checkInvalidInfo(tablesFound, columnsAdded, "All the matching tables already had that column");
        } catch (InvalidArgumentsNumberException | SQLException | InvalidInfoException | DatabaseException e) {
            throw new CustomChangeException("Error enabling trigger: " + e);
        }
    }
if (!getColumnName().matches("\\p{AlNum}+")) {
    throw new CustomChangeException(
        "Invalid column name: \"" + getColumnName() + "\"");
}
if (!after.matches("\\p{AlNum}+")) {
    throw new CustomChangeException(
        "Invalid 'after' column name: \"" + after + "\"");
}
if (!getColumnType().matches("\\p{AlNum}+")) {
    throw new CustomChangeException(
        "Invalid column type: \"" + getColumnType() + "\"");
}