Well, this is where it helps to know something about the implementation of LINQ-to-SQL
you are using. I would imagine that every implementation would by default escape arguments to the LINQ
extension methods, but never hurts to double-check.
In general, you want there to always be a middle-man sitting between the user interface and the service layer. You probably have them all over your apps; validators. They are more obviously-necessary in the case of validating that a number is a number or that a zip code is a zip code, but nowhere are the stakes higher than for validating that all user input is not unescaped. But that's not good enough - that's just the beginning.
What I would recommend is to institute something like what ASP.NET
provides at the boundary - to prevent HTML
from being inputted into user interface inputs as well - but also at the boundary between your thin controller and thick service, or as its own layer.
In such a design, maybe you can implement an attribute or annotation like InterrogateTheCarrierAttribute
on every database input parameter (assuming you have parameterized into functions all of your database calls, and you are not concatenating strings to make queries). And on anything like it: every Powershell
call wrapper or sh
wrapper or function to access bank accounts and withdraw money, etc. Then, as the objects make their way in one form or another, every time they cross a "validation boundary," they have to be sanitized as if there is no guarantee of sanitation beyond. This is overkill but unless the validation is costly, why not?
Think of this: instead of bad user interface input, what if a text file or a trusted web service becomes compromised instead? If you think about it in terms of "this tier, this tier," you can convince yourself that there is safety where there is not. Microsoft's web server would never send you malformed packets, right? Your logger would never send your database bad SQL
, right? But it can happen. So with the "cross-cutting" approach to validation, you always validate at the boundaries, at least on the way in, and possibly on the way out. And by doing so, you make it less likely for a bad assumption to leave your database interface wide open.
Example: take your query. The issue at stake is 1) whether username
gets escaped, and 2) whether it is possible for an unescaped username
to somehow overcome the fact that LINQ to SQL
is a major abstraction and doesn't lend itself immediately to injection.
Now you should know the answers to those, but our system shouldn't require omniscience to be effective. So, I propose implementing a cross-cutting layer for validation, however you want to do it.