When it comes to common injection vulnerabilities, there are three that you need to know about if you want to keep your web app secure: SQL injection, OS injection and LDAP injection. If you don’t yet know how they work, how to prevent them or what they mean in practice, you’re missing out on some very important info — it could be the difference between your application being secure or not! Read on to learn more about these three vulnerabilities, how they work and how you can protect yourself from them.
For those unfamiliar with the subject, injection vulnerabilities are a very dangerous type of attack. Injection attacks are characterized by, as its name indicates, injecting code that is interpreted on the website or application under attack, allowing malicious activities and queries to be performed and, in the worst case, escalating privileges to take control and steal confidential data.
In most cases, attackers take advantage of a poorly programmed application or website (sometimes we, the developers, know that we are not very careful😉) and this allows an attacker to execute queries or commands for malicious purposes.
There is quite a large variety of types of injections but we will focus on the 3 most important ones:
- SQL Injection
- OS Injection
- LDAP Injection
Well, let’s start to see what each of the 3 is about and how we can avoid them in a simple way:
A Structured Query Language Injection (or for friends: SQL injection) is the most common and dangerous injection attack, mainly because it is related to the database we have connected to the application or website.
With this type of vulnerability, the attacker executes SQL queries without permission, allowing access to sensitive and confidential information. It must be taken into account that most of the companies do not have a good security to avoid this type of attacks, for that reason, it is very important to know its origin and to know how to prevent them.
How to avoid it?
One of the best ways to avoid this is to use an ORM (Object Relational Mapper). What an ORM allows us to do is to convert the objects of our application to a suitable format so that they can be stored in any type of database. In this way we will save any SQL query to perform any kind of operation on the database (such as read, write, delete or update).
For .NET I recommend using Entity Framework
The second easiest way to protect against SQL injections is to use parameterized queries instead of direct queries. These parameterized queries are queries in which the values are passed by means of SQL type parameters.
If you don’t use an ORM, then it will end up being detrimental to your database when an intruder takes advantage of the vulnerability. They may be able to steal or modify important data without anyone even noticing if they are particularly skilled in doing so.
Let’s see this OWASP example of how they use them with Entity Framework:
var sql = @"Update [User] SET FirstName = @FirstName WHERE Id = @Id"; context.Database.ExecuteSqlCommand( sql, new SqlParameter("@FirstName", firstname), new SqlParameter("@Id", id));
❌Warning: Contacting SQL strings anywhere in the code is not good either. This is known as dynamic SQL.
Also, as OWASP warns us in their cheatsheetseries, there is still the possibility of doing this by accident with an ORM, so they recommend always checking all parts that may be vulnerable. Let’s take a look at OWASP example:
string strQry = "SELECT * FROM Users WHERE UserName='" + txtUser.Text + "' AND Password='" + txtPassword.Text + "'"; EXEC strQry // SQL Injection vulnerability!
And last but not least, try to connect to the database always with a user with the minimum required permissions. If a user is not going to write to the database, it should not have write permissions. Simple but effective.
It is known in various ways (OS Command Injection or simply Command Injection). This is a type of attack in which the attacker takes advantage of the lack of input validation to execute (inject) commands into the operating system using the vulnerable software.
The danger of this attack is based on the attacker using commands to gain access to confidential information, modify parts of the system or even escalate administrator privileges to initiate SSH connections or enable backdoors.
Let me give a simple example:
Imagine you have an application that has a value input and the user provides a value to interact with it (for example, imagine that the user wants to make a super cool logo design: opens Paint):
At first (apart from the fact that the user does not know much about design), the program opens without problems and so far nothing unusual.
But now imagine that the user not only wants to design a cool logo, but also wants to gain access to the application, web or software. In this case it is as easy as contacting the malicious command with the original one, for example:
mspaint && echo "pwned"
This is what would happen:
As we can see, the user can execute other commands and there would already be an entry to start escalating privileges.
Of course, if for some reason the application runs with administrator permissions and is vulnerable to this type of injections, it is like opening the door to a thief who comes to steal and we give him the house keys.
How to avoid it?
The first way to avoid this is to validate user input. In what way? There are several ways:
- If commands are involved, create a whitelist of allowed commands and check if the one entered by the user is on it. If not, do not execute it.
- In the same way, you can create a blacklist exclusively with the commands that should not be executed.
- If we talk about arguments, in the same way that the commands you must define a list of allowed arguments.
- Check the allowed characters. If for example the user is expected to enter a name, then you should not allow special characters as part of the Regular Expressions.
Example of special characters:
! \ ` < > $ | & ;
In .NET we can use
System.Diagnostics.Process.Start for this. Let’s see the OWASP example in its cheatsheetseries:
var process = new System.Diagnostics.Process(); var startInfo = new System.Diagnostics.ProcessStartInfo(); startInfo.FileName = "validatedCommand"; startInfo.Arguments = "validatedArg1 validatedArg2 validatedArg3"; process.StartInfo = startInfo; process.Start();
Although this is a way to prevent OS injection attacks, it still does not guarantee 100% security.
Another way is to send the information encoded (for example in Base64) and then decode it in the application.
🧠Note: If you want to learn in depth about how to validate user inputs, I recommend the OWASP article: Input Validation Cheat Sheet.
The Lightwight Directory Access Protocol Injection (simply said LDAP Injection) is the least common of the 3 types of injections, but no less dangerous. It is somewhat similar to SQL injection in that, especially in web applications, LDAP access is similar to database access.
The main difference between these two types of attacks is that, while SQL injection attacks the SQL server, LDAP injection attacks the user validation system. This would allow the attacker to take control of users, modify their permissions, create new users or even access other computers or zones in the LDAP domain.
According to OWASP LDAP attack prevention, the main reasons for this vulnerability are:
- The lack of safer, parameterized LDAP query interfaces
- The widespread use of LDAP to authenticate users to systems
How to avoid it?
The main way to avoid these attacks is to escape all the variables. On the one hand you have to escape characters in DN (Distiguished Name) and on the other hand also in Search Filter.
A DN example is this:
cn=Juan España, ou=Cybersecurity Department, dc=ByteHide, dc=com
There are a number of characters that in this case are considered special, according to Ldapwiki, the special characters are as follows:
- Backslash character
- Pound sign
- Plus sign
- Less than symbol
- Greater than symbol
- Double quote
- Equal sign
Although these characters can be used in DN, we must escape them with the backslash
If you want to know more about the different types of characters there are and which ones you should or should not escape them, I recommend you Ldapwiki: DN Escape Values
For .NET of course, Microsoft has the solution for us with
System.Web.Security.AntiXss and its main utility is to encode strings to prevent LDAP attacks (it is also used to prevent XSS attacks).
And if you already want to learn in depth about how you can protect yourself from LDAP injection attacks, I highly recommend the OWASP source article: LDAP Injection Prevention.
I hope that this article, like the others, will be of value to you and that you will be able to put into practice what you have learned.