Everything you wanted to know about SQL injection (but were afraid to ask)
troyhunt.com
troyhunt.com
The main reason to use an ORM is for programmer efficiency. Sure I can write a bunch of CRUD operations but why bother if I can have the ORM do it for me? Since CRUD operations are either inserting a new row or accessing/updating by a primary key it'll be indexed as well so no perf issues[2]. The additional work by your app code for the ORM library is meaningless compared to the DB round trip anyway. My favorite part? Adding a new field goes straight to the model and nowhere else[3].
The big place for raw SQL is as the secret sauce on the meat and potatoes of your apps. Once you've got a real data set and you want to combine, slice, dice, you're not going to do that through an ORM. You want those queries to be as performant as possible. If you've structured your tables properly (proper foreign keys, normalization, etc) then the writing custom SQL will also be much more straightforward then trying to kludge together ORM commands to do what you want. On top of that, the work will happen on the database where it can filter it prior to your app processing it.
For our app[4] most of the CRUD pages are handled by an ORM but there's quite a bit of custom SQL too. One example is for security authorizations. Validating security authorizations (can user X access DB y) is a hierarchical check. The logic is all done in a Postgres stored proc (well technically a function). Doing it via an ORM would inefficient, both in programmer time and computer runtime.
[1]: You probably should though. It's generally a good idea to have some kind of white listing for what is an acceptable value for a field. Either way though you need to make sure you escape them when outputing HTML for webapps to prevent XSS. That combined with prepared statements when interacting with user inputs is the only right way to do things.
[2]: For basic CRUD operations and even simple one-to-many lists. Beyond that things can and do get hairy but those aren't the majority of cases. The majority of app code is vanilla id-based select, inserts, updates, and deletes.
I hear that these sorts of things use EAV [1], which is traditionally something that ORMs do not handle well. The rationale of EAV over another model is that entities have MANY optional attributes and you'd have horrible data sparseness (without EAV).
But you say you use an ORM:
> Our ORM can express higher level queries and a wider set of queries than raw SQL
Are the anecdotes I hear about using EAV in these sorts of applications right or is the problem domain so big that there's room for EAV and non-EAV and nobody's wrong?
Just curious.
[1] http://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%...
EAVT/Datomic is a better fit for apps with complex structured data than an ORM over SQL, but migrating there is no trivial feat. Nor is convincing my customers in their due diligence phase, as they have surely been burned before by some kid pushing MongoDB, but they understand SQL and know the product can be successful with SQL, they know they can go get Oracle consultants to save their ass in 10 years when my company is sold, etc.
I think the Anorm developers say this best: "SQL is already the best DSL for accessing relational databases. We don’t need to invent something new." http://www.playframework.com/documentation/2.1.1/ScalaAnorm
If your app is simple CRUD on 10 tables, anorm is great. But even for CRUD on complex types (nested objects, objects with collections of objects, objects with values that aren't primitives e.g. dictionary types where possible values aren't known until runtime...) those queries will be crazy complex and repetitive in raw SQL and you will quickly see you need an orm (or move off sql to some other acid alternative like datomic). Anorm would be an ideal layer to write your own ORM in though.
on the project/team i work on, this statement is false. If it's true for some other team, maybe they are "doing it wrong". I'm sure it depends on one's particular ORM implementation, and whether it is any good, and what it's design goals are.
I don't like the large ORMs, at all, though. I've used a few Micros (C#) and settled into PetaPoco for a few tasks which are CRUD heavy to allow internal users to maintain some data and it has saved me a lot of time.
I can write the hell out of some SQL, but sometimes I don't need to be doing it, it's just dead simple stuff. There can be concerns for people currently unfamiliar with SQL which I understand.
This is not always the case. Consider an application that presents a table, and that the application can sort on any of the columns presented. Perhaps there is a dropdown, listing all of the column names.
Column names not parameterizeable in prepared statements. Thus, you will need to do input sanitization in this case.
You should still use prepared statements for these types of queries as more than likely they will have parameters as well. You might end up with a couple more SQL statements in you statement cache but that should be a non-issue and if anything be faster, not slower.
> Thus, you will need to do input sanitization in this case.
If you're dynamically sorting based on user input then you shouldn't sanitize the input, you should white list it. If you're using an RDBMS then there's a fixed, finite, set of columns the user can sort on that you can check against.
Sanitizing fields for sorting (or even querying) is more important for NoSQL databases as the interface is programmatic. MongoDB is a good (bad?) example as it interprets strings as commands so; you have to go out of your way to escape inputs even though you're programmatically using them as field names.
I think of sanitizing user input as including white listing.
ORMs makes things alot simpler, in some cases, and get in your way more often than not. I don't do much .Net anymore, mostly Django stuff, but in both cases the ORMs just forces me to learn a new query syntax. In the end prepared statements and SQL would have been quicker, more flexible... and perhaps safer. I get the concept of the ORM, but I don't really plan to switch database anytime soon and I have needed for the flexibility of having "no ORM". ( Could that be a thing, like No-SQL, No-ORM? )
The funniest SQL injection attacks I've seen have been against our search pages. Attackers assume that search is done as dynamic MySQL queries, that fact that you are actually using Sphinx or Solr seems to escape most wanna be hackers.
If you use an ORM then SQLi should be impossible, unless there's a bug in your ORM.
objects = orm.rawQueryForObjects("select * from people where name = '" + name + "')
objects = People.query.filter_by(name=name).all()
When I said 'build the sql query' I meant using SQLAlchemy core, which is also safe:
objects = select([People]).where(People.name == name)
session.query(Object).from_statement("SELECT * ...")
http://docs.sqlalchemy.org/en/rel_0_8/orm/query.html#sqlalch...
Generally the same statement can be built using internal SQLAlchemy...
But if you want to do your own, you can in sqlalchemy while still being as safe:
http://docs.sqlalchemy.org/en/rel_0_5/sqlexpression.html#usi...
But it's possible and people do it. Which is, I believe the point was, the counterpoint to "SQLi should be impossible".
Sure, One can avoid shooting themselves in the foot with an ORM. But that's also true in SQL.
not sure if you get the concept of ORM, because switching databases is not what ORMs are primarily designed for, it's more of a common feature / side effect that may get invalidated when you use unsupported dbms features.
> and I have needed for the flexibility of having "no ORM".
http://docs.sqlalchemy.org/en/latest/core/index.html
http://docs.sqlalchemy.org/en/rel_0_8/core/tutorial.html
or a clojure example http://sqlkorma.com/ you can probably find something similar for python, there are a few lightweight sql generation libs.
> The funniest SQL injection attacks I've seen have been against our search pages. Attackers assume that search is done as dynamic MySQL queries, that fact that you are actually using Sphinx or Solr seems to escape most wanna be hackers.
bots. they see a form, they submit crap to it.
An example would be you would have your binding take care of something like :foo: as a sort of preprocessing before the db takes care of the others like :foo
There is no reason for your standard app user to have access to the core database object tables to do DDL lookups or mess around with the internals. Further, most queries should only run through the RO user. Finally, no user for your app should have DROP or SUPER privileges. You also should disable multi-query requests out the gate.
Of course the dev's will need to remember to use the proper set of creds from their favorite SQL IDE, and there will be a few hiccups for 10min until you've got the proper creds set for the app user, but then you can limit the worries from an attack.
Why, other than "because one might forget it"?
That is, what if bits of the query depend on various conditions and need to be constructed part by part? Keeping the placeholders and the actual values synced seems like a nightmare in those cases.. unless I am missing something.
public static void AddParameterValue(this SqlCommand cmd, string paramName, object value)
{
if (cmd.CommandText.Contains("@" + paramName))
cmd.Parameters.AddWithValue(paramName, value);
}
to help set parameters only if they are referenced in the SQL statement.That being said, this is not necessarily an issue with the DB tier as it is with the data input tier.
The blind timing-based information leak is pretty clever and makes a nice counterexample to a lot of wrong common-knowledge.