parsonsisconsulting

Parsons Software Security Consulting Blog

Archive for February 2011

How many software security bugs can you find in OWASP web goat below?

leave a comment »

Today’s post is going to be interactive.  I am going to show the source code of a file in web goat.    The file name is BlindSQLInjection.java.   I am asking my readers to point out the security vulnerabilities in the code and post below in comments.  I will post my answers in a couple days.

Many thanks to OWASP, Jeff Williams, Aspect Security and Bruce Mayhew and anyone else that have worked on the web goat project.


package org.owasp.webgoat.lessons;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.<a class="zem_slink" title="Dynamic array" rel="wikipedia" href="http://en.wikipedia.org/wiki/Dynamic_array">ArrayList</a>;
import java.util.List;
import org.apache.ecs.Element;
import org.apache.ecs.ElementContainer;
import org.apache.ecs.StringElement;
import org.apache.ecs.html.Input;
import org.apache.ecs.html.P;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.ECSFactory;
import org.owasp.webgoat.session.WebSession;

/***************************************************************************************************
 *
 *
 * This file is part of WebGoat, an <a class="zem_slink" title="OWASP" rel="wikipedia" href="http://en.wikipedia.org/wiki/OWASP">Open Web Application Security Project</a> utility. For details,
 * please see http://www.owasp.org/
 *
 * Copyright (c) 2002 - 2007 Bruce Mayhew
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the
 * <a class="zem_slink" title="GNU General Public License" rel="wikipedia" href="http://en.wikipedia.org/wiki/GNU_General_Public_License">GNU General Public License</a> as published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the <a class="zem_slink" title="Implied warranty" rel="wikipedia" href="http://en.wikipedia.org/wiki/Implied_warranty">implied warranty of MERCHANTABILITY</a> or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; if
 * not, write to the <a class="zem_slink" title="Free Software Foundation" rel="homepage" href="http://www.fsf.org/">Free Software Foundation, Inc.</a>, 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * Getting Source ==============
 *
 * Source for this application is maintained at code.google.com, a repository for free software
 * projects.
 *
 * For details, please see http://code.google.com/p/webgoat/
 *
 * @author Chuck Willis <a href="http://www.securityfoundry.com">Chuck's web site</a> (this lesson
 *         is heavily based on Bruce Mayhews' <a class="zem_slink" title="SQL" rel="wikipedia" href="http://en.wikipedia.org/wiki/SQL">SQL</a> Injection lesson
 * @created January 14, 2005
 */
public class BlindSqlInjection extends LessonAdapter
{

 private final static String ACCT_NUM = "account_number";

 private final static int TARGET_ACCT_NUM = 15613;

 /**
 * Description of the Method
 *
 * @param s
 *            Description of the Parameter
 * @return Description of the <a class="zem_slink" title="Return statement" rel="wikipedia" href="http://en.wikipedia.org/wiki/Return_statement">Return Value</a>
 */
 protected Element createContent(WebSession s)
 {
 ElementContainer ec = new ElementContainer();

 try
 {
 Connection connection = DatabaseUtilities.getConnection(s);

 ec.addElement(new P().addElement("Enter your Account Number: "));

 String accountNumber = s.getParser().getRawParameter(ACCT_NUM, "101");
 Input input = new Input(Input.TEXT, ACCT_NUM, accountNumber.toString());
 ec.addElement(input);

 Element b = ECSFactory.makeButton("Go!");
 ec.addElement(b);

 String query = "<a class="zem_slink" title="Select (SQL)" rel="wikipedia" href="http://en.wikipedia.org/wiki/Select_%28SQL%29">SELECT</a> * FROM user_data WHERE userid = " + accountNumber;
 String answer_query;
 answer_query = "SELECT TOP 1 first_name FROM user_data WHERE userid = " + TARGET_ACCT_NUM;

 try
 {
 Statement answer_statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
 ResultSet.CONCUR_READ_ONLY);
 ResultSet answer_results = answer_statement.executeQuery(answer_query);
 answer_results.first();
 //System.out.println("Account: " + accountNumber);
 //System.out.println("Answer : " + answer_results.getString(1));
 if (accountNumber.toString().equals(answer_results.getString(1)))
 {
 makeSuccess(s);
 }
 else
 {

 Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
 ResultSet.CONCUR_READ_ONLY);
 ResultSet results = statement.executeQuery(query);

 if ((results != null) && (results.first() == true))
 {
 ec.addElement(new P().addElement("<a class="zem_slink" title="National identification number" rel="wikipedia" href="http://en.wikipedia.org/wiki/National_identification_number">Account number</a> is valid"));
 }
 else
 {
 ec.addElement(new P().addElement("Invalid account number"));
 }
 }
 } catch (SQLException sqle)
 {
 ec.addElement(new P().addElement("An error occurred, please try again."));
 }
 } catch (Exception e)
 {
 s.setMessage("Error generating " + this.getClass().getName());
 e.printStackTrace();
 }

 return (ec);
 }

 /**
 * Gets the category attribute of the SqlInjection object
 *
 * @return The category value
 */
 protected Category getDefaultCategory()
 {
 return Category.INJECTION;
 }

 /**
 * Gets the credits attribute of the AbstractLesson object
 *
 * @return The credits value
 */
 public Element getCredits()
 {
 return new StringElement("By Chuck Willis");
 }

 /**
 * Gets the hints attribute of the DatabaseFieldScreen object
 *
 * @return The hints value
 */
 protected List<String> getHints(WebSession s)
 {
 List<String> hints = new ArrayList<String>();
 hints.add("Compound SQL statements can be made by joining multiple tests with keywords like AND and OR. "
 + "Create a SQL statement that you can use as a true/false test and then "
 + "select the first character of the target element and do a start narrowing "
 + "down the character using > and <"
 + "<br><br>The backend database is HSQLDB.  Keep that in mind if you research SQL functions "
 + "on the Internet since different databases use some different functions and syntax.");
 hints.add("This is the code for the query being built and issued by WebGoat:<br><br> "
 + "\"SELECT * FROM user_data WHERE userid = \" + accountNumber ");
 hints.add("The application is taking your input and inserting it at the end of a pre-formed SQL command. "
 + "You will need to make use of the following SQL functions: "
 + "<br><br>SELECT - query for your target data and get a string "
 + "<br><br>substr(string, start, length) - returns a "
 + "substring of string starting at the start character and going for length characters "
 + "<br><br>ascii(string) will return the ascii value of the first character in string "
 + "<br><br>&gt and &lt - once you have a character's value, compare it to a choosen one");
 hints.add("Example: is the first character of the first_name of userid " + TARGET_ACCT_NUM
 + " less than 'M' (ascii 77)? "
 + "<br><br>101 AND (ascii( substr((SELECT first_name FROM user_data WHERE userid=" + TARGET_ACCT_NUM
 + ") , 1 , 1) ) < 77 ); "
 + "<br><br>If you get back that account number is valid, then yes.  If get back that the number is"
 + "invalid then answer is no.");
 hints.add("Another example: is the second character of the first_name of userid "
 + TARGET_ACCT_NUM
 + " greater than 'm' (ascii 109)? "
 + "<br><br>101 AND (ascii( substr((SELECT first_name FROM user_data WHERE userid="
 + TARGET_ACCT_NUM
 + ") , 2 , 1) ) > 109 ); "
 + "<br><br>If you get back that account number is valid, then yes.  If get back that the number is "
 + "invalid then answer is no.");
 return hints;
 }

 /**
 * Gets the instructions attribute of the SqlInjection object
 *
 * @return The instructions value
 */
 public String getInstructions(WebSession s)
 {
 String instructions = "The form below allows a user to enter an account number and determine if "
 + "it is valid or not.  Use this form to develop a true / false test check other entries in the database.  "
 + "<br><br>Reference Ascii Values: 'A' = 65   'Z' = 90   'a' = 97   'z' = 122 "
 + "<br><br>The goal is to find the value of " + "the first_name in table user_data for userid "
 + TARGET_ACCT_NUM
 + ".  Put the discovered name in the form to pass the lesson.  Only the discovered name "
 + "should be put into the form field, paying close attention to the spelling and capitalization.";

 return (instructions);
 }

 private final static Integer DEFAULT_RANKING = new Integer(70);

 protected Integer getDefaultRanking()
 {
 return DEFAULT_RANKING;
 }

 /**
 * Gets the title attribute of the DatabaseFieldScreen object
 *
 * @return The title value
 */
 public String getTitle()
 {
 return ("Blind SQL Injection");
 }

 /**
 * Constructor for the DatabaseFieldScreen object
 *
 * @param s
 *            Description of the Parameter
 */
 public void handleRequest(WebSession s)
 {
 try
 {
 super.handleRequest(s);
 } catch (Exception e)
 {
 //System.out.println("Exception caught: " + e);
 e.printStackTrace(System.out);
 }
 }
}

 

Matt Parsons, CISSP, MSM

mparsons1980@gmail.com

Parsons Software Security Consulting, LLC

Threat Model for OWASP web goat

leave a comment »

I am trying to completely dissect OWASP’s web goat and link source code findings with web penetration findings.   In my quest to do this I have created a very, very rough threat model.   There is a lot more that needs to be added to the threat model.   I have completed probably ten threat models for different clients’ of mine.   I used the Microsoft Threat Model tool. I used an older version.  I think there are newer ones and better ones.   It is a good idea to use a threat model to see all of the components of the application.   It allows a security analyst or a developer to see the users’ of the application, the data and the possible data exposure of the data of the confidentiality, integrity and availibility of your application.    You can then create use and abuse cases for the application.

 

 

 

 

 

 

 

 

Matt Parsons, CISSP, MSM

mparsons1980@gmail.com

Parsons Software Security Consulting, LLC

Reflected Cross Site Scripting in OWASP Web Goat source code

leave a comment »

I am doing another web goat vulnerability.  This time once again I scanned Web Goat with a commercial static code analyzer.   The tool is telling me that the below vulnerability is reflected cross site scripting.    With reflected XSS attacks an attacker tricks a user into sending malicious code to a vulnerable web server.   This could access the user’s cookie.


Description of the Exception

*/

public String getRawParameter(String name) throws ParameterNotFoundException

{

String[] values = request.getParameterValues(name);

if (values == null)

{

throw new ParameterNotFoundException(name + " not found");

}

else if (values[0].length() == 0) { throw new ParameterNotFoundException(name + " was empty"); }

return (values[0]);


public String getRawParameter(String name, String def)

{

try

{

return getRawParameter(name);

} catch (Exception e)

{

return def;

}

}

/**

* Gets the rawParameter attribute of the ParameterParser object

*

String to = s.getParser().getRawParameter(HIDDEN_TO, "");

String gId = s.getParser().getRawParameter(GMAIL_ID, "");

String gPass = s.getParser().getRawParameter(GMAIL_PASS, "");

String message = s.getParser().getRawParameter(MESSAGE, "");

String subject = s.getParser().getRawParameter(SUBJECT, "");

boolean haveCredentials = !(YOUR_REAL_GMAIL_ID.equals(gId) || YOUR_REAL_GMAIL_PASSWORD.equals(gPass));

ec.addElement(new HR());

createGoogleCredentials(s, ec);

ec.addElement(new HR());

ec.addElement(new BR());

createMailMessage(s, subject, message, ec);

{

if (haveCredentials)

{

Message sentMessage = sendGoogleMail(to, subject, message, emailFromAddress, gId, gPass);

formatMail(ec, sentMessage);

}

else

{

sendSimulatedMail(ec, to, subject, message);

}

}

From reading the code it looks like it gets your gmail information and then sends the message without validating any inputs or encoding any outputs.

All of this takes place inside of the Web Goat file uncheckedemail.java.

Once again thanks to OWASP and Aspect Security for creating and supporting web goat.  It’s a great web application security to practice white box ethical hacking, secure code review without going to prison for real hacking.


msg.setRecipients(Message.RecipientType.TO, addressTo);

// Setting the Subject and Content Type

msg.setSubject(subject);

msg.setContent(message, "text/plain");

Transport.send(msg);

return msg;
<pre>

I couldn't find the page in Web goat that the above code references, but I was able to find the reflected XSS lesson in web goat.
I went to the recently retired from software security blogging, RSNAKE's hackers.org website.

I used the following script to attack it.   
 
<IMG SRC=`javascript:alert("Parsons Software Security Consulting says, 'XSS'")`>


Matt Parsons, CISSP, MSM
Parsons Software Security Consulting, LLC
mparsons1980@gmail.com

Parsons Software Security Consulting, LLC Video Introduction

leave a comment »

OWASP web goat source code SQL injection code vulnerability

with 3 comments

For this post, I have to give credit to OWASP for creating web goat.   I scanned the vulnerable application with different commercial static code analysis analyzers which allow the user to see the code behind the vulnerabilities.


public String getRawParameter(String name) throws ParameterNotFoundException

{

String[] values = request.getParameterValues(name);

if (values == null)

{

throw new ParameterNotFoundException(name + " not found");

}

else if (values[0].length() == 0) { throw new ParameterNotFoundException(name + " was empty"); }

return (values[0]);

Notice that there is not a validation mechanism for the values USERNAME and PASSWORD.


try

{

String username = "";

String password = "";

username = s.getParser().getRawParameter(USERNAME);

password = s.getParser().getRawParameter(PASSWORD);


// If they get back more than one user they succeeded

if (results.getRow() >= 1)

{

// Make sure this isn't data from an sql injected query.

if (results.getString(2).equals(username) && results.getString(3).equals(password))

{

String insertData1 = "INSERT INTO user_login VALUES ( '" + username + "', '"

+ s.getUserName() + "' )";

statement.executeUpdate(insertData1);

}

// check the total count of logins

query = "SELECT * FROM user_login WHERE webgoat_user = '" + s.getUserName() + "'";

results = statement.executeQuery(query);

results.last();

// If they get back more than one user they succeeded

if (results.getRow() >= 3)

{

makeSuccess(s);

Above is the visual smart trace of the SQL injection code so you can visually see it and understand it.   The red boxes are sources and sinks.  The blue boxes are sinks as well.   The grey boxes allow code to pass through them.  The grey boxes should have validation mechanisms in them.   Those grey boxes don’t and this allows for SQL injection.   Webgoat by design, is also using dynamic SQL statements and not parameterized queries which allow for SQL injection that it teaches on the front end of the lessson.

Here are the screen shots of the application which is vulnerable to SQL injection.   Thanks for Aspect Security for creating this application.

My passion is software security and linking web penetration testing with source code analysis.

Matt Parsons, CISSP, MSM, mparsons1980@gmail.com

Parsons Software Security Consulting, LLC