Pretty simple: 100% of the time use prepared statements, NEVER build an SQL query yourself.
Tada, 0% SQLi.
I might naively underestimate the amount of pure "naked SQL" code still written, but I suspect that in this age, more SQLi accidents happen in "95% safe" environments. Kind of like the class of accidents we expect from 95% autonomous cars, where an unfocused and out of practice driver is expected to take over the wheel when the robot brain decides that driving is to difficult.
The problem isn't that some people are idiots. The problem is that we, as an industry, don't have great security solutions.
Process that could help mitigate this bugs -
- Security / safe coding training
- Code audits
- Testing - static and dynamic
- Policies that are communicated such as "Always use prepared statements" or "use X framework"
[1] https://www.schneier.com/crypto-gram/archives/2000/0515.html
I’ve had quite a few codebases I’ve worked on where I had to replace naive code [1], and until now, it’s always been easily possible to ensure that the entire space of possible inputs is limited enough to prevent SQL injections.
Sure, there are rare projects where you have to do such very complicated systems, but for 99%, it’s possible to get guaranteed protection from SQL injections.
________________________
1: "db->query('SELECT 1 FROM users WHERE username = "' + $_POST['username'] + '" AND password = "' + md5($_POST['password']) + ';"');" was real code I’ve seen
- Outsourcing offshore to lower costs through a 3PP
- Junior developers with inadequate training
- Sheer incompetence
Incompetence can be extended to management - i.e. a lack of policies and auditing to undertake due diligence.
Sometimes SQLi isn't always obvious even if they are aware of the attack vector if the developer is not thinking defensively. For example inputs from a cookie or HTTP headers such as HTTP referer etc.