In late 1998, when I was just beginning my career in technology, I read in the venerable Phrack magazine how poor input sanitization allowed rain.forest.puppy (the pseudonym used by Jeff Forristal) to pass SQL query strings directly to the back-end database of a Web application.
It’s an unfortunate reality that a quarter of a century later, SQL injection — among the lowest hanging of security fruit — is still included in the Open Worldwide Application Security Project (OWASP) Top 10 list of security vulnerabilities. One of the worst attacks ever occurred back in 2008, when Heartland Payment Systems was breached and more than 130 million credit and debit card numbers were compromised. In 2023, the Cl0p ransomware group exploited previously unknown SQL injection vulnerabilities in MOVEit, Progress Software’s file transfer program, and compromised hundreds of victims as part of a supply chain attack.
We do not have insight into Progress Software’s software development life cycle or security practices to ascertain what happened. While a vulnerability assessment system or even a bug hunting program could have potentially identified SQL injection flaws in the code before it was exploited, focusing on producing code that is secure by construction is an even better way to address this class of vulnerability.
Methods include using stored procedures instead of directly passing SQL queries and incorporating software libraries to sanitize input. This ensures that the code produced is secure by construction and doesn’t require teams to employ quality control or bug hunts afterward, both of which can be expensive and error-prone.
Shifting Left — All the Way to Education
“Secure by construction” is really the key here, and that requires education — for both developers and security teams. We often talk about “shifting left,” and the furthest left you can shift is to education (such as OpenSSF’s Secure Software Development Fundamentals Courses). Had developers used stored procedures and consistent input sanitization across the code base, MOVEit could have structurally avoided this exploit. Security must be embedded within the software development life cycle (SDLC) as an integrated part of code quality, not just as a checkpoint or an SDLC gate before release.
Accurately identifying security defects early allows developers to address them systemically. In production, ensuring good operational practices, such as continuous repaving through infrastructure as code, least privilege execution, sandboxing, and domain isolation, can help ensure that threat groups do not gain persistent access to exploited services.
Most developers know what to do but weigh speed over security. Education, therefore, must include the value of secure coding practices and the exponential costs of ignoring those practices. However, this education will be effective only if developers feel supported in taking the time needed to code securely. If developers are being told to code securely but the organizational culture is implicitly or explicitly penalizing them for being “slow,” they will most assuredly drop back to insecure ways.
Education doesn’t just go one way. Security teams providing developers with vulnerability information with little context complicates matters. This information, often delivered as a report that must be remediated at a checkpoint late in the software development life cycle, impedes developer velocity as they sift valid findings from false positives. Educating security teams to be better software engineers can help reduce the toil of unactionable security reports and help software engineers produce better code.
Planning for the Next Breach
The MOVEit vulnerability illustrates how critical it is for every organization to understand the software supply chain. Accurate asset inventories of software and infrastructure are prerequisites for companies to respond to cybersecurity events, before they become breaches; that’s why the OpenSSF SBOM Everywhere SIG exists.
Of course, there are no silver bullets, and the complexity of the software supply chain almost guarantees that more incidents will occur in the future. Companies must have a well-practiced incident response plan in place that will help ensure that security and engineering teams are prepared to address issues through well-known runbooks and procedures, rather than panic and intuition.
Indeed, while our ability to respond to security issues has become a lot better over the years, the reports of panicked responses to MOVEit are evidence that we still have a long way to go. Engineering teams and security teams need to be more practiced in their response to security incidents. This means documenting runbooks and practicing them regularly through tabletop exercises. After an incident — whether real or practice — organizations should develop a “hot wash,” or after-action report, to identify areas for improvement and ensure better execution during the next incident.
Finally, good security is a team sport, accomplished through multidisciplinary teams with diverse backgrounds and points of view. We cannot solve our issues through the homogenous thinking that caused them; diversity of thought is critical.
My hope is that if someone comes across this article in 2033, they will say, “Thank goodness companies got their security acts together,” and not, “How is SQL injection still a problem today?”