A question came through the pipeline recently about Broadleaf Commerce and how we handle the OWASP top 10 security exploits. This is a pretty important question given the security climate these days and the number of vulnerabilities that have been exposed in the online properties of several major retailers. In the race to build out new features, companies often forget to, or don't make time to, properly harden their e-commerce application for security. They inadvertently use ill advised techniques and practices that leave the door open to savvy attackers, allowing sensitive customer information to be mined or unauthorized operations to be performed. Even security conscious developers can be bitten by third party libraries that introduce security risk they weren't even aware of. Consideration for security should be a first-class citizen in your application design and included in your third party library selection as well. At Broadleaf Commerce, we take security very seriously and strive to provide a framework on which our customers can construct a security hardened e-commerce presence. In this series, I would like to discuss, and dive a bit deeper into, the OWASP top 10 and how we handle these threats here a Broadleaf Commerce. Even if you're not using Broadleaf, this discussion can benefit almost any online application.
To start, here are the OWASP top 10 exploits as of 2013:
- Broken Authentication and Session Management
- Cross-Site Scripting
- Insecure Direct Object References
- Security Misconfiguration
- Sensitive Data Exposure
- Missing Function Level Access Control
- Cross-Site Request Forgery
- Using Components with Known Vulnerabilities
- Unvalidated Redirects And Forwards
This list addresses a mixture of concerns, from development practices to configuration. All, however, are important to consider, since skimping at any point can make unwanted, and possibly disastrous, information available to a hacker.
Today, I'd like to touch on "Injection". The OWASP site describes this flaw as:
"Injection flaws, such as SQL, OS, and LDAP injection occur when untrusted data is sent to an interpreter as part of a command or query. The attacker?s hostile data can trick the interpreter into executing unintended commands or accessing data without proper authorization."
OWASP goes on further to describe an example attack scenario. Their example is apt, so I'll include it here as well.
Scenario #1: The application uses untrusted data in the construction of the following vulnerable SQL call:
String query = "SELECT * FROM accounts WHERE custID='" + request.getParameter("id") + "'";
Scenario #2: Similarly, an application?s blind trust in frameworks may result in queries that are still vulnerable, (e.g., Hibernate Query Language (HQL)):
Query HQLQuery = session.createQuery(?FROM accounts WHERE custID='? + request.getParameter("id") + "'");
In both cases, the attacker modifies the ?id? parameter value in her browser to send: ' or '1'='1. For example:
http://example.com/app/accountView?id=' or '1'='1
It's a common application requirement to filter information from the database based on some set of parameters either implicitly or explicitly provided by the user. A straightforward, but naive, approach is to construct the application query logic in such a way that a user submission (in the example case - a http request parameter) is included directly into a SQL query through string concatenation and is executed against the database backing the application. Since not all user's intentions are good, it's possible that mischievous data can be included in the user submission. With a little bit of SQL knowledge, an attacker can submit data that, when combined into the application's dynamic query, can produce a new, valid query that yields unexpected results.
I'm always surprised when I see this is still a common exploit, since there's so much tooling available to help with this kind of problem. The most common technique to protect against SQL injection is to use an API that provides a parameterized interface. In Java applications, JDBC provides such an interface in the form of JDBC prepared statements. Again, from the OWASP site:
String selectStatement = "SELECT * FROM User WHERE userId = ? ";
PreparedStatement prepStmt = con.prepareStatement(selectStatement);
ResultSet rs = prepStmt.executeQuery();
By using a proper prepared statement, the JDBC driver will escape the "userId" parameter, forcing it to remain a filter parameter, rather than allowing it to possibly change the behavior of the query in unanticipated ways.
Of course, many applications abstract away from JDBC and use ORM frameworks on top of JDBC to handle the mapping of the database records to a object model that is more easy for the application to consume. In these cases, the SQL construction is generally handled by the ORM framework (in the case of Broadleaf Commerce, it's Hibernate under JPA). This can end up involving special query languages on top of SQL (Hibernate uses HQL). These special query languages, just like SQL, are not immune to injection problems and should be constructed and dealt with using the same care. JPA and Hibernate both provide APIs that benefit from parameterized HQL query construction to help avoid the pitfalls of string concatenation when constructing queries.
JPA and Hibernate also provide a criteria API for retrieving data that does not involve a SQL or HQL query string, per se. Usage of this API is also protected, as the parameters that are entered using the API are eventually escaped correctly in the same way as the parameterized query example from above.
At Broadleaf Commerce, we are careful to use parameterized queries without string concatenation and we consistently monitor how user supplied data is incorporated into queries made against the datastore. This is just one of the ways in which we strive to provide a great framework for constructing secure e-commerce applications.
In the next installment, I look forward to exploring more of the OWASP top 10.