Showing posts with label owasp. Show all posts
Showing posts with label owasp. Show all posts

Monday, 14 June 2010

The Problem with XSS

Dear Junior
I guess that one of the first things you have to do to address security risks like Cross-Site Scripting (XSS) is to learn what they are about. Here I must admin that even though I have been interested in security, I have lived in ignorance about several of the most common attack techniques. OK, I had some vague idea what a XSS attack was like, but would not be able to explain it. Really I have to thank my colleagues Michael Boman and John Wilander for finally setting the details for me.
Deep down XSS is really about making someone run a program that they did not intended to run. That program might be a harmless pop-up “You have been XSS”, it might be a local port-scan, or it might be installing a keylogger.
The road to make this happen is to mix up the distinction between code and data. This is typically in a web browser which is fooled to accept something that looks like content (data), but actually is JavaScript (code) that gets executed in the browser.
There are several ways to make a XSS happen but the one I have found most easy to understand is what is known as the “stored” attack.
Imagine that you have a community site with some discussion forum on – say – how to raise children. Member parents can enter posts and comments to a discussion. When you go to the discussion page, all posts and comments are sent to you as an HTML page and rendered onto your screen by your browser.
Let us imagine what happens if some evil pretend-to-be-parent enters a comment saying “I think you should <script>alert(‘Spank them!’)</script>be nice to kids”; what would happen? When you, the unsuspecting victim, browse the discussion you get back an HTML page. To start with, the page you get back is valid HTML – it is allowed to drop in a javascript almost wherever you want to. Your browser will render the text “I think you should be nice to kids”, and the script will be executed popping up an alert saying “Spank them!”. Of course, a yet more evil pretend-to-be-parent would substitute ‘alert’ for less pleasant, and now the computers of all unsuspecting parents are infected with keyloggers stealing their credit card numbers and uploading them to some obscure server in unknown jurisdiction.
This variant is called “stored” because the attacking script is stored on the forum server. There are other variants for getting the javascript into the poor browser, but I have found this the easiest to understand.
So, what is the problem? A simple way out is to blame it on bad indata validation. The forum comment “I think you should <script>alert(‘Spank them!’)</script>be nice to kids” should simply not have been accepted – and in this case that might be true. If it had been a discussion on JavaScripts, it might have been a little trickier.
Another way to view the problem is that the browser has mixed up data and code. What was data (the forum comment) was interpreted as code and executed. No good. But that would be a case of blame-shifting, because we (the programmers developing the forum site) are perfectly aware about how browsers work.
So really, the problem is in the forum application that mixes up domains. It takes what is a comment in the in-data domain (text field and http request), and happily let it go over to the presentation domain in which it is interpreted not as content, but as code. How come? Well – if we want the string “<script>alert(Spank them!)</script>” to be interpreted as content in a browser we must encode it properly. So, the long-and-winding answer is that we have missed to apply the proper encoding when transforming from the comment domain to the html-presentation domain.
Now, here we have formulated XSS as a problem in Domain Driven Design terminology – then we can see what Domain Driven Design would do to address the problem.
But that must be the subject of another letter
Yours
Dan

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

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 Omegapoint’s 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