You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DataAdapter.SelectCommand与SQL注入:导出功能优化的安全疑问

Is dynamically selecting columns from a config file risky for SQL injection?

Great question—this is a common pitfall when dynamically building SQL for column selection, so let’s break this down clearly.

First: Yes, this approach has SQL injection risks

When you directly concatenate columns from a (potentially compromised) config file into your SQL string, you’re opening yourself up to malicious input. For example, if an attacker modifies the config to include something like:

ID, (SELECT password FROM secret_users), 1; DROP TABLE WHATEVER--

Your resulting SQL would become:

SELECT ID, (SELECT password FROM secret_users), 1; DROP TABLE WHATEVER-- FROM WHATEVER WHERE ID=:ID

This could execute two harmful actions: first stealing sensitive data, then deleting your table. Even with OracleDataAdapter, this leads to data exfiltration, table destruction, or other malicious outcomes—Oracle allows multiple statements in a single command depending on configuration, and even without that, subqueries can still leak sensitive information.

Removing spaces won’t protect you

Stripping spaces from column names is ineffective for SQL injection prevention. Attackers can bypass this using:

  • Comment syntax: ID/**/(SELECT/**/password/**/FROM/**/secret_users)
  • URL-encoded whitespace: ID%2C(SELECT%20password%20FROM%20secret_users)
  • No spaces at all (valid in many SQL dialects): ID,(SELECTpasswordFROMsecret_users)

Worse, stripping spaces could break legitimate column names if your schema uses columns with spaces (e.g., User Name—though this is bad practice, it’s possible).

The safe solution: Whitelist validation

The only reliable way to prevent this is to validate incoming column names against a whitelist of actual columns in your table. Here’s how to implement this:

  1. Fetch valid column names from the database (cache this result to avoid repeated queries):

    private HashSet<string> GetValidTableColumns(string tableName, string schemaName)
    {
        var validColumns = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
        using (var cmd = ConFactory.CreateOracleCommand())
        {
            // Query Oracle's system catalog to get valid columns for the table
            cmd.CommandText = @"
                SELECT COLUMN_NAME 
                FROM ALL_TAB_COLUMNS 
                WHERE TABLE_NAME = :TABLE_NAME 
                AND OWNER = :SCHEMA_NAME";
            cmd.Parameters.Add("TABLE_NAME", OracleDbType.Varchar2).Value = tableName;
            cmd.Parameters.Add("SCHEMA_NAME", OracleDbType.Varchar2).Value = schemaName;
            
            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    validColumns.Add(reader.GetString(0));
                }
            }
        }
        return validColumns;
    }
    
  2. Filter your input columns against the whitelist:

    // Get cached valid columns for your table
    var validColumns = GetValidTableColumns("WHATEVER", "YOUR_SCHEMA_NAME");
    // Filter incoming columns to only include valid ones
    var safeColumns = columns
        .Select(col => col.Trim())
        .Where(col => validColumns.Contains(col))
        .ToList();
    
    // Handle edge case: no valid columns selected
    if (!safeColumns.Any())
    {
        throw new InvalidOperationException("No valid columns specified for export.");
        // Or fall back to a default set of columns
        // safeColumns = new List<string> { "ID", "DEFAULT_COLUMN" };
    }
    
    // Build your safe SQL string
    string sColumns = string.Join(",", safeColumns);
    var sql = string.Format("SELECT {0} FROM WHATEVER WHERE ID=:ID", sColumns);
    
  3. Secure your config file:
    Even with validation, restrict file system permissions on your config file so only trusted users can modify it. This reduces the chance of malicious changes in the first place.

Why parameterization doesn’t work here

Note that you can’t parameterize column names—SQL parameters only work for values (like the :ID in your query), not for identifiers (columns, tables). So whitelisting is the only viable approach here.

内容的提问来源于stack exchange,提问作者Stokke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:44:09