SQL injection is officially Top 1 Web Application Security Risk in current OWASP Top 10 list. Hence, it should be approached with highest care. Here you can find notes/rules taken from experience acquired in dealing with noticeable number of such vulnerabilities.
1) Don't rely on "escaping" (e.g. addslashes())
- Also known as "HTML sanitization"
- It won't help you with integer and/or date values (to be honest, you could use hard typecasting here like intval() but in the long run you'll just mess and/or forget things up)
- Escaping of string queries can be circumvented (example: http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string)
- You'll end up with unnecessary complex code which potentially will result in new "bugs". Also, as I am a programmer myself, I can tell you from my own experience that programmers tend to "loose the complexity of code" and this just clears the way for new potential bugs/problems/injections
- I don't have anything against usage of those as a last line of defense, and I know from my experience that there are already TOP people working on those (kudos goes to Mario Heiderich (@0x6D6172696F) as a true expert), but plain installation of those as a MITM defender for plugging some of your lazy programming "tryouts" is like putting a big cannon at the center of some capitol with unlocked entrances to all houses around. Generally, it will do the job, but won't protect you in the long run. When people are eager enough they'll eventually find holes in those (obvious example: ModSecurity SQL Injection Challenge)
- Notable mentions can be found here: "Top 10 Open Source Web Application Firewalls (WAF) for WebApp Security"
- Lots of bypass examples (kudos goes to Roberto Salgado (@LightOS)) can be found here and also a great reference can be found here
- "Blacklists" (e.g. list with common SQL keywords SELECT, UNION, INSERT,...) are easy to circumvent (e.g. with usage of inline comments like SEL/**/ECT) and will trigger false positives in the long run (to be honest, you can do it in the low traffic site, and putting keywords like: SELECT, FROM and WHERE will keep 95% of attackers away, but those 5% will eventually find a way)
- Experts at WAF/IDS/IPS do this already far better than you'll ever do
- Please, don't you ever trust people that don't have experience in this field. I've been struck by a "new method" of prevention called "inverted queries" (How "·$% developers defeat the web vulnerability scanners). In short, author claims that you should use "SELECT * FROM users WHERE '.$_GET['id'].'=id" instead of: "SELECT * FROM users WHERE id='.$_GET['id']"'. This can be easily circumvent with a PLAIN SQL comment (e.g. '-- ') at the end of injection payload
- Obvious example of marketing tricks and selling of "snake oil" is "HP's Webinspect Real-Time" (Pushing Technology - "Blind SQL Injection" is Dead) - "Forget it, those days are over."..."Essentially, as the ... title says ...no more Blind SQL Injection ... because we're no longer blind.". Any comment is really unnecessary, than the following. I'll gladly have a public discussion about the techniques used in that "silver bullet tool" if they are willing to. That kind of false marketing is called "Inducement - False Representation". Why do I say that? Because they are using fraudulent misrepresentation of solving "blind injection" problem in terms that "they are no longer blind". Anyone telling you that they have a "silver bullet tool" is lying at least, especially if they are after your money
- You have to know that "SQL injection" is not inherently the DBMS fault, but the "lazy/unknowing programmers" fault. DBMS just executes commands "crafted" by the programmer (and attacker if there is a flaw at the parameter level). Manual concatenation of parameters to the SQL query "skeletons" (e.g. "SELECT * FROM users WHERE id='.$_GET['id']"') will always result in "SQL injection". It doesn't matter if it's done at the higher language level and/or inside SQL stored procedure, "dumb" concatenation of parameters to SQL queries is a "deadly sin" (recommended read: Web Application Sins).
- If the backend DBMS supports "subquerying" nothing stops attacker(s) from "snooping" around if the sql injection hole is present (e.g. MySQL < 4.1 doesn't support "subquerying" but you mustn't use such outdated versions as they inherently have other deadly/exploitable problems - e.g. MySQL 3.23.x/4.0.x remote exploit).
- Lack of "information_schema"-like table (e.g. like in Microsoft Access, MySQL < 5,...) won't prevent attacker from brute forcing the table/column names (e.g. --common-tables/--common-columns switch(es) in sqlmap)
- First thing that all attacker(s) do is a deliberate changing of parameter value(s) with some invalid SQL form (e.g. ')('"(). If they are able to provoke visible change (worst case scenario is a detailed DBMS error message) they'll "smell blood" and continue with the attack for sure
- Error-based injections (in short, putting subqueries into the erroneous sql form and retrieval of the results from the error reports - lots of DBMSes precalculate subqueries and report back the results in the form of error message) are quite popular and among fastest ways how to retrieve data. Also, error reports are a indispensable help for the attacker as he/she'll immediately know the type of backend DBMS - this shortens the time of attack by a factor of two
- Turn (at least detailed) error reporting off in a production environment (e.g. PHP). It won't help you to prevent SQL injection attacks but in a long run you'll at least know that you won't provide help to attacker(s)
- All popular sites prevent information leakage in form of suppressing this kind of output
- SQL drivers and libraries will automatically "sanitize" input to parameterized SQL statements. In simple terms, parameters inside those kind of statements are really treated as "values" and not as a potential part of the "queries". This means that the parameter values can't be used for building SQL queries (excellent illustration(s) can be found at (slides 42-46): Sql Injection Myths and Fallacies)
- Easy and currently the best way to avoid SQL injection holes/attacks and deal with this whole problem (i am highly biased because this really works)
- Programming examples for bundle of programming languages can be found at:
- You should always consider worse case scenario(s). In this case you should expect someone breaking into your DBMS through SQLi
- Worse thing you can do is running the DBMS connector (query interface between your web application and backend DBMS) with highest database privileges (e.g. "DBA"). This is very common mistake which provides the attacker vast list of possibilities for data retrieval and/or complete takeover
- Pentesting/security/SQLi tools have quality as of people working on them (honestly, good ones dealing with SQLi can be counted on a hand with missing fingers)
- Majority of "popular" ones are prone to false positives (!) and are relying solely on error-message recognition (malpractice used by lots of them - parsed error message(s) do(es)n't prove anything)
- Not a single tool can guarantee you with 100% accuracy that the target is NOT prone to SQL injection attacks
- Manual exploitation is used where tools fail. If there is a hole to be exploited, be sure that eager attacker will eventually find it and use it against your will
- One final (gratis) tip. All commercial tools use only the error-message parsing along with the simpleton blind injection payloads (e.g. AND 1=1) to check for the SQLi existence (this can be coded in less than 100 lines of code! - (if needed) i'll gladly do it out of fun on request by people offended by these lines). Don't you ever trust them. Searching for SQLi is a far greater problem than "parameter poisoning" with values like ')((''. If you need proof, just scan your web page with int()-typecasted parameter values and turned on FormatException messages - they'll all fail with false positives. They won't provide the through testing (out of sheer ignorance) but the attacker will. These people don't use (commercial) tools, I can guarantee you that, and you'll see there lots of hacked high PR companies that still use these kind of commercial "half-products"
p.s. and answer to you question is no, SSL won't help you against SQLi
p.p.s. couple of days after this post i've done that tool under 100 lines of code mentioned in lines above :)
p.p.p.s. if you really need to stick with the old "concatenated" code best advice I could give is to go through the list of Most Popular Wordpress Plugins (link), search for
"mysql_"inside the code and learn from their practice. I won't claim that they are all free of SQLi but I can guarantee you that those at the top are doing a fine job protecting against this kind of threat(s)