Sunday, April 13, 2008

Building Highly Secure Applications

Building highly secure applications need much more than an after thought Penetration Test and a rare Secure Code Review. Over the past two years the need to integrate security into the SDLC has become larger than ever. There is a growing acceptance & place for security within the application development teams these days. Challenge however has been what, where & how. A key need is to not overdo since it might repel potential adopters.

Recently there have been several resources flooding the Internet on how to meet this challenge. I found several that were over-blown & several that were inadequate. Having said that there were fairly good ones. The one that I liked the most & thought met my perception was the Secure Development Lifecycle from Microsoft.

As seen above it highlights what security practices need to be incorporated and where in an SDLC. As you dig deeper it addresses the how part as well http://msdn.microsoft.com/en-us/security/cc420639.aspx. I personally like OWASP guides for the how part specifically following
- Secure Coding Guide http://www.owasp.org/index.php/Category:OWASP_Guide_Project
- Static Analysis/Code Review http://www.owasp.org/index.php/OWASP_Code_Review_Guide_Table_of_Contents
- Dynamic Analysis/Penetration Test http://www.owasp.org/index.php/Category:OWASP_Testing_Project

Saturday, April 5, 2008

J2EE / ASP.Net XSS Protection

J2EE

We again leverage Hacme Books for an example vulnerable code.

Here the victim requests feedbackitem that may potentially comprise malicious code.

We fix this using output encoding method. Here we use Struts bean:write tag that supports output filtering of dangerous characters in the HTTP Response by default.

As you might have noticed, we did not do any input validation and instead accepted the malicious code in first place. Depending on the use cases or the functional requirements, it might or it might not be required. If needed, Struts Validator class could be used. As a best practice it is always recommended to do input validation as well.

ASP.Net

Below is a vulnerable code Hacme Bank.

string messageSubject = txtSubject.Text;
string messageText = txtText.Text;

Here txtSubject.Text and txtText.Text could be injected with malicious code.

However if we use Microsoft Anti-Cross Site Scripting Library the malicious code would be encoded when displayed to a victim and hence rendered harmless.

string messageSubject = AntiXss.HtmlEncode(txtSubject.Text);
string messageText = AntiXss.HtmlEncode(txtText.Text);

Again we allowed the application to accept malicious input in first place. If threat profiling of use cases necessitate, ASP.Net in-built validation routine called RegularExpressionValidator could be leveraged to filter the unwanted input.

The example below enforces txtSubject.Text and txtText.Text to accept alphabets and numbers only.

Friday, April 4, 2008

J2EE / ASP.NET SQL Injection Protection

J2EE

Let's take a vulnerable code example from Hacme Books.

String query = "select * from products where " + “lower(title) like '%" + keyword.toLowerCase() + "%‘”;

As seen
keyword is passed to the interpreter without validation or encoding.

For SQL Injection protection, the secure version with Prepared Statement as shown below can be used.

PreparedStatement query = con.prepareStatement( “select * from products where lower(title) like ?");
query.setString(1, keyword);
updateSales.executeUpdate():

ASP.Net

A vulnerable code example from Hacme Bank looks like this.

string sqlQuery = "select user_id from fsb_users where login_id = '" + loginID+ "' and password = '" + password + "'";

Here the loginID and password are passed to the MS SQL server without validation or encoding .

Using a secure replacement with SQLParameters as below this attack can be mitigated.

string sqlQuery = "select user_id from fsb_users where login_id = @loginID and password = @password";

//Assuming you have defined a command called 'cmd'
cmd.Parameters.Add(New SQLParameter("@loginID", loginID))
cmd.Parameters.Add(New SQLParameter("@password", password))