I have a query that is dynamically created for a search page that Snyk is flagging as a sql injection issue. I've tried to parameterize everything I can, but it doesn't seem like it's picking it up. Here's a simplified version the code. Snyk is complaining about {sbWhere}
and {sort}
portion of the main query. But I can't use a variable for the sort value or I get the error The SELECT item identified by the ORDER BY number 1 contains a variable
. And it's also not realizing that the sbWhere is already a built up string of parameters. I'm not sure what to do to get this to work so Synk doesn't see it as a sql injection issue.
var bHaveCriteria = false;
var sbWhere = new StringBuilder();
var parameters = new DynamicParameters();
if (search.LastModifiedDateFrom.HasValue || search.LastModifiedDateTo.HasValue)
{
bHaveCriteria = true;
var dtFrom = search.LastModifiedDateFrom ?? DateTime.Now;
var dtTo = search.LastModifiedDateTo ?? DateTime.Now;
if (dtFrom.CompareTo(dtTo) > 0)
{
parameters.Add("@dateTo", dtTo.ToShortDateString());
sbWhere.Append($" (DateDiff(day, LastModified, @dateTo) >= 0)");
}
else
{
var ts = dtTo.Subtract(dtFrom);
parameters.Add("@dateTo", dtTo.ToShortDateString());
parameters.Add("@dateFrom", dtFrom.ToShortDateString());
parameters.Add("@dateTs", ts.TotalDays);
sbWhere.Append(" (DateDiff(day, @dateFrom, LastModified) >= 0 AND DateDiff(day, @dateTo, LastModified) <= @dateTs) ");
}
}
var states = new List<string>();
foreach (var state in search.States)
{
states.Add(state.State);
}
if (states.Count > 0)
{
if (bHaveCriteria)
sbWhere.Append(" AND ");
else
bHaveCriteria = true;
sbWhere.Append($" (State IN @stateList) ");
parameters.Add("@stateList", states);
}
if (bHaveCriteria)
{
parameters.Add("@pageSize", search.PageSize);
parameters.Add("@skip", search.CurrentPage * search.PageSize);
var sortDirection = search.SortDirection == SortOrder.Ascending ? " asc " : " desc ";
var sort = !string.IsNullOrEmpty(search.OrderBy) ? search.OrderBy.PrepStringForSql() : " FirmName ";
var mainQry = @$"select KeyId, FirmName, EmailAddress, PhoneNumber, City, State, TotalDeals from Customers where {sbWhere}
order by {sort} {sortDirection} OFFSET @skip ROWS FETCH NEXT @pageSize ROWS ONLY";
var countQry = $"select count(*) from Customers where {sbWhere}";
var results = await _repository.SqlQuery<SearchResultsItemViewModel>(mainQry, parameters);
var total = (await _repository.SqlQuery<int>(countQry, parameters)).First();
retval.TotalCount = total;
retval.Results = results.ToList();
}