【问题标题】:Unable to stop SQL injection errors无法停止 SQL 注入错误
【发布时间】:2015-08-12 07:13:54
【问题描述】:

我终于明白了。这不仅仅是我用来执行 ExecuteScalar 方法的代码,而是主要是执行类的上游代码。一切都在调用您的代码。也就是说,有人可以看看执行我的 SQL 类的代码是否有错误。我仍然无法通过扫描。首先,我将向您展示两个调用我的代码的代码示例,然后是调用代码,最后是执行代码,这是我在上一篇文章中制定和展示的。

三个参数的调用代码:

public bool isTamAsp(int aspKey, int fy, string accountCode)
{
    MyParam myParam;

    string sqlQuery = "select isTamMacom = count(macom_key) FROM hier_fy " +
        "WHERE hier_key = @aspKey AND fy = @fy  AND @accountCode NOT IN (3,4,7,8) AND macom_key IN (select hier_key from lkup_e581_MacomThatRequireTAM) AND is_visible = 1 AND is_active = 1";

    QueryContainer Instance = new QueryContainer(sqlQuery);

    myParam = new MyParam();

    myParam.SqlParam = new SqlParameter("@aspKey", Instance.AddParameterType(_DbTypes.Int));

    myParam.SqlParam.Value = aspKey;

    Instance.parameterList.Add(myParam);

    myParam = new MyParam();

    myParam.SqlParam = new SqlParameter("@fy", Instance.AddParameterType(_DbTypes.Int));

    myParam.SqlParam.Value = fy;

    Instance.parameterList.Add(myParam);

    myParam = new MyParam();

    myParam.SqlParam = new SqlParameter("@accountCode", Instance.AddParameterType(_DbTypes._string));

    myParam.SqlParam.Value = accountCode;

    Instance.parameterList.Add(myParam);

    if (Convert.ToInt32(ExecuteScaler(Instance)) < 1)
        return false;

    return true;
}

不带参数的调用代码:

public long GetMarinesUploadNextUploadKey()
{
    string query = "SELECT MAX(upload_key) FROM temp_auth_usmc_upload";

    QueryContainer Instance = new QueryContainer(query);

    string result = Convert.ToString(ExecuteScaler(Instance));
    if (string.IsNullOrEmpty(result))
        return 1;
    else
        return Convert.ToInt64(result) + 1;
} 

代码用三个参数调用我之前的代码:

public bool isTamAsp(int aspKey, int fy, string accountCode)
{
    return e581provider.isTamAsp(aspKey, fy, accountCode);
}

方法调用执行我的代码的 SQL:

DbCommand command = _provider.CreateCommand();

command.Connection = _connection;
{
    command.CommandText = Instance.Query;
    command.CommandType = CommandType.Text;

    if (Instance.parameterList.Count > 0)
    {
        foreach (var p in Instance.parameterList)
        {
            command.Parameters.Add(p.SqlParam);
        }
    }

    if (_useTransaction) { command.Transaction = _transaction; }

    try
    {
        returnValue = command.ExecuteScalar();
    }

My Class 包含 SQL 字符串和 cmd 参数列表

public enum _DbTypes
{
    Int = 1, _string = 2, _long = 3, _bool = 4, _DateTime = 5,
    _decimal = 6, _float = 7, _short = 8, _bite = 9
} 

public class MyParam
{
    public SqlParameter SqlParam { get; set; }
}
/// <summary>
/// Summary description for QueryContainer SGH
/// </summary>
public class QueryContainer
{

    string _query;

    public List<MyParam> parameterList = new List<MyParam>();

    public QueryContainer(string query) { _query = query; }

    public SqlDbType AddParameterType(_DbTypes id)
    {
        switch (id)
        {
            case _DbTypes.Int:
                return (SqlDbType)Enum.Parse(typeof(SqlDbType), "int", true);
            case _DbTypes._string:
                return (SqlDbType)Enum.Parse(typeof(SqlDbType), "NVarChar", true);
            case _DbTypes._long:
                return (SqlDbType)Enum.Parse(typeof(SqlDbType), "SqlDbType.BigInt", true);
            case _DbTypes._bool:
                return (SqlDbType)Enum.Parse(typeof(SqlDbType), "SqlDbType.Bit", true);
        }

        return SqlDbType.VarChar;

    }

    public string Query
    {
        get
        {
            return _query;
        }

        set { _query = value; }
    }
}

【问题讨论】:

  • , _bite = 9 nom nom nom
  • 我不明白。您在此处的代码不易 容易受到 sql 注入攻击。我看到的最糟糕的事情是GetMarinesUploadNextUploadKey() 方法的竞争条件(您应该在那里使用标识列或序列)。该代码还经历了很多不必要的工作来为现有类型生成它自己的包装器,而你为这项工作得到的只是比你已经拥有的更复杂的东西。
  • 第一种方法叫什么? “accountCode”是否可能包含 SQL 注入攻击?它被直接放入一个最终执行的字符串中;或许这就是你遇到漏洞的原因?

标签: c# sql-server ado.net sql-injection


【解决方案1】:

我没有在该代码中看到漏洞,但我知道扫描可能要求什么。问题可能是此代码使开发人员很容易忽略您类中的parameterList 集合。如果我是您组织中尚未发现 Sql 注入的新开发人员,我会很想忽略所有复杂的查询参数内容,并在设置 Query 属性之前使用字符串连接。

我更习惯于看到的是具有如下签名的单个方法,而不是将其包装在一个类中:

IEnumerable<T> GetData<T>(string query, IEnumerable<Sqlparameter> parameters)

...或该方法签名的一些排列,可能使用数组或列表而不是IEnumerable。这迫使下游开发人员处理该方法的 parameters 参数。他们不能忽略它,因此减少了使用快速、惰性的字符串连接调用将一些用户提供的数据替换到查询中的诱惑。

【讨论】:

  • 我担心的一个问题是,如果查询字符串没有参数,是否会显示为结果?
猜你喜欢
  • 1970-01-01
  • 2013-01-10
  • 2013-10-30
  • 2013-04-25
  • 1970-01-01
  • 2022-01-15
  • 2011-06-12
相关资源
最近更新 更多