Where should security be enforced?

In today's world of massive software development projects being started everyday, and new websites being published almost every minute, the question for many organizations is "Where should security be enforced?" For way to many companies, this question never comes up in meetings with developers, and even worse in meetings with senior management. I cannot count the times that I have been asked, "Who would want to do that?" or "Why would someone go through all that trouble just to put a pop-up box on the screen?". Obviously, these people do not get security, and educating them to a point where they will can is going to take some effort. In the mean time, projects are going to continue to get developed and bugs are going to continuously be pushed out to the masses and get exploited.

Nonetheless, we still have to answer the question of "Where should security be enforced?". To me this question is simple: In every step of the software development life cycle.

From conception to design to maintenance and support, security is a relevant part of any new application, and is paramount in the patches that go out to fix existing vulnerabilities. Without security viewed as a feature, software will never be as secure as it could be.

CSRF, The Waking Giant

Jeremiah Grossman recently posted an article on his blog about CSRF and how many security professionals have little knowledge of the attack and its consequences. Another issue Grossman points out is that developers know even less - which is the more troubling of the two.

Anyway, he continues and points out that CSRF may be useful in creating a DDoS attack. By placing img tags, or tags that can make off-site references, that reference the victim site on any large forum or popular website, visitors to the site would then transparently make a set number of requests to the victim site. Through the use of the trigger site's popularity, the number of requests is multiplied significantly therefore triggering a potential DDoS.

This is really scary stuff. Even as a security professional I did not make the leap that Grossman and his other cohorts made, although as most things when it is presented it seems only logical. The simplicity of the attack is also its greatest strength. It is similar in nature to the ' OR 1=1 -- attack used to bypass authentication mechanisms vulnerable to SQLi. Both attacks require a minimum amount of payload to be effective which cuts down on the complexity as well as the preparation significantly.

This simple attack - <* img src="http://victim.com" /> - could turn out to be the next big thing that attackers use. This also makes you wonder, or at least it makes me wonder, what other monsters are out there waiting to to pounce that no one is really aware of yet.

Conquering SQLi


After reviewing numerous applications and pondering some of the commonalities between them, it became abundantly clear that developers have a hard time securely communicating with back end data stores. I am not talking so much about the underlying networking protocols available, but rather the manner in which queries for these back-end systems were being formed. In most cases, the data access layer of the application is exactly modeled on the exact same pattern: (1) Get input from the user, (2) form the query string (mostly through string concatenation), (3)execute the newly formed query, (4) retrieve and parse the results and return the necessary information to the user. In a few cases the input was first sent through some form of input validation function, but none of these functions sanitized the input in any way regarding where it was about to be used. Because of this, finding a comment field or search box in most of the applications led to full compromise. Developers were obviously stunned, management was ultimately scared, and upper management just looked pissed that their developers would create such an "insecure application in the first place." In almost every case the assessment team had to come to the defense of the developers and point out that this issue is more pervasive than most people realize, and that most of the example code found on the internet to do these interactions are vulnerable to this exact attack, SQLi - SQL Injection.

After management calmed down and the meeting got back underway, the logical question arose: How do you query data stores securely? The answer is surprisingly simple: Parameterized Queries. A parameterized query is data structure available in all modern programming languages that allows a developer to staticly declare a query's structure, but dynamically add user input to the query as needed. In Java, this structure is implemented through the PreparedStatement class. In .NET, developers can use a SqlCommand or OleDbCommand object.

So, for those who can go off and fix you code by yourself feel free. For those that want an example of some vulnerable code, read on. Let's take a look at a simple Java login class that returns a User object upon successful presentation of credentials by a user.
import java.sql.Connection;
import java.sql.Driver;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Login {

public User login(String username, String password, Connection dbConnection) throws Exception{
String sqlQuery = "select count(*) " +
" from users " +
" where username = '" + username + "'" +
" and password = '" + password + "'";

Statement sqlStmt = dbConnection.createStatement();
ResultSet results = sqlStmt.executeQuery(sqlQuery);
boolean loggedIn = false;
while (results.hasNext()) {
loggedIn = true;
break;
}

return new User(username, password, loggedIn);
}
}
The problem with the above code is that user input is directly injected into the SQL query. It could be safe to assume that input validation occurred before the login method is called, but that still does not solve our problem. If either the username or the password field contains a single quote('), the structure of the SQL query will be changed. For instance, if the username contains only a quote then the resulting query becomes select count(*) from users where username = ''' and password = 'password'. The odd number of single quotes will generate an error from the database which could alert an attacker that the login mechanism can be bypassed. To bypass it, an attacker simply provides the string ' OR 1=1 -- for either the username or password. Because the logic in that statement always evaluates to true, the result set will always return at least one value which will allow the attacker to login.

Now, to fix the above code one could do something like the following (relevant changes are highlighted):
import java.sql.Connection;
import java.sql.Driver;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;

public class Login {

public User login(String username, String password, Connection dbConnection) throws Exception{

String sqlQuery = "select count(*) from users where username = ? and password = ?";
PreparedStatement sqlStmt = dbConnection.prepareStatement();

// Safely apply the user data to the SQL Query
sqlStmt.setString(1, username);
sqlStmt.setString(2, password);
sqlStmt.setMaxRows(1);
sqlStmt.setFetchSize(1);


ResultSet results = sqlStmt.executeQuery();
boolean loggedIn = false;
while (results.hasNext()) {
loggedIn = true;
break;
}

return new User(username, password, loggedIn);
}
}
Parameterized queries are really the way to go to prevent SQLi attacks on your application. What may don't know is that such queries can also increase the performance of the application due to the manner in which modern DBMSs cache and reuse parameterized queries.