Skip to content

FormattableString overload on ExecuteSqlCommand invites subtle SQL injection vulnerability #10080

@breyed

Description

@breyed

This code is safe:

db.ExecuteSqlCommand($"delete from Log where Time<{time}");

But this is not:

db.ExecuteSqlCommand(useLogA ?
    $"delete from LogA where Time<{time}" :
    $"delete from LogB where Time<{time}");

Likewise, this is not:

db.ExecuteSqlCommand(
    $"delete from Log " +
    $"where Time<{time}");

In the first unsafe case, when two FormattableString operands are used with the conditional operator, the expression evaluates to a string, not another FormattableString. Unless you know this subtle (and I find rather unintuitive) rule, you might easily write code expecting the argument to be passed as a SQL parameter, only to find you've really dumped unsanitized user content into a SQL command.

In the second unsafe case, you're using multiple lines for readability. If you're a big C# fan, you might think C# is awesome enough to use string literal concatenation with interpolated strings. You'll be extra disappointed when your evil hacker trim, who hates C#, thinks otherwise, and proves he's right by bringing down your site.

In both unsafe cases the implicit conversion from string to RawSqlString causes the unintended overload to be invoked.

Proposed resolution:

  1. Long term: Improve C# string interpolation.
  2. Short term: Mark the FormattableString overload obsolete so that a warning alerts devs to the potential danger. Create a replacement that simply has a different name from the RawSqlString overload, perhaps ExecuteFormattedSqlCommand.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions