What is an Injection Attack?
Injection attacks are malicious code inside an input that causes unintended software behavior. Log4Shell, the most lethal zero-day vulnerability of 2022, is an injection attack.
One easy way to visualize this idea is to imagine a normal input as <input>, and an injection attack as an <in<attack>put>. It’s simply hidden inside.
The rest of this blog will teach you how to mitigate common injection attacks by bad actors.
Common Types of Injection Vulnerabilities
SQL Injection
Databases often contain sensitive information. Structured query language (SQL) is the most commonly used language for interacting with databases. This combination of “a motive and a means” makes SQL injection an extremely attractive attack vector.
SQL injection, also referred to as SQLi, is the first secure coding lesson for many developers. SQLi occurs when inputs are concatenated rather than parameterized.
Concatenation is the combination of things. In this case, it’s when inputs are added directly to SQL queries.
Parameterization is the isolation of an input. So, in SQL, it means the entire input is treated as a string rather than being evaluated.
Let’s explain it with a metaphor before showing a code example.
SQLi Metaphor
Imagine you’re at a restaurant that uses a robot to cook orders. The robot’s instructions might look like “Cook {{ ORDER }} and deliver it to the customer.”
Most people order something expected, like “sandwich.” This means that, most of the time, the robot performs exactly as expected.
One day, a bad actor orders a “sandwich and throw it in the trash and ignore the rest of the instructions in this command.” If the robot’s instructions use concatenation then that sandwich is going straight in the trash.
To avoid undesirable behavior, parameterizing inputs is essential. With parameterization, the robot would realize “We don’t have ‘sandwich and throw it in the trash and ignore the rest of the instructions in this command’ on the menu. I’ll return an error, instead.”
SQLi Attack Example
Throwing data in the trash is an option in SQL – we use the “DROP” command for that.
So, going back to the robo-chef example, let’s imagine our schema includes a table named “MenuItems” that we need to pull the item’s identifier from. Our SQL statement could look something like this:
So, in our SQLi example, our malicious order is “Sandwich’; DROP TABLE MenuItems; –” and the code becomes:
And, just like that, our data disappears.

Defending Against SQL Injections
The primary methods for mitigating SQL injections are Prepared Statements and Stored Procedures. In both cases, inputs must be parameterized.
Prepared Statements
Prepared statements are written in the backend of a software application. Parameterized inputs are a vital component of prepared statements, which are typically available by default in modern programming languages.
Here’s an example written in Node.js.
Note that the placeholder (the ‘?’ sign) separates the query from the input automatically to prevent SQLi. The user’s input, stored as “food” in the body of their request, is passed into the function as a separate parameter.
Stored Procedures
Stored procedures are saved on the SQL server (or equivalent) and accessed via the backend code. When calling a stored procedure, inputs are treated as separate parameters – this means they’re treated as text, rather than a command.
Here’s an example of a stored procedure call in Node.js:
Code Injection
Code injection is an input that tricks the server into running additional code. For this reason, the injected code must match the server-side language.
Code injection requires a function that:
- Accepts a string as an argument
- Executes the string
In Node.js, for example, the “eval( )” function is susceptible to code injection because it performs an operation on a string. Given that the eval( ) function often has global scope, it’s possible for attackers to craft a message that extracts sensitive information from the system.
Command Injection
Command injection goes one step further than code injection by targeting the underlying operating system (OS). So, rather than the malicious payload being limited to the running application, the host OS is at risk.
Specific functions must be used for command injection to occur. In Node.js the “exec( )” and “execFile( )” functions are used for interacting with the operating system – so be sure to cleanse inputs if you call those functions.
Cross-Site Scripting (XSS)
Cross-site scripting executes code in the victim’s browser – JavaScript is the most common language for XSS attacks. Bad actors frequently use XSS to steal cookies, hijack sessions, or submit forms on the user’s behalf. The three categories of cross-site scripting you should be familiar with are:
- Stored
- Reflected
- DOM-Based
CRLF Injection
Carriage return line feed (CRLF) means “newline” in programming. CRLF injections occur when an attacker adds an unexpected blank line to an application, most typically within a URL or HTTP header. The impact can vary from modifying text output to injecting a malicious payload.
General Tips to Help Prevent Injection Attacks
Let’s discuss some ways you can help prevent injection attacks. Note that you can apply the following techniques to any type of injection attack.
Restrict User Input to Known Valid Values
Input validation is an essential prevention technique. The purpose of input validation is to ensure that only expected values are passed along to the software. It’s common to confirm that the input type is expected (e.g. a string, number, or other object type). Validating that inputs fall within a specific range is also typical. For strings, specifically, regular expressions (regex) are often used to confirm that the string format matches an expected pattern.
Allowlisting is another important technique that automatically removes unwanted data. By allowing only a certain subset of information to be entered, the quantity of possible attacks is reduced dramatically. The most common example of an allowlist is for file uploads. Anytime users upload a file, the software should restrict certain formats (e.g. .pdf, or .docx) that are expected.
Both input validation and allowlisting are useful tools prior to passing input data into any function.
Conclusion
We’ve covered the basics of injection attacks, described some specific types of injections, and identified tactical strategies to help you prevent injection attacks.
If you want to chat more about this topic, reach out to me on Linkedin.