Postgres FromSqlRaw Doesn't take params correctly

1.6k views Asked by At

TL&DR:

  1. When I perform string interpolation OUTSIDE of FromSqlRaw, the SQL Command works.
  2. When I use SQLRAW and pass a variable, within the function. It no longer works, even though the documentation says it should.

Below is a working INSECURE method of performing string interpolation.

    [HttpGet("/home/dashboard/search")] 
    public async Task<ActionResult> dashboard_search([FromQuery] string search_string)
    {

    var query_string = $"select id, country_code, country_name, count(*) OVER() as total_count from ipaddresses where ipaddress::text LIKE '%{search_string}%' limit 8;";

    var results = await this._context.getDashboardSearchIpAddresses.FromSqlRaw(query_string).ToListAsync();

    return Ok(results);

    }

This is however vulnerable to a SQL injection. <-- DON'T DO THIS !!!

The Microsoft documentation says the following:

FromSqlInterpolated is similar to FromSqlRaw but allows you to use string interpolation syntax. Just like FromSqlRaw, FromSqlInterpolated can only be used on query roots. As with the previous example, the value is converted to a DbParameter and isn't vulnerable to SQL injection.

When I try to use the FromSqlRaw i get an empty result set

    [HttpGet("/home/dashboard/search")]
    public async Task<ActionResult> dashboard_search([FromQuery] string search_string)
    {
        var results = await this._context.getDashboardSearchIpAddresses.FromSqlRaw("select id, country_code, country_name, count(*) OVER() as total_count from ipaddresses where ipaddress::text LIKE '%{0}%' limit 8;",search_string).ToListAsync(); 
return Ok(results); }

SEE Reference: https://learn.microsoft.com/en-us/ef/core/querying/raw-sql

2

There are 2 answers

0
FlyingV On BEST ANSWER

The above is the 'correct' answer for all cases, except when using Postgres

  var searchParam = new NpgsqlParameter("searchParam", $"%{search_string}%");
  var results = await this._context.getDashboardSearchIpAddresses.FromSqlRaw("select id, split_part(text(ipaddress),'/',1) as ipaddress, country_code, country_name, count(*) OVER() as total_count from ipaddresses where ipaddress::text LIKE @searchParam limit 8;", searchParam).ToListAsync();
1
fuzzy_logic On

Sorry not in front of PC to test, maybe something like:

var searchParam = new SqlParameter("searchParam", search_string);
var results = await this._context.getDashboardSearchIpAddresses.FromSqlInterpolated($"select id, country_code, country_name, count(*) OVER() as total_count from ipaddresses where ipaddress::text LIKE %{searchParam}% limit 8").ToListAsync();

Or this using Raw:

var searchParam = new SqlParameter("searchParam", $"%{search_string}%");
var results = await this._context.getDashboardSearchIpAddresses.FromSqlRaw("select id, country_code, country_name, count(*) OVER() as total_count from ipaddresses where ipaddress::text LIKE @searchParam limit 8;",searchParam).ToListAsync();