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

The parameter of the Regex.IsMatch method is not escaped #3292

Closed
hostage2222 opened this issue Sep 23, 2024 · 3 comments · Fixed by #3299
Closed

The parameter of the Regex.IsMatch method is not escaped #3292

hostage2222 opened this issue Sep 23, 2024 · 3 comments · Fixed by #3299
Assignees
Labels
bug Something isn't working
Milestone

Comments

@hostage2222
Copy link

Usually, constants are escaped when converting to SQL (the example uses the table injection_regex_table with a single field "field", and as a constant, a simple SQL injection is used). The expression

query.Where(entity => entity.Field == "';delete from injection_regex_table;select '")

is converted into:

SELECT i.field
FROM injection_regex_table AS i
WHERE i.field = ''';delete from injection_regex_table;select '''

But when using Regex.IsMatch (and possibly some other functions), this is not the case. The expression

query.Where(entity => Regex.IsMatch(entity.Field,
    "';delete from injection_regex_table;select '",
    RegexOptions.IgnoreCase))

is converted into:

SELECT i.field
FROM injection_regex_table AS i
WHERE i.field ~* '(?p)';delete from injection_regex_table;select ''

The behavior changed when upgrading from version 7.0.18 to version 8.0.0-preview.1; in version 7.0.18, this same expression was still being escaped:

SELECT i.field
FROM injection_regex_table AS i
WHERE i.field ~ ('(?ip)' || ''';delete from injection_regex_table;select ''')

Potentially, this can create issues when generating Expression in the code if it's done incorrectly (using Expression.Constant). An example can be found here: https://github.com/hostage2222/testdbregex/tree/8.0.0-preview.1. For version 7.0.18, check the branch https://github.com/hostage2222/testdbregex/tree/7.0.18 or just change version in the project. You need a running PostgreSQL instance with default port and credentials or you need to specify them directly in the code. Upon execution, the public.injection_regex_table table is created.
This doesn't seem like a serious security issue, but getting an SQL injection without using raw SQL is rather unpleasant. This actually happened in our project when migrating from .NET 6 to .NET 8; we are now using the following code (which also helped us avoid memory leaks due to cache misses when converting Expression -> SQL inside EF Core):

private class FakeFieldClass<TValue>
{
    public TValue Value = default!;
}

public static MemberExpression CreateArgument<TValue>(TValue value)
{
    var fakeField = new FakeFieldClass<TValue> { Value = value };
    return Expression.Field(Expression.Constant(fakeField), nameof(fakeField.Value));
}
@roji
Copy link
Member

roji commented Sep 23, 2024

Thanks, I'll take a look at this very soon and make sure a patch is released.

@roji roji self-assigned this Sep 23, 2024
@roji roji added the bug Something isn't working label Sep 23, 2024
roji added a commit to roji/efcore.pg that referenced this issue Sep 26, 2024
@roji
Copy link
Member

roji commented Sep 26, 2024

The regression here happened as part of #2585. I've just submitted #3299 to fix this and will backport to 8.0.x.

@roji roji added this to the 8.0.5 milestone Sep 26, 2024
@roji roji closed this as completed in d316b35 Sep 26, 2024
roji added a commit that referenced this issue Sep 26, 2024
@roji
Copy link
Member

roji commented Sep 27, 2024

FYI 8.0.8 is now being released including a patch for this. Thanks again for raising the issue!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants