Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQL injection vulnerability when using Expression.Constant? #296

Closed
appetere opened this issue Nov 17, 2015 · 2 comments
Closed

SQL injection vulnerability when using Expression.Constant? #296

appetere opened this issue Nov 17, 2015 · 2 comments

Comments

@appetere
Copy link

I wrote the code at the end to generate a "contains" expression. But the SQL generated by linq2db did not use parameters for the words in the search, resulting in a SQL injection vulnerability.

Testing it on a Firebird database, the SQL generated did not use parameters for each word in the search.

WHERE
((1 = 0 OR Lower(t2.Location) LIKE '%in%') OR Lower(t2.Location) LIKE '%basement%')

To work around this, where the code now says:

var word = Expression.Constant(separateWord);

I replaced this with:

var word = Expression.Property(Expression.Constant(new {Value = separateWord}), "Value");

This time I get the expected parameterisation:

WHERE
    ((1 = 0 OR Lower(t2.Location) LIKE @p1 ESCAPE '~') OR Lower(t2.Location) LIKE @p2 ESCAPE '~')

Parameters:
Name:p1 Type:VarChar    Used Value:%in%
Name:p2 Type:VarChar    Used Value:%basement%

Is this expected behaviour? I was expecting that the constant would be parameterised in the generated query.

    public static Expression<Func<T, bool>> ContainsAnyWords<T>(Expression<Func<T, string>> searchItem, string words)
    {
        var parameter = searchItem.Parameters[0];
        var property = searchItem.Body;

        var separateWords = words
            .Split(' ')
            .Where(x => !string.IsNullOrWhiteSpace(x));

        var predicate = False<T>();

        MethodInfo contains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
        MethodInfo toLower = typeof(string).GetMethod("ToLower", Type.EmptyTypes);

        foreach (var separateWord in separateWords)
        {
            var word = Expression.Constant(separateWord);
            var lowerWord = Expression.Call(word, toLower);
            var lowerProperty = Expression.Call(property, toLower);
            var containsExpression = Expression.Call(lowerProperty, contains, lowerWord);

            var lambda = Expression.Lambda<Func<T, bool>>(containsExpression, parameter);

            predicate = predicate.Or(lambda);
        }

        return predicate;
    }
@MaceWindu
Copy link
Contributor

linq2db escapes LIKE pattern value before adding it to query text.
The only option for SQL Injection here - error in escaping logic in general or for specific database provider, like #169

@appetere
Copy link
Author

@MaceWindu Thanks for that information. Having tested the code above with some attack-type syntax can see now that it is escaped properly in the LIKE clauses and parameters are therefore not needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants