I am a bit confused by the description of your escaping practice, so I'll just drop you pointers on what I think is your problem, and you will meanwhile elaborate on your concerns.
I only escape GPC data and Ill tell you why I don't escape config variables or data from a database, INI file, etc...
Escaping is not a security measure. It ensures data integrity. (Only a subset of all possibly mishandled data is data that causes SQL injection).
Anytime changes are made to those sources they come from GPC which are sanitized...so how is it that second order SQL injection attacks occur, especially if my models are the ones that escape all data before querying?
Why would I sanitize config variables from INI or database or XML or whatever before using that in a SQL query. While I agree with sanitizing data I'm not sure I see the point behind escaping data that has already been escaped???
Whoo, walking on thin ice here.
It seems to me that besides missing the purpose of escaping, you also miss how it works on the database side of the deal.
I'll give you a counter-question. Why is that data which gets escaped before being put in the database, is not being unescaped after being retrieved from the database? Surely someone would mind all those \-s in the data?
The answer is that data escaping is needed only on the
input interface of the database. It ensures data integrity on its entrance, because it comes in a bunch of SQL syntax. Data egress, on the other hand, doesn't happen in a special context, it's just formatted data. The characters in the data don't have meaning, so we don't need to treat some of them in a special way (unlike when the data enters the database). Note that it doesn't mean that "the database unescapes it for us" (a misconception I've heard once or twice) - it has never been "escaped" in the database! It is escaped only at the entrance, no further than that.
How does it relate to your case and second order injection:
1. SQL injection vector arrives on $_GET.
2. Your code correctly escapes it, and it safely enters the database without doing anything.
3. Parts of your model class pull data from the database, one of them happens to be the SQL injection vector.
4. The Update() method of your model gets called.
Here, I'm not sure what happens in your code, becase you're telling two different stories:
If "
my models are the ones that escape all data before querying" is true, you're doing the right thing. The vector will get escaped once again, and will be safely handed to the database.
If "
I only escape GPC data" is true, you're doing it wrong [insert lolcat joke here].
This is how second order SQL injection happens! If at Update() your model wants to discriminate between GPC and other data, and escape only the GPC data, it will leave the vector unescaped, and it will cause SQL injection.
In that case, the model failed to ensure the data integrity, and it led not just to a broken query (if the mishandled piece of data was benign - i.e. "O'Henry") but to full-blown malicious SQL injection.
------------
I will repeat my main thesis again -
escaping is not a security measure! Remember that your model will want to pull the name "O'Henry" from the database and then put it back there. That's your true concern, but if you handle it correctly, SQL injection will not happen as well.