Pages

Wednesday, 30 September 2009

SQL Injection is not a Trivial Problem

Dear Junior

If Domain Driven Security is to be useful, then it must provide some value in usual situations – situations that programmers encounter every day.

So, what are those usual security problems in applications? Well, to start let’s note that we are not looking for the hardest problems, neither for the most intricate solutions. We are looking for the kind of stuff that does harm, just because we have no really good way to handle them.

If we have a look at OWASP Top Ten we find Cross-Site Scripting (XSS) at the top. It is a really interesting problem, but as XSS is not so widely understood I’d like to save that for a moment. Instead, let us have a look at number two and see if we can wrap our heads around it. At number two on the list we find Injection Flaws with SQL Injection as its prime representative. Well, SQL Injection is no news so let’s go for that one.

The canonical SQL Injection flaw is a login/authentication service that handles its parameters a little bit too sloppy.

/** Service for management of user accounts,

* authentication etc. */

public class AccountService {

private DataSource accountDs;


/** Authenticates a user with a given password.

* @param username

* @param passwordMD5 hash of password

* @return user id, or null if no matching account

*/

Integer authenticate(String username, String passwordMD5)

throws SQLException {

Connection con = accountDs.getConnection();

Statement stmt = con.createStatement();

String sqlSelect = "SELECT uid FROM Accounts";

String usernameMatch = "username = '" + username + "'";

String passwdHashMatch = "passwdHash = '" + passwordMD5 + "'";

String sql = sqlSelect +

" WHERE " + usernameMatch +

" AND " + passwdHashMatch;

ResultSet rs = stmt.executeQuery(sql);

Integer result;

if(rs.next()) { // found account with matching password

result = rs.getInt("uid");

} else { // no matching account

result = null;

}

return result;

}

}

The string parameters are probably fetched from some form, where the password is hashed with MD5 before sending off for authentication.

Typing in username’ OR 1=1 -- (note the initial single quote) and password doesntmatter, the executed SQL will look like this, with everything after “--“ being an SQL comment..

SELECT uid FROM Accounts WHERE username = ‘’ OR 1=1 -- ‘ AND passwdHash = ‘doesntmatter’

Obviously “1=1” is true for any row, so we will get back all rows in the Account table. From this resultset we will get the user id of the first row. And, there is a fair chance this is the first user that entered the database, which might be the fully authorized “bootstrap init user”. So, presenting yourself as ’ OR 1=1 --/doesntmatter gives you full privileges to the system.

A usual reaction on this attack is “what the ---, but that is not a proper username” often combined with “that is just bad indata validation”, where after the problem is dismissed as trivial, uninteresting, and not worth further efforts.

True, the attack string might not be what we consider a valid user name, and there are problem with the indata handling. However, obviously that analysis does not suffice. If those two sentences of analysis where useful, then SQL Injection would not be number two de facto problem on the OWASP list. Bear in mind that the OWASP Ten Top is not the list of the hardest problem around – it is about what we actually find in code out there, and that are exploited on a daily basis. And most of that code is written by pretty smart people.

The usual advice to solve SQL Injection is to use prepared statements. In Java, the SQL API have a PreparedStatment interface, and using “SELECT uid FROM Accounts WHERE username = ? and passwdHash = ?” solves the problem in this specific case. If all SQL Injections where like that, the story could end there.

Unfortunately, the situation can be more convoluted. The SQL might be inside a stored procedure which we call, or locked up in some part of the application we do not have access to – third part vendor or other department with which we have complicated diplomatic relations (yepp, such happens).

It might also be that we are not working with SQL, but with some (possibly legacy) backend-system with some SQL-like syntax, and where the API (if such exists) does not provide any equivalence of prepared statements.

It is easy to dismiss SQL Injection with “bad indata validation” and “use prepared statements”, but I think that is a mistake made by analysing the simplest example without considering that the situation could be a lot more complicated. Had it been so simple, then it would not be so many problems – so evidence speaks against the “SQL Injection is simple” hypothesis.

SQL Injection is clearly a problem that needs to be taken seriously, analysed more in depth, and target for finding design patterns and mindsets that address and avoid it.

Yours

Dan

ps Of course, in-data validation is a nice step in a good direction

Monday, 21 September 2009

Application Security is Your Concern

Dear Junior
There was a time when security incidents where often due to bad configurations of firewalls or other deficiencies in infrastructure. Those days are long gone. According to my friends who do pen-testing (trying to get into systems while wearing a white hat) only 5 % of their success are bad infrastructure. The remaining 95 % is bad applications. Applications written by programmers like you and me. Applications, which accidentally have left holes big enough for an attacker to creep through. Holes, left by programmers like you and me. Holes, which might enable an exploiter to download all the data in the database, or to install arbitrary programs on the backend servers. Or, equally bad, to use our site as a springboard to attack the rest of the world probably starting with our customers.

How come we leave holes in our applications? I think that we programmers in general have not yet realised that the applications we publish on public web sites (such as on-line) are routes that lead down to business critical data and business critical infrastructure. But of course they are, without access to the data, and access to the infrastructure, what value would the application have?
So, someone have to stop the outside from using our application to misuse the data and the infrastructure.
That someone is you and me.
OK, the alarm bell has rung. There are holes in the hull, ship is sinking. What do we do about it? What tools are around to grab?
I grab the Domain Driven Design toolbox and hope that clarity-of-purpose and quality-of-code will cover up at least a fair quantity of the biggest holes.
If we can use those tools to cover up e g Cross-Site Scripting and Injection attacks, then there is hope. Then we might be successful with other more complicated and subtle security problems.
That is what Domain Driven Security is about to me.
Yours
Dan
ps Using value objects can solve SQL injection in a lot of situations, but not the general case.


Wednesday, 16 September 2009

Introducing Domain Driven Security

Dear Junior
As you know I have always had a soft spot for security. It has been one of my favourite non-functional requirements, both because it contains so many facets, and because it is often the one craving the most maturity from both tech-side and business-side. When starting at Omegapoint about six years ago I had two missions: to build up a Java/J2EE group, and to apply the security competence of the company into the system architecture space. The first half, well I have been doing that quite a lot with all the talented colleagues I have had the pleasure of working with. The second half has just come full circle around.
In various discussions, my colleague John Wilander and I have talked about the tangent points and crossroads of Domain Driven Design on one hand and application security a la OWASP on the other hand coming from two different directions, but with an interested eye on the other side. We have now come so far we dare to put a label on our ideas, and we call it Domain Driven Security. John is really the one to explain it from the application security point of view, read his description at the OWASP Sweden blog.
I will try to say what I see from my Domain Driven Design point-of-view.
The OWASP community have identified what they classify as the top ten threats against security of applications. At the top of the current list are Cross-Site Scripting (XSS) and Injection Flaws (e g SQL Injection). So, the list points out things you should be aware of, but is not specific on how to avoid them. To me, there are good breeding ground for taking ideas from Domain Driven Design and using them as tools to address these security concerns, even though the tools were not originally designed specific for security issues.
For example XSS is an attack where some text is send in as content (text) and the system is fooled to interpret it as executable code, often executing it as javascript inside the browser of the victim. Likewise, the basics of SQL Injection is to write some maliciously designed value in a text field that is used as an SQL parameter and doing so in a way that makes the malicious text become part of the query structure, bending it into doing something completely different. The underlying problem is that something intended for one context (data) is misinterpreted in another context (code) in DDD terminology a domain model violation. My idea is that using DDD mindset and a judicious use of e g value objects could address this.
Addressing the OWASP Top Ten is however not the complete ambition of Domain Driven Security I think it might range further than so. I see potential to also address more subtle problems with information security in different forms.
I better get a little bit more specific and give some examples. As security is something that is often surrounded by hush-hush I will tell you some stories. They might be true, they might be not; I might have been there, I might have not; it might be hearsay, it might be not.
An international Swedish retailer (there are several, selling different kinds of stuff) had an on-line order system on their website. However, if you ordered -5 of their popular Kagazboo-stuff, the system reacted by issuing a debit note. Well, you can simply say that it is bad indata validation, but what should you validate against if not a model of the domain? And for that validation to be valuable, the model must be strict in the same way that DDD prescribes. In this case, the missing concept is amount, which is only allowed to be non-negative. This might have caused the retailer monetary harm as they where exploited, or it might have not as the problem was found by a pen-test team. Either is possible and plausible.
Another kind of reseller had lots of similar terminology for closely related stuff around delivery of goods and money. They where taking about order, payment agreement, contract and imbursement together with a bunch of different terms. As the company was quite big, the different departments used almost the same words. Some departments did not need the full set of terms; sometimes they used the same word with different meaning, and sometimes with the same meaning apart from some subtle detail. Well: it turned out that in some cases customers could cancel an order and get a reimbursement even though they had not paid the goods yet. This was because the reimbursement systems thought that an order with status final had been paid, because that is what shipping thought, and that is where they got their data from. However, shipping only got the payment agreements from sales (what they called “payments” for short), and not the imbursements from accounting because they had never had need for that data. Or, it might have been the other way around
Nevertheless, the bottom line of this semantic soup is that it is totally uninteresting whether someone was right or wrong, or whoever owned the definition of ‘payment agreement. For each system the terminology made perfect sense and fulfilled its purpose. However, on a holistic scale loopholes appeared when systems where integrated. The company might have lost money, or they might have not. It might not even have happened, but as story it serves explain my idea.
The obvious, and wrong, solution would be to call everybody into a room and workshop until you had created a full Enterprise Information Model (model in the sky). People have tried that and it simply does not work once you scale up to the level where you need it.
However, using Context Mapping a la Strategic DDD, would concentrate on each integration and ensure that not only the right data was transformed, but also that it was interpreted in a correct way. Doing that would probably have surfaced that the integration was conceptually broken and the integration patterns would have changed.
So, I see an enormous potential in using Domain Driven Design to address information security problems which I see as the goal of Domain Driven Security.
To start somewhere we are preparing a presentation for Omegapoints upcoming annual “competence conference where John and I will attempt to sort out the XSS and SQL Injection problem using Domain Driven Design value objects. If that turns out well, we will try other audiences, conferences and start working with our clients.
I realise that describing this as coming full circle is simply not true. This is not a closing. It is the start of a really interesting field.
Yours
Dan

ps The committee for OWASP AppSec 2010 have selected to let me present this idea at the conference. Thrilling. There I will focus on using Domain Driven Security to address Injection Flaw, the validation problem, and Cross-Site Scripting

Saturday, 5 September 2009

97 Things Every Programmer Should Know

Dear Junior

I just got to know that the initiative 97 Things Every Programmer Should Know under the lead of Kevlin Henney, has just gone public on the O’Reilly web site. The goal of the project is to distil ninety-seven “pearls of wisdom” each condensed to a short article. This is definitely a source of great ideas on programming – what we do and how we do it. Among the contributors you can find well known names like Richard Monson-Haefel, Kevlin Henney, Kirk Pepperdine, Uncle Bob, Dan North, Michael Feathers, and Michael Hunger.

I have also had the honour to be asked to contribute and on the list of Edited Contributions there are two articles of my writing: number 22 Know Your Next Commit about work habits, and number 29 Distinguish Business Exceptions from Technical on code structure.

Apart from starting with Code in the Language of the Domain by Dan North which is bang-in-the-middle of where I started my interest in Domain Driven Design, I would recommend the writing of the Norwegians Einar Landre (who also has a lot to say about DDD) and Johannes Brodwall.

Happy reading!

Yours

Dan