();
+ hints.add( "The application is taking your input and inserting it at the end of a pre-formed SQL command." );
+ hints.add( "This is the code for the query being built and issued by WebGoat:
" +
+ "\"SELECT * FROM user_data WHERE last_name = \" + accountName " );
+ hints.add( "Compound SQL statements can be made by joining multiple tests with keywords like AND and OR." +
+ "Try appending a SQL statement that always resolves to true");
+ hints.add( "Try entering [ smith' OR '1' = '1 ]." );
+
+ return hints;
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(75);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the title attribute of the DatabaseFieldScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "How to Perform String SQL Injection" );
+ }
+
+
+ /**
+ * Constructor for the DatabaseFieldScreen object
+ *
+ * @param s Description of the Parameter
+ */
+ public void handleRequest( WebSession s )
+ {
+ try
+ {
+ super.handleRequest( s );
+
+ if ( connection == null )
+ {
+ connection = DatabaseUtilities.makeConnection( s );
+ }
+ }
+ catch ( Exception e )
+ {
+ System.out.println( "Exception caught: " + e );
+ e.printStackTrace( System.out );
+ }
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/StoredXss.java b/ webgoat/main/project/org/owasp/webgoat/lessons/StoredXss.java
new file mode 100644
index 000000000..2c6055a48
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/StoredXss.java
@@ -0,0 +1,333 @@
+package org.owasp.webgoat.lessons;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.StringElement;
+import org.apache.ecs.html.A;
+import org.apache.ecs.html.B;
+import org.apache.ecs.html.H1;
+import org.apache.ecs.html.HR;
+import org.apache.ecs.html.Input;
+import org.apache.ecs.html.P;
+import org.apache.ecs.html.TD;
+import org.apache.ecs.html.TR;
+import org.apache.ecs.html.Table;
+import org.apache.ecs.html.TextArea;
+import org.owasp.webgoat.session.*;
+import org.owasp.webgoat.util.HtmlEncoder;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public class StoredXss extends LessonAdapter
+{
+ private final static String MESSAGE = "message";
+ private final static int MESSAGE_COL = 3;
+ private final static String NUMBER = "Num";
+ private final static int NUM_COL = 1;
+ private final static String STANDARD_QUERY = "SELECT * FROM messages";
+ private final static String TITLE = "title";
+ private final static int TITLE_COL = 2;
+ private static Connection connection = null;
+ private static int count = 1;
+ private final static int USER_COL = 4; // Added by Chuck Willis - used to show user who posted message
+
+
+ /**
+ * Adds a feature to the Message attribute of the MessageBoardScreen object
+ *
+ * @param s The feature to be added to the Message attribute
+ */
+ protected void addMessage( WebSession s )
+ {
+ try
+ {
+ String title = HtmlEncoder.encode( s.getParser().getRawParameter( TITLE, "" ) );
+ String message = s.getParser().getRawParameter( MESSAGE, "" );
+
+ if ( connection == null )
+ {
+ connection = DatabaseUtilities.makeConnection( s );
+ }
+
+ String query = "INSERT INTO messages VALUES (?, ?, ?, ? )";
+
+ PreparedStatement statement = connection.prepareStatement( query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+ statement.setInt(1, count++);
+ statement.setString(2, title);
+ statement.setString(3, message);
+ statement.setString(4, s.getUserName());
+ ResultSet results = statement.executeQuery();
+ }
+ catch ( Exception e )
+ {
+ // ignore the empty resultset on the insert. There are a few more SQL Injection errors
+ // that could be trapped here but we will let them try. One error would be something
+ // like "Characters found after end of SQL statement."
+ if ( e.getMessage().indexOf("No ResultSet was produced") == -1 )
+ {
+ s.setMessage( "Could not add message to database" );
+ }
+ }
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( WebSession s )
+ {
+ addMessage( s );
+
+ ElementContainer ec = new ElementContainer();
+ ec.addElement( makeInput( s ) );
+ ec.addElement( new HR() );
+ ec.addElement( makeCurrent( s ) );
+ ec.addElement( new HR() );
+ ec.addElement( makeList( s ) );
+
+ return ( ec );
+ }
+
+
+ /**
+ * Gets the category attribute of the StoredXss object
+ *
+ * @return The category value
+ */
+ protected Category getDefaultCategory()
+ {
+ return AbstractLesson.A4;
+ }
+
+
+ /**
+ * Gets the hints attribute of the MessageBoardScreen object
+ *
+ * @return The hints value
+ */
+ protected List getHints()
+ {
+ List hints = new ArrayList();
+ hints.add( "You can put HTML tags in your message." );
+ hints.add( "Bury a SCRIPT tag in the message to attack anyone who reads it." );
+ hints.add( "Enter this: <script language=\"javascript\" type=\"text/javascript\">alert(\"Ha Ha Ha\");</script> in the message field." );
+ hints.add( "Enter this: <script>alert(\"document.cookie\");</script> in the message field." );
+
+ return hints;
+ }
+
+
+
+
+ private final static Integer DEFAULT_RANKING = new Integer(100);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the title attribute of the MessageBoardScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "How to Perform Stored Cross Site Scripting (XSS)" );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element makeCurrent( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ try
+ {
+ int messageNum = s.getParser().getIntParameter( NUMBER, 0 );
+
+ if ( connection == null )
+ {
+ connection = DatabaseUtilities.makeConnection( s );
+ }
+
+ // edit by Chuck Willis - Added logic to associate similar usernames
+ // The idea is that users chuck-1, chuck-2, etc will see each other's messages
+ // but not anyone elses. This allows users to try out XSS to grab another user's
+ // cookies, but not get confused by other users scripts
+
+ String query = "SELECT * FROM messages WHERE user_name LIKE ? and num = ?";
+ PreparedStatement statement = connection.prepareStatement( query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+ statement.setString(1, getNameroot( s.getUserName() ) + "%");
+ statement.setInt(2, messageNum);
+ ResultSet results = statement.executeQuery();
+
+ if ( ( results != null ) && results.first() )
+ {
+ ec.addElement( new H1( "Message Contents For: " + results.getString( TITLE_COL )) );
+ Table t = new Table( 0 ).setCellSpacing( 0 ).setCellPadding( 0 ).setBorder( 0 );
+ TR row1 = new TR( new TD( new B(new StringElement( "Title:" )) ) );
+ row1.addElement( new TD( new StringElement( results.getString( TITLE_COL ) ) ) );
+ t.addElement( row1 );
+
+ String messageData = results.getString( MESSAGE_COL );
+ TR row2 = new TR( new TD( new B(new StringElement( "Message:" )) ) );
+ row2.addElement( new TD( new StringElement( messageData ) ) );
+ t.addElement( row2 );
+
+ // Edited by Chuck Willis - added display of the user who posted the message, so that
+ // if users use a cross site request forgery or XSS to make another user post a message,
+ // they can see that the message is attributed to that user
+
+ TR row3 = new TR( new TD( new StringElement( "Posted By:" ) ) );
+ row3.addElement( new TD( new StringElement( results.getString( USER_COL ) ) ) );
+ t.addElement( row3 );
+
+ ec.addElement( t );
+
+ // Some sanity checks that the script may be correct
+ if ( messageData.toLowerCase().indexOf( "" ) != -1 &&
+ messageData.toLowerCase().indexOf( "alert" ) != -1 )
+ {
+ makeSuccess( s );
+ }
+
+ }
+ else
+ {
+ if ( messageNum != 0 )
+ {
+ ec.addElement( new P().addElement( "Could not find message " + messageNum ) );
+ }
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error generating " + this.getClass().getName() );
+ e.printStackTrace();
+ }
+
+ return ( ec );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element makeInput( WebSession s )
+ {
+ Table t = new Table( 0 ).setCellSpacing( 0 ).setCellPadding( 0 ).setBorder( 0 );
+ TR row1 = new TR();
+ TR row2 = new TR();
+ row1.addElement( new TD( new StringElement( "Title: " ) ) );
+
+ Input inputTitle = new Input( Input.TEXT, TITLE, "" );
+ row1.addElement( new TD( inputTitle ) );
+
+ TD item1 = new TD();
+ item1.setVAlign( "TOP" );
+ item1.addElement( new StringElement( "Message: " ) );
+ row2.addElement( item1 );
+
+ TD item2 = new TD();
+ TextArea ta = new TextArea( MESSAGE, 5, 60 );
+ item2.addElement( ta );
+ row2.addElement( item2 );
+ t.addElement( row1 );
+ t.addElement( row2 );
+
+ Element b = ECSFactory.makeButton( "Submit" );
+ ElementContainer ec = new ElementContainer();
+ ec.addElement( t );
+ ec.addElement( new P().addElement( b ) );
+
+ return ( ec );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static Element makeList( WebSession s )
+ {
+ Table t = new Table( 0 ).setCellSpacing( 0 ).setCellPadding( 0 ).setBorder( 0 );
+
+ try
+ {
+ if ( connection == null )
+ {
+ connection = DatabaseUtilities.makeConnection( s );
+ }
+
+ Statement statement = connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+ // edit by Chuck Willis - Added logic to associate similar usernames
+ // The idea is that users chuck-1, chuck-2, etc will see each other's messages
+ // but not anyone elses. This allows users to try out XSS to grab another user's
+ // cookies, but not get confused by other users scripts
+
+ ResultSet results = statement.executeQuery( STANDARD_QUERY + " WHERE user_name LIKE '" + getNameroot( s.getUserName() ) + "%'" );
+
+ if ( ( results != null ) && ( results.first() == true ) )
+ {
+ results.beforeFirst();
+
+ for ( int i = 0; results.next(); i++ )
+ {
+ A a = ECSFactory.makeLink( results.getString( TITLE_COL ), NUMBER, results.getInt( NUM_COL ) );
+ TD td = new TD().addElement( a );
+ TR tr = new TR().addElement( td );
+ t.addElement( tr );
+ }
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error while getting message list." );
+ }
+
+ ElementContainer ec = new ElementContainer();
+ ec.addElement( new H1( "Message List" ) );
+ ec.addElement( t );
+
+ return ( ec );
+ }
+
+ private static String getNameroot( String name )
+ {
+ String nameroot = name;
+ if (nameroot.indexOf('-') != -1)
+ {
+ nameroot = nameroot.substring(0, nameroot.indexOf('-'));
+ }
+ return nameroot;
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/ThreadSafetyProblem.java b/ webgoat/main/project/org/owasp/webgoat/lessons/ThreadSafetyProblem.java
new file mode 100644
index 000000000..f693108fd
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/ThreadSafetyProblem.java
@@ -0,0 +1,181 @@
+package org.owasp.webgoat.lessons;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+import java.util.ArrayList;
+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.*;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public class ThreadSafetyProblem extends LessonAdapter
+{
+ private final static String USER_NAME = "username";
+ private Connection connection = null;
+ private static String currentUser;
+ private String originalUser;
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ try
+ {
+ if ( connection == null )
+ {
+ connection = DatabaseUtilities.makeConnection( s );
+ }
+
+ ec.addElement( new StringElement( "Enter user name: " ) );
+ ec.addElement( new Input( Input.TEXT, USER_NAME, "" ) );
+ currentUser = s.getParser().getRawParameter( USER_NAME, "" );
+ originalUser = currentUser;
+
+ // Store the user name
+ String user1 = new String( currentUser );
+
+ Element b = ECSFactory.makeButton( "Submit" );
+ ec.addElement( b );
+ ec.addElement( new P() );
+
+ if ( !"".equals( currentUser ) )
+ {
+ Thread.sleep( 1500 );
+
+ // Get the users info from the DB
+ String query = "SELECT * FROM user_system_data WHERE user_name = '" + currentUser + "'";
+ 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("Account information for user: " + originalUser + "
");
+ ResultSetMetaData resultsMetaData = results.getMetaData();
+ ec.addElement( DatabaseUtilities.writeTable( results, resultsMetaData ) );
+ }
+ else
+ {
+ s.setMessage("'" + currentUser + "' is not a user in the WebGoat database.");
+ }
+ }
+ if ( !user1.equals( currentUser ) )
+ {
+ makeSuccess( s );
+ }
+
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error generating " + this.getClass().getName() );
+ e.printStackTrace();
+ }
+
+ return ( ec );
+ }
+
+
+ /**
+ * Gets the hints attribute of the ConcurrencyScreen object
+ *
+ * @return The hints value
+ */
+ protected List getHints()
+ {
+ List hints = new ArrayList();
+ hints.add( "Web applications handle many HTTP requests at the same time." );
+ hints.add( "Developers use variables that are not thread safe." );
+ hints.add( "Show the Java source code and trace the 'currentUser' variable" );
+ hints.add( "Open two browsers and send 'jeff' in one and 'dave' in the other." );
+
+ return hints;
+ }
+
+
+ /**
+ * Gets the instructions attribute of the ThreadSafetyProblem object
+ *
+ * @return The instructions value
+ */
+ public String getInstructions(WebSession s)
+ {
+
+ String instructions = "The user should be able to exploit the concurrency error in this web application " +
+ "and view login information for another user that is attempting the same function " +
+ "at the same time. This will require the use of two browsers. Valid user " +
+ "names are 'jeff' and 'dave'." +
+ "Please enter your username to access your account.";
+
+ return (instructions );
+ }
+
+
+ private final static Integer DEFAULT_RANKING = new Integer(80);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ protected Category getDefaultCategory()
+ {
+ return AbstractLesson.GENERAL;
+ }
+
+ /**
+ * Gets the title attribute of the ConcurrencyScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "How to Exploit Thread Safety Problems" );
+ }
+
+
+ /**
+ * Constructor for the ConcurrencyScreen object
+ *
+ * @param s Description of the Parameter
+ */
+ public void handleRequest( WebSession s )
+ {
+ try
+ {
+ super.handleRequest( s );
+
+ if ( connection == null )
+ {
+ connection = DatabaseUtilities.makeConnection( s );
+ }
+ }
+ catch ( Exception e )
+ {
+ System.out.println( "Exception caught: " + e );
+ e.printStackTrace( System.out );
+ }
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/TraceXSS.java b/ webgoat/main/project/org/owasp/webgoat/lessons/TraceXSS.java
new file mode 100644
index 000000000..82cb1aa7d
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/TraceXSS.java
@@ -0,0 +1,225 @@
+package org.owasp.webgoat.lessons;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.html.BR;
+import org.apache.ecs.html.Center;
+import org.apache.ecs.html.H1;
+import org.apache.ecs.html.HR;
+import org.apache.ecs.html.Input;
+import org.apache.ecs.html.TD;
+import org.apache.ecs.html.TH;
+import org.apache.ecs.html.TR;
+import org.apache.ecs.html.Table;
+import org.owasp.webgoat.session.ECSFactory;
+import org.owasp.webgoat.session.WebSession;
+import org.owasp.webgoat.util.HtmlEncoder;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+
+public class TraceXSS extends LessonAdapter
+{
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ protected Element createContent( WebSession s )
+ {
+
+ ElementContainer ec = new ElementContainer();
+ String regex1 = "^[0-9]{3}$";// any three digits
+ Pattern pattern1 = Pattern.compile( regex1 );
+
+ try
+ {
+ String param1 = s.getParser().getRawParameter( "field1", "111" );
+ String param2 = HtmlEncoder.encode( s.getParser().getRawParameter( "field2", "4128 3214 0002 1999" ) );
+ float quantity = 1.0f;
+ float total = 0.0f;
+ float runningTotal = 0.0f;
+
+ // test input field1
+ if ( !pattern1.matcher( param1 ).matches() )
+ {
+ if ( param1.toLowerCase().indexOf( "script" ) != -1 && param1.toLowerCase().indexOf( "trace" ) != -1)
+ {
+ makeSuccess( s );
+ }
+
+ s.setMessage( "Whoops! You entered " + param1 + " instead of your three digit code. Please try again." );
+ }
+
+ // FIXME: encode output of field2, then s.setMessage( field2 );
+
+ ec.addElement( new HR().setWidth("90%") );
+ ec.addElement( new Center().addElement( new H1().addElement( "Shopping Cart " )));
+ Table t = new Table().setCellSpacing( 0 ).setCellPadding( 2 ).setBorder( 1 ).setWidth("90%").setAlign("center");
+
+ if ( s.isColor() )
+ {
+ t.setBorder( 1 );
+ }
+
+ TR tr = new TR();
+ tr.addElement( new TH().addElement("Shopping Cart Items -- To Buy Now").setWidth("80%"));
+ tr.addElement( new TH().addElement("Price:").setWidth("10%"));
+ tr.addElement( new TH().addElement("Quantity:").setWidth("3%"));
+ tr.addElement( new TH().addElement("Total").setWidth("7%"));
+ t.addElement( tr );
+
+ tr = new TR();
+ tr.addElement( new TD().addElement("Studio RTA - Laptop/Reading Cart with Tilting Surface - Cherry "));
+ tr.addElement( new TD().addElement("69.99").setAlign("right"));
+ tr.addElement( new TD().addElement(new Input( Input.TEXT, "QTY1", s.getParser().getStringParameter("QTY1", "1") )).setAlign( "right" ));
+ quantity = s.getParser().getFloatParameter("QTY1", 1.0f);
+ total = quantity * 69.99f;
+ runningTotal += total;
+ tr.addElement( new TD().addElement("$" +total));
+ t.addElement( tr );
+ tr = new TR();
+ tr.addElement( new TD().addElement("Dynex - Traditional Notebook Case"));
+ tr.addElement( new TD().addElement("27.99").setAlign("right"));
+ tr.addElement( new TD().addElement(new Input( Input.TEXT, "QTY2", s.getParser().getStringParameter("QTY2", "1") )).setAlign( "right" ));
+ quantity = s.getParser().getFloatParameter("QTY2", 1.0f);
+ total = quantity * 27.99f;
+ runningTotal += total;
+ tr.addElement( new TD().addElement("$" +total));
+ t.addElement( tr );
+ tr = new TR();
+ tr.addElement( new TD().addElement("Hewlett-Packard - Pavilion Notebook with Intel® Centrino™"));
+ tr.addElement( new TD().addElement("1599.99").setAlign("right"));
+ tr.addElement( new TD().addElement(new Input( Input.TEXT, "QTY3", s.getParser().getStringParameter("QTY3", "1") )).setAlign( "right" ));
+ quantity = s.getParser().getFloatParameter("QTY3", 1.0f);
+ total = quantity * 1599.99f;
+ runningTotal += total;
+ tr.addElement( new TD().addElement("$" +total));
+ t.addElement( tr );
+ tr = new TR();
+ tr.addElement( new TD().addElement("3 - Year Performance Service Plan $1000 and Over "));
+ tr.addElement( new TD().addElement("299.99").setAlign("right"));
+
+ tr.addElement( new TD().addElement(new Input( Input.TEXT, "QTY4", s.getParser().getStringParameter("QTY4", "1") )).setAlign( "right" ));
+ quantity = s.getParser().getFloatParameter("QTY4", 1.0f);
+ total = quantity * 299.99f;
+ runningTotal += total;
+ tr.addElement( new TD().addElement("$" +total));
+ t.addElement( tr );
+
+ ec.addElement(t);
+
+ t = new Table().setCellSpacing( 0 ).setCellPadding( 2 ).setBorder( 0 ).setWidth("90%").setAlign("center");
+
+ if ( s.isColor() )
+ {
+ t.setBorder( 1 );
+ }
+
+ ec.addElement( new BR() );
+
+ tr = new TR();
+ tr.addElement( new TD().addElement( "The total charged to your credit card:" ) );
+ tr.addElement( new TD().addElement( "$" + runningTotal ));
+ tr.addElement( new TD().addElement( ECSFactory.makeButton( "Update Cart" )));
+ t.addElement( tr );
+ tr = new TR();
+ tr.addElement( new TD().addElement( " " ).setColSpan(2) );
+ t.addElement( tr );
+ tr = new TR();
+ tr.addElement( new TD().addElement( "Enter your credit card number:" ) );
+ tr.addElement( new TD().addElement( new Input( Input.TEXT, "field2", param2 )));
+ t.addElement( tr );
+ tr = new TR();
+ tr.addElement( new TD().addElement( "Enter your three digit access code:" ) );
+ tr.addElement( new TD().addElement( new Input( Input.TEXT, "field1", param1 )));
+ t.addElement( tr );
+
+ Element b = ECSFactory.makeButton( "Purchase" );
+ tr = new TR();
+ tr.addElement( new TD().addElement( b ).setColSpan(2).setAlign("center"));
+ t.addElement( tr );
+
+ ec.addElement( t );
+ ec.addElement( new BR() );
+ ec.addElement( new HR().setWidth("90%") );
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error generating " + this.getClass().getName() );
+ e.printStackTrace();
+ }
+ return ( ec );
+ }
+
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ protected Category getDefaultCategory()
+ {
+ return AbstractLesson.A4;
+ }
+
+
+
+ /**
+ * Gets the hints attribute of the AccessControlScreen object
+ *
+ * @return The hints value
+ */
+ protected List getHints()
+ {
+ List hints = new ArrayList();
+ hints.add( "Most web servers support GET/POST. Many default installations also support TRACE");
+ hints.add( "JavaScript has the ability to post a URL:
" +
+ "<script type=\"text/javascript\">if ( navigator.appName.indexOf(\"Microsoft\") !=-1)" +
+ " {var xmlHttp = new ActiveXObject(\"Microsoft.XMLHTTP\");xmlHttp.open(\"GET\", \"./\", false);" +
+ " xmlHttp.send();str1=xmlHttp.responseText; " +
+ "document.write(str1);</script>");
+ hints.add( "Try changing the HTTP GET to a HTTP TRACE" );
+ hints.add( "Try a cross site trace (XST) Command:
" +
+ "<script type=\"text/javascript\">if ( navigator.appName.indexOf(\"Microsoft\") !=-1)" +
+ " {var xmlHttp = new ActiveXObject(\"Microsoft.XMLHTTP\");xmlHttp.open(\"TRACE\", \"./\", false);" +
+ " xmlHttp.send();str1=xmlHttp.responseText; while (str1.indexOf(\"\\n\") > -1) str1 = str1.replace(\"\\n\",\"<br>\"); " +
+ "document.write(str1);}</script>");
+ return hints;
+ }
+//
+
+ private final static Integer DEFAULT_RANKING = new Integer(130);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the title attribute of the AccessControlScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "How to Perform Cross Site Trace Attacks" );
+ }
+}
+
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/UncheckedEmail.java b/ webgoat/main/project/org/owasp/webgoat/lessons/UncheckedEmail.java
new file mode 100644
index 000000000..a955670a6
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/UncheckedEmail.java
@@ -0,0 +1,226 @@
+package org.owasp.webgoat.lessons;
+
+import java.text.Format;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.StringElement;
+import org.apache.ecs.html.B;
+import org.apache.ecs.html.BR;
+import org.apache.ecs.html.Center;
+import org.apache.ecs.html.H1;
+import org.apache.ecs.html.H3;
+import org.apache.ecs.html.HR;
+import org.apache.ecs.html.Input;
+import org.apache.ecs.html.TD;
+import org.apache.ecs.html.TH;
+import org.apache.ecs.html.TR;
+import org.apache.ecs.html.Table;
+import org.apache.ecs.html.TextArea;
+
+import org.owasp.webgoat.session.ECSFactory;
+import org.owasp.webgoat.session.WebSession;
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+
+public class UncheckedEmail extends LessonAdapter
+{
+
+ private final static String MESSAGE = "msg";
+ private final static String TO = "to";
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ protected Element createContent( WebSession s )
+ {
+
+ ElementContainer ec = new ElementContainer();
+ try
+ {
+ String to = s.getParser().getRawParameter( TO, "" );
+
+ Table t = new Table().setCellSpacing( 0 ).setCellPadding( 2 ).setBorder( 0 ).setWidth("90%").setAlign("center");
+
+ if ( s.isColor() )
+ {
+ t.setBorder( 1 );
+ }
+
+ TR tr = new TR();
+ tr.addElement( new TH().addElement("Send OWASP your Comments
").setAlign("left").setColSpan(3));
+ t.addElement( tr );
+
+ tr = new TR();
+ tr.addElement( new TD().addElement( " ").setColSpan(3));
+ t.addElement( tr );
+
+ tr = new TR();
+ tr.addElement( new TH().addElement(new H1("Contact Us")).setAlign("left").setWidth("55%").setVAlign("BOTTOM"));
+ tr.addElement( new TH().addElement( " "));
+ tr.addElement( new TH().addElement(new H3("Contact Information:")).setAlign("left").setVAlign("BOTTOM"));
+ t.addElement( tr );
+
+
+ tr = new TR();
+ tr.addElement( new TD().addElement("We value your comments. To send OWASP your questions or comments regarding the " +
+ "WebGoat tool, please enter your comments below. The information you provide will be handled according " +
+ "to our Privacy Policy."));
+ tr.addElement( new TD().addElement( " "));
+ tr.addElement( new TD().addElement("OWASP
" +
+ "9175 Guilford Rd
Suite 300
" +
+ "Columbia, MD. 21046").setVAlign("top"));
+ t.addElement( tr );
+
+
+
+ tr = new TR();
+ tr.addElement( new TD().addElement( " ").setColSpan(3));
+ t.addElement( tr );
+
+ Input input = new Input( Input.HIDDEN, TO, "webgoat.admin@owasp.org" );
+ tr = new TR();
+ tr.addElement( new TD().addElement( "Questions or Comments:"));
+ tr.addElement( new TD().addElement( " "));
+ tr.addElement( new TD().setAlign( "LEFT" ).addElement( input ));
+ t.addElement( tr );
+
+
+ tr = new TR();
+ String message = s.getParser().getRawParameter( MESSAGE, "" );
+ TextArea ta = new TextArea( MESSAGE, 5, 40 );
+ ta.addElement( new StringElement( convertMetachars(message) ));
+ tr.addElement( new TD().setAlign( "LEFT" ).addElement( ta ));
+ tr.addElement( new TD().setAlign( "LEFT" ).setVAlign( "MIDDLE" ).addElement( ECSFactory.makeButton( "Send!" ) ) );
+ tr.addElement( new TD().addElement( " "));
+ t.addElement( tr );
+ ec.addElement( t );
+
+ // Eventually we could send the actually mail, but the point should already be made
+ //ec.addElement(exec( use java mail here + to));
+
+ if ( to.length() > 0 )
+ {
+ Format formatter;
+ // Get today's date
+ Date date = new Date();
+ formatter = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z");
+ String today = formatter.format(date);
+ // Tue, 09 Jan 2002 22:14:02 -0500
+
+ ec.addElement( new HR() );
+ ec.addElement( new Center().addElement( new B().addElement( "You sent the following message to: " + to ) ) );
+ ec.addElement( new BR() );
+ ec.addElement( new StringElement("Return-Path: <webgoat@owasp.org>"));
+ ec.addElement( new BR() );
+ ec.addElement( new StringElement("Delivered-To: " + to));
+ ec.addElement( new BR() );
+ ec.addElement( new StringElement("Received: (qmail 614458 invoked by uid 239); " + today));
+ ec.addElement( new BR() );
+ ec.addElement( new StringElement("for <" + to+">; " + today ));
+ ec.addElement( new BR() );
+ ec.addElement( new StringElement("To: " + to));
+ ec.addElement( new BR() );
+ ec.addElement( new StringElement("From: Blame it on the Goat <webgoat@owasp.org>"));
+ ec.addElement( new BR() );
+ ec.addElement( new StringElement("Subject: OWASP security issues"));
+ ec.addElement( new BR() );
+ ec.addElement( new BR() );
+ ec.addElement( new StringElement( message ) );
+ }
+
+ // only complete the lesson if they changed the "to" hidden field
+ if ( to.length() > 0 && ! "webgoat.admin@owasp.org".equals( to ) )
+ {
+ makeSuccess( s );
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error generating " + this.getClass().getName() );
+ e.printStackTrace();
+ }
+ return ( ec );
+ }
+
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ protected Category getDefaultCategory()
+ {
+ return AbstractLesson.A1;
+ }
+
+
+ /**
+ * Gets the hints attribute of the EmailScreen object
+ *
+ * @return The hints value
+ */
+ protected List getHints()
+ {
+ List hints = new ArrayList();
+ hints.add( "Try sending an anonymous message to yourself." );
+ hints.add( "Try inserting some html or javascript code in the message field" );
+ hints.add( "Look at the hidden fields in the HTML.");
+ hints.add( "Insert <A href=\"http://www.aspectsecurity.com/webgoat.html\">Click here for Aspect</A> in the message field" );
+ hints.add( "Insert <script>alert(\"Bad Stuff\");</script> in the message field" );
+ return hints;
+ }
+
+
+ /**
+ * Gets the instructions attribute of the UncheckedEmail object
+ *
+ * @return The instructions value
+ */
+ public String getInstructions(WebSession s)
+ {
+ String instructions = "This form is an example of a customer support page. Using the form below try to:
"
+ + "1) Send a malicious script to the website admin.
"
+ + "2) Send a malicious script to a 'friend' from OWASP.
";
+ return ( instructions );
+ }
+
+
+
+
+ private final static Integer DEFAULT_RANKING = new Integer(55);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the title attribute of the EmailScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "How to Exploit Unchecked Email" );
+ }
+}
+
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/WSDLScanning.java b/ webgoat/main/project/org/owasp/webgoat/lessons/WSDLScanning.java
new file mode 100644
index 000000000..af19722ce
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/WSDLScanning.java
@@ -0,0 +1,262 @@
+/*
+ * Created on May 26, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.owasp.webgoat.lessons;
+
+import java.rmi.RemoteException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+import javax.xml.rpc.ParameterMode;
+import javax.xml.rpc.ServiceException;
+
+import org.apache.axis.client.Call;
+import org.apache.axis.client.Service;
+import org.apache.axis.encoding.XMLType;
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.html.A;
+import org.apache.ecs.html.BR;
+import org.apache.ecs.html.IMG;
+import org.apache.ecs.html.Input;
+import org.apache.ecs.html.Option;
+import org.apache.ecs.html.P;
+import org.apache.ecs.html.Select;
+import org.apache.ecs.html.TD;
+import org.apache.ecs.html.TR;
+import org.apache.ecs.html.Table;
+
+import org.owasp.webgoat.session.DatabaseUtilities;
+import org.owasp.webgoat.session.ECSFactory;
+import org.owasp.webgoat.session.WebSession;
+
+/**
+ * @author asmolen
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class WSDLScanning extends LessonAdapter {
+ static boolean completed = false;
+ static boolean beenRestartedYet = false;
+ public static Connection connection = null;
+ public final static String firstName = "getFirstName";
+ public final static String lastName = "getLastName";
+ public final static String loginCount = "getLoginCount";
+ public final static String ccNumber = "getCreditCard";
+ final static IMG CREDITS_LOGO = new IMG( "images/logos/parasoft.jpg" ).setAlt( "Parasoft" ).setBorder( 0 ).setHspace( 0 ).setVspace( 0 );
+
+ protected Category getDefaultCategory()
+ {
+ return AbstractLesson.WEB_SERVICES;
+ }
+
+ protected List getHints()
+ {
+ List hints = new ArrayList();
+ hints.add( "Try connecting to the WSDL with a browser or Web Service tool." );
+ hints.add( "Sometimes the WSDL will define methods that are not available through a web API. " +
+ "Try to find operations that are in the WSDL, but not part of this API");
+ hints.add( "The URL for the web service is: http://localost/WebGoat/services/WSDLScanning
" +
+ "The WSDL can usually be viewed by adding a ?WSDL on the end of the request.");
+ hints.add( "Look in the WSDL for the getCreditCard operation and insert the field in an intercepted request.");
+ return hints;
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(120);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ public String getTitle()
+ {
+ return "WSDL Scanning";
+ }
+ public Object accessWGService(String serv, String proc, String parameterName, Object parameterValue) {
+ String targetNamespace = "WebGoat";
+ try {
+ QName serviceName = new QName(targetNamespace, serv);
+ QName operationName = new QName(targetNamespace, proc);
+ Service service = new Service();
+ Call call = (Call) service.createCall();
+ call.setOperationName(operationName);
+ call.addParameter( parameterName, serviceName, ParameterMode.INOUT );
+ call.setReturnType( XMLType.XSD_STRING );
+ call.setUsername("guest");
+ call.setPassword("guest");
+ call.setTargetEndpointAddress(
+ "http://localhost/WebGoat/services/" + serv);
+ Object result = call.invoke( new Object[] { parameterValue } );
+ return result;
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ } catch (ServiceException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+ protected Element createContent(WebSession s)
+ {
+ ElementContainer ec = new ElementContainer();
+
+
+ Table t1 = new Table().setCellSpacing( 0 ).setCellPadding( 2 );
+
+ if ( s.isColor() )
+ {
+ t1.setBorder( 1 );
+ }
+ TR tr = new TR();
+ tr.addElement(new TD( "Enter your account number: " ));
+ tr.addElement(new TD( new Input( Input.TEXT, "id", "101")));
+ t1.addElement(tr);
+
+ tr = new TR();
+ tr.addElement( new TD( "Select the fields to return: " ));
+ tr.addElement(new TD( new Select("field").setMultiple(true)
+ .addElement(new Option(firstName).addElement("First Name"))
+ .addElement(new Option(lastName).addElement("Last Name"))
+ .addElement(new Option(loginCount).addElement("Login Count"))));
+ t1.addElement(tr);
+
+ tr = new TR();
+ Element b = ECSFactory.makeButton( "Submit" );
+ tr.addElement( new TD(b).setAlign("CENTER").setColSpan(2) );
+ t1.addElement(tr);
+
+ ec.addElement(t1);
+
+ try {
+ String[] fields = s.getParser().getParameterValues( "field" );
+ int id = s.getParser().getIntParameter( "id" );
+ if ( connection == null )
+ {
+ connection = DatabaseUtilities.makeConnection( s );
+ }
+
+ Table t = new Table().setCellSpacing( 0 ).setCellPadding( 2 ).setBorder( 1 );
+
+ if ( s.isColor() )
+ {
+ t.setBorder( 1 );
+ }
+ TR header = new TR();
+ TR results = new TR();
+ for (int i=0; iAspect Security
+ * @created October 28, 2003
+ */
+public class WeakAuthenticationCookie extends LessonAdapter
+{
+ /**
+ * Description of the Field
+ */
+ protected final static String AUTHCOOKIE = "AuthCookie";
+ /**
+ * Description of the Field
+ */
+ protected final static String LOGOUT = "WACLogout";
+ /**
+ * Description of the Field
+ */
+ protected final static String PASSWORD = "Password";
+ /**
+ * Description of the Field
+ */
+ protected final static String USERNAME = "Username";
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ * @exception Exception Description of the Exception
+ */
+ protected String checkCookie( WebSession s ) throws Exception
+ {
+ String cookie = getCookie( s );
+
+ if ( cookie != null )
+ {
+ if ( cookie.equals( encode( "webgoat12345" ) ) )
+ {
+ return ( "webgoat" );
+ }
+
+ if ( cookie.equals( encode( "aspect12345" ) ) )
+ {
+ return ( "aspect" );
+ }
+
+ if ( cookie.equals( encode( "alice12345" ) ) )
+ {
+ makeSuccess( s );
+ return ( "alice" );
+ }
+ else
+ {
+ s.setMessage( "Invalid cookie" );
+ s.eatCookies();
+ }
+ }
+
+ return ( null );
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ * @exception Exception Description of the Exception
+ */
+ protected String checkParams( WebSession s ) throws Exception
+ {
+ String username = s.getParser().getStringParameter( USERNAME, "" );
+ String password = s.getParser().getStringParameter( PASSWORD, "" );
+
+ if ( ( username.length() > 0 ) && ( password.length() > 0 ) )
+ {
+ String loginID = "";
+
+ if ( username.equals( "webgoat" ) && password.equals( "webgoat" ) )
+ {
+ loginID = encode( "webgoat12345" );
+ }
+ else if ( username.equals( "aspect" ) && password.equals( "aspect" ) )
+ {
+ loginID = encode( "aspect12345" );
+ }
+
+ if ( loginID != "" )
+ {
+ Cookie newCookie = new Cookie( AUTHCOOKIE, loginID );
+ s.setMessage( "Your identity has been remembered" );
+ s.getResponse().addCookie( newCookie );
+
+ return ( username );
+ }
+ else
+ {
+ s.setMessage( "Invalid username and password entered." );
+ }
+ }
+
+ return ( null );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( WebSession s )
+ {
+ boolean logout = s.getParser().getBooleanParameter( LOGOUT, false );
+
+ if ( logout )
+ {
+ s.setMessage( "Goodbye! Your password has been forgotten" );
+ s.eatCookies();
+
+ return ( makeLogin( s ) );
+ }
+
+ try
+ {
+ String user = checkCookie( s );
+
+ if ( ( user != null ) && ( user.length() > 0 ) )
+ {
+ return ( makeUser( s, user, "COOKIE" ) );
+ }
+
+ user = checkParams( s );
+
+ if ( ( user != null ) && ( user.length() > 0 ) )
+ {
+ return ( makeUser( s, user, "PARAMETERS" ) );
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error generating " + this.getClass().getName() );
+ e.printStackTrace();
+ }
+
+ return ( makeLogin( s ) );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param value Description of the Parameter
+ * @return Description of the Return Value
+ */
+ private String encode( String value )
+ {
+ //
+ StringBuffer encoded = new StringBuffer();
+
+ for ( int i = 0; i < value.length(); i++ )
+ {
+ encoded.append( String.valueOf( (char) ( value.charAt( i ) + 1 ) ) );
+ }
+
+ return encoded.reverse().toString();
+ //
+ }
+
+
+ /**
+ * Gets the category attribute of the WeakAuthenticationCookie object
+ *
+ * @return The category value
+ */
+ protected Category getDefaultCategory()
+ {
+ return AbstractLesson.A3;
+ }
+
+
+ /**
+ * Gets the cookie attribute of the CookieScreen object
+ *
+ * @param s Description of the Parameter
+ * @return The cookie value
+ */
+ protected String getCookie( WebSession s )
+ {
+ Cookie[] cookies = s.getRequest().getCookies();
+
+ for ( int i = 0; i < cookies.length; i++ )
+ {
+ if ( cookies[i].getName().equalsIgnoreCase( AUTHCOOKIE ) )
+ {
+ return ( cookies[i].getValue() );
+ }
+ }
+
+ return ( null );
+ }
+
+
+ /**
+ * Gets the hints attribute of the CookieScreen object
+ *
+ * @return The hints value
+ */
+ protected List getHints()
+ {
+ List hints = new ArrayList();
+ hints.add( "The server skips authentication if you send the right cookie." );
+ hints.add( "Is the AuthCookie value guessable knowing the username and password?" );
+ hints.add( "Add 'AuthCookie=********;' to the Cookie: header using WebScarab." );
+
+ return hints;
+ }
+
+
+ /**
+ * Gets the instructions attribute of the WeakAuthenticationCookie object
+ *
+ * @return The instructions value
+ */
+ public String getInstructions(WebSession s)
+ {
+ String instructions = "Login using the webgoat/webgoat account to see what happens. You may also try aspect/aspect. When you understand the authentication cookie, try changing your identity to alice.";
+
+ return ( instructions );
+ }
+
+
+
+
+ private final static Integer DEFAULT_RANKING = new Integer(90);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the title attribute of the CookieScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "How to Spoof an Authentication Cookie" );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element makeLogin( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ ec.addElement( new H1().addElement( "Sign In " ));
+ Table t = new Table().setCellSpacing( 0 ).setCellPadding( 2 ).setBorder( 0 ).setWidth("90%").setAlign("center");
+
+ if ( s.isColor() )
+ {
+ t.setBorder( 1 );
+ }
+
+ TR tr = new TR();
+ tr.addElement( new TH().addElement("Please sign in to your account. See the OWASP admin if you do not have an account.")
+ .setColSpan(2).setAlign("left"));
+ t.addElement( tr );
+
+ tr = new TR();
+ tr.addElement( new TD().addElement("*Required Fields").setWidth("30%"));
+ t.addElement( tr );
+
+ tr = new TR();
+ tr.addElement( new TD().addElement(" ").setColSpan(2));
+ t.addElement( tr );
+
+ TR row1 = new TR();
+ TR row2 = new TR();
+ row1.addElement( new TD( new B( new StringElement( "*User Name: " ) ) ));
+ row2.addElement( new TD( new B(new StringElement( "*Password: " ) ) ));
+
+ Input input1 = new Input( Input.TEXT, USERNAME, "" );
+ Input input2 = new Input( Input.PASSWORD, PASSWORD, "" );
+ row1.addElement( new TD( input1 ) );
+ row2.addElement( new TD( input2 ) );
+ t.addElement( row1 );
+ t.addElement( row2 );
+
+ Element b = ECSFactory.makeButton( "Login" );
+ t.addElement( new TR( new TD( b ) ) );
+ ec.addElement( t );
+
+ return ( ec );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @param user Description of the Parameter
+ * @param method Description of the Parameter
+ * @return Description of the Return Value
+ * @exception Exception Description of the Exception
+ */
+ protected Element makeUser( WebSession s, String user, String method ) throws Exception
+ {
+ ElementContainer ec = new ElementContainer();
+ ec.addElement( new P().addElement( "Welcome, " + user ) );
+ ec.addElement( new P().addElement( "You have been authenticated with " + method ) );
+ ec.addElement( new P().addElement( ECSFactory.makeLink( "Logout", LOGOUT, true ) ) );
+ ec.addElement( new P().addElement( ECSFactory.makeLink( "Refresh", "", "" ) ) );
+
+ return ( ec );
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/WeakSessionID.java b/ webgoat/main/project/org/owasp/webgoat/lessons/WeakSessionID.java
new file mode 100644
index 000000000..90a5c4ba6
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/WeakSessionID.java
@@ -0,0 +1,218 @@
+package org.owasp.webgoat.lessons;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.Cookie;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.StringElement;
+import org.apache.ecs.html.B;
+import org.apache.ecs.html.H1;
+import org.apache.ecs.html.Input;
+import org.apache.ecs.html.TD;
+import org.apache.ecs.html.TH;
+import org.apache.ecs.html.TR;
+import org.apache.ecs.html.Table;
+
+import org.owasp.webgoat.session.ECSFactory;
+import org.owasp.webgoat.session.ParameterNotFoundException;
+import org.owasp.webgoat.session.WebSession;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Rogan Dawes Rogan Dawes
+ * @created March 30, 2005
+ */
+public class WeakSessionID extends LessonAdapter {
+ /**
+ * Description of the Field
+ */
+ protected final static String SESSIONID = "WEAKID";
+
+ /**
+ * Description of the Field
+ */
+ protected final static String PASSWORD = "Password";
+
+ /**
+ * Description of the Field
+ */
+ protected final static String USERNAME = "Username";
+
+ protected static List sessionList = new ArrayList();
+ protected static long seq = Math.round(Math.random() * 10240) + 10000;
+ protected static long lastTime = System.currentTimeMillis();
+
+ /**
+ * Gets the credits attribute of the AbstractLesson object
+ *
+ * @return The credits value
+ */
+ public Element getCredits() {
+ return new StringElement("By Rogan Dawes");
+ }
+
+ protected String newCookie() {
+ long now = System.currentTimeMillis();
+ seq ++;
+ if (seq % 29 == 0) {
+ String target = encode(seq++, lastTime + (now - lastTime)/2);
+ sessionList.add(target);
+ if (sessionList.size()>100)
+ sessionList.remove(0);
+ }
+ lastTime = now;
+ return encode(seq, now);
+ }
+
+ private String encode(long seq, long time) {
+ return new String( Long.toString(seq) + "-" + Long.toString(time) );
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( WebSession s ) {
+ try {
+ String sessionid = s.getCookie( SESSIONID );
+ if ( sessionid != null && sessionList.indexOf(sessionid) > -1) {
+ return makeSuccess( s );
+ }
+ else {
+ return makeLogin( s );
+ }
+ }
+ catch ( Exception e ) {
+ s.setMessage( "Error generating " + this.getClass().getName() );
+ e.printStackTrace();
+ }
+
+ return ( null );
+ }
+
+
+ /**
+ * Gets the category attribute of the WeakAuthenticationCookie object
+ *
+ * @return The category value
+ */
+ protected Category getDefaultCategory() {
+ return AbstractLesson.A3;
+ }
+
+
+
+ /**
+ * Gets the hints attribute of the CookieScreen object
+ *
+ * @return The hints value
+ */
+ protected List getHints() {
+ List hints = new ArrayList();
+ hints.add( "The server skips authentication if you send the right cookie." );
+ hints.add( "Is the cookie value predictable? Can you see gaps where someone else has acquired a cookie?" );
+ hints.add( "Try harder, you brute!" );
+
+ return hints;
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(90);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the title attribute of the CookieScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle() {
+ return ( "How to hijack a session" );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element makeLogin( WebSession s ) {
+ ElementContainer ec = new ElementContainer();
+
+ String weakid = s.getCookie(SESSIONID);
+
+ if (weakid == null) {
+ weakid = newCookie();
+ Cookie cookie = new Cookie( SESSIONID, weakid );
+ s.getResponse().addCookie(cookie);
+ }
+
+ ec.addElement( new H1().addElement( "Sign In " ));
+ Table t = new Table().setCellSpacing( 0 ).setCellPadding( 2 ).setBorder( 0 ).setWidth("90%").setAlign("center");
+
+ if ( s.isColor() ) {
+ t.setBorder( 1 );
+ }
+
+ String username = null;
+ String password = null;
+
+ try {
+ username = s.getParser().getStringParameter( USERNAME );
+ } catch (ParameterNotFoundException pnfe) {}
+ try {
+ password = s.getParser().getStringParameter( PASSWORD );
+ } catch (ParameterNotFoundException pnfe) {}
+
+ if (username != null || password != null) {
+ s.setMessage("Invalid username or password.");
+ }
+
+ TR tr = new TR();
+ tr.addElement( new TH().addElement("Please sign in to your account.")
+ .setColSpan(2).setAlign("left"));
+ t.addElement( tr );
+
+ tr = new TR();
+ tr.addElement( new TD().addElement("*Required Fields").setWidth("30%"));
+ t.addElement( tr );
+
+ tr = new TR();
+ tr.addElement( new TD().addElement(" ").setColSpan(2));
+ t.addElement( tr );
+
+ TR row1 = new TR();
+ TR row2 = new TR();
+ row1.addElement( new TD( new B( new StringElement( "*User Name: " ) ) ));
+ row2.addElement( new TD( new B(new StringElement( "*Password: " ) ) ));
+
+ Input input1 = new Input( Input.TEXT, USERNAME, "" );
+ Input input2 = new Input( Input.PASSWORD, PASSWORD, "" );
+ Input input3 = new Input( Input.HIDDEN, SESSIONID, weakid );
+ row1.addElement( new TD( input1 ) );
+ row2.addElement( new TD( input2 ) );
+ t.addElement( row1 );
+ t.addElement( row2 );
+ t.addElement( input3 );
+
+ Element b = ECSFactory.makeButton( "Login" );
+ t.addElement( new TR( new TD( b ) ) );
+ ec.addElement( t );
+
+ return ( ec );
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/WelcomeScreen.java b/ webgoat/main/project/org/owasp/webgoat/lessons/WelcomeScreen.java
new file mode 100644
index 000000000..f87db8ff1
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/WelcomeScreen.java
@@ -0,0 +1,128 @@
+package org.owasp.webgoat.lessons;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.HtmlColor;
+import org.apache.ecs.StringElement;
+import org.apache.ecs.html.Center;
+import org.apache.ecs.html.Form;
+import org.apache.ecs.html.TD;
+import org.apache.ecs.html.TR;
+import org.apache.ecs.html.Table;
+import org.owasp.webgoat.session.*;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public class WelcomeScreen extends Screen
+{
+ /**
+ * Constructor for the WelcomeScreen object
+ *
+ * @param s Description of the Parameter
+ */
+ public WelcomeScreen( WebSession s )
+ {
+ setup( s );
+ }
+
+ /**
+ * Constructor for the WelcomeScreen object
+ */
+ public WelcomeScreen() { }
+
+
+ public void setup( WebSession s )
+ {
+ // call createContent first so messages will go somewhere
+
+ Form form = new Form( "attack", Form.POST ).setName( "form" ).setEncType( "" );
+
+ form.addElement( wrapForm( s ) );
+
+ TD lowerright = new TD().setHeight( "100%" ).setVAlign( "top" ).setAlign( "left" ).addElement( form );
+ TR row = new TR().addElement( lowerright );
+ Table layout = new Table().setBgColor( HtmlColor.WHITE ).setCellSpacing( 0 ).setCellPadding( 0 ).setBorder( 0 );
+
+ layout.addElement( row );
+
+ setContent(layout);
+ }
+
+ protected Element wrapForm( WebSession s )
+ {
+ if ( s == null )
+ {
+ return new StringElement( "Invalid Session" );
+ }
+
+ Table container = new Table().setWidth( "100%" ).setCellSpacing( 10 ).setCellPadding( 0 ).setBorder( 0 );
+
+ // CreateContent can generate error messages so you MUST call it before makeMessages()
+ Element content = createContent( s );
+ container.addElement( new TR().addElement( new TD().setColSpan( 2 ).setVAlign( "TOP" ).addElement(
+ makeMessages( s ) ) ) );
+ container.addElement( new TR().addElement( new TD().setColSpan( 2 ).addElement( content ) ) );
+ container.addElement( new TR() );
+
+ return ( container );
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+ Element b = ECSFactory.makeButton( "Start the Course!" );
+ ec.addElement( new Center( b ) );
+
+ return ( ec );
+ }
+
+ public Element getCredits()
+ {
+ return new ElementContainer();
+ }
+
+ /**
+ * Gets the instructions attribute of the WelcomeScreen object
+ *
+ * @return The instructions value
+ */
+ protected String getInstructions()
+ {
+ String instructions = "Enter your name and learn how HTTP really works!";
+
+ return ( instructions );
+ }
+
+
+ /**
+ * Gets the title attribute of the WelcomeScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "Welcome to the Penetration Testing Course" );
+ }
+
+ /* (non-Javadoc)
+ * @see session.Screen#getRole()
+ */
+ public String getRole() {
+ return AbstractLesson.USER_ROLE;
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/WsSAXInjection.java b/ webgoat/main/project/org/owasp/webgoat/lessons/WsSAXInjection.java
new file mode 100644
index 000000000..bc4b7be2e
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/WsSAXInjection.java
@@ -0,0 +1,180 @@
+/*
+ * Created on Jun 1, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.owasp.webgoat.lessons;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.StringElement;
+import org.apache.ecs.html.B;
+import org.apache.ecs.html.Input;
+import org.apache.ecs.html.P;
+import org.apache.ecs.html.PRE;
+
+import org.owasp.webgoat.session.ECSFactory;
+import org.owasp.webgoat.session.WebSession;
+import org.owasp.webgoat.util.HtmlEncoder;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * @author rdawes
+ *
+ * TODO To change the template for this generated type comment go to Window -
+ * Preferences - Java - Code Style - Code Templates
+ */
+public class WsSAXInjection extends LessonAdapter {
+ private final static String PASSWORD = "password";
+
+ private String password;
+
+ private static String template1 = "\n"
+ + "\n"
+ + " \n"
+ + " \n"
+ + " 101\n"
+ + " ";
+
+ private static String template2 = "\n"
+ + " \n" + " \n"
+ + "";
+
+ static boolean completed;
+
+ protected Category getDefaultCategory() {
+ return AbstractLesson.WEB_SERVICES;
+ }
+
+ protected List getHints() {
+ List hints = new ArrayList();
+
+ hints.add("The backend parses the XML received using a SAX parser.");
+ hints.add("SAX parsers often don't care if an element is repeated.");
+ hints.add("If there are repeated elements, the last one is the one that is effective");
+ hints.add("Try injecting matching 'close' tags, and creating your own XML elements");
+
+ return hints;
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(150);
+
+ protected Integer getDefaultRanking() {
+ return DEFAULT_RANKING;
+ }
+
+ public String getTitle() {
+ return "Web Service SAX Injection";
+ }
+
+ protected Element makeInputLine(WebSession s) {
+ ElementContainer ec = new ElementContainer();
+
+ ec.addElement(new P().addElement("Please change your password: "));
+
+ Input input = new Input(Input.TEXT, PASSWORD);
+ ec.addElement(input);
+
+ Element b = ECSFactory.makeButton("Go!");
+ ec.addElement(b);
+
+ return ec;
+ }
+
+ protected Element createContent(WebSession s) {
+ ElementContainer ec = new ElementContainer();
+ try {
+ ec.addElement(makeInputLine(s));
+
+ password = s.getParser().getRawParameter(PASSWORD, null);
+
+ PRE pre = new PRE();
+ String xml = template1;
+ xml = xml + (password == null ? "[password]" : password);
+ xml = xml + template2;
+ pre.addElement(HtmlEncoder.encode(xml));
+ ec.addElement(pre);
+
+ if (password != null) {
+ ec.addElement(checkXML(s, xml));
+ }
+ } catch (Exception e) {
+ s.setMessage("Error generating " + this.getClass().getName());
+ e.printStackTrace();
+ }
+ return (ec);
+ }
+
+ private Element checkXML(WebSession s, String xml) {
+ try {
+ XMLReader reader = XMLReaderFactory.createXMLReader();
+ PasswordChanger changer = new PasswordChanger();
+ reader.setContentHandler(changer);
+ reader.parse(new InputSource(new StringReader(xml)));
+ if (!"101".equals(changer.getId())) {
+ makeSuccess(s);
+ return new B(HtmlEncoder.encode("You have changed the passsword for userid " + changer.getId() + " to '" + changer.getPassword() + "'"));
+ } else {
+ return new StringElement("You changed the password for userid 101. Try again.");
+ }
+ } catch (SAXException saxe) {
+ return new StringElement("The XML was not well formed: " + saxe.getLocalizedMessage());
+ } catch (IOException ioe) {
+ return new StringElement(ioe.getLocalizedMessage());
+ }
+ }
+
+ private static class PasswordChanger extends DefaultHandler {
+ private static String PASSWORD_TAG = "password";
+ private static String ID_TAG = "id";
+
+ private String id = null;
+ private String password = null;
+
+ private StringBuffer text = new StringBuffer();
+
+ public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+ text.delete(0, text.length());
+ }
+
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ text.append(ch, start, length);
+ }
+
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if (localName.equals(ID_TAG))
+ id = text.toString();
+ if (localName.equals(PASSWORD_TAG))
+ password = text.toString();
+ text.delete(0, text.length());
+ }
+
+ public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+ text.append(ch, start, length);
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/WsSqlInjection.java b/ webgoat/main/project/org/owasp/webgoat/lessons/WsSqlInjection.java
new file mode 100644
index 000000000..ed9c93a85
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/WsSqlInjection.java
@@ -0,0 +1,217 @@
+/*
+ * Created on Jun 1, 2005
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package org.owasp.webgoat.lessons;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.html.A;
+import org.apache.ecs.html.BR;
+import org.apache.ecs.html.IMG;
+import org.apache.ecs.html.Input;
+import org.apache.ecs.html.P;
+import org.apache.ecs.html.PRE;
+
+import org.owasp.webgoat.session.DatabaseUtilities;
+import org.owasp.webgoat.session.ECSFactory;
+import org.owasp.webgoat.session.WebSession;
+
+/**
+ * @author asmolen
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class WsSqlInjection extends LessonAdapter {
+ public final static String ccNumber = "cc_number";
+ private final static String ACCT_NUM = "account_number";
+ private String accountNumber;
+ final static IMG CREDITS_LOGO = new IMG( "images/logos/parasoft.jpg" ).setAlt( "Parasoft" ).setBorder( 0 ).setHspace( 0 ).setVspace( 0 );
+ private static Connection connection = null;
+ /* (non-Javadoc)
+ * @see lessons.AbstractLesson#getMenuItem()
+ */
+ static boolean completed;
+
+ protected Category getDefaultCategory()
+ {
+ return AbstractLesson.WEB_SERVICES;
+ }
+
+ protected List getHints()
+ {
+ List hints = new ArrayList();
+ hints.add( "Try connecting to the WSDL with a browser or Web Service tool." );
+ hints.add( "Sometimes the server side code will perform input validation before issuing " +
+ "the request to the web service operation. Try to bypass this check by " +
+ "accessing the web service directly");
+ hints.add( "The URL for the web service is: http://localhost/WebGoat/services/WsSqlInjection?WSDL
" +
+ "The WSDL can usually be viewed by adding a ?WSDL on the end of the request.");
+ hints.add( "Create a new soap request for the getCreditCard(String id) operation.");
+ hints.add("A soap request uses the following HTTP header:
" +
+ "SOAPAction: some action header, can be ""
" +
+ "The soap message body has the following format:
" +
+ "<?xml version='1.0' encoding='UTF-8'?>
" +
+ " <SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
" +
+ " <SOAP-ENV:Body>
" +
+ " <ns1:getCreditCard SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:ns1='http://lessons'>
" +
+ " <id xsi:type='xsd:string'>101</id>
" +
+ " </ns1:getCreditCard>
" +
+ " </SOAP-ENV:Body>
" +
+ " </SOAP-ENV:Envelope>
" +
+ "");
+/* "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
" +
+ " <SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"
" +
+ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
" +
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">
" +
+ " <SOAP-ENV:Body>
" +
+ " <ns1:getCreditCard SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:ns1=\"http://lessons\">
" +
+ " <id xsi:type=\"xsd:string\">101</id>
"+
+ " </ns1:getCreditCard>
" +
+ " </SOAP-ENV:Body>
" +
+ " </SOAP-ENV:Envelope>
" +
+ "Intercept the HTTP request and try to create a soap request."); */
+ return hints;
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(150);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ public String getTitle()
+ {
+ return "Web Service SQL Injection";
+ }
+ protected Element makeAccountLine( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ ec.addElement( new P().addElement( "Enter your Account Number: " ) );
+
+ 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 );
+
+ return ec;
+ }
+ protected Element createContent(WebSession s)
+ {
+ ElementContainer ec = new ElementContainer();
+ try
+ {
+ if ( connection == null )
+ {
+ connection = DatabaseUtilities.makeConnection( s );
+ }
+ ec.addElement( makeAccountLine(s) );
+
+ String query = "SELECT * FROM user_data WHERE userid = " + accountNumber ;
+ ec.addElement( new PRE( query ) );
+ for (int i=0; i '9') {
+ ec.addElement("Invalid account number. ");
+ accountNumber = "0";
+ }
+ }
+ try
+ {
+ ResultSet results = getResults(accountNumber);
+ if ( ( results != null ) && ( results.first() == true ) )
+ {
+ ResultSetMetaData resultsMetaData = results.getMetaData();
+ ec.addElement( DatabaseUtilities.writeTable( results, resultsMetaData ) );
+ results.last();
+ if ( results.getRow() >= 6 )
+ {
+ //this should never happen
+ }
+ }
+ else
+ {
+ ec.addElement( "No results matched. Try Again." );
+ }
+ }
+ catch ( SQLException sqle )
+ {
+ ec.addElement( new P().addElement( sqle.getMessage() ) );
+ }
+ A a = new A("services/WsSqlInjection?WSDL","WebGoat WSDL");
+ ec.addElement(new P().addElement("Exploit the following WSDL to access sensitive data:"));
+ ec.addElement(new BR());
+ ec.addElement(a);
+ getLessonTracker( s ).setCompleted( completed );
+ }
+ catch (Exception e)
+ {
+ s.setMessage("Error generating " + this.getClass().getName());
+ e.printStackTrace();
+ }
+ return (ec);
+ }
+ public ResultSet getResults (String id) {
+ try
+ {
+ Connection connection = DatabaseUtilities.makeConnection();
+ if (connection == null) {
+ return null;
+ }
+ String query = "SELECT * FROM user_data WHERE userid = " + id ;
+ try
+ {
+ Statement statement = connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+ ResultSet results = statement.executeQuery( query );
+ return results;
+ }
+ catch ( SQLException sqle )
+ {
+ }
+ }
+ catch ( Exception e )
+ {
+ }
+ return null;
+ }
+ public String[] getCreditCard(String id) {
+ ResultSet results = getResults(id);
+ if ((results != null)) {
+ try {
+ results.last();
+ String[] users = new String[results.getRow()];
+ if (users.length > 4) {
+ completed = true;
+ }
+ results.beforeFirst();
+ while (results.next() == true) {
+ int i = results.getRow();
+ users[i-1] = results.getString(ccNumber);
+ }
+ return users;
+ } catch (SQLException sqle) {
+ }
+ }
+ return null;
+ }
+
+ public Element getCredits()
+ {
+ return super.getCustomCredits("By Alex Smolen", CREDITS_LOGO);
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/admin/AdminScreen.java b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/AdminScreen.java
new file mode 100644
index 000000000..79ce5f2b7
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/AdminScreen.java
@@ -0,0 +1,76 @@
+package org.owasp.webgoat.lessons.admin;
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.session.Screen;
+import org.owasp.webgoat.session.WebSession;
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public abstract class AdminScreen extends Screen
+{
+ /**
+ * Description of the Field
+ */
+ protected String query = null;
+
+
+ /**
+ * Constructor for the AdminScreen object
+ *
+ * @param s Description of the Parameter
+ * @param q Description of the Parameter
+ */
+ public AdminScreen( WebSession s, String q )
+ {
+ setQuery( q );
+
+ // setupAdmin(s); FIXME: what was this supposed to do?
+ }
+
+
+ /**
+ * Constructor for the AdminScreen object
+ *
+ * @param s Description of the Parameter
+ */
+ public AdminScreen( WebSession s ) { }
+
+
+ /**
+ * Constructor for the AdminScreen object
+ */
+ public AdminScreen() { }
+
+
+ /**
+ * Gets the title attribute of the AdminScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "Admin Information" );
+ }
+
+
+ public String getRole() {
+ return AbstractLesson.ADMIN_ROLE;
+ }
+
+ /**
+ * Sets the query attribute of the AdminScreen object
+ *
+ * @param q The new query value
+ */
+ public void setQuery( String q )
+ {
+ query = q;
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/admin/ProductsAdminScreen.java b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/ProductsAdminScreen.java
new file mode 100644
index 000000000..e34453902
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/ProductsAdminScreen.java
@@ -0,0 +1,105 @@
+package org.owasp.webgoat.lessons.admin;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.owasp.webgoat.lessons.Category;
+import org.owasp.webgoat.lessons.LessonAdapter;
+import org.owasp.webgoat.session.DatabaseUtilities;
+import org.owasp.webgoat.session.WebSession;
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public class ProductsAdminScreen extends LessonAdapter
+{
+ private final static String QUERY = "SELECT * FROM product_system_data";
+ private static Connection connection = null;
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ try
+ {
+ if ( connection == null )
+ {
+ connection = DatabaseUtilities.makeConnection( s );
+ }
+
+ Statement statement = connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+ ResultSet results = statement.executeQuery( QUERY );
+
+ if ( results != null )
+ {
+ makeSuccess( s );
+ ResultSetMetaData resultsMetaData = results.getMetaData();
+ ec.addElement( DatabaseUtilities.writeTable( results, resultsMetaData ) );
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error generating " + this.getClass().getName() );
+ e.printStackTrace();
+ }
+
+ return ( ec );
+ }
+
+
+ /**
+ * Gets the category attribute of the ProductsAdminScreen object
+ *
+ * @return The category value
+ */
+ protected Category getDefaultCategory()
+ {
+ return ADMIN_FUNCTIONS;
+ }
+
+ /**
+ * Gets the role attribute of the ProductsAdminScreen object
+ *
+ * @return The role value
+ */
+ public String getRole()
+ {
+ return HACKED_ADMIN_ROLE;
+ }
+
+
+ /**
+ * Gets the title attribute of the ProductsAdminScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "Product Information" );
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(1000);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/admin/RefreshDBScreen.java b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/RefreshDBScreen.java
new file mode 100644
index 000000000..910b646e3
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/RefreshDBScreen.java
@@ -0,0 +1,143 @@
+package org.owasp.webgoat.lessons.admin;
+
+import java.sql.Connection;
+import org.owasp.webgoat.lessons.*;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.StringElement;
+import org.apache.ecs.html.A;
+import org.apache.ecs.html.TD;
+import org.apache.ecs.html.TR;
+import org.apache.ecs.html.Table;
+import org.owasp.webgoat.session.*;
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public class RefreshDBScreen extends LessonAdapter
+{
+ private final static String REFRESH = "Refresh";
+ private static Connection connection = null;
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ try
+ {
+ boolean refresh = s.getParser().getBooleanParameter( REFRESH, false );
+
+ if ( refresh )
+ {
+ refreshDB( s );
+ ec.addElement( new StringElement( "Successfully refreshed the database." ) );
+ }
+ else
+ {
+ Element label = new StringElement( "Refresh the database? " );
+ A link1 = ECSFactory.makeLink( "Yes", REFRESH, true );
+ A link2 = ECSFactory.makeLink( "No", REFRESH, false );
+ TD td1 = new TD().addElement( label );
+ TD td2 = new TD().addElement( link1 );
+ TD td3 = new TD().addElement( link2 );
+ TR row = new TR().addElement( td1 ).addElement( td2 ).addElement( td3 );
+ Table t = new Table().setCellSpacing( 40 ).setWidth( "50%" );
+
+ if ( s.isColor() )
+ {
+ t.setBorder( 1 );
+ }
+
+ t.addElement( row );
+ ec.addElement( t );
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error generating " + this.getClass().getName() );
+ e.printStackTrace();
+ }
+
+ return ( ec );
+ }
+
+
+ /**
+ * Gets the category attribute of the RefreshDBScreen object
+ *
+ * @return The category value
+ */
+ protected Category getDefaultCategory()
+ {
+ return ADMIN_FUNCTIONS;
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(1000);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the role attribute of the RefreshDBScreen object
+ *
+ * @return The role value
+ */
+ public String getRole()
+ {
+ return ADMIN_ROLE;
+ }
+
+
+ /**
+ * Gets the title attribute of the RefreshDBScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "Refresh Database" );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ */
+ public void refreshDB( WebSession s )
+ {
+ try
+ {
+ if ( connection == null )
+ {
+ connection = DatabaseUtilities.makeConnection( s );
+ }
+
+ CreateDB db = new CreateDB();
+ db.makeDB( connection );
+ System.out.println( "Successfully refreshed the database." );
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error refreshing database " + this.getClass().getName() );
+ e.printStackTrace();
+ }
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/admin/ReportCardScreen.java b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/ReportCardScreen.java
new file mode 100644
index 000000000..a5f863518
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/ReportCardScreen.java
@@ -0,0 +1,278 @@
+package org.owasp.webgoat.lessons.admin;
+
+import java.util.Iterator;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.HtmlColor;
+import org.apache.ecs.StringElement;
+import org.apache.ecs.html.Center;
+import org.apache.ecs.html.H2;
+import org.apache.ecs.html.TD;
+import org.apache.ecs.html.TH;
+import org.apache.ecs.html.TR;
+import org.apache.ecs.html.Table;
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.Category;
+import org.owasp.webgoat.lessons.LessonAdapter;
+import org.owasp.webgoat.session.LessonTracker;
+import org.owasp.webgoat.session.Screen;
+import org.owasp.webgoat.session.UserTracker;
+import org.owasp.webgoat.session.WebSession;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public class ReportCardScreen extends LessonAdapter
+{
+
+ /**
+ * Description of the Field
+ */
+ protected final static String USERNAME = "Username";
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ String user = null;
+
+ try
+ {
+ if ( s.getRequest().isUserInRole( WebSession.WEBGOAT_ADMIN ) )
+ {
+ user = s.getParser().getRawParameter( USERNAME );
+ }
+ else
+ {
+ user = s.getUserName();
+ }
+ }
+ catch ( Exception e )
+ {
+ }
+
+ if ( user == null )
+ {
+ user = s.getUserName();
+ }
+
+ ec.addElement( makeFeedback( s ));
+ ec.addElement( makeReportCard( s, user ) );
+
+ return ec;
+ }
+
+
+ private Element makeFeedback( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+ ec.addElement( new Center( new StringElement( "Comments and suggestions are welcome. " + s.getFeedbackAddress() )) );
+
+ return ec;
+ }
+ /**
+ * Gets the category attribute of the UserAdminScreen object
+ *
+ * @return The category value
+ */
+ protected Category getDefaultCategory()
+ {
+ return ADMIN_FUNCTIONS;
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(1000);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the role attribute of the UserAdminScreen object
+ *
+ * @return The role value
+ */
+ public String getRole()
+ {
+ return USER_ROLE;
+ }
+
+
+ /**
+ * Gets the title attribute of the UserAdminScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "Report Card" );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param screen Description of the Parameter
+ * @param s Description of the Parameter
+ * @param user Description of the Parameter
+ * @return Description of the Return Value
+ */
+ private TR makeLessonRow( WebSession s, String user, Screen screen )
+ {
+ LessonTracker lessonTracker = UserTracker.instance().getLessonTracker( s, user, screen );
+ TR tr = new TR();
+ if ( lessonTracker.getCompleted() )
+ {
+ tr.setBgColor( HtmlColor.LIGHTGREEN );
+ }
+ else if ( lessonTracker.getNumVisits() == 0 )
+ {
+ tr.setBgColor( HtmlColor.LIGHTBLUE );
+ }
+ else if ( !lessonTracker.getCompleted() && lessonTracker.getNumVisits() > 10 )
+ {
+ tr.setBgColor( HtmlColor.RED );
+ }
+ else
+ {
+ tr.setBgColor( HtmlColor.YELLOW );
+ }
+ tr.addElement( new TD().addElement( screen.getTitle() ) );
+ tr.addElement( new TD().setAlign( "CENTER" ).addElement( lessonTracker.getCompleted() ? "Y" : "N" ) );
+ tr.addElement( new TD().setAlign( "CENTER" ).addElement( Integer.toString( lessonTracker.getNumVisits() ) ) );
+ tr.addElement( new TD().setAlign( "CENTER" ).addElement( Integer.toString( lessonTracker.getMaxHintLevel() ) ) );
+ tr.addElement( new TD().setAlign( "CENTER" ).addElement( lessonTracker.getViewedCookies() ? "Y" : "N" ) );
+ tr.addElement( new TD().setAlign( "CENTER" ).addElement( lessonTracker.getViewedHtml() ? "Y" : "N" ) );
+ tr.addElement( new TD().setAlign( "CENTER" ).addElement( lessonTracker.getViewedLessonPlan() ? "Y" : "N" ) );
+ tr.addElement( new TD().setAlign( "CENTER" ).addElement( lessonTracker.getViewedParameters() ? "Y" : "N" ) );
+ tr.addElement( new TD().setAlign( "CENTER" ).addElement( lessonTracker.getViewedSource() ? "Y" : "N" ) );
+ return tr;
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element makeMessages( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ return ( ec );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @param user Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public Element makeReportCard( WebSession s, String user )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ ec.addElement( makeUser( s, user ) );
+ Table t = new Table().setCellSpacing( 0 ).setCellPadding( 2 ).setBorder( 1 );
+
+ if ( s.isColor() )
+ {
+ t.setBorder( 1 );
+ }
+ TR tr = new TR();
+ t.addElement( makeUserHeaderRow() );
+
+ // These are all the user lesson
+ tr = new TR();
+ tr.addElement( new TD().setAlign( "CENTER" ).setColSpan( 9 ).addElement( "Normal user lessons" ) );
+ t.addElement( tr );
+ for ( Iterator lessonIter = s.getCourse().getLessons( s, AbstractLesson.USER_ROLE ).iterator(); lessonIter.hasNext(); )
+ {
+ Screen screen = (Screen) lessonIter.next();
+ t.addElement( makeLessonRow( s, user, screen ) );
+ }
+
+ // The user figured out there was a hackable admin acocunt
+ tr = new TR();
+ tr.addElement( new TD().setAlign( "CENTER" ).setColSpan( 9 ).addElement( "Hackable Admin Screens" ) );
+ t.addElement( tr );
+ for ( Iterator lessonIter = s.getCourse().getLessons( s, AbstractLesson.HACKED_ADMIN_ROLE ).iterator(); lessonIter.hasNext(); )
+ {
+ Screen screen = (Screen) lessonIter.next();
+ t.addElement( makeLessonRow( s, user, screen ) );
+ }
+
+ // The user figured out how to actually hack the admin acocunt
+ tr = new TR();
+ tr.addElement( new TD().setAlign( "CENTER" ).setColSpan( 9 ).addElement( "Actual Admin Screens" ) );
+ t.addElement( tr );
+ for ( Iterator lessonIter = s.getCourse().getLessons( s, AbstractLesson.ADMIN_ROLE ).iterator(); lessonIter.hasNext(); )
+ {
+ Screen screen = (Screen) lessonIter.next();
+ t.addElement( makeLessonRow( s, user, screen ) );
+ }
+
+ ec.addElement( t );
+ return ( ec );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @param user Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element makeUser( WebSession s, String user )
+ {
+ H2 h2 = new H2();
+ // FIXME: The session is the current session, not the session of the user we are reporting.
+ //String type = s.isAdmin() ? " [Administrative User]" : s.isHackedAdmin() ? " [Normal User - Hacked Admin Access]" : " [Normal User]";
+ String type = "";
+ h2.addElement( new StringElement( "Results for: " + user + type ) );
+ return h2;
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @return Description of the Return Value
+ */
+ private TR makeUserHeaderRow()
+ {
+ TR tr = new TR();
+
+ tr.addElement( new TH( "Lesson" ) );
+ tr.addElement( new TH( "Complete" ) );
+ tr.addElement( new TH( "Visits" ) );
+ tr.addElement( new TH( "Hints" ) );
+ tr.addElement( new TH( "Cookies" ) );
+ tr.addElement( new TH( "HTML" ) );
+ tr.addElement( new TH( "LessonPlan" ) );
+ tr.addElement( new TH( "Parameters" ) );
+ tr.addElement( new TH( "Source" ) );
+
+ return tr;
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/admin/SummaryReportCardScreen.java b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/SummaryReportCardScreen.java
new file mode 100644
index 000000000..9b3349665
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/SummaryReportCardScreen.java
@@ -0,0 +1,292 @@
+package org.owasp.webgoat.lessons.admin;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.HtmlColor;
+import org.apache.ecs.html.Center;
+import org.apache.ecs.html.Input;
+import org.apache.ecs.html.P;
+import org.apache.ecs.html.TD;
+import org.apache.ecs.html.TH;
+import org.apache.ecs.html.TR;
+import org.apache.ecs.html.Table;
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.Category;
+import org.owasp.webgoat.lessons.LessonAdapter;
+import org.owasp.webgoat.session.LessonTracker;
+import org.owasp.webgoat.session.Screen;
+import org.owasp.webgoat.session.UserTracker;
+import org.owasp.webgoat.session.WebSession;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public class SummaryReportCardScreen extends LessonAdapter
+{
+
+ private int totalUsersNormalComplete = 0;
+ private int totalUsersAdminComplete = 0;
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ String selectedUser = null;
+
+ try
+ {
+ if ( s.getRequest().isUserInRole( WebSession.WEBGOAT_ADMIN ) )
+ {
+ Enumeration e = s.getParser().getParameterNames();
+
+ while ( e.hasMoreElements() )
+ {
+ String key = (String) e.nextElement();
+ if ( key.startsWith( "View_" ) )
+ {
+ selectedUser = key.substring( "View_".length() );
+ ReportCardScreen reportCard = new ReportCardScreen();
+ return reportCard.makeReportCard( s, selectedUser );
+ }
+ if ( key.startsWith( "Delete_" ) )
+ {
+ selectedUser = key.substring( "Delete_".length() );
+ deleteUser( selectedUser );
+ }
+ }
+ }
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace();
+ }
+
+ ec.addElement( new Center().addElement(makeSummary(s)) );
+
+ ec.addElement( new P() );
+
+ Table t = new Table().setCellSpacing( 0 ).setCellPadding( 4 ).setBorder( 1 ).setWidth("100%");
+ if ( s.isColor() )
+ {
+ t.setBorder( 1 );
+ }
+ t.addElement( makeUserSummaryHeader() );
+
+ for ( Iterator userIter = UserTracker.instance().getAllUsers(WebSession.WEBGOAT_USER).iterator(); userIter.hasNext(); )
+ {
+
+ String user = (String) userIter.next();
+ t.addElement( makeUserSummaryRow( s, user ) );
+ }
+
+ ec.addElement( new Center().addElement( t ) );
+
+ return ec;
+ }
+
+
+ protected Element makeSummary( WebSession s)
+ {
+ Table t = new Table().setCellSpacing( 0 ).setCellPadding( 2 ).setBorder( 0 ).setWidth("100%");
+ if ( s.isColor() )
+ {
+ t.setBorder( 1 );
+ }
+ TR tr = new TR();
+ //tr.addElement( new TH().addElement( "Summary").setColSpan(1));
+ //t.addElement( tr );
+
+ tr = new TR();
+ tr.addElement( new TD().setWidth("60%").addElement( "Total number of users"));
+ tr.addElement( new TD().setAlign("LEFT").addElement(Integer.toString( UserTracker.instance().getAllUsers(WebSession.WEBGOAT_USER).size() )));
+ t.addElement( tr );
+
+ tr = new TR();
+ tr.addElement( new TD().setWidth("60%").addElement( "Total number of users that completed all normal lessons"));
+ tr.addElement( new TD().setAlign("LEFT").addElement(Integer.toString( totalUsersNormalComplete )));
+ t.addElement( tr );
+
+ tr = new TR();
+ tr.addElement( new TD().setWidth("60%").addElement( "Total number of users that completed all admin lessons"));
+ tr.addElement( new TD().setAlign("LEFT").addElement(Integer.toString( totalUsersAdminComplete )));
+ t.addElement( tr );
+ return t;
+ }
+
+ private void deleteUser( String user )
+ {
+ UserTracker.instance().deleteUser( user );
+ }
+
+ /**
+ * Gets the category attribute of the UserAdminScreen object
+ *
+ * @return The category value
+ */
+ protected Category getDefaultCategory()
+ {
+ return ADMIN_FUNCTIONS;
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(1000);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the role attribute of the UserAdminScreen object
+ *
+ * @return The role value
+ */
+ public String getRole()
+ {
+ return ADMIN_ROLE;
+ }
+
+
+ /**
+ * Gets the title attribute of the UserAdminScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "Summary Report Card" );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element makeMessages( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ return ( ec );
+ }
+
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @return Description of the Return Value
+ */
+ protected Element makeUserSummaryHeader()
+ {
+ TR tr = new TR();
+
+ tr.addElement( new TH( "User Name" ) );
+ tr.addElement( new TH( "Normal Complete" ) );
+ tr.addElement( new TH( "Admin Complete" ) );
+ tr.addElement( new TH( "View" ) );
+ tr.addElement( new TH( "Delete" ) );
+
+ return tr;
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @param user Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element makeUserSummaryRow( WebSession s, String user )
+ {
+ TR tr = new TR();
+
+ tr.addElement( new TD().setAlign( "LEFT" ).addElement( user ) );
+ int lessonCount = 0;
+ int passedCount = 0;
+ boolean normalComplete = false;
+ boolean adminComplete = false;
+
+ for ( Iterator lessonIter = s.getCourse().getLessons( s, AbstractLesson.USER_ROLE ).iterator(); lessonIter.hasNext(); )
+ {
+ lessonCount++;
+ Screen screen = (Screen) lessonIter.next();
+
+ LessonTracker lessonTracker = UserTracker.instance().getLessonTracker( s, user, screen );
+ if ( lessonTracker.getCompleted() )
+ {
+ passedCount++;
+ }
+ }
+ if ( lessonCount == passedCount )
+ {
+ normalComplete = true;
+ totalUsersNormalComplete++;
+ }
+ String text = Integer.toString( passedCount ) + " of " + Integer.toString( lessonCount );
+ tr.addElement( new TD().setAlign( "CENTER" ).addElement( text ) );
+
+ lessonCount = 0;
+ passedCount = 0;
+ for ( Iterator lessonIter = s.getCourse().getLessons( s, AbstractLesson.HACKED_ADMIN_ROLE ).iterator(); lessonIter.hasNext(); )
+ {
+ lessonCount++;
+ Screen screen = (Screen) lessonIter.next();
+
+ LessonTracker lessonTracker = UserTracker.instance().getLessonTracker( s, user, screen );
+ if ( lessonTracker.getCompleted() )
+ {
+ passedCount++;
+ }
+ }
+ if ( lessonCount == passedCount )
+ {
+ adminComplete = true;
+ totalUsersAdminComplete++;
+ }
+ text = Integer.toString( passedCount ) + " of " + Integer.toString( lessonCount );
+ tr.addElement( new TD().setAlign( "CENTER" ).addElement( text ) );
+
+ tr.addElement( new TD().setAlign( "CENTER" ).addElement( new Input( Input.SUBMIT, "View_" + user, "View" ) ) );
+ tr.addElement( new TD().setAlign( "CENTER" ).addElement( new Input( Input.SUBMIT, "Delete_" + user, "Delete" ) ) );
+
+ if ( normalComplete && adminComplete )
+ {
+ tr.setBgColor( HtmlColor.GREEN );
+ }
+ else if ( normalComplete )
+ {
+ tr.setBgColor( HtmlColor.LIGHTGREEN );
+ }
+ else
+ {
+ tr.setBgColor( HtmlColor.LIGHTBLUE );
+ }
+
+ return ( tr );
+ }
+
+ public boolean isEnterprise()
+ {
+ return true;
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/admin/UserAdminScreen.java b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/UserAdminScreen.java
new file mode 100644
index 000000000..bf669a79c
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/UserAdminScreen.java
@@ -0,0 +1,106 @@
+package org.owasp.webgoat.lessons.admin;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.owasp.webgoat.lessons.Category;
+import org.owasp.webgoat.lessons.LessonAdapter;
+import org.owasp.webgoat.session.DatabaseUtilities;
+import org.owasp.webgoat.session.WebSession;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public class UserAdminScreen extends LessonAdapter
+{
+ private final static String QUERY = "SELECT * FROM user_system_data";
+ private static Connection connection = null;
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ try
+ {
+ if ( connection == null )
+ {
+ connection = DatabaseUtilities.makeConnection( s );
+ }
+
+ Statement statement = connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+ ResultSet results = statement.executeQuery( QUERY );
+
+ if ( results != null )
+ {
+ makeSuccess( s );
+ ResultSetMetaData resultsMetaData = results.getMetaData();
+ ec.addElement( DatabaseUtilities.writeTable( results, resultsMetaData ) );
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error generating " + this.getClass().getName() );
+ e.printStackTrace();
+ }
+
+ return ( ec );
+ }
+
+
+ /**
+ * Gets the category attribute of the UserAdminScreen object
+ *
+ * @return The category value
+ */
+ protected Category getDefaultCategory()
+ {
+ return ADMIN_FUNCTIONS;
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(1000);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the role attribute of the UserAdminScreen object
+ *
+ * @return The role value
+ */
+ public String getRole()
+ {
+ return HACKED_ADMIN_ROLE;
+ }
+
+
+ /**
+ * Gets the title attribute of the UserAdminScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "User Information" );
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/admin/ViewDatabase.java b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/ViewDatabase.java
new file mode 100644
index 000000000..59afa59f7
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/ViewDatabase.java
@@ -0,0 +1,147 @@
+package org.owasp.webgoat.lessons.admin;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import org.owasp.webgoat.lessons.*;
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.StringElement;
+import org.apache.ecs.html.Input;
+import org.owasp.webgoat.session.*;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public class ViewDatabase extends LessonAdapter
+{
+ private final static String SQL = "sql";
+ private static Connection connection = null;
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ try
+ {
+ ec.addElement( new StringElement( "Enter a SQL statement: " ) );
+
+ StringBuffer sqlStatement = new StringBuffer( s.getParser().getRawParameter( SQL, "" ) );
+ Input input = new Input( Input.TEXT, SQL, sqlStatement.toString() );
+ ec.addElement( input );
+
+ Element b = ECSFactory.makeButton( "Go!" );
+ ec.addElement( b );
+
+ if ( connection == null )
+ {
+ connection = DatabaseUtilities.makeConnection( s );
+ }
+
+ if(sqlStatement.length() > 0)
+ {
+
+ Statement statement = connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+ ResultSet results = statement.executeQuery( sqlStatement.toString() );
+
+ if ( ( results != null ) && ( results.first() == true ) )
+ {
+ makeSuccess( s );
+ ResultSetMetaData resultsMetaData = results.getMetaData();
+ ec.addElement( DatabaseUtilities.writeTable( results, resultsMetaData ) );
+ }
+
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error generating " + this.getClass().getName() );
+ e.printStackTrace();
+ }
+
+ return ( ec );
+ }
+
+ /**
+ * Gets the category attribute of the DatabaseScreen object
+ *
+ * @return The category value
+ */
+ protected Category getDefaultCategory()
+ {
+ return ADMIN_FUNCTIONS;
+ }
+
+ private final static Integer DEFAULT_RANKING = new Integer(1000);
+
+ protected Integer getDefaultRanking()
+ {
+ return DEFAULT_RANKING;
+ }
+
+ /**
+ * Gets the hints attribute of the DatabaseScreen object
+ *
+ * @return The hints value
+ */
+ protected List getHints()
+ {
+ List hints = new ArrayList();
+ hints.add( "There are no hints defined" );
+
+ return hints;
+ }
+
+
+ /**
+ * Gets the instructions attribute of the ViewDatabase object
+ *
+ * @return The instructions value
+ */
+ public String getInstructions(WebSession s)
+ {
+ String instructions = "Please post a message to to the WebGoat forum. Your messages will be available for everyone to read.";
+
+ return ( instructions );
+ }
+
+
+ /**
+ * Gets the role attribute of the ViewDatabase object
+ *
+ * @return The role value
+ */
+ public String getRole()
+ {
+ return HACKED_ADMIN_ROLE;
+ }
+
+
+ /**
+ * Gets the title attribute of the DatabaseScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "Database Dump" );
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/admin/WelcomeAdminScreen.java b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/WelcomeAdminScreen.java
new file mode 100644
index 000000000..93d83a03f
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/admin/WelcomeAdminScreen.java
@@ -0,0 +1,67 @@
+package org.owasp.webgoat.lessons.admin;
+
+import org.owasp.webgoat.lessons.WelcomeScreen;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.html.Center;
+import org.apache.ecs.html.H1;
+import org.owasp.webgoat.session.WebSession;
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public class WelcomeAdminScreen extends WelcomeScreen
+{
+ /**
+ * Constructor for the WelcomeAdminScreen object
+ *
+ * @param s Description of the Parameter
+ */
+ public WelcomeAdminScreen( WebSession s )
+ {
+ super( s );
+ }
+
+
+ /**
+ * Constructor for the WelcomeAdminScreen object
+ */
+ public WelcomeAdminScreen() { }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( WebSession s )
+ {
+ ElementContainer ec = new ElementContainer();
+
+ ec.addElement( new Center( new H1( "You are logged on as an administrator" ) ) );
+ ec.addElement( super.createContent( s ) );
+
+ return ( ec );
+ }
+
+
+ /**
+ * Gets the title attribute of the WelcomeAdminScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "Admin Welcome" );
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/CrossSiteScripting/FindProfile_i.java b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/CrossSiteScripting/FindProfile_i.java
new file mode 100644
index 000000000..3d2c04768
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/CrossSiteScripting/FindProfile_i.java
@@ -0,0 +1,57 @@
+package org.owasp.webgoat.lessons.instructor.CrossSiteScripting;
+
+
+import java.util.regex.Pattern;
+
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.LessonAction;
+import org.owasp.webgoat.lessons.CrossSiteScripting.FindProfile;
+import org.owasp.webgoat.session.ParameterNotFoundException;
+import org.owasp.webgoat.session.ValidationException;
+import org.owasp.webgoat.session.WebSession;
+
+/* STAGE 5 FIXES
+Solution Summary: Edit FindProfile.java and change getRequestParameter().
+ Modify getRequestParameter() with lines denoted by // STAGE 5 - FIX.
+Solution Steps:
+1. Talk about the different parser methods. We could have used the parser method that takes a regular expression.
+2. Call validate on the request parameter.
+ return validate(s.getParser().getRawParameter(name), (Pattern) patterns.get(name));
+
+ Note: patterns.get(name) is used to fetch the XSS validation pattern that is defined
+ in FindProfile.Java
+
+ protected static Map patterns = new HashMap();
+ static
+ {
+ patterns.put(CrossSiteScripting.SEARCHNAME, Pattern.compile("[a-zA-Z ]{0,20}"));
+ }
+
+*/
+
+public class FindProfile_i extends FindProfile
+{
+ public FindProfile_i(AbstractLesson lesson, String lessonName, String actionName, LessonAction chainedAction)
+ {
+ super(lesson, lessonName, actionName, chainedAction);
+ }
+
+ protected String getRequestParameter(WebSession s, String name)
+ throws ParameterNotFoundException, ValidationException
+ {
+ // NOTE:
+ //
+ // In order for this to work generically, the name of the parameter and the name
+ // of the regular expression validation patter must be the same.
+ //
+ // Another way this could be done is to use the reguler expression method in the
+ // ParameterParser class
+
+ // STAGE 5 - FIX
+ return validate(s.getParser().getRawParameter(name), (Pattern) patterns.get(name));
+
+ // Note the design goal here...
+ //return s.getParser().getStringParameter(name), (Pattern) patterns.get(name));
+ }
+
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/CrossSiteScripting/UpdateProfile_i.java b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/CrossSiteScripting/UpdateProfile_i.java
new file mode 100644
index 000000000..b36434dcc
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/CrossSiteScripting/UpdateProfile_i.java
@@ -0,0 +1,109 @@
+package org.owasp.webgoat.lessons.instructor.CrossSiteScripting;
+
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.LessonAction;
+import org.owasp.webgoat.lessons.CrossSiteScripting.CrossSiteScripting;
+import org.owasp.webgoat.lessons.CrossSiteScripting.UpdateProfile;
+import org.owasp.webgoat.session.Employee;
+import org.owasp.webgoat.session.ParameterNotFoundException;
+import org.owasp.webgoat.session.ParameterParser;
+import org.owasp.webgoat.session.ValidationException;
+import org.owasp.webgoat.session.WebSession;
+
+/* STAGE 2 FIXES
+Solution Summary: Edit UpdateProfile.java and change parseEmployeeProfile().
+ Modify parseEmployeeProfile() with lines denoted by // STAGE 2 - FIX.
+Solution Steps:
+1. Talk about the different parser methods.
+ a. parseEmployeeProfile(subjectId, s.getRequest())
+ - uses the request object directly.
+ - calling validate() on the appropriate parameter
+ b. parseEmployeeProfile(subjectId, s.getParser())
+ - uses the parser object to pull request data (centralized mechanism)
+
+2. Fix the request object version of the call // STAGE 2 - FIX
+ Replace the call to:
+ String address1 = request.getParameter(CrossSiteScripting.ADDRESS1);
+
+ With:
+ final Pattern PATTERN_ADDRESS1 = Pattern.compile("[a-zA-Z0-9,\\.\\- ]{0,80}"); // STAGE 2 - FIX
+ String address1 = validate(request.getParameter(CrossSiteScripting.ADDRESS1), PATTERN_ADDRESS1); // STAGE 2 - FIX
+
+
+3. Fix the parser version of the call. // STAGE 2 - ALTERNATE FIX
+ Change all calls in parseEmployeeProfile(subjectId, s.getParser()) to use
+ the appropriate parser.method() call
+*/
+
+public class UpdateProfile_i extends UpdateProfile
+{
+ public UpdateProfile_i(AbstractLesson lesson, String lessonName, String actionName, LessonAction chainedAction)
+ {
+ super(lesson, lessonName, actionName, chainedAction);
+ }
+
+
+ protected Employee parseEmployeeProfile(int subjectId, WebSession s) throws ParameterNotFoundException, ValidationException
+ {
+ HttpServletRequest request = s.getRequest();
+ String firstName = request.getParameter(CrossSiteScripting.FIRST_NAME);
+ String lastName = request.getParameter(CrossSiteScripting.LAST_NAME);
+ String ssn = request.getParameter(CrossSiteScripting.SSN);
+ String title = request.getParameter(CrossSiteScripting.TITLE);
+ String phone = request.getParameter(CrossSiteScripting.PHONE_NUMBER);
+
+ // Validate this parameter against a regular expression pattern designed for street addresses.
+ final Pattern PATTERN_ADDRESS1 = Pattern.compile("[a-zA-Z0-9,\\.\\- ]{0,80}"); // STAGE 2 - FIX
+ String address1 = validate(request.getParameter(CrossSiteScripting.ADDRESS1), PATTERN_ADDRESS1); // STAGE 2 - FIX
+
+ String address2 = request.getParameter(CrossSiteScripting.ADDRESS2);
+ int manager = Integer.parseInt(request.getParameter(CrossSiteScripting.MANAGER));
+ String startDate = request.getParameter(CrossSiteScripting.START_DATE);
+ int salary = Integer.parseInt(request.getParameter(CrossSiteScripting.SALARY));
+ String ccn = request.getParameter(CrossSiteScripting.CCN);
+ int ccnLimit = Integer.parseInt(request.getParameter(CrossSiteScripting.CCN_LIMIT));
+ String disciplinaryActionDate = request.getParameter(CrossSiteScripting.DISCIPLINARY_DATE);
+ String disciplinaryActionNotes = request.getParameter(CrossSiteScripting.DISCIPLINARY_NOTES);
+ String personalDescription = request.getParameter(CrossSiteScripting.DESCRIPTION);
+
+ Employee employee = new Employee(subjectId, firstName, lastName, ssn, title, phone,
+ address1, address2, manager, startDate, salary,
+ ccn, ccnLimit, disciplinaryActionDate, disciplinaryActionNotes,
+ personalDescription);
+
+ return employee;
+ }
+
+ protected Employee parseEmployeeProfile(int subjectId, ParameterParser parser)
+ throws ParameterNotFoundException, ValidationException
+ {
+ // STAGE 2 - ALTERNATE FIX
+ String firstName = parser.getStrictAlphaParameter(CrossSiteScripting.FIRST_NAME, 20);
+ String lastName = parser.getStrictAlphaParameter(CrossSiteScripting.LAST_NAME, 20);
+ String ssn = parser.getSsnParameter(CrossSiteScripting.SSN);
+ String title = parser.getStrictAlphaParameter(CrossSiteScripting.TITLE, 20);
+ String phone = parser.getPhoneParameter(CrossSiteScripting.PHONE_NUMBER);
+ String address1 = parser.getStringParameter(CrossSiteScripting.ADDRESS1);
+ String address2 = parser.getStringParameter(CrossSiteScripting.ADDRESS2);
+ int manager = parser.getIntParameter(CrossSiteScripting.MANAGER);
+ String startDate = parser.getDateParameter(CrossSiteScripting.START_DATE);
+ int salary = parser.getIntParameter(CrossSiteScripting.SALARY);
+ String ccn = parser.getCcnParameter(CrossSiteScripting.CCN);
+ int ccnLimit = parser.getIntParameter(CrossSiteScripting.CCN_LIMIT);
+ String disciplinaryActionDate = parser.getDateParameter(CrossSiteScripting.DISCIPLINARY_DATE);
+ String disciplinaryActionNotes = parser.getStrictAlphaParameter(CrossSiteScripting.DISCIPLINARY_NOTES, 60);
+ String personalDescription = parser.getStrictAlphaParameter(CrossSiteScripting.DESCRIPTION, 60);
+
+ Employee employee = new Employee(subjectId, firstName, lastName, ssn, title, phone,
+ address1, address2, manager, startDate, salary,
+ ccn, ccnLimit, disciplinaryActionDate, disciplinaryActionNotes,
+ personalDescription);
+
+ return employee;
+ }
+
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/CrossSiteScripting/ViewProfile_i.java b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/CrossSiteScripting/ViewProfile_i.java
new file mode 100644
index 000000000..7fcf7334c
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/CrossSiteScripting/ViewProfile_i.java
@@ -0,0 +1,19 @@
+package org.owasp.webgoat.lessons.instructor.CrossSiteScripting;
+
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.CrossSiteScripting.ViewProfile;
+
+/* STAGE 4 FIXES
+Solution Summary: Look in the WebContent/lesson/CrossSiteScripting/ViewProfile.jsp
+
+Look for the <-- STAGE 4 - FIX in the ViewProfile.jsp
+
+*/
+
+public class ViewProfile_i extends ViewProfile
+{
+ public ViewProfile_i(AbstractLesson lesson, String lessonName, String actionName)
+ {
+ super(lesson, lessonName, actionName);
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/DeleteProfile_i.java b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/DeleteProfile_i.java
new file mode 100644
index 000000000..5a50b38a8
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/DeleteProfile_i.java
@@ -0,0 +1,55 @@
+package org.owasp.webgoat.lessons.instructor.RoleBasedAccessControl;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.LessonAction;
+import org.owasp.webgoat.lessons.RoleBasedAccessControl.DeleteProfile;
+import org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl;
+import org.owasp.webgoat.session.UnauthorizedException;
+import org.owasp.webgoat.session.WebSession;
+
+public class DeleteProfile_i extends DeleteProfile
+{
+
+
+ public DeleteProfile_i(AbstractLesson lesson, String lessonName, String actionName, LessonAction chainedAction)
+ {
+ super(lesson, lessonName, actionName, chainedAction);
+ }
+
+ public void doDeleteEmployeeProfile(WebSession s, int userId, int employeeId)
+ throws UnauthorizedException
+ {
+ if (s.isAuthorizedInLesson(userId, RoleBasedAccessControl.DELETEPROFILE_ACTION)) // FIX
+ {
+ try
+ {
+ String query = "DELETE FROM employee WHERE userid = " + employeeId;
+ //System.out.println("Query: " + query);
+ try
+ {
+ Statement statement = RoleBasedAccessControl.getConnection(s).createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+ statement.executeUpdate(query);
+ }
+ catch ( SQLException sqle )
+ {
+ s.setMessage( "Error deleting employee profile" );
+ sqle.printStackTrace();
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error deleting employee profile" );
+ e.printStackTrace();
+ }
+ }
+ else
+ {
+ throw new UnauthorizedException(); // FIX
+ }
+ }
+
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/EditProfile_i.java b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/EditProfile_i.java
new file mode 100644
index 000000000..6f15af162
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/EditProfile_i.java
@@ -0,0 +1,102 @@
+package org.owasp.webgoat.lessons.instructor.RoleBasedAccessControl;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.RoleBasedAccessControl.EditProfile;
+import org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl;
+import org.owasp.webgoat.lessons.SQLInjection.SQLInjection;
+import org.owasp.webgoat.session.Employee;
+import org.owasp.webgoat.session.UnauthorizedException;
+import org.owasp.webgoat.session.WebSession;
+
+/**
+ * Copyright (c) 2006 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ */
+
+/*************************************************/
+/* */
+/* This file is not currently used in the course */
+/* */
+/*************************************************/
+
+public class EditProfile_i extends EditProfile
+{
+ public EditProfile_i(AbstractLesson lesson, String lessonName, String actionName)
+ {
+ super(lesson, lessonName, actionName);
+ }
+
+ public Employee getEmployeeProfile(WebSession s, int userId, int subjectUserId)
+ throws UnauthorizedException
+ {
+ // Query the database to determine if this employee has access to this function
+ // Query the database for the profile data of the given employee if "owned" by the given user
+
+ Employee profile = null;
+
+ if (s.isAuthorizedInLesson(userId, RoleBasedAccessControl.EDITPROFILE_ACTION)) // FIX
+ {
+ // Query the database for the profile data of the given employee
+ try
+ {
+ String query = "SELECT * FROM employee WHERE userid = ?";
+
+ try
+ {
+ PreparedStatement answer_statement = SQLInjection.getConnection(s).prepareStatement( query,
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+ answer_statement.setInt(1, subjectUserId);
+ ResultSet answer_results = answer_statement.executeQuery();
+ if (answer_results.next())
+ {
+ // Note: Do NOT get the password field.
+ profile = new Employee(
+ answer_results.getInt("userid"),
+ answer_results.getString("first_name"),
+ answer_results.getString("last_name"),
+ answer_results.getString("ssn"),
+ answer_results.getString("title"),
+ answer_results.getString("phone"),
+ answer_results.getString("address1"),
+ answer_results.getString("address2"),
+ answer_results.getInt("manager"),
+ answer_results.getString("start_date"),
+ answer_results.getInt("salary"),
+ answer_results.getString("ccn"),
+ answer_results.getInt("ccn_limit"),
+ answer_results.getString("disciplined_date"),
+ answer_results.getString("disciplined_notes"),
+ answer_results.getString("personal_description"));
+/* System.out.println("Retrieved employee from db: " +
+ profile.getFirstName() + " " + profile.getLastName() +
+ " (" + profile.getId() + ")");
+*/ }
+ }
+ catch ( SQLException sqle )
+ {
+ s.setMessage( "Error getting employee profile" );
+ sqle.printStackTrace();
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error getting employee profile" );
+ e.printStackTrace();
+ }
+ }
+ else
+ {
+ throw new UnauthorizedException(); // FIX
+ }
+
+ return profile;
+ }
+
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/RoleBasedAccessControl_i.java b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/RoleBasedAccessControl_i.java
new file mode 100644
index 000000000..a14a8a62a
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/RoleBasedAccessControl_i.java
@@ -0,0 +1 @@
+package org.owasp.webgoat.lessons.instructor.RoleBasedAccessControl;
import org.apache.ecs.ElementContainer;
import org.owasp.webgoat.lessons.LessonAction;
import org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl;
import org.owasp.webgoat.session.ParameterNotFoundException;
import org.owasp.webgoat.session.UnauthenticatedException;
import org.owasp.webgoat.session.UnauthorizedException;
import org.owasp.webgoat.session.ValidationException;
import org.owasp.webgoat.session.WebSession;
/**
* Copyright (c) 2006 Free Software Foundation developed under the custody of the Open Web
* Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
* under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
* this software.
*
*/
/* STAGE 2 FIXES
Solution Summary: Edit RoleBasedAccessControl.java and change handleRequest().
Modify handleRequest() with lines denoted by // STAGE 2 - FIX.
Solution Steps:
1. This solution adds an access control check in the controller.
Point out that their architecture may require the check to occur in the business function.
2. Look at the RoleBasedAccessControl class identify where execution happens of an action.
a. action.handleRequest(s); is not protected by an access control check.
b. look at handleRequest(s) to determine where access control check should occur.
c. add protection by a programmatic authorization check before dispatching to the action:
1. Add an isAuthorized() call before dispatching to the action,
and throw an unauthorized exception. Tell student this exception exists.
Use eclipse command completion to find the isAuthorized() call on the action.
From command completion - determine calling arguments of isAuthorized()
int userId = action.getUserId(s);
if (action.isAuthorized(s, userId, action.getActionName()))
{
action.handleRequest(s);
}
else
throw new UnauthorizedException();
Repeat stage 1 and note that the function fails with a "Not authorized" message.
Tom will be in the list again, because the DB is reset when lesson restarts.
Adding the access check in the RoleBasedAccessControl:handleRequest() is putting the check in the “Controller”
The access check can also be added to DeleteProfile.deleteEmployeeProfile(), which is putting the check in the “Business Function”
*/
public class RoleBasedAccessControl_i extends RoleBasedAccessControl
{
public void handleRequest(WebSession s)
{
//System.out.println("RoleBasedAccessControl.handleRequest()");
if (s.getLessonSession(this) == null)
s.openLessonSession(this);
String requestedActionName = null;
try
{
requestedActionName = s.getParser().getStringParameter("action");
}
catch (ParameterNotFoundException pnfe)
{
// Missing the action - send them back to login.
requestedActionName = LOGIN_ACTION;
}
try
{
LessonAction action = getAction(requestedActionName);
if (action != null)
{
// FIXME: This code has gotten much uglier
//System.out.println("RoleBasedAccessControl.handleRequest() dispatching to: " + action.getActionName());
if (!action.requiresAuthentication())
{
// Access to Login does not require authentication.
action.handleRequest(s);
}
else
{
if (action.isAuthenticated(s))
{
int userId = action.getUserId(s); // STAGE 2 - FIX
// action.getActionName() returns the user requested function which
// is tied to the button click from the listStaff jsp
//
// Checking isAuthorized() for the requested action
if (action.isAuthorized(s, userId, action.getActionName())) // STAGE 2 - FIX
{
// Calling the handleRequest() method for the requested action
action.handleRequest(s);
}
else
throw new UnauthorizedException(); // STAGE 2 - FIX
}
else
throw new UnauthenticatedException();
}
}
else
setCurrentAction(s, ERROR_ACTION);
}
catch (ParameterNotFoundException pnfe)
{
System.out.println("Missing parameter");
pnfe.printStackTrace();
setCurrentAction(s, ERROR_ACTION);
}
catch (ValidationException ve)
{
System.out.println("Validation failed");
ve.printStackTrace();
setCurrentAction(s, ERROR_ACTION);
}
catch (UnauthenticatedException ue)
{
s.setMessage("Login failed");
System.out.println("Authentication failure");
ue.printStackTrace();
}
catch (UnauthorizedException ue2)
{
s.setMessage("You are not authorized to perform this function");
System.out.println("Authorization failure");
setCurrentAction(s, ERROR_ACTION);
ue2.printStackTrace();
}
// All this does for this lesson is ensure that a non-null content exists.
setContent(new ElementContainer());
}
}
\ No newline at end of file
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/UpdateProfile_i.java b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/UpdateProfile_i.java
new file mode 100644
index 000000000..7167a3bee
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/UpdateProfile_i.java
@@ -0,0 +1,138 @@
+package org.owasp.webgoat.lessons.instructor.RoleBasedAccessControl;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.LessonAction;
+import org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl;
+import org.owasp.webgoat.lessons.RoleBasedAccessControl.UpdateProfile;
+import org.owasp.webgoat.session.Employee;
+import org.owasp.webgoat.session.UnauthorizedException;
+import org.owasp.webgoat.session.WebSession;
+
+/**
+ * Copyright (c) 2006 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ */
+
+/*************************************************/
+/* */
+/* This file is not currently used in the course */
+/* */
+/*************************************************/
+
+
+public class UpdateProfile_i extends UpdateProfile
+{
+ public UpdateProfile_i(AbstractLesson lesson, String lessonName, String actionName, LessonAction chainedAction)
+ {
+ super(lesson, lessonName, actionName, chainedAction);
+ }
+
+ public void changeEmployeeProfile(WebSession s, int userId, int subjectId, Employee employee)
+ throws UnauthorizedException
+ {
+ if (s.isAuthorizedInLesson(userId, RoleBasedAccessControl.UPDATEPROFILE_ACTION)) // FIX
+ {
+ try
+ {
+ // Note: The password field is ONLY set by ChangePassword
+ String query = "UPDATE employee SET first_name = '" + employee.getFirstName() +
+ "', last_name = '" + employee.getLastName() +
+ "', ssn = '" + employee.getSsn() +
+ "', title = '" + employee.getTitle() +
+ "', phone = '" + employee.getPhoneNumber() +
+ "', address1 = '" + employee.getAddress1() +
+ "', address2 = '" + employee.getAddress2() +
+ "', manager = " + employee.getManager() +
+ ", start_date = '" + employee.getStartDate() +
+ "', ccn = '" + employee.getCcn() +
+ "', ccn_limit = " + employee.getCcnLimit() +
+ // "', disciplined_date = '" + employee.getDisciplinaryActionDate() +
+ // "', disciplined_notes = '" + employee.getDisciplinaryActionNotes() +
+ ", personal_description = '" + employee.getPersonalDescription() +
+ "' WHERE userid = " + subjectId;
+ //System.out.println("Query: " + query);
+ try
+ {
+ Statement answer_statement = RoleBasedAccessControl.getConnection(s).createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+ ResultSet answer_results = answer_statement.executeQuery( query );
+ }
+ catch ( SQLException sqle )
+ {
+ s.setMessage( "Error updating employee profile" );
+ sqle.printStackTrace();
+ }
+
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error updating employee profile" );
+ e.printStackTrace();
+ }
+ }
+ else
+ {
+ throw new UnauthorizedException(); // FIX
+ }
+ }
+
+
+ public void createEmployeeProfile(WebSession s, int userId, Employee employee)
+ throws UnauthorizedException
+ {
+ if (s.isAuthorizedInLesson(userId, RoleBasedAccessControl.UPDATEPROFILE_ACTION)) // FIX
+ {
+ try
+ {
+ // FIXME: Cannot choose the id because we cannot guarantee uniqueness
+ String query = "INSERT INTO employee VALUES ( max(userid)+1, '"
+ + employee.getFirstName() + "','"
+ + employee.getLastName() + "','"
+ + employee.getSsn() + "','"
+ + employee.getFirstName().toLowerCase() + "','"
+ + employee.getTitle() + "','"
+ + employee.getPhoneNumber() + "','"
+ + employee.getAddress1() + "','"
+ + employee.getAddress2() + "',"
+ + employee.getManager() + ",'"
+ + employee.getStartDate() + "',"
+ + employee.getSalary() + ",'"
+ + employee.getCcn() + "',"
+ + employee.getCcnLimit() + ",'"
+ + employee.getDisciplinaryActionDate() + "','"
+ + employee.getDisciplinaryActionNotes() + "','"
+ + employee.getPersonalDescription()
+ + "')";
+
+ //System.out.println("Query: " + query);
+
+ try
+ {
+ Statement statement = RoleBasedAccessControl.getConnection(s).createStatement();
+ statement.executeUpdate(query);
+ }
+ catch ( SQLException sqle )
+ {
+ s.setMessage( "Error updating employee profile" );
+ sqle.printStackTrace();
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error updating employee profile" );
+ e.printStackTrace();
+ }
+ }
+ else
+ {
+ throw new UnauthorizedException(); // FIX
+ }
+ }
+
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/ViewProfile_i.java b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/ViewProfile_i.java
new file mode 100644
index 000000000..17203c57b
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/RoleBasedAccessControl/ViewProfile_i.java
@@ -0,0 +1,132 @@
+package org.owasp.webgoat.lessons.instructor.RoleBasedAccessControl;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl;
+import org.owasp.webgoat.lessons.RoleBasedAccessControl.ViewProfile;
+import org.owasp.webgoat.session.Employee;
+import org.owasp.webgoat.session.UnauthorizedException;
+import org.owasp.webgoat.session.WebSession;
+
+/* STAGE 4 FIXES
+1. Find the code location where this flaw of directly retrieving the profile without data-level access control checking exists:
+ public void handleRequest( WebSession s )
+ { …
+ Employee employee = getEmployeeProfile(s, userId, employeeId);
+ … }
+ public Employee getEmployeeProfile(WebSession s, int employeeId, int subjectUserId) throws UnauthorizedException { …
+ return getEmployeeProfile(s, employeeId, subjectUserId);
+ … }
+2. The solution requires a data-level access control check to ensure the user has the rights to access the data they are requesting.
+ a. There is a common method you can take advantage of:
+ isAuthorizedForEmployee(s, userId, subjectUserId)
+ Either tell the student this exists or have them look in DefaultLessonAction.
+ Note that this is not required to implement data access control but is for detection of violations.
+ b. Uncomment the modified query retrieving the user data to have data access control
+ String query = "SELECT * FROM employee,ownership WHERE employee.userid = ownership.employee_id and " +
+ "ownership.employer_id = " + userId + " and ownership.employee_id = " + subjectUserId;
+3. Bundle the entire logic with this call and throw an unauthorized exception
+ if (isAuthorizedForEmployee(s, userId, subjectUserId))
+ { ...
+ //String query = "SELECT * FROM employee WHERE userid = " + subjectUserId;
+ String query = "SELECT * FROM employee,ownership WHERE employee.userid = ownership.employee_id and " +
+ "ownership.employer_id = " + userId + " and ownership.employee_id = " + subjectUserId; // STAGE 4 - FIX
+ ...
+ }
+ else
+ {
+ throw new UnauthorizedException();
+ }
+4. Repeat stage 3 and note that the function fails with a "Not authorized" message.
+Adding the access check in the query is providing data-level access control.
+The access check from isAuthorizedForEmployee is used to detect a violation.
+The same logic could've been applied after the query but isAuthorizedForEmployee provides a nice centralized abstraction of that logic.
+*/
+
+public class ViewProfile_i extends ViewProfile
+{
+ public ViewProfile_i(AbstractLesson lesson, String lessonName, String actionName)
+ {
+ super(lesson, lessonName, actionName);
+ }
+
+
+ public Employee getEmployeeProfile(WebSession s, int userId, int subjectUserId)
+ throws UnauthorizedException
+ {
+ // Query the database to determine if the given employee is owned by the given user
+ // Query the database for the profile data of the given employee
+
+ Employee profile = null;
+
+ // isAuthorizedForEmployee() allows us to determine authorization violations
+
+ if (isAuthorizedForEmployee(s, userId, subjectUserId)) // STAGE 4 - (ALTERNATE) FIX
+ {
+ // Query the database for the profile data of the given employee
+ try
+ {
+ //String query = "SELECT * FROM employee WHERE userid = " + subjectUserId; // STAGE 4 - FIX
+
+ // Switch to this query to add Data Access Control
+ //
+ // Join employee and ownership to get all valid record combinations
+ // - qualify on ownership.employer_id to see only the current userId records
+ // - qualify on ownership.employee_id to see the current selected employee profile
+
+ String query = "SELECT * FROM employee,ownership WHERE employee.userid = ownership.employee_id and " +
+ "ownership.employer_id = " + userId + " and ownership.employee_id = " + subjectUserId; // STAGE 4 - FIX
+
+ try
+ {
+ Statement answer_statement = RoleBasedAccessControl.getConnection(s).createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+ ResultSet answer_results = answer_statement.executeQuery( query );
+ if (answer_results.next())
+ {
+ // Note: Do NOT get the password field.
+ profile = new Employee(
+ answer_results.getInt("userid"),
+ answer_results.getString("first_name"),
+ answer_results.getString("last_name"),
+ answer_results.getString("ssn"),
+ answer_results.getString("title"),
+ answer_results.getString("phone"),
+ answer_results.getString("address1"),
+ answer_results.getString("address2"),
+ answer_results.getInt("manager"),
+ answer_results.getString("start_date"),
+ answer_results.getInt("salary"),
+ answer_results.getString("ccn"),
+ answer_results.getInt("ccn_limit"),
+ answer_results.getString("disciplined_date"),
+ answer_results.getString("disciplined_notes"),
+ answer_results.getString("personal_description"));
+/* System.out.println("Retrieved employee from db: " +
+ profile.getFirstName() + " " + profile.getLastName() +
+ " (" + profile.getId() + ")");
+*/ }
+ }
+ catch ( SQLException sqle )
+ {
+ s.setMessage( "Error getting employee profile" );
+ sqle.printStackTrace();
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error getting employee profile" );
+ e.printStackTrace();
+ }
+ }
+ else
+ {
+ throw new UnauthorizedException(); // STAGE 4 - ALTERNATE FIX
+ }
+
+ return profile;
+ }
+
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/SQLInjection/Login_i.java b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/SQLInjection/Login_i.java
new file mode 100644
index 000000000..c41c14b10
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/SQLInjection/Login_i.java
@@ -0,0 +1,80 @@
+package org.owasp.webgoat.lessons.instructor.SQLInjection;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.LessonAction;
+import org.owasp.webgoat.lessons.SQLInjection.Login;
+import org.owasp.webgoat.lessons.SQLInjection.SQLInjection;
+import org.owasp.webgoat.session.WebSession;
+
+/*
+Solution Summary: Edit Login.java and change login().
+ Modify login() with lines denoted by // STAGE 2 - FIX.
+Solution Steps:
+1. Change dynamic query to parameterized query.
+ a. Replace the dynamic varaibles with the "?"
+ String query = "SELECT * FROM employee WHERE userid = ? and password = ?"
+
+ b. Create a preparedStatement using the new query
+ PreparedStatement answer_statement = SQLInjection.getConnection(s).prepareStatement(
+ query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+
+ c. Set the values of the parameterized query
+ answer_statement.setString(1, userId); // STAGE 2 - FIX
+ answer_statement.setString(2, password); // STAGE 2 - FIX
+
+ d. Execute the preparedStatement
+ ResultSet answer_results = answer_statement.executeQuery();
+*/
+
+public class Login_i extends Login
+{
+ public Login_i(AbstractLesson lesson, String lessonName, String actionName, LessonAction chainedAction)
+ {
+ super(lesson, lessonName, actionName, chainedAction);
+ }
+
+ public boolean login(WebSession s, String userId, String password)
+ {
+ //System.out.println("Logging in to lesson");
+ boolean authenticated = false;
+
+ try
+ {
+ String query = "SELECT * FROM employee WHERE userid = ? and password = ?"; // STAGE 2 - FIX
+
+ try
+ {
+ PreparedStatement answer_statement = SQLInjection.getConnection(s).prepareStatement( query,
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); // STAGE 2 - FIX
+ answer_statement.setString(1, userId); // STAGE 2 - FIX
+ answer_statement.setString(2, password); // STAGE 2 - FIX
+ ResultSet answer_results = answer_statement.executeQuery(); // STAGE 2 - FIX
+ if (answer_results.first())
+ {
+ setSessionAttribute(s, getLessonName() + ".isAuthenticated", Boolean.TRUE);
+ setSessionAttribute(s, getLessonName() + "." + SQLInjection.USER_ID, userId);
+ authenticated = true;
+ }
+
+ }
+ catch ( SQLException sqle )
+ {
+ s.setMessage( "Error logging in" );
+ sqle.printStackTrace();
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error logging in" );
+ e.printStackTrace();
+ }
+
+ //System.out.println("Lesson login result: " + authenticated);
+ return authenticated;
+ }
+
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/SQLInjection/ViewProfile_i.java b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/SQLInjection/ViewProfile_i.java
new file mode 100644
index 000000000..e2d80701d
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/lessons/instructor/SQLInjection/ViewProfile_i.java
@@ -0,0 +1,99 @@
+package org.owasp.webgoat.lessons.instructor.SQLInjection;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.SQLInjection.SQLInjection;
+import org.owasp.webgoat.lessons.SQLInjection.ViewProfile;
+import org.owasp.webgoat.session.Employee;
+import org.owasp.webgoat.session.UnauthorizedException;
+import org.owasp.webgoat.session.WebSession;
+
+/*
+Solution Summary: Edit ViewProfile.java and change getEmployeeProfile().
+ Modify getEmployeeProfile() with lines denoted by // STAGE 4 - FIX.
+
+Solution Steps:
+1. Change dynamic query to parameterized query.
+ a. Replace the dynamic varaibles with the "?"
+ String query = "SELECT * FROM employee WHERE userid = ?";
+
+ b. Create a preparedStatement using the new query
+ PreparedStatement answer_statement = SQLInjection.getConnection(s).prepareStatement(
+ query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+
+ c. Set the values of the parameterized query
+ answer_statement.setInt(1, Integer.parseInt(subjectUserId));
+
+ d. Execute the preparedStatement
+ ResultSet answer_results = answer_statement.executeQuery();
+*/
+
+public class ViewProfile_i extends ViewProfile
+{
+ public ViewProfile_i(AbstractLesson lesson, String lessonName, String actionName)
+ {
+ super(lesson, lessonName, actionName);
+ }
+
+ public Employee getEmployeeProfile(WebSession s, String userId, String subjectUserId)
+ throws UnauthorizedException
+ {
+ // Query the database to determine if this employee has access to this function
+ // Query the database for the profile data of the given employee if "owned" by the given user
+
+ Employee profile = null;
+
+ try
+ {
+ String query = "SELECT * FROM employee WHERE userid = ?"; // STAGE 4 - FIX
+
+ try
+ {
+ PreparedStatement answer_statement = SQLInjection.getConnection(s).prepareStatement( query,
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); // STAGE 4 - FIX
+ answer_statement.setInt(1, Integer.parseInt(subjectUserId)); // STAGE 4 - FIX
+ ResultSet answer_results = answer_statement.executeQuery(); // STAGE 4 - FIX
+ if (answer_results.next())
+ {
+ // Note: Do NOT get the password field.
+ profile = new Employee(
+ answer_results.getInt("userid"),
+ answer_results.getString("first_name"),
+ answer_results.getString("last_name"),
+ answer_results.getString("ssn"),
+ answer_results.getString("title"),
+ answer_results.getString("phone"),
+ answer_results.getString("address1"),
+ answer_results.getString("address2"),
+ answer_results.getInt("manager"),
+ answer_results.getString("start_date"),
+ answer_results.getInt("salary"),
+ answer_results.getString("ccn"),
+ answer_results.getInt("ccn_limit"),
+ answer_results.getString("disciplined_date"),
+ answer_results.getString("disciplined_notes"),
+ answer_results.getString("personal_description"));
+/* System.out.println("Retrieved employee from db: " +
+ profile.getFirstName() + " " + profile.getLastName() +
+ " (" + profile.getId() + ")");
+*/ }
+ }
+ catch ( SQLException sqle )
+ {
+ s.setMessage( "Error getting employee profile" );
+ sqle.printStackTrace();
+ }
+ }
+ catch ( Exception e )
+ {
+ s.setMessage( "Error getting employee profile" );
+ e.printStackTrace();
+ }
+
+ return profile;
+ }
+
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/servlets/Controller.java b/ webgoat/main/project/org/owasp/webgoat/servlets/Controller.java
new file mode 100644
index 000000000..5860d48ec
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/servlets/Controller.java
@@ -0,0 +1,32 @@
+package org.owasp.webgoat.servlets;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class Controller extends HttpServlet
+{
+
+ private static final long serialVersionUID = 1L;
+
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ doPost(request, response);
+ }
+
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ String userAgent = request.getHeader("user-agent");
+ String clientBrowser = "Not known!";
+ if (userAgent != null)
+ {
+ clientBrowser = userAgent;
+ }
+ request.setAttribute("client.browser", clientBrowser);
+ request.getRequestDispatcher("/view.jsp").forward(request, response);
+ }
+
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/Authorization.java b/ webgoat/main/project/org/owasp/webgoat/session/Authorization.java
new file mode 100644
index 000000000..bff0471f6
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/Authorization.java
@@ -0,0 +1,24 @@
+package org.owasp.webgoat.session;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+public class Authorization
+{
+ Map permissions = new Hashtable();
+
+ public Authorization()
+ {
+ }
+
+ public void setPermission(int userId, int functionId)
+ {
+ permissions.put(new Integer(userId), new Integer(functionId));
+ }
+
+ public boolean isAllowed(int userId, int functionId)
+ {
+ return (permissions.get(new Integer(userId)) != null);
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/Course.java b/ webgoat/main/project/org/owasp/webgoat/session/Course.java
new file mode 100644
index 000000000..934bef011
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/Course.java
@@ -0,0 +1,448 @@
+package org.owasp.webgoat.session;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.servlet.ServletContext;
+
+import org.owasp.webgoat.HammerHead;
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.Category;
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public class Course
+{
+ private List lessons = new ArrayList();
+ private final static String PROPERTIES_FILENAME = HammerHead.propertiesPath;
+ private WebgoatProperties properties = null;
+
+ public Course()
+ {
+ try
+ {
+ properties = new WebgoatProperties(PROPERTIES_FILENAME);
+ }
+ catch (IOException e)
+ {
+ System.out.println("Error loading WebGoat properties");
+ e.printStackTrace();
+ }
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param fileName Description of the Parameter
+ * @param path Description of the Parameter
+ * @param ext Description of the Parameter
+ * @return Description of the Return Value
+ */
+ private String clean( String fileName, String path, String ext )
+ {
+ fileName = fileName.trim();
+
+ // check if file is a directory
+ if ( fileName.endsWith( "/" ) )
+ {
+ return fileName;
+ }
+
+ // check if file is a class or java file
+ if ( !fileName.endsWith( ext ) )
+ {
+ return null;
+ }
+
+ // if the file is in /WEB-INF/classes strip the dir info off
+ int index = fileName.indexOf( "/WEB-INF/classes/" );
+ if ( index != -1 )
+ {
+ fileName = fileName.substring( index + "/WEB-INF/classes/".length(), fileName.length() - ext.length() );
+ fileName = fileName.replace( '/', '.' );
+ fileName = fileName.replace( '\\', '.' );
+ }
+ else
+ {
+ // Strip off the leading path info
+ fileName = fileName.substring( path.length(), fileName.length() - ext.length() );
+ }
+
+ return fileName;
+ }
+
+
+ /**
+ * Description of the Method
+ * @param lesson Description of the Parameter
+ * @param context Description of the Parameter
+ * @param path Description of the Parameter
+ * @param courseName Description of the Parameter
+ * @param extension TODO
+ */
+ private void findSourceResource( AbstractLesson lesson, ServletContext context, String path, String className, String extension )
+ {
+ //System.out.println("findSourceResource() looking for source files in: " + path);
+ //System.out.println("findSourceResource() looking for source files for class: " + className);
+ Set files = context.getResourcePaths( path );
+ Iterator fileIter = files.iterator();
+ String resource = null;
+
+ while ( fileIter.hasNext() )
+ {
+ resource = (String) fileIter.next();
+ //System.out.println("findSourceResource() inspecting resource: " + resource);
+ String lessonName = clean( resource, path, extension );
+ //System.out.println("findSourceResource() cleaned resource name: " + lessonName);
+ //if ( className != null )
+ //{
+ // System.out.println("Resource to check: " + resource);
+ // System.out.println("Lesson name: " + lessonName);
+ //}
+
+ // Not a match
+ if ( lessonName == null )
+ {
+ continue;
+ }
+ // A subdirectory
+ else if ( ( lessonName.length() != 1 ) && lessonName.endsWith( "/" ) )
+ {
+ findSourceResource( lesson, context, lessonName, className, extension );
+ }
+ // A source file
+ else
+ {
+ // Course name will be the fully qualified name:
+ // like lesson.admin.lessonName
+ if ( className.endsWith( lessonName ) )
+ {
+ int length = 0;
+ int index = className.indexOf("admin.");
+ if ( index == -1 )
+ {
+ index = className.indexOf("lessons.");
+ length = "lessons.".length();
+ }
+ else
+ {
+ length = "admin.".length();
+ }
+ className = className.substring(index + length);
+ //System.out.println("Resource to check: " + resource);
+ //System.out.println("Lesson name: " + lessonName);
+
+ //store the web path of the source file in the lesson
+ lesson.setSourceFileName(resource);
+
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Description of the Method
+ * @param lesson Description of the Parameter
+ * @param context Description of the Parameter
+ * @param path Description of the Parameter
+ * @param courseName Description of the Parameter
+ * @param extension TODO
+ */
+ private void findLessonPlanResource( AbstractLesson lesson, ServletContext context, String path, String courseName, String extension )
+ {
+ Set files = context.getResourcePaths( path );
+ Iterator fileIter = files.iterator();
+ String resource = null;
+
+ while ( fileIter.hasNext() )
+ {
+ resource = (String) fileIter.next();
+ String className = clean( resource, path, extension );
+ //if ( className != null )
+ //{
+ // System.out.println("ClassName: " + className);
+ // System.out.println("ResourceToCheck: " + resourceToCheck);
+ //}
+
+ if ( className == null )
+ {
+ continue;
+ }
+ else if ( ( className.length() != 1 ) && className.endsWith( "/" ) )
+ {
+ findLessonPlanResource( lesson, context, className, courseName, extension );
+ }
+ else
+ {
+ // Course name will be the fully qualified name:
+ // like lesson.admin.lessonName
+ if ( courseName.endsWith( className ) )
+ {
+ int length = 0;
+ int index = courseName.indexOf("admin.");
+ if ( index == -1 )
+ {
+ index = courseName.indexOf("lessons.");
+ length = "lessons.".length();
+ }
+ else
+ {
+ length = "admin.".length();
+ }
+ courseName = courseName.substring(index + length);
+ //System.out.println("ClassName: " + className);
+ //System.out.println("ResourceToCheck: " + resource);
+
+ //store the web path of the source file in the lesson
+ lesson.setLessonPlanFileName(resource);
+
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Gets the categories attribute of the Course object
+ *
+ * @return The categories value
+ */
+ public List getCategories()
+ {
+ List categories = new ArrayList();
+ Iterator iter = lessons.iterator();
+
+ while ( iter.hasNext() )
+ {
+ AbstractLesson lesson = (AbstractLesson) iter.next();
+
+ if ( !categories.contains( lesson.getCategory() ) )
+ {
+ categories.add( lesson.getCategory() );
+ }
+ }
+
+ Collections.sort( categories );
+
+ return categories;
+ }
+
+
+ /**
+ * Gets the firstLesson attribute of the Course object
+ *
+ * @return The firstLesson value
+ */
+ public AbstractLesson getFirstLesson()
+ {
+ List roles = new ArrayList();
+ roles.add( AbstractLesson.USER_ROLE );
+ // Category 0 is the admin function. We want the first real category
+ // to be returned. This is noramally the General category and the Http Basics lesson
+ return ((AbstractLesson)getLessons( (Category)getCategories().get(1), roles).get(0));
+ }
+
+
+ /**
+ * Gets the lesson attribute of the Course object
+ *
+ * @param lessonId Description of the Parameter
+ * @param role Description of the Parameter
+ * @return The lesson value
+ */
+ public AbstractLesson getLesson( WebSession s, int lessonId, List roles )
+ {
+ if (s.isHackedAdmin())
+ {
+ roles.add(AbstractLesson.HACKED_ADMIN_ROLE);
+ }
+ //System.out.println("getLesson() with roles: " + roles);
+ Iterator iter = lessons.iterator();
+
+ while ( iter.hasNext() )
+ {
+ AbstractLesson lesson = (AbstractLesson) iter.next();
+
+ //System.out.println("getLesson() at role: " + lesson.getRole());
+ if ( lesson.getScreenId() == lessonId && roles.contains(lesson.getRole()) )
+ {
+ return lesson;
+ }
+ }
+
+ return null;
+ }
+
+ public AbstractLesson getLesson( WebSession s, int lessonId, String role )
+ {
+ List roles = new Vector();
+ roles.add(role);
+ return getLesson(s, lessonId, roles);
+ }
+
+ public List getLessons( WebSession s, String role )
+ {
+ List roles = new Vector();
+ roles.add(role);
+ return getLessons(s, roles);
+ }
+
+ /**
+ * Gets the lessons attribute of the Course object
+ *
+ * @param role Description of the Parameter
+ * @return The lessons value
+ */
+ public List getLessons( WebSession s, List roles )
+ {
+ if (s.isHackedAdmin())
+ {
+ roles.add(AbstractLesson.HACKED_ADMIN_ROLE);
+ }
+ List lessonList = new ArrayList();
+ Iterator categoryIter = getCategories().iterator();
+
+ while ( categoryIter.hasNext() )
+ {
+ lessonList.addAll( getLessons( s, (Category) categoryIter.next(), roles ) );
+ }
+ return lessonList;
+ }
+
+
+ /**
+ * Gets the lessons attribute of the Course object
+ *
+ * @param category Description of the Parameter
+ * @param role Description of the Parameter
+ * @return The lessons value
+ */
+ private List getLessons( Category category, List roles )
+ {
+ List lessonList = new ArrayList();
+
+ Iterator iter = lessons.iterator();
+ while ( iter.hasNext() )
+ {
+ AbstractLesson lesson = (AbstractLesson) iter.next();
+
+ if ( lesson.getCategory().equals( category ) && roles.contains(lesson.getRole()) )
+ {
+ lessonList.add( lesson );
+ }
+ }
+
+ Collections.sort( lessonList );
+// System.out.println(java.util.Arrays.asList(lessonList));
+ return lessonList;
+ }
+
+ public List getLessons( WebSession s, Category category, String role )
+ {
+ List roles = new Vector();
+ roles.add(role);
+ return getLessons(s, category, roles);
+ }
+
+ public List getLessons(WebSession s, Category category, List roles)
+ {
+ if (s.isHackedAdmin())
+ {
+ roles.add(AbstractLesson.HACKED_ADMIN_ROLE);
+ }
+ return getLessons(category, roles);
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @param path Description of the Parameter
+ * @param context Description of the Parameter
+ */
+ public void loadCourses( boolean enterprise, ServletContext context, String path )
+ {
+ Set files = context.getResourcePaths( path );
+ Iterator fileIter = files.iterator();
+
+ while ( fileIter.hasNext() )
+ {
+ String file = (String) fileIter.next();
+ String className = clean( file, path, ".class" );
+
+ //if ( className != null )
+ //{
+ // System.out.println( "Checking file: " + file );
+ // System.out.println( " class: " + className );
+ //}
+ if ( className == null )
+ {
+ continue;
+ }
+ else if ( ( className.length() != 1 ) && className.endsWith( "/" ) )
+ {
+ loadCourses( enterprise, context, className );
+ }
+ else
+ {
+ Class lessonClass = null;
+ try
+ {
+ lessonClass = Class.forName( className );
+ Object possibleLesson = lessonClass.newInstance();
+
+ if ( possibleLesson instanceof AbstractLesson )
+ {
+ AbstractLesson lesson = (AbstractLesson) possibleLesson;
+
+ // Determine if the screen is to be loaded. Look
+ // to see if the session parameter has been initialized.
+ // Look to see if the screen is an enterprise edition screen.
+ if ( !enterprise )
+ {
+ if ( lesson.isEnterprise() )
+ {
+ continue;
+ }
+ }
+
+ // Do not load instructor screens. Currently, they must be manually deployed.
+ if (lesson.getClass().getName().indexOf("instructor") > -1)
+ continue;
+
+ // There are two methods instead of one because the developer was not
+ // smart enough to figure out the recursive return value
+ findSourceResource( lesson, context, "/", className, ".java" );
+ findLessonPlanResource( lesson, context, "/", className, ".html" );
+
+ // Override lesson attributes based on properties.
+ lesson.update(properties);
+
+ if(lesson.getHidden() == false)
+ lessons.add( lesson );
+ //System.out.println( "Found lesson: " + lesson );
+ }
+ }
+ catch ( Exception e )
+ {
+ //System.out.println("Could not load lesson: " + className);
+ //e.printStackTrace();
+ }
+ }
+ }
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/CreateDB.java b/ webgoat/main/project/org/owasp/webgoat/session/CreateDB.java
new file mode 100644
index 000000000..9006fa2bf
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/CreateDB.java
@@ -0,0 +1,852 @@
+package org.owasp.webgoat.session;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.owasp.webgoat.lessons.AbstractLesson;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of
+ * the Open Web Application Security Project (http://www.owasp.org) This
+ * software package org.owasp.webgoat.is published by OWASP under the GPL. You should read and
+ * accept the LICENSE before you use, modify and/or redistribute this
+ * software.
+ *
+ * @author Jeff Williams Aspect Security
+ */
+public class CreateDB
+{
+ /**
+ * The main program for the AccessSqlInjection class
+ *
+ * @param args The command line arguments
+ */
+ public static void main(String[] args)
+ {
+
+ CreateDB db = new CreateDB();
+ Connection connection = null;
+
+ try
+ {
+ Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
+ }
+ catch ( Exception e )
+ {
+ System.out.println("Failed to load DB driver");
+ e.printStackTrace();
+ }
+
+ try
+ {
+
+ connection = DriverManager.getConnection("jdbc:odbc:;DRIVER=Microsoft Access Driver (*.mdb);DBQ=c:/webgoat.mdb;PWD=webgoat", "webgoat", "webgoat");
+ db.makeDB(connection);
+ }
+ catch ( Exception e )
+ {
+ System.out.println("Driver Manager failed!");
+ e.printStackTrace();
+ }
+
+ /**
+ * getAllEmployees
+ */
+ String query = "SELECT userid,first_name,last_name FROM employee WHERE userid in (SELECT employee_id FROM ownership WHERE employer_id = 101)";
+
+ try
+ {
+ Statement answer_statement = connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+ ResultSet answer_results = answer_statement.executeQuery( query );
+ answer_results.first();
+ int employeeId = answer_results.getInt("userid");
+ String firstName = answer_results.getString("first_name");
+ String lastName = answer_results.getString("last_name");
+ System.out.println("Query 1 Results: " + firstName + " " + lastName + " " + employeeId);
+ }
+ catch ( SQLException sqle )
+ {
+ sqle.printStackTrace();
+ }
+
+ /**
+ * isAllowed
+ */
+
+ query = "SELECT * FROM auth WHERE role in (SELECT role FROM roles WHERE userid = 101) and functionid = 113";
+
+ try
+ {
+ Statement answer_statement = connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
+ ResultSet answer_results = answer_statement.executeQuery( query );
+ boolean allowed = answer_results.first();
+ //boolean allowed = answer_results.next();
+
+ if(allowed)
+ System.out.println("User is allowed");
+ else
+ System.out.println("User is NOT allowed");
+ }
+ catch ( SQLException sqle )
+ {
+ sqle.printStackTrace();
+ }
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param connection Description of the Parameter
+ *
+ * @exception SQLException Description of the Exception
+ */
+ private void createMessageTable(Connection connection) throws SQLException
+ {
+ Statement statement = connection.createStatement();
+
+ // Drop admin user table
+ try
+ {
+ String dropTable = "DROP TABLE messages";
+ statement.executeUpdate(dropTable);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error dropping message database");
+ }
+
+ // Create the new table
+ try
+ {
+ String createTableStatement = "CREATE TABLE messages ("
+ + "num int not null,"
+ + "title varchar(50),"
+ + "message varchar(200),"
+ + "user_name varchar(50) not null "
+ + ")";
+ statement.executeUpdate(createTableStatement);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error creating message database");
+ e.printStackTrace();
+ }
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param connection Description of the Parameter
+ *
+ * @exception SQLException Description of the Exception
+ */
+ private void createProductTable(Connection connection) throws SQLException
+ {
+ Statement statement = connection.createStatement();
+
+ // Drop admin user table
+ try
+ {
+ String dropTable = "DROP TABLE product_system_data";
+ statement.executeUpdate(dropTable);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error dropping product database");
+ }
+
+ // Create the new table
+ try
+ {
+ String createTableStatement = "CREATE TABLE product_system_data ("
+ + "productid varchar(6) not null primary key,"
+ + "product_name varchar(20),"
+ + "price varchar(10)" + ")";
+ statement.executeUpdate(createTableStatement);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error creating product database");
+ e.printStackTrace();
+ }
+
+ // Populate
+ String insertData1 = "INSERT INTO product_system_data VALUES ('32226','Dog Bone','$1.99')";
+ String insertData2 = "INSERT INTO product_system_data VALUES ('35632','DVD Player','$214.99')";
+ String insertData3 = "INSERT INTO product_system_data VALUES ('24569','60 GB Hard Drive','$149.99')";
+ String insertData4 = "INSERT INTO product_system_data VALUES ('56970','80 GB Hard Drive','$179.99')";
+ String insertData5 = "INSERT INTO product_system_data VALUES ('14365','56 inch HDTV','$6999.99')";
+ statement.executeUpdate(insertData1);
+ statement.executeUpdate(insertData2);
+ statement.executeUpdate(insertData3);
+ statement.executeUpdate(insertData4);
+ statement.executeUpdate(insertData5);
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param connection Description of the Parameter
+ *
+ * @exception SQLException Description of the Exception
+ */
+ private void createUserAdminTable(Connection connection) throws SQLException
+ {
+ Statement statement = connection.createStatement();
+
+ // Drop admin user table
+ try
+ {
+ String dropTable = "DROP TABLE user_system_data";
+ statement.executeUpdate(dropTable);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error dropping user admin database");
+ }
+
+ // Create the new table
+ try
+ {
+ String createTableStatement = "CREATE TABLE user_system_data ("
+ + "userid varchar(5) not null primary key,"
+ + "user_name varchar(12),"
+ + "password varchar(10),"
+ + "cookie varchar(30)"
+ + ")";
+ statement.executeUpdate(createTableStatement);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error creating user admin database");
+ e.printStackTrace();
+ }
+
+ // Populate
+ String insertData1 = "INSERT INTO user_system_data VALUES ('101','jsnow','passwd1', '')";
+ String insertData2 = "INSERT INTO user_system_data VALUES ('102','jdoe','passwd2', '')";
+ String insertData3 = "INSERT INTO user_system_data VALUES ('103','jplane','passwd3', '')";
+ String insertData4 = "INSERT INTO user_system_data VALUES ('104','jeff','jeff', '')";
+ String insertData5 = "INSERT INTO user_system_data VALUES ('105','dave','dave', '')";
+ statement.executeUpdate(insertData1);
+ statement.executeUpdate(insertData2);
+ statement.executeUpdate(insertData3);
+ statement.executeUpdate(insertData4);
+ statement.executeUpdate(insertData5);
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param connection Description of the Parameter
+ *
+ * @exception SQLException Description of the Exception
+ */
+ private void createUserDataTable(Connection connection) throws SQLException
+ {
+ Statement statement = connection.createStatement();
+
+ // Delete table if there is one
+ try
+ {
+ String dropTable = "DROP TABLE user_data";
+ statement.executeUpdate(dropTable);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error dropping user database");
+ }
+
+ // Create the new table
+ try
+ {
+ String createTableStatement = "CREATE TABLE user_data ("
+ + "userid int not null,"
+ + "first_name varchar(20),"
+ + "last_name varchar(20),"
+ + "cc_number varchar(30),"
+ + "cc_type varchar(10),"
+ + "cookie varchar(20),"
+ + "login_count int"
+ + ")";
+ statement.executeUpdate(createTableStatement);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error creating user database");
+ e.printStackTrace();
+ }
+
+ // Populate it
+ String insertData1 = "INSERT INTO user_data VALUES (101,'Joe','Snow','987654321','VISA',' ',0)";
+ String insertData2 = "INSERT INTO user_data VALUES (101,'Joe','Snow','2234200065411','MC',' ',0)";
+ String insertData3 = "INSERT INTO user_data VALUES (102,'John','Smith','2435600002222','MC',' ',0)";
+ String insertData4 = "INSERT INTO user_data VALUES (102,'John','Smith','4352209902222','AMEX',' ',0)";
+ String insertData5 = "INSERT INTO user_data VALUES (103,'Jane','Plane','123456789','MC',' ',0)";
+ String insertData6 = "INSERT INTO user_data VALUES (103,'Jane','Plane','333498703333','AMEX',' ',0)";
+ String insertData7 = "INSERT INTO user_data VALUES (10312,'Jolly','Hershey','176896789','MC',' ',0)";
+ String insertData8 = "INSERT INTO user_data VALUES (10312,'Jolly','Hershey','333300003333','AMEX',' ',0)";
+ String insertData9 = "INSERT INTO user_data VALUES (10323,'Grumpy','White','673834489','MC',' ',0)";
+ String insertData10 = "INSERT INTO user_data VALUES (10323,'Grumpy','White','33413003333','AMEX',' ',0)";
+ String insertData11 = "INSERT INTO user_data VALUES (15603,'Peter','Sand','123609789','MC',' ',0)";
+ String insertData12 = "INSERT INTO user_data VALUES (15603,'Peter','Sand','338893453333','AMEX',' ',0)";
+ String insertData13 = "INSERT INTO user_data VALUES (15613,'Joesph','Something','33843453533','AMEX',' ',0)";
+ statement.executeUpdate(insertData1);
+ statement.executeUpdate(insertData2);
+ statement.executeUpdate(insertData3);
+ statement.executeUpdate(insertData4);
+ statement.executeUpdate(insertData5);
+ statement.executeUpdate(insertData6);
+ statement.executeUpdate(insertData7);
+ statement.executeUpdate(insertData8);
+ statement.executeUpdate(insertData9);
+ statement.executeUpdate(insertData10);
+ statement.executeUpdate(insertData11);
+ statement.executeUpdate(insertData12);
+ statement.executeUpdate(insertData13);
+ }
+
+ private void createLoginTable(Connection connection) throws SQLException
+ {
+ Statement statement = connection.createStatement();
+
+ // Delete table if there is one
+ try
+ {
+ String dropTable = "DROP TABLE user_login";
+ statement.executeUpdate(dropTable);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error dropping user_login table");
+ }
+
+ // Create the new table
+ try
+ {
+ String createTableStatement = "CREATE TABLE user_login ("
+ + "userid varchar(5),"
+ + "webgoat_user varchar(20)"
+ + ")";
+ statement.executeUpdate(createTableStatement);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error creating user database");
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @param connection Description of the Parameter
+ *
+ * @exception SQLException Description of the Exception
+ */
+ private void createWeatherDataTable(Connection connection) throws SQLException
+ {
+ Statement statement = connection.createStatement();
+
+ // Delete table if there is one
+ try
+ {
+ String dropTable = "DROP TABLE weather_data";
+ statement.executeUpdate(dropTable);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error dropping weather database");
+ }
+
+ // Create the new table
+ try
+ {
+ String createTableStatement = "CREATE TABLE weather_data ("
+ + "station int not null,"
+ + "name varchar(20) not null,"
+ + "state char(2) not null,"
+ + "min_temp int not null,"
+ + "max_temp int not null"
+ + ")";
+ statement.executeUpdate(createTableStatement);
+ }
+ catch (SQLException e)
+ {
+ System.out.println("Error creating weather database");
+ e.printStackTrace();
+ }
+
+ // Populate it
+ String insertData1 = "INSERT INTO weather_data VALUES (101,'Columbia','MD',-10,102)";
+ String insertData2 = "INSERT INTO weather_data VALUES (102,'Seattle','WA',-15,90)";
+ String insertData3 = "INSERT INTO weather_data VALUES (103,'New York','NY',-10,110)";
+ String insertData4 = "INSERT INTO weather_data VALUES (104,'Houston','TX',20,120)";
+ String insertData5 = "INSERT INTO weather_data VALUES (10001,'Camp David','MD',-10,100)";
+ String insertData6 = "INSERT INTO weather_data VALUES (11001,'Ice Station Zebra','NA',-60,30)";
+ statement.executeUpdate(insertData1);
+ statement.executeUpdate(insertData2);
+ statement.executeUpdate(insertData3);
+ statement.executeUpdate(insertData4);
+ statement.executeUpdate(insertData5);
+ statement.executeUpdate(insertData6);
+ }
+
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+ //
+ // The tables below are for WebGoat Financials
+ //
+ // DO NOT MODIFY THESE TABLES - unless you change the org chart
+ // and access control matrix documents
+ //
+ //--------------------------------------------------------------------------
+ //--------------------------------------------------------------------------
+
+
+ private void createEmployeeTable(Connection connection) throws SQLException
+ {
+ Statement statement = connection.createStatement();
+
+ try
+ {
+ String dropTable = "DROP TABLE employee";
+ statement.executeUpdate(dropTable);
+ }
+ catch ( SQLException e )
+ {
+ System.out.println("Error: unable to drop employee table");
+ }
+
+ // Create Table
+ try
+ {
+ String createTable = "CREATE TABLE employee ("
+ //+ "userid INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,"
+ + "userid INT NOT NULL PRIMARY KEY,"
+ + "first_name VARCHAR(20),"
+ + "last_name VARCHAR(20),"
+ + "ssn VARCHAR(12),"
+ + "password VARCHAR(10),"
+ + "title VARCHAR(20),"
+ + "phone VARCHAR(13),"
+ + "address1 VARCHAR(80),"
+ + "address2 VARCHAR(80),"
+ + "manager INT,"
+ + "start_date CHAR(8),"
+ + "salary INT,"
+ + "ccn VARCHAR(30),"
+ + "ccn_limit INT,"
+ + "disciplined_date CHAR(8)," // date of write up, NA otherwise
+ + "disciplined_notes VARCHAR(60)," // reason for the recent write-up
+ + "personal_description VARCHAR(60)" // We can be rude here
+ //+ ",CONSTRAINT fl UNIQUE NONCLUSTERED (first_name, last_name)"
+ + ")";
+
+ statement.executeUpdate(createTable);
+ }
+ catch ( SQLException e )
+ {
+ System.out.println("Error: unable to create employee table");
+ }
+
+ String insertData1 = "INSERT INTO employee VALUES (101, 'Larry', 'Stooge', '386-09-5451', 'larry'," +
+ "'Technician','443-689-0192','9175 Guilford Rd','New York, NY', 102, 01012000,55000,'2578546969853547'," +
+ "5000,010106,'Constantly harrassing coworkers','Does not work well with others')";
+
+ String insertData2 = "INSERT INTO employee VALUES (102, 'Moe', 'Stooge', '936-18-4524','moe'," +
+ "'CSO','443-938-5301', '3013 AMD Ave', 'New York, NY', 112, 03082003, 140000, 'NA', 0, 0101013, " +
+ "'Hit Curly over head', 'Very dominating over Larry and Curly')";
+
+ String insertData3 = "INSERT INTO employee VALUES (103, 'Curly', 'Stooge', '961-08-0047','curly'," +
+ "'Technician','410-667-6654', '1112 Crusoe Lane', 'New York, NY', 102, 02122001, 50000, 'NA', 0, 0101014, " +
+ "'Hit Moe back', 'Owes three-thousand to company for fradulent purchases')";
+
+ String insertData4 = "INSERT INTO employee VALUES (104, 'Eric', 'Walker', '445-66-5565','eric'," +
+ "'Engineer','410-887-1193', '1160 Prescott Rd', 'New York, NY', 107, 12152005, 13000, 'NA', 0, 0101013, " +
+ "'Bothering Larry about webgoat problems', 'Late. Always needs help. Too intern-ish.')";
+
+ String insertData5 = "INSERT INTO employee VALUES (105, 'Tom', 'Cat', '792-14-6364','tom'," +
+ "'Engineer','443-599-0762', '2211 HyperThread Rd.', 'New York, NY', 106, 01011999, 80000, '5481360857968521', 30000, 0, " +
+ "'NA', 'Co-Owner.')";
+
+ String insertData6 = "INSERT INTO employee VALUES (106, 'Jerry', 'Mouse', '858-55-4452','jerry'," +
+ "'Human Resources','443-699-3366', '3011 Unix Drive', 'New York, NY', 102, 01011999, 70000, '6981754825013564', 20000, 0, " +
+ "'NA', 'Co-Owner.')";
+
+ String insertData7 = "INSERT INTO employee VALUES (107, 'David', 'Giambi', '439-20-9405','david'," +
+ "'Human Resources','610-521-8413', '5132 DIMM Avenue', 'New York, NY', 102, 05011999, 100000, '6981754825018101', 10000, 061402, " +
+ "'Hacked into accounting server. Modified personal pay.', 'Strong work habbit. Questionable ethics.')";
+
+ String insertData8 = "INSERT INTO employee VALUES (108, 'Bruce', 'McGuirre', '707-95-9482','bruce'," +
+ "'Engineer','610-282-1103', '8899 FreeBSD Drive ', 'New York, NY', 107, 03012000, 110000, '6981754825854136', 30000, 061502, " +
+ "'Tortuous Boot Camp workout at 5am. Employees felt sick.', 'Enjoys watching others struggle in exercises.')";
+
+ String insertData9 = "INSERT INTO employee VALUES (109, 'Sean', 'Livingston', '136-55-1046','sean'," +
+ "'Engineer','610-878-9549', '6422 dFlyBSD Road', 'New York, NY', 107, 06012003, 130000, '6981754825014510', 5000, 072804, " +
+ "'Late to work 30 days in row due to excessive Halo 2', 'Has some fascination with Steelers. Go Ravens.')";
+
+ String insertData10 = "INSERT INTO employee VALUES (110, 'Joanne', 'McDougal', '789-54-2413','joanne'," +
+ "'Human Resources','610-213-6341', '5567 Broadband Lane', 'New York, NY', 106, 01012001, 90000, '6981754825081054', 300, 112005, " +
+ "'Used company cc to purchase new car. Limit adjusted.', 'Finds it necessary to leave early every day.')";
+
+ String insertData11 = "INSERT INTO employee VALUES (111, 'John', 'Wayne', '129-69-4572', 'john'," +
+ "'CTO','610-213-1134', '129 Third St', 'New York, NY', 112, 01012001, 200000, '4437334565679921', 300, 112005, " +
+ "'', '')";
+ String insertData12 = "INSERT INTO employee VALUES (112, 'Neville', 'Bartholomew', '111-111-1111', 'socks'," +
+ "'CEO','408-587-0024', '1 Corporate Headquarters', 'San Jose, CA', 112, 03012000, 450000, '4803389267684109', 300, 112005, " +
+ "'', '')";
+
+ statement.executeUpdate(insertData1);
+ statement.executeUpdate(insertData2);
+ statement.executeUpdate(insertData3);
+ statement.executeUpdate(insertData4);
+ statement.executeUpdate(insertData5);
+ statement.executeUpdate(insertData6);
+ statement.executeUpdate(insertData7);
+ statement.executeUpdate(insertData8);
+ statement.executeUpdate(insertData9);
+ statement.executeUpdate(insertData10);
+ statement.executeUpdate(insertData11);
+ statement.executeUpdate(insertData12);
+
+ }
+
+ private void createRolesTable(Connection connection) throws SQLException
+ {
+ Statement statement = connection.createStatement();
+
+ try
+ {
+ String dropTable = "DROP TABLE roles";
+ statement.executeUpdate(dropTable);
+ }
+ catch ( SQLException e )
+ {
+ System.out.println("Error: unable to drop roles");
+ }
+
+ try
+ {
+ String createTable = "CREATE TABLE roles ("
+ + "userid INT NOT NULL,"
+ + "role VARCHAR(10) NOT NULL,"
+ + "PRIMARY KEY (userid, role)"
+ + ")";
+
+ statement.executeUpdate(createTable);
+ }
+ catch ( SQLException e )
+ {
+ System.out.println ("Error: Unable to create role table");
+ }
+
+ String insertData1 = "INSERT INTO roles VALUES (101, 'employee')";
+ String insertData2 = "INSERT INTO roles VALUES (102, 'manager')";
+ String insertData3 = "INSERT INTO roles VALUES (103, 'employee')";
+ String insertData4 = "INSERT INTO roles VALUES (104, 'employee')";
+ String insertData5 = "INSERT INTO roles VALUES (105, 'employee')";
+ String insertData6 = "INSERT INTO roles VALUES (106, 'hr')";
+ String insertData7 = "INSERT INTO roles VALUES (107, 'manager')";
+ String insertData8 = "INSERT INTO roles VALUES (108, 'employee')";
+ String insertData9 = "INSERT INTO roles VALUES (109, 'employee')";
+ String insertData10 = "INSERT INTO roles VALUES (110, 'hr')";
+ String insertData11 = "INSERT INTO roles VALUES (111, 'admin')";
+ String insertData12 = "INSERT INTO roles VALUES (112, 'admin')";
+
+ statement.executeUpdate(insertData1);
+ statement.executeUpdate(insertData2);
+ statement.executeUpdate(insertData3);
+ statement.executeUpdate(insertData4);
+ statement.executeUpdate(insertData5);
+ statement.executeUpdate(insertData6);
+ statement.executeUpdate(insertData7);
+ statement.executeUpdate(insertData8);
+ statement.executeUpdate(insertData9);
+ statement.executeUpdate(insertData10);
+ statement.executeUpdate(insertData11);
+ statement.executeUpdate(insertData12);
+ }
+
+ private void createAuthTable(Connection connection) throws SQLException
+ {
+ Statement statement = connection.createStatement();
+
+ try
+ {
+ String dropTable = "DROP TABLE auth";
+ statement.executeUpdate(dropTable);
+ }
+ catch ( SQLException e )
+ {
+ System.out.println("Error: unable to drop auth");
+ }
+
+ try
+ {
+ String createTable = "CREATE TABLE auth ("
+ + "role VARCHAR(10) NOT NULL,"
+ + "functionid VARCHAR(20) NOT NULL,"
+ + "PRIMARY KEY (role, functionid)"
+ + ")";
+
+ statement.executeUpdate(createTable);
+ }
+ catch ( SQLException e )
+ {
+ System.out.println("Error: unable to create auth table");
+ }
+
+ String insertData1 = "INSERT INTO auth VALUES('employee', 'Logout')";
+ String insertData2 = "INSERT INTO auth VALUES('employee', 'ListStaff')";
+ String insertData3 = "INSERT INTO auth VALUES('employee', 'ViewProfile')";
+ String insertData4 = "INSERT INTO auth VALUES('employee', 'EditProfile')";
+ String insertData4_1 = "INSERT INTO auth VALUES('employee', 'SearchStaff')";
+ String insertData4_2 = "INSERT INTO auth VALUES('employee', 'FindProfile')";
+ String insertData5 = "INSERT INTO auth VALUES('manager', 'Logout')";
+ String insertData6 = "INSERT INTO auth VALUES('manager', 'ListStaff')";
+ String insertData7 = "INSERT INTO auth VALUES('manager', 'ViewProfile')";
+ String insertData7_1 = "INSERT INTO auth VALUES('manager', 'SearchStaff')";
+ String insertData7_2 = "INSERT INTO auth VALUES('manager', 'FindProfile')";
+// String insertData8 = "INSERT INTO auth VALUES('manager', 'EditProfile')";
+// String insertData9 = "INSERT INTO auth VALUES('manager', 'CreateProfile')";
+// String insertData10 = "INSERT INTO auth VALUES('manager', 'DeleteProfile')";
+// String insertData11 = "INSERT INTO auth VALUES('manager', 'UpdateProfile')";
+ String insertData12 = "INSERT INTO auth VALUES('hr', 'Logout')";
+ String insertData13 = "INSERT INTO auth VALUES('hr', 'ListStaff')";
+ String insertData14 = "INSERT INTO auth VALUES('hr', 'ViewProfile')";
+ String insertData15 = "INSERT INTO auth VALUES('hr', 'EditProfile')";
+ String insertData16 = "INSERT INTO auth VALUES('hr', 'CreateProfile')";
+ String insertData17 = "INSERT INTO auth VALUES('hr', 'DeleteProfile')";
+ String insertData18 = "INSERT INTO auth VALUES('hr', 'UpdateProfile')";
+ String insertData18_1 = "INSERT INTO auth VALUES('hr', 'SearchStaff')";
+ String insertData18_2 = "INSERT INTO auth VALUES('hr', 'FindProfile')";
+ String insertData19 = "INSERT INTO auth VALUES('admin', 'Logout')";
+ String insertData20 = "INSERT INTO auth VALUES('admin', 'ListStaff')";
+ String insertData21 = "INSERT INTO auth VALUES('admin', 'ViewProfile')";
+ String insertData22 = "INSERT INTO auth VALUES('admin', 'EditProfile')";
+ String insertData23 = "INSERT INTO auth VALUES('admin', 'CreateProfile')";
+ String insertData24 = "INSERT INTO auth VALUES('admin', 'DeleteProfile')";
+ String insertData25 = "INSERT INTO auth VALUES('admin', 'UpdateProfile')";
+ String insertData25_1 = "INSERT INTO auth VALUES('admin', 'SearchStaff')";
+ String insertData25_2 = "INSERT INTO auth VALUES('admin', 'FindProfile')";
+
+ // Add a permission for the webgoat role to see the source.
+ // The challenge(s) will change the default role to "challenge"
+ String insertData26 = "INSERT INTO auth VALUES('" + AbstractLesson.USER_ROLE + "','" + WebSession.SHOWSOURCE +"')";
+ String insertData27 = "INSERT INTO auth VALUES('" + AbstractLesson.USER_ROLE + "','" + WebSession.SHOWHINTS + "')";
+
+ statement.executeUpdate(insertData1);
+ statement.executeUpdate(insertData2);
+ statement.executeUpdate(insertData3);
+ statement.executeUpdate(insertData4);
+ statement.executeUpdate(insertData4_1);
+ statement.executeUpdate(insertData4_2);
+ statement.executeUpdate(insertData5);
+ statement.executeUpdate(insertData6);
+ statement.executeUpdate(insertData7);
+ statement.executeUpdate(insertData7_1);
+ statement.executeUpdate(insertData7_2);
+// statement.executeUpdate(insertData8);
+// statement.executeUpdate(insertData9);
+// statement.executeUpdate(insertData10);
+// statement.executeUpdate(insertData11);
+ statement.executeUpdate(insertData12);
+ statement.executeUpdate(insertData13);
+ statement.executeUpdate(insertData14);
+ statement.executeUpdate(insertData15);
+ statement.executeUpdate(insertData16);
+ statement.executeUpdate(insertData17);
+ statement.executeUpdate(insertData18);
+ statement.executeUpdate(insertData18_1);
+ statement.executeUpdate(insertData18_2);
+ statement.executeUpdate(insertData19);
+ statement.executeUpdate(insertData20);
+ statement.executeUpdate(insertData21);
+ statement.executeUpdate(insertData22);
+ statement.executeUpdate(insertData23);
+ statement.executeUpdate(insertData24);
+ statement.executeUpdate(insertData25);
+ statement.executeUpdate(insertData25_1);
+ statement.executeUpdate(insertData25_2);
+ statement.executeUpdate(insertData26);
+ statement.executeUpdate(insertData27);
+ }
+
+ private void createOwnershipTable(Connection connection) throws SQLException
+ {
+ Statement statement = connection.createStatement();
+
+ try
+ {
+ String dropTable = "DROP TABLE ownership";
+ statement.executeUpdate(dropTable);
+ }
+ catch ( SQLException e )
+ {
+ System.out.println("Error: unable to drop ownership");
+ }
+
+ try
+ {
+ String createTable = "CREATE TABLE ownership ("
+ + "employer_id INT NOT NULL,"
+ + "employee_id INT NOT NULL,"
+ + "PRIMARY KEY (employee_id, employer_id)"
+ + ")";
+
+ statement.executeUpdate(createTable);
+ }
+ catch ( SQLException e )
+ {
+ System.out.println("Error: unable to create ownership table");
+ }
+
+ String inputData = "INSERT INTO ownership VALUES (112, 101)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (112, 102)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (112, 103)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (112, 104)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (112, 105)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (112, 106)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (112, 107)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (112, 108)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (112, 109)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (112, 110)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (112, 111)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (112, 112)";
+ statement.executeUpdate(inputData);
+
+ inputData = "INSERT INTO ownership VALUES (102, 101)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (102, 102)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (102, 103)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (102, 104)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (102, 105)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (102, 106)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (102, 107)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (102, 108)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (102, 109)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (102, 110)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (102, 111)";
+ statement.executeUpdate(inputData);
+
+ inputData = "INSERT INTO ownership VALUES (111, 101)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (111, 102)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (111, 103)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (111, 104)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (111, 105)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (111, 106)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (111, 107)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (111, 108)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (111, 109)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (111, 110)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (111, 111)";
+ statement.executeUpdate(inputData);
+
+ inputData = "INSERT INTO ownership VALUES (106, 105)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (106, 106)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (106, 110)";
+ statement.executeUpdate(inputData);
+
+ inputData = "INSERT INTO ownership VALUES (101, 101)";
+ statement.executeUpdate(inputData);
+
+ inputData = "INSERT INTO ownership VALUES (103, 103)";
+ statement.executeUpdate(inputData);
+
+ inputData = "INSERT INTO ownership VALUES (107, 104)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (107, 108)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (107, 109)";
+ statement.executeUpdate(inputData);
+ inputData = "INSERT INTO ownership VALUES (107, 107)";
+ statement.executeUpdate(inputData);
+
+ inputData = "INSERT INTO ownership VALUES (105, 105)";
+ statement.executeUpdate(inputData);
+
+ inputData = "INSERT INTO ownership VALUES (110, 110)";
+ statement.executeUpdate(inputData);
+
+ inputData = "INSERT INTO ownership VALUES (104, 104)";
+ statement.executeUpdate(inputData);
+
+ inputData = "INSERT INTO ownership VALUES (108, 108)";
+ statement.executeUpdate(inputData);
+
+ inputData = "INSERT INTO ownership VALUES (109, 109)";
+ statement.executeUpdate(inputData);
+
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // End of WebGoat Financials
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Description of the Method
+ *
+ * @param connection Description of the Parameter
+ *
+ * @exception SQLException Description of the Exception
+ */
+ public void makeDB(Connection connection) throws SQLException
+ {
+ System.out.println("Successful connection to database");
+ createUserDataTable(connection);
+ createLoginTable(connection);
+ createUserAdminTable(connection);
+ createProductTable(connection);
+ createMessageTable(connection);
+ createEmployeeTable(connection);
+ createRolesTable(connection);
+ createAuthTable(connection);
+ createOwnershipTable(connection);
+ createWeatherDataTable(connection);
+ System.out.println("Success: creating tables.");
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/DatabaseUtilities.java b/ webgoat/main/project/org/owasp/webgoat/session/DatabaseUtilities.java
new file mode 100644
index 000000000..5e7ca2d67
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/DatabaseUtilities.java
@@ -0,0 +1,135 @@
+package org.owasp.webgoat.session;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import org.apache.ecs.MultiPartElement;
+import org.apache.ecs.html.B;
+import org.apache.ecs.html.TD;
+import org.apache.ecs.html.TR;
+import org.apache.ecs.html.Table;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of
+ * the Open Web Application Security Project (http://www.owasp.org) This
+ * software package org.owasp.webgoat.is published by OWASP under the GPL. You should read and
+ * accept the LICENSE before you use, modify and/or redistribute this
+ * software.
+ *
+ * @author Jeff Williams Aspect Security
+ */
+public class DatabaseUtilities
+{
+ public static String servletContextRealPath = null;
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ *
+ * @return Description of the Return Value
+ *
+ * @exception ClassNotFoundException Description of the Exception
+ * @exception SQLException Description of the Exception
+ */
+ public static Connection makeConnection(WebSession s) throws ClassNotFoundException, SQLException
+ {
+ Class.forName(s.getDatabaseDriver());
+
+ return (DriverManager.getConnection(s.getDatabaseConnectionString()));
+ }
+
+ public static Connection makeConnection(String driverName, String connectionString)
+ throws ClassNotFoundException, SQLException
+ {
+ Class.forName(driverName);
+
+ return (DriverManager.getConnection(connectionString));
+ }
+
+ public static Connection makeConnection() {
+ try
+ {
+ // FIXME: Work around for not having a session object with the web service lessons
+ // This is the same "logic" in the web.xml file
+ // Get the path to webgoat database
+
+ String dbName = (servletContextRealPath + "database" + File.separator);
+ String os = System.getProperty("os.name","Windows");
+ if ( os.toLowerCase().indexOf("window") != -1 )
+ {
+ dbName = dbName.concat("webgoat.mdb");
+ System.out.println("DBName: " + dbName);
+ Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
+ return DriverManager.getConnection("jdbc:odbc:;DRIVER=Microsoft Access Driver (*.mdb);DBQ=" + dbName + ";PWD=webgoat");
+ }
+ else
+ {
+ dbName = dbName.concat("database.prp");
+ Class.forName("org.enhydra.instantdb.jdbc.idbDriver");
+ return DriverManager.getConnection("jdbc:idb:" + dbName);
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param results Description of the Parameter
+ * @param resultsMetaData Description of the Parameter
+ *
+ * @return Description of the Return Value
+ *
+ * @exception IOException Description of the Exception
+ * @exception SQLException Description of the Exception
+ */
+ public static MultiPartElement writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException, SQLException
+ {
+ int numColumns = resultsMetaData.getColumnCount();
+ results.beforeFirst();
+
+ if (results.next())
+ {
+ Table t = new Table(1); // 1 = with border
+ t.setCellPadding(1);
+
+ TR tr = new TR();
+
+ for (int i = 1; i < (numColumns + 1); i++)
+ {
+ tr.addElement(new TD(new B(resultsMetaData.getColumnName(i))));
+ }
+
+ t.addElement(tr);
+ results.beforeFirst();
+
+ while (results.next())
+ {
+ TR row = new TR();
+
+ for (int i = 1; i < (numColumns + 1); i++)
+ {
+ row.addElement(new TD(results.getString(i).replaceAll(" ", " ")));
+ }
+
+ t.addElement(row);
+ }
+
+ return (t);
+ }
+ else
+ {
+ return (new B("Query Successful; however no data was returned from this query."));
+ }
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/ECSFactory.java b/ webgoat/main/project/org/owasp/webgoat/session/ECSFactory.java
new file mode 100644
index 000000000..d1d796e1f
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/ECSFactory.java
@@ -0,0 +1,688 @@
+package org.owasp.webgoat.session;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.StringElement;
+import org.apache.ecs.html.A;
+import org.apache.ecs.html.BR;
+import org.apache.ecs.html.H3;
+import org.apache.ecs.html.Input;
+import org.apache.ecs.html.Label;
+import org.apache.ecs.html.Option;
+import org.apache.ecs.html.P;
+import org.apache.ecs.html.Select;
+import org.apache.ecs.html.TD;
+import org.apache.ecs.html.TH;
+import org.apache.ecs.html.TR;
+import org.apache.ecs.html.U;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams (jeff.williams@aspectsecurity.com)
+ * @created October 29, 2003
+ */
+
+public class ECSFactory
+{
+
+ /**
+ * Description of the Field
+ */
+
+ public final static String ON = "On";
+
+ /**
+ * Description of the Field
+ */
+
+ public final static String PASSWORD = "Password";
+
+
+
+ /**
+ * Don't let anyone instantiate this class
+ */
+
+ private ECSFactory() { }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param name Description of the Parameter
+ * @param value Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static Element makeBox( String name, String value )
+ {
+
+ Input i = new Input( Input.CHECKBOX, name, ON );
+
+ i.setChecked( value.equals( ON ) );
+
+ return ( i );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param text Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static Element makeButton( String text )
+ {
+
+ Input b = new Input();
+
+ b.setType( Input.SUBMIT );
+ b.setValue( text );
+ b.setName(Input.SUBMIT);
+
+ return ( b );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param labeltext Description of the Parameter
+ * @param value Description of the Parameter
+ * @param e Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static TR makeField( String labeltext, String value, Element e )
+ {
+
+ TD left = new TD().setAlign( "right" );
+
+ Label label = new Label().addElement( labeltext );
+
+ left.addElement( label );
+
+ TD right = new TD().setAlign( "left" );
+
+ right.addElement( e );
+
+ TR row = new TR();
+
+ row.addElement( left );
+
+ row.addElement( right );
+
+ return ( row );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param labeltext Description of the Parameter
+ * @param name Description of the Parameter
+ * @param value Description of the Parameter
+ * @param size Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static TR makeField( String labeltext, String name, String value, int size )
+ {
+
+ Input field = new Input().setName( name ).setValue( value ).setSize( size ).setMaxlength( size );
+
+ // double check in case someone means to make a * starred out password field
+
+ if ( name.equals( PASSWORD ) )
+ {
+
+ field.setType( Input.PASSWORD );
+
+ }
+
+ return ( makeField( labeltext, value, field ) );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param label Description of the Parameter
+ * @param type Description of the Parameter
+ * @param name Description of the Parameter
+ * @param value Description of the Parameter
+ * @param alignment Description of the Parameter
+ * @param selected Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static Element makeInput( String label, String type, String name, boolean value, boolean selected, String alignment )
+ {
+
+ return makeInput( label, type, name, new Boolean( value ).toString(), selected, alignment );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param label Description of the Parameter
+ * @param type Description of the Parameter
+ * @param name Description of the Parameter
+ * @param value Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static Element makeInput( String label, String type, String name, String value )
+ {
+
+ return makeInput( label, type, name, value, new Boolean( value ).booleanValue(), "RIGHT" );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param label Description of the Parameter
+ * @param type Description of the Parameter
+ * @param name Description of the Parameter
+ * @param value Description of the Parameter
+ * @param alignment Description of the Parameter
+ * @param selected Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static Element makeInput( String label, String type, String name, String value, boolean selected, String alignment )
+ {
+
+ ElementContainer ec = new ElementContainer();
+
+ if ( !alignment.equalsIgnoreCase( "LEFT" ) )
+ {
+
+ ec.addElement( new StringElement( label ) );
+
+ }
+
+ Input input = new Input( type, name, value );
+
+ ec.addElement( input );
+
+ if ( alignment.equalsIgnoreCase( "LEFT" ) )
+ {
+
+ ec.addElement( new StringElement( label ) );
+
+ }
+
+ if ( type.equalsIgnoreCase( "CHECKBOX" ) )
+ {
+
+ input.setChecked( selected );
+
+ }
+
+ return ( ec );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param text Description of the Parameter
+ * @param name Description of the Parameter
+ * @param value Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static A makeLink( String text, String name, String value )
+ {
+
+ String href = "attack?" + name;
+
+ if ( value.length() > 0 )
+ {
+
+ href = href + "=" + value;
+
+ }
+
+ A a = new A( href );
+
+ a.addElement( new U().addElement( text ) );
+
+ a.addAttribute( "style", "cursor:hand" );
+
+ return ( a );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param text Description of the Parameter
+ * @param name Description of the Parameter
+ * @param value Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static A makeLink( String text, String name, int value )
+ {
+
+ return ( makeLink( text, name, Integer.toString( value ) ) );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param text Description of the Parameter
+ * @param name Description of the Parameter
+ * @param value Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static A makeLink( String text, String name, boolean value )
+ {
+
+ return ( makeLink( text, name, new Boolean( value ).toString() ) );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param text Description of the Parameter
+ * @param clickAction Description of the Parameter
+ * @param type Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static Input makeOnClickInput( String text, String clickAction, String type )
+ {
+
+ Input b = new Input();
+
+ b.setType( type );
+
+ b.setValue( text );
+
+ b.setOnClick( clickAction );
+
+ return ( b );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param labeltext Description of the Parameter
+ * @param value Description of the Parameter
+ * @param e Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static TR makeOption( String labeltext, String value, Element e )
+ {
+
+ TD left = new TD().setAlign( "left" ).setWidth( "10%" );
+
+ left.addElement( e );
+
+ TD right = new TD().setAlign( "right" );
+
+ Label label = new Label().addElement( labeltext );
+
+ right.addElement( label );
+
+ TR row = new TR();
+
+ row.addElement( right );
+
+ row.addElement( left );
+
+ return ( row );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param label Description of the Parameter
+ * @param value Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static Option makeOption( String label, boolean value )
+ {
+
+ Option option = new Option( label, new Boolean( value ).toString() );
+
+ option.setSelected( value );
+
+ return option;
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param line Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ private static org.apache.ecs.html.Option makeOption( String line )
+ {
+
+ StringTokenizer st = new StringTokenizer( line, "|" );
+
+ org.apache.ecs.html.Option o = new org.apache.ecs.html.Option();
+
+ String token = "";
+
+ if ( st.hasMoreTokens() )
+ {
+
+ token = st.nextToken();
+
+ }
+
+ o.addElement( token );
+
+ return ( o );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param name Description of the Parameter
+ * @param options Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static Element makePulldown( String name, List options )
+ {
+
+ Select s = new Select( name );
+
+ s.addElement( (String[]) options.toArray( new String[options.size()] ) );
+
+ return ( s );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param results Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static Element makePulldown( String name, String results )
+ {
+
+ Select select = new Select(name);
+
+ StringTokenizer st = new StringTokenizer( results, "\n" );
+
+ if ( !st.hasMoreTokens() )
+ {
+
+ return ( new StringElement( "" ) );
+ }
+
+ while ( st.hasMoreTokens() )
+ {
+
+ String line = st.nextToken();
+
+ select.addElement( makeOption( line ) );
+
+ }
+
+ select.addElement( "-------------------------" );
+
+ return ( select );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param name Description of the Parameter
+ * @param list Description of the Parameter
+ * @param selected Description of the Parameter
+ * @param rowsShowing Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static Select makePulldown( String name, Object[] list, String selected, int rowsShowing )
+ {
+
+ Select select = new Select( name );
+
+ for ( int loop = 0; loop < list.length; loop++ )
+ {
+
+ String value = list[loop].toString();
+
+ org.apache.ecs.html.Option o = new org.apache.ecs.html.Option( value, value, value );
+
+ if ( value.equals( selected ) )
+ {
+
+ o.setSelected( true );
+
+ }
+
+ select.addElement( o );
+
+ }
+
+ select.setSize( rowsShowing );
+
+ return select;
+ }
+
+
+
+ /**
+ * Default size of 1 for rows showing in select box.
+ *
+ * @param diffNames Description of the Parameter
+ * @param select Description of the Parameter
+ * @param name Description of the Parameter
+ * @param options Description of the Parameter
+ * @param list Description of the Parameter
+ * @param selected Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static Element makeSelect( boolean diffNames, Select select, String name, Vector options, String[] list, String selected )
+ {
+
+ return makeSelect( diffNames, select, name, options, list, selected, 1 );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param diffNames Description of the Parameter
+ * @param select Description of the Parameter
+ * @param name Description of the Parameter
+ * @param options Description of the Parameter
+ * @param list Description of the Parameter
+ * @param selected Description of the Parameter
+ * @param rowsShowing Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static Select makeSelect( boolean diffNames, Select select, String name, Vector options, String[] list, String selected, int rowsShowing )
+ {
+
+ if ( select == null )
+ {
+
+ select = new Select( name );
+
+ if ( diffNames )
+ {
+
+ for ( int loop = 0; loop < list.length; loop += 2 )
+ {
+
+ String value = list[loop];
+
+ String label = list[loop + 1];
+
+ org.apache.ecs.html.Option o = new org.apache.ecs.html.Option( value );
+
+ if ( loop == 0 )
+ {
+
+ o.setSelected( true );
+
+ }
+
+ options.addElement( o );// add to Vector containing all options
+
+ select.addElement( o );
+
+ select.addElement( label );
+
+ }
+
+ }
+
+ else
+ {
+
+ for ( int loop = 0; loop < list.length; loop++ )
+ {
+
+ String value = list[loop];
+
+ org.apache.ecs.html.Option o = new org.apache.ecs.html.Option( value );
+
+ if ( loop == 0 )
+ {
+
+ o.setSelected( true );
+
+ }
+
+ options.addElement( o );// add to Vector containing all options
+
+ select.addElement( o );
+
+ select.addElement( value );
+
+ }
+
+ }
+
+ }
+
+ // find selected option and set selected
+
+ Iterator i = options.iterator();
+
+ while ( i.hasNext() )
+ {
+
+ org.apache.ecs.html.Option o = (org.apache.ecs.html.Option) i.next();
+
+ if ( selected.equalsIgnoreCase( o.getAttribute( "value" ) ) )
+ {
+
+ o.setSelected( true );
+
+ }
+
+ }
+
+ select.setSize( rowsShowing );
+
+ return ( select );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param title Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static Element makeTallHeader( String title )
+ {
+ StringBuffer buff = new StringBuffer();
+ for ( int i = 0; i < title.length(); i++ )
+ {
+ buff.append( title.charAt( i ) );
+ buff.append( "
" );
+ }
+ return new TH( buff.toString() );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param title Description of the Parameter
+ * @param text Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ public static Element makeTextArea( String title, String text )
+ {
+
+ ElementContainer ec = new ElementContainer();
+
+ ec.addElement( new BR() );
+
+ ec.addElement( new H3().addElement( title ) );
+
+ ec.addElement( new P() );
+
+ ec.addElement( "" );
+
+ ec.addElement( new BR() );
+
+ ec.addElement( new BR() );
+
+ return ( ec );
+ }
+
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/Employee.java b/ webgoat/main/project/org/owasp/webgoat/session/Employee.java
new file mode 100644
index 000000000..aef7e7785
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/Employee.java
@@ -0,0 +1,218 @@
+package org.owasp.webgoat.session;
+
+import java.io.Serializable;
+
+public class Employee implements Serializable
+{
+ public final static String EMPLOYEE_ROLE = "employee";
+ public final static String MANAGER_ROLE = "manager";
+ public final static String HR_ROLE = "hr";
+
+ private int id;
+
+ private String firstName;
+
+ private String lastName;
+
+ private String title;
+
+ private String ssn;
+
+ private String phone;
+
+ private String address1;
+
+ private String address2;
+
+ private int manager;
+
+ private String startDate;
+
+ private int salary;
+
+ private String ccn;
+
+ private int ccnLimit;
+
+ private String disciplinaryActionDate;
+
+ private String disciplinaryActionNotes;
+
+ private String personalDescription;
+
+ // FIXME: To be deleted
+ public Employee()
+ {
+ }
+
+ public Employee(
+ int id,
+ String firstName,
+ String lastName,
+ String ssn,
+ String title,
+ String phone,
+ String address1,
+ String address2,
+ int manager,
+ String startDate,
+ int salary,
+ String ccn,
+ int ccnLimit,
+ String disciplinaryActionDate,
+ String disciplinaryActionNotes,
+ String personalDescription)
+ {
+ this.id = id;
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.ssn = ssn;
+ this.title = title;
+ this.phone = phone;
+ this.address1 = address1;
+ this.address2 = address2;
+ this.manager = manager;
+ this.startDate = startDate;
+ this.salary = salary;
+ this.ccn = ccn;
+ this.ccnLimit = ccnLimit;
+ this.disciplinaryActionDate = disciplinaryActionDate;
+ this.disciplinaryActionNotes = disciplinaryActionNotes;
+ this.personalDescription = personalDescription;
+ }
+
+ public String getAddress1()
+ {
+ return address1;
+ }
+
+ public void setAddress1(String address1)
+ {
+ this.address1 = address1;
+ }
+
+ public String getAddress2()
+ {
+ return address2;
+ }
+
+ public void setAddress2(String address2)
+ {
+ this.address2 = address2;
+ }
+
+ public String getCcn()
+ {
+ return ccn;
+ }
+
+ public void setCcn(String ccn)
+ {
+ this.ccn = ccn;
+ }
+
+ public int getCcnLimit()
+ {
+ return ccnLimit;
+ }
+
+ public void setCcnLimit(int ccnLimit)
+ {
+ this.ccnLimit = ccnLimit;
+ }
+
+ public String getFirstName()
+ {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName)
+ {
+ this.firstName = firstName;
+ }
+
+ public String getLastName()
+ {
+ return lastName;
+ }
+
+ public void setLastName(String lastName)
+ {
+ this.lastName = lastName;
+ }
+
+ public String getPhoneNumber()
+ {
+ return phone;
+ }
+
+ public void setPhoneNumber(String phone)
+ {
+ this.phone = phone;
+ }
+
+ public int getSalary()
+ {
+ return salary;
+ }
+
+ public void setSalary(int salary)
+ {
+ this.salary = salary;
+ }
+
+ public String getSsn()
+ {
+ return ssn;
+ }
+
+ public void setSsn(String ssn)
+ {
+ this.ssn = ssn;
+ }
+
+ public String getStartDate()
+ {
+ return startDate;
+ }
+
+ public void setStartDate(String startDate)
+ {
+ this.startDate = startDate;
+ }
+
+ public int getId()
+ {
+ return id;
+ }
+
+ public void setId(int id)
+ {
+ this.id = id;
+ }
+
+ public String getTitle()
+ {
+ return this.title;
+ }
+
+ public int getManager()
+ {
+ return this.manager;
+ }
+
+ public String getDisciplinaryActionDate()
+ {
+ return this.disciplinaryActionDate;
+ }
+
+ public String getDisciplinaryActionNotes()
+ {
+ return this.disciplinaryActionNotes;
+ }
+
+ public String getPersonalDescription()
+ {
+ return this.personalDescription;
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/EmployeeStub.java b/ webgoat/main/project/org/owasp/webgoat/session/EmployeeStub.java
new file mode 100644
index 000000000..659b99626
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/EmployeeStub.java
@@ -0,0 +1,44 @@
+package org.owasp.webgoat.session;
+
+import java.io.Serializable;
+
+public class EmployeeStub implements Serializable
+{
+ private int id;
+ private String firstName;
+ private String lastName;
+ private String role;
+
+ public EmployeeStub(int id, String firstName, String lastName)
+ {
+ this(id, firstName, lastName, Employee.EMPLOYEE_ROLE);
+ }
+
+ public EmployeeStub(int id, String firstName, String lastName, String role)
+ {
+ this.id = id;
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.role = role;
+ }
+
+ public String getFirstName()
+ {
+ return firstName;
+ }
+
+ public int getId()
+ {
+ return id;
+ }
+
+ public String getLastName()
+ {
+ return lastName;
+ }
+
+ public String getRole()
+ {
+ return role;
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/ErrorScreen.java b/ webgoat/main/project/org/owasp/webgoat/session/ErrorScreen.java
new file mode 100644
index 000000000..06b152b4a
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/ErrorScreen.java
@@ -0,0 +1,255 @@
+package org.owasp.webgoat.session;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+import java.util.StringTokenizer;
+import javax.servlet.ServletException;
+
+import org.owasp.webgoat.lessons.AbstractLesson;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.ElementContainer;
+import org.apache.ecs.HtmlColor;
+import org.apache.ecs.StringElement;
+import org.apache.ecs.html.Div;
+import org.apache.ecs.html.Form;
+import org.apache.ecs.html.H2;
+import org.apache.ecs.html.Small;
+import org.apache.ecs.html.TD;
+import org.apache.ecs.html.TR;
+import org.apache.ecs.html.Table;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created November 4, 2003
+ */
+public class ErrorScreen extends Screen
+{
+ /**
+ * Description of the Field
+ */
+ protected Throwable error;
+
+ /**
+ * Description of the Field
+ */
+ protected String message;
+
+
+
+ /**
+ * Constructor for the ErrorScreen object
+ *
+ * @param s Description of the Parameter
+ * @param t Description of the Parameter
+ */
+ public ErrorScreen( WebSession s, Throwable t )
+ {
+ this.error = t;
+ fixCurrentScreen( s );
+ setup( s );
+ }
+
+
+ /**
+ * Constructor for the ErrorScreen object
+ *
+ * @param s Description of the Parameter
+ * @param msg Description of the Parameter
+ */
+ public ErrorScreen( WebSession s, String msg )
+ {
+ this.message = msg;
+ fixCurrentScreen( s );
+ setup( s );
+ }
+
+
+ public void fixCurrentScreen( WebSession s )
+ {
+ // So the user can't get stuck on the error screen, reset the
+ // current screen to something known
+ if ( s!= null )
+ {
+ try
+ {
+ s.setCurrentScreen( s.getCourse().getFirstLesson().getScreenId() );
+ }
+ catch ( Throwable t )
+ {
+ s.setCurrentScreen( WebSession.WELCOME );
+ }
+ }
+ }
+
+
+ public void setup( WebSession s )
+ {
+ // call createContent first so messages will go somewhere
+
+ Form form = new Form( "attack", Form.POST ).setName( "form" ).setEncType( "" );
+
+ form.addElement( wrapForm( s ) );
+
+ TD lowerright = new TD().setHeight( "100%" ).setVAlign( "top" ).setAlign( "left" ).addElement( form );
+ TR row = new TR().addElement( lowerright );
+ Table layout = new Table().setBgColor( HtmlColor.WHITE ).setCellSpacing( 0 ).setCellPadding( 0 ).setBorder( 0 );
+
+ layout.addElement( row );
+
+ setContent(layout);
+ }
+
+ protected Element wrapForm( WebSession s )
+ {
+ if ( s == null )
+ {
+ return new StringElement( "Invalid Session" );
+ }
+
+ Table container = new Table().setWidth( "100%" ).setCellSpacing( 10 ).setCellPadding( 0 ).setBorder( 0 );
+
+ // CreateContent can generate error messages so you MUST call it before makeMessages()
+ Element content = createContent( s );
+ container.addElement( new TR().addElement( new TD().setColSpan( 2 ).setVAlign( "TOP" ).addElement(
+ makeMessages( s ) ) ) );
+ container.addElement( new TR().addElement( new TD().setColSpan( 2 ).addElement( content ) ) );
+ container.addElement( new TR() );
+
+ return ( container );
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( WebSession s )
+ {
+ System.out.println( "errorscreen createContent Error:" + this.error + " message:" + this.message );
+
+ Element content;
+
+ if ( this.error != null )
+ {
+ content = createContent( this.error );
+ }
+ else if ( this.message != null )
+ {
+ content = createContent( this.message );
+ }
+ else
+ {
+ content = new StringElement( "An unknown error occurred." );
+ }
+
+ return content;
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( String s )
+ {
+ StringElement list = new StringElement( s );
+
+ return ( list );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param t Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected Element createContent( Throwable t )
+ {
+ StringElement list = new StringElement();
+ list.addElement( new H2().addElement( new StringElement( "Error Message: " + t.getMessage() ) ) );
+ list.addElement( formatStackTrace( t ) );
+
+ if ( t instanceof ServletException )
+ {
+ Throwable root = ( (ServletException) t ).getRootCause();
+
+ if ( root != null )
+ {
+ list.addElement( new H2().addElement( new StringElement( "Root Message: " + root.getMessage() ) ) );
+ list.addElement( formatStackTrace( root ) );
+ }
+ }
+
+ return ( new Small().addElement( list ) );
+ }
+
+ public Element getCredits()
+ {
+ return new ElementContainer();
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param t Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static Element formatStackTrace( Throwable t )
+ {
+ String trace = getStackTrace( t );
+ StringElement list = new StringElement();
+ StringTokenizer st = new StringTokenizer( trace, "\r\n\t" );
+
+ while ( st.hasMoreTokens() )
+ {
+ String line = st.nextToken();
+ list.addElement( new Div( line ) );
+ }
+
+ return ( list );
+ }
+
+
+ /**
+ * Gets the stackTrace attribute of the ErrorScreen class
+ *
+ * @param t Description of the Parameter
+ * @return The stackTrace value
+ */
+ public static String getStackTrace( Throwable t )
+ {
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ PrintWriter writer = new PrintWriter( bytes, true );
+ t.printStackTrace( writer );
+
+ return ( bytes.toString() );
+ }
+
+
+ /**
+ * Gets the title attribute of the ErrorScreen object
+ *
+ * @return The title value
+ */
+ public String getTitle()
+ {
+ return ( "Error" );
+ }
+
+ public String getRole() {
+ return AbstractLesson.USER_ROLE;
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/LessonSession.java b/ webgoat/main/project/org/owasp/webgoat/session/LessonSession.java
new file mode 100644
index 000000000..5c36cd505
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/LessonSession.java
@@ -0,0 +1,36 @@
+package org.owasp.webgoat.session;
+
+/**
+ * Represents a virtual session for a lesson. Lesson-specific session data may
+ * be stored here.
+ *
+ * @author David Anderson Aspect Security
+ * @created January 19, 2006
+ */
+public class LessonSession
+{
+ private boolean isAuthenticated = false;
+
+ private String currentLessonScreen;
+
+ public void setAuthenticated(boolean isAuthenticated)
+ {
+ this.isAuthenticated = isAuthenticated;
+ }
+
+ public boolean isAuthenticated()
+ {
+ return this.isAuthenticated;
+ }
+
+ public void setCurrentLessonScreen(String currentLessonScreen)
+ {
+ this.currentLessonScreen = currentLessonScreen;
+ }
+
+ public String getCurrentLessonScreen()
+ {
+ return this.currentLessonScreen;
+ }
+
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/LessonTracker.java b/ webgoat/main/project/org/owasp/webgoat/session/LessonTracker.java
new file mode 100644
index 000000000..65d907df0
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/LessonTracker.java
@@ -0,0 +1,384 @@
+package org.owasp.webgoat.session;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Properties;
+
+
+/**
+ * Description of the Class
+ *
+ * @author Bruce Mayhew
+ * @created October 29, 2003
+ */
+public class LessonTracker
+{
+ private boolean completed = false;
+ private int currentStage = 1;
+ private int maxHintLevel = 0;
+
+ private int numVisits = 0;
+ private boolean viewedCookies = false;
+ private boolean viewedHtml = false;
+ private boolean viewedLessonPlan = false;
+ private boolean viewedParameters = false;
+ private boolean viewedSource = false;
+
+ Properties lessonProperties = new Properties();
+
+
+ /**
+ * Gets the completed attribute of the LessonTracker object
+ *
+ * @return The completed value
+ */
+ public boolean getCompleted()
+ {
+ return completed;
+ }
+
+
+ public int getStage()
+ {
+ return currentStage;
+ }
+
+ public void setStage(int stage)
+ {
+ currentStage = stage;
+ }
+
+ /**
+ * Gets the maxHintLevel attribute of the LessonTracker object
+ *
+ * @return The maxHintLevel value
+ */
+ public int getMaxHintLevel()
+ {
+ return maxHintLevel;
+ }
+
+
+ /**
+ * Gets the numVisits attribute of the LessonTracker object
+ *
+ * @return The numVisits value
+ */
+ public int getNumVisits()
+ {
+ return numVisits;
+ }
+
+
+ /**
+ * Gets the viewedCookies attribute of the LessonTracker object
+ *
+ * @return The viewedCookies value
+ */
+ public boolean getViewedCookies()
+ {
+ return viewedCookies;
+ }
+
+
+ /**
+ * Gets the viewedHtml attribute of the LessonTracker object
+ *
+ * @return The viewedHtml value
+ */
+ public boolean getViewedHtml()
+ {
+ return viewedHtml;
+ }
+
+
+
+ /**
+ * Gets the viewedLessonPlan attribute of the LessonTracker object
+ *
+ * @return The viewedLessonPlan value
+ */
+ public boolean getViewedLessonPlan()
+ {
+ return viewedLessonPlan;
+ }
+
+
+ /**
+ * Gets the viewedParameters attribute of the LessonTracker object
+ *
+ * @return The viewedParameters value
+ */
+ public boolean getViewedParameters()
+ {
+ return viewedParameters;
+ }
+
+
+ /**
+ * Gets the viewedSource attribute of the LessonTracker object
+ *
+ * @return The viewedSource value
+ */
+ public boolean getViewedSource()
+ {
+ return viewedSource;
+ }
+
+
+ /**
+ * Description of the Method
+ */
+ public void incrementNumVisits()
+ {
+ numVisits++;
+ }
+
+
+ /**
+ * Sets the properties attribute of the LessonTracker object
+ *
+ * @param props The new properties value
+ */
+ private void setProperties( Properties props, Screen screen )
+ {
+ completed = Boolean.valueOf( props.getProperty( screen.getTitle() + ".completed" ) ).booleanValue();
+ maxHintLevel = Integer.parseInt( props.getProperty( screen.getTitle() + ".maxHintLevel" ) );
+ currentStage = Integer.parseInt( props.getProperty( screen.getTitle() + ".currentStage" ) );
+ numVisits = Integer.parseInt( props.getProperty( screen.getTitle() + ".numVisits" ) );
+ viewedCookies = Boolean.valueOf( props.getProperty( screen.getTitle() + ".viewedCookies" ) ).booleanValue();
+ viewedHtml = Boolean.valueOf( props.getProperty( screen.getTitle() + ".viewedHtml" ) ).booleanValue();
+ viewedLessonPlan = Boolean.valueOf( props.getProperty( screen.getTitle() + ".viewedLessonPlan" ) ).booleanValue();
+ viewedParameters = Boolean.valueOf( props.getProperty( screen.getTitle() + ".viewedParameters" ) ).booleanValue();
+ viewedSource = Boolean.valueOf( props.getProperty( screen.getTitle() + ".viewedSource" ) ).booleanValue();
+ }
+
+
+ public static String getUserDir( WebSession s )
+ {
+ return s.getContext().getRealPath( "users" ) +"/";
+ }
+
+ private static String getTrackerFile( WebSession s, String user, Screen screen )
+ {
+ return getUserDir( s ) + user + "." + screen.getClass().getName() + ".props";
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param screen Description of the Parameter
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static LessonTracker load( WebSession s, String user, Screen screen )
+ {
+ FileInputStream in = null;
+ try
+ {
+ String fileName = getTrackerFile(s, user, screen);
+ if ( fileName != null )
+ {
+ Properties tempProps = new Properties();
+ //System.out.println("Loading lesson state from: " + fileName);
+ in = new FileInputStream( fileName );
+ tempProps.load( in );
+ // allow the screen to use any custom properties it may have set
+ LessonTracker tempLessonTracker = screen.createLessonTracker( tempProps );
+ tempLessonTracker.setProperties( tempProps, screen );
+ return tempLessonTracker;
+ }
+ }
+ catch ( FileNotFoundException e )
+ {
+ // Normal if the lesson has not been accessed yet.
+ }
+ catch ( Exception e )
+ {
+ System.out.println("Failed to load lesson state for " + screen);
+ e.printStackTrace();
+ }
+ finally
+ {
+ try
+ {
+ in.close();
+ }
+ catch (Exception e) {}
+ }
+
+ return screen.createLessonTracker();
+ }
+
+
+ /**
+ * Sets the completed attribute of the LessonTracker object
+ *
+ * @param completed The new completed value
+ */
+ public void setCompleted( boolean completed )
+ {
+ this.completed = completed;
+ }
+
+
+
+ /**
+ * Sets the maxHintLevel attribute of the LessonTracker object
+ *
+ * @param maxHintLevel The new maxHintLevel value
+ */
+ public void setMaxHintLevel( int maxHintLevel )
+ {
+ this.maxHintLevel = Math.max( this.maxHintLevel, maxHintLevel );
+ }
+
+
+ /**
+ * Sets the viewedCookies attribute of the LessonTracker object
+ *
+ * @param viewedCookies The new viewedCookies value
+ */
+ public void setViewedCookies( boolean viewedCookies )
+ {
+ this.viewedCookies = viewedCookies;
+ }
+
+
+ /**
+ * Sets the viewedHtml attribute of the LessonTracker object
+ *
+ * @param viewedHtml The new viewedHtml value
+ */
+ public void setViewedHtml( boolean viewedHtml )
+ {
+ this.viewedHtml = viewedHtml;
+ }
+
+
+
+ /**
+ * Sets the viewedLessonPlan attribute of the LessonTracker object
+ *
+ * @param viewedLessonPlan The new viewedLessonPlan value
+ */
+ public void setViewedLessonPlan( boolean viewedLessonPlan )
+ {
+ this.viewedLessonPlan = viewedLessonPlan;
+ }
+
+
+ /**
+ * Sets the viewedParameters attribute of the LessonTracker object
+ *
+ * @param viewedParameters The new viewedParameters value
+ */
+ public void setViewedParameters( boolean viewedParameters )
+ {
+ this.viewedParameters = viewedParameters;
+ }
+
+
+ /**
+ * Sets the viewedSource attribute of the LessonTracker object
+ *
+ * @param viewedSource The new viewedSource value
+ */
+ public void setViewedSource( boolean viewedSource )
+ {
+ this.viewedSource = viewedSource;
+ }
+
+
+ /**
+ * Allows the storing of properties for the logged in and a screen.
+ *
+ * @param s Description of the Parameter
+ */
+ public void store( WebSession s, Screen screen )
+ {
+ store( s, screen, s.getUserName() );
+ }
+
+ /**
+ * Allows the storing of properties for a user and a screen.
+ *
+ * @param s Description of the Parameter
+ */
+ public void store( WebSession s, Screen screen, String user )
+ {
+ FileOutputStream out = null;
+ String fileName = getTrackerFile(s, user, screen);
+ //System.out.println( "Storing data to" + fileName );
+ lessonProperties.setProperty( screen.getTitle() + ".completed", Boolean.toString( completed ) );
+ lessonProperties.setProperty( screen.getTitle() + ".currentStage", Integer.toString( currentStage ) );
+ lessonProperties.setProperty( screen.getTitle() + ".maxHintLevel", Integer.toString( maxHintLevel ) );
+ lessonProperties.setProperty( screen.getTitle() + ".numVisits", Integer.toString( numVisits ) );
+ lessonProperties.setProperty( screen.getTitle() + ".viewedCookies", Boolean.toString( viewedCookies ) );
+ lessonProperties.setProperty( screen.getTitle() + ".viewedHtml", Boolean.toString( viewedHtml ) );
+ lessonProperties.setProperty( screen.getTitle() + ".viewedLessonPlan", Boolean.toString( viewedLessonPlan ) );
+ lessonProperties.setProperty( screen.getTitle() + ".viewedParameters", Boolean.toString( viewedParameters ) );
+ lessonProperties.setProperty( screen.getTitle() + ".viewedSource", Boolean.toString( viewedSource ) );
+ try
+ {
+ out = new FileOutputStream( fileName );
+ lessonProperties.store( out, s.getUserName() );
+ }
+ catch ( Exception e )
+ {
+ // what do we want to do, I think nothing.
+ System.out.println( "Warning User data for " + s.getUserName() + " will not persist" );
+ }
+ finally
+ {
+ try
+ {
+ out.close();
+ }
+ catch (Exception e) {}
+ }
+
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @return Description of the Return Value
+ */
+ public String toString()
+ {
+ StringBuffer buff = new StringBuffer();
+ buff.append( "LessonTracker:" + "\n" );
+ buff.append( " - completed:.......... " + completed + "\n" );
+ buff.append( " - currentStage:....... " + currentStage + "\n" );
+ buff.append( " - maxHintLevel:....... " + maxHintLevel + "\n" );
+ buff.append( " - numVisits:.......... " + numVisits + "\n" );
+ buff.append( " - viewedCookies:...... " + viewedCookies + "\n" );
+ buff.append( " - viewedHtml:......... " + viewedHtml + "\n" );
+ buff.append( " - viewedLessonPlan:... " + viewedLessonPlan + "\n" );
+ buff.append( " - viewedParameters:... " + viewedParameters + "\n" );
+ buff.append( " - viewedSource:....... " + viewedSource + "\n" + "\n" );
+ return buff.toString();
+ }
+
+ /**
+ * @return Returns the lessonProperties.
+ */
+ public Properties getLessonProperties()
+ {
+ return lessonProperties;
+ }
+
+ /**
+ * @param lessonProperties The lessonProperties to set.
+ */
+ public void setLessonProperties(Properties lessonProperties)
+ {
+ this.lessonProperties = lessonProperties;
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/Parameter.java b/ webgoat/main/project/org/owasp/webgoat/session/Parameter.java
new file mode 100644
index 000000000..1374df68e
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/Parameter.java
@@ -0,0 +1,46 @@
+package org.owasp.webgoat.session;
+
+public class Parameter implements Comparable {
+
+ String name;
+ String value;
+
+ public Parameter(String name, String value) {
+ this.name=name;
+ this.value=value;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+
+ //@Override
+ public boolean equals(Object obj) {
+ if ( obj instanceof Parameter )
+ {
+ Parameter other = (Parameter)obj;
+ return ( name.equals( other.getName() ) && value.equals( other.getValue() ) );
+ }
+ return false;
+ }
+
+ //@Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ //@Override
+ public String toString() {
+ return( name + "=" + value );
+ }
+
+ public int compareTo(Object o) {
+ return toString().compareTo( o.toString() );
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/ParameterNotFoundException.java b/ webgoat/main/project/org/owasp/webgoat/session/ParameterNotFoundException.java
new file mode 100644
index 000000000..a843615a3
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/ParameterNotFoundException.java
@@ -0,0 +1,32 @@
+package org.owasp.webgoat.session;
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of
+ * the Open Web Application Security Project (http://www.owasp.org) This
+ * software package org.owasp.webgoat.is published by OWASP under the GPL. You should read and
+ * accept the LICENSE before you use, modify and/or redistribute this software.
+ *
+ * @author Jeff Williams Aspect Security
+ */
+public class ParameterNotFoundException extends Exception
+{
+ /**
+ * Constructs a new ParameterNotFoundException with no detail message.
+ */
+ public ParameterNotFoundException()
+ {
+ super();
+ }
+
+
+ /**
+ * Constructs a new ParameterNotFoundException with the specified detail
+ * message.
+ *
+ *@param s the detail message
+ */
+ public ParameterNotFoundException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/ParameterParser.java b/ webgoat/main/project/org/owasp/webgoat/session/ParameterParser.java
new file mode 100644
index 000000000..b10bac0e8
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/ParameterParser.java
@@ -0,0 +1,1032 @@
+package org.owasp.webgoat.session;
+
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.regex.Pattern;
+
+import javax.servlet.ServletRequest;
+
+import org.owasp.webgoat.util.HtmlEncoder;
+
+
+/**
+ * Copyright (c) 2002-2004 Free Software Foundation developed under the custody of
+ * the Open Web Application Security Project (http://www.owasp.org) This
+ * software package org.owasp.webgoat.is published by OWASP under the GPL. You should read and
+ * accept the LICENSE before you use, modify and/or redistribute this software.
+ *
+ * @author Jeff Williams Aspect Security
+ */
+public class ParameterParser
+{
+ private final static String ALLOWED_CHARACTERS = "$()-?.@!,:;=//+"; // Don't allow #& specifically
+ private ServletRequest request;
+
+ /**
+ * Constructs a new ParameterParser to handle the parameters of the given
+ * request.
+ *
+ *@param request the servlet request
+ */
+ public ParameterParser(ServletRequest request)
+ {
+ this.request = request;
+ }
+
+ /**
+ * Description of the Method
+ *
+ *@param s Description of the Parameter
+ *@return Description of the Return Value
+ */
+ private String clean(String s)
+ {
+ StringBuffer clean = new StringBuffer();
+
+ for (int loop = 0; loop < s.length(); loop++)
+ {
+ char c = s.charAt(loop);
+
+ if (Character.isLetterOrDigit(c) || Character.isWhitespace(c) || (ALLOWED_CHARACTERS.indexOf(c) != -1))
+ {
+ clean.append(c);
+ }
+ else
+ {
+ clean.append('.');
+ }
+ }
+
+ return (clean.toString());
+ }
+
+
+ /**
+ * Gets the named parameter value as a boolean
+ *
+ *@param name the parameter name
+ *@return the parameter value as a boolean
+ *@exception ParameterNotFoundException if the parameter was not found
+ */
+ public boolean getBooleanParameter(String name) throws ParameterNotFoundException
+ {
+ return new Boolean(getStringParameter(name)).booleanValue();
+ }
+
+
+ /**
+ * Gets the named parameter value as a boolean, with a default. Returns the
+ * default value if the parameter is not found.
+ *
+ *@param name the parameter name
+ *@param def the default parameter value
+ *@return the parameter value as a boolean, or the default
+ */
+ public boolean getBooleanParameter(String name, boolean def)
+ {
+ try
+ {
+ return getBooleanParameter(name);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Gets the booleanSubParameter attribute of the ParameterParser object
+ *
+ *@param first Description of the Parameter
+ *@param next Description of the Parameter
+ *@param def Description of the Parameter
+ *@return The booleanSubParameter value
+ */
+ public boolean getBooleanSubParameter(String first, String next, boolean def)
+ {
+ try
+ {
+ return new Boolean(getSubParameter(first, next)).booleanValue();
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Gets the named parameter value as a byte
+ *
+ *@param name the parameter name
+ *@return the parameter value as a byte
+ *@exception ParameterNotFoundException if the parameter was not found
+ *@exception NumberFormatException if the parameter value could not be
+ * converted to a byte
+ */
+ public byte getByteParameter(String name) throws ParameterNotFoundException, NumberFormatException
+ {
+ return Byte.parseByte(getStringParameter(name));
+ }
+
+
+ /**
+ * Gets the named parameter value as a byte, with a default. Returns the
+ * default value if the parameter is not found or cannot be converted to a
+ * byte.
+ *
+ *@param name the parameter name
+ *@param def the default parameter value
+ *@return the parameter value as a byte, or the default
+ */
+ public byte getByteParameter(String name, byte def)
+ {
+ try
+ {
+ return getByteParameter(name);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Gets the named parameter value as a char
+ *
+ *@param name the parameter name
+ *@return the parameter value as a char
+ *@exception ParameterNotFoundException if the parameter was not found or was
+ * the empty string
+ */
+ public char getCharParameter(String name) throws ParameterNotFoundException
+ {
+ String param = getStringParameter(name);
+
+ if (param.length() == 0)
+ {
+ throw new ParameterNotFoundException(name + " is empty string");
+ }
+ else
+ {
+ return (param.charAt(0));
+ }
+ }
+
+
+ /**
+ * Gets the named parameter value as a char, with a default. Returns the
+ * default value if the parameter is not found.
+ *
+ *@param name the parameter name
+ *@param def the default parameter value
+ *@return the parameter value as a char, or the default
+ */
+ public char getCharParameter(String name, char def)
+ {
+ try
+ {
+ return getCharParameter(name);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Gets the classNameParameter attribute of the ParameterParser object
+ *
+ *@param name Description of the Parameter
+ *@return The classNameParameter value
+ */
+ public String getClassNameParameter(String name) throws ParameterNotFoundException
+ {
+ String p = getStringParameter(name);
+ StringTokenizer st = new StringTokenizer(p);
+
+ return (st.nextToken().trim());
+ }
+
+
+ // FIXME: check for [a-zA-Z].([a-zA-Z])*
+
+ /**
+ * Gets the classNameParameter attribute of the ParameterParser object
+ *
+ *@param name Description of the Parameter
+ *@param def Description of the Parameter
+ *@return The classNameParameter value
+ */
+ public String getClassNameParameter(String name, String def)
+ {
+ try
+ {
+ return getClassNameParameter(name);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Gets the named parameter value as a double
+ *
+ *@param name the parameter name
+ *@return the parameter value as a double
+ *@exception ParameterNotFoundException if the parameter was not found
+ *@exception NumberFormatException if the parameter could not be
+ * converted to a double
+ */
+ public double getDoubleParameter(String name) throws ParameterNotFoundException, NumberFormatException
+ {
+ return new Double(getStringParameter(name)).doubleValue();
+ }
+
+
+ /**
+ * Gets the named parameter value as a double, with a default. Returns the
+ * default value if the parameter is not found.
+ *
+ *@param name the parameter name
+ *@param def the default parameter value
+ *@return the parameter value as a double, or the default
+ */
+ public double getDoubleParameter(String name, double def)
+ {
+ try
+ {
+ return getDoubleParameter(name);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Gets the named parameter value as a float
+ *
+ *@param name the parameter name
+ *@return the parameter value as a float
+ *@exception ParameterNotFoundException if the parameter was not found
+ *@exception NumberFormatException if the parameter could not be
+ * converted to a float
+ */
+ public float getFloatParameter(String name) throws ParameterNotFoundException, NumberFormatException
+ {
+ return new Float(getStringParameter(name)).floatValue();
+ }
+
+
+ /**
+ * Gets the named parameter value as a float, with a default. Returns the
+ * default value if the parameter is not found.
+ *
+ *@param name the parameter name
+ *@param def the default parameter value
+ *@return the parameter value as a float, or the default
+ */
+ public float getFloatParameter(String name, float def)
+ {
+ try
+ {
+ return getFloatParameter(name);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Gets the named parameter value as an IP String, with a default. Returns the
+ * default value if the parameter is not found or is the empty string.
+ *
+ *@param name the parameter name
+ *@param def the default parameter value
+ *@return the parameter value as a String, or the default
+ */
+ public String getIPParameter(String name, String def)
+ {
+ try
+ {
+ return getIPParameter(name);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Gets the named parameter value as an IP String
+ *
+ *@param name the parameter name
+ *@return the parameter value as a valid IP
+ * String or an Empty string if invalid
+ *@exception ParameterNotFoundException if the parameter was not found or was
+ * the empty string
+ */
+ public String getIPParameter(String name) throws ParameterNotFoundException
+ {
+ boolean valid = true;
+ String[] values = request.getParameterValues(name);
+ String value;
+
+ if (values == null)
+ {
+ throw new ParameterNotFoundException(name + " not found");
+ }
+ else if (values[0].length() == 0)
+ {
+ throw new ParameterNotFoundException(name + " was empty");
+ }
+ else
+ {
+ // trim illegal characters
+ value = clean(values[0].trim());
+
+ if (value.indexOf("&") > 0)
+ {
+ // truncate additional parameters that follow &
+ value = value.substring(0, value.indexOf("&"));
+ }
+
+ // validate the IP ex: 124.143.12.254
+ int startIndex = 0;
+ int endIndex = 0;
+ int octetCount = 0;
+ int octetValue;
+ String octet;
+
+ // if no .'s then it's not an IP
+ if (value.indexOf(".") >= 0)
+ {
+ while ((valid == true) && (octetCount < 4))
+ {
+ endIndex = value.indexOf(".", startIndex);
+
+ if (endIndex == -1)
+ {
+ endIndex = value.length();
+ }
+
+ octet = value.substring(startIndex, endIndex);
+ startIndex = endIndex + 1;
+
+ try
+ {
+ octetValue = Integer.parseInt(octet);
+
+ if ((octetValue <= 0) || (octetValue >= 256))
+ {
+ valid = false;
+ }
+ }
+ catch (Exception e)
+ {
+ valid = false;
+ }
+
+ octetCount++;
+ }
+ }
+ else
+ {
+ // Not a valid IP
+ valid = false;
+ }
+
+ // Check for any extra garbage. If the last octet was a large value
+ // it would be trapped by the above range check.
+ if (value.length() != endIndex)
+ {
+ valid = false;
+ }
+
+ return valid ? value : null;
+ }
+ }
+
+
+ /**
+ * Gets the named parameter value as a int
+ *
+ *@param name the parameter name
+ *@return the parameter value as a int
+ *@exception ParameterNotFoundException if the parameter was not found
+ *@exception NumberFormatException if the parameter could not be
+ * converted to a int
+ */
+ public int getIntParameter(String name) throws ParameterNotFoundException, NumberFormatException
+ {
+ return Integer.parseInt(getStringParameter(name));
+ }
+
+
+ /**
+ * Gets the named parameter value as a int, with a default. Returns the
+ * default value if the parameter is not found.
+ *
+ *@param name the parameter name
+ *@param def the default parameter value
+ *@return the parameter value as a int, or the default
+ */
+ public int getIntParameter(String name, int def)
+ {
+ try
+ {
+ return getIntParameter(name);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Gets the named parameter value as a long
+ *
+ *@param name the parameter name
+ *@return the parameter value as a long
+ *@exception ParameterNotFoundException if the parameter was not found
+ *@exception NumberFormatException if the parameter could not be
+ * converted to a long
+ */
+ public long getLongParameter(String name) throws ParameterNotFoundException, NumberFormatException
+ {
+ return Long.parseLong(getStringParameter(name));
+ }
+
+
+ /**
+ * Gets the named parameter value as a long, with a default. Returns the
+ * default value if the parameter is not found.
+ *
+ *@param name the parameter name
+ *@param def the default parameter value
+ *@return the parameter value as a long, or the default
+ */
+ public long getLongParameter(String name, long def)
+ {
+ try
+ {
+ return getLongParameter(name);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Determines which of the required parameters were missing from the request.
+ * Returns null if all the parameters are present.
+ *
+ *@param requestuired Description of the Parameter
+ *@return an array of missing parameters, or null if none are
+ * missing
+ */
+ public String[] getMissingParameters(String[] requestuired)
+ {
+ Vector missing = new Vector();
+
+ for (int i = 0; i < requestuired.length; i++)
+ {
+ String val = getStringParameter(requestuired[i], null);
+
+ if (val == null)
+ {
+ missing.addElement(requestuired[i]);
+ }
+ }
+
+ if (missing.size() == 0)
+ {
+ return null;
+ }
+ else
+ {
+ String[] ret = new String[missing.size()];
+ missing.copyInto(ret);
+
+ return ret;
+ }
+ }
+
+
+ /**
+ * Gets the parameterNames attribute of the ParameterParser object
+ *
+ *@return The parameterNames value
+ */
+ public Enumeration getParameterNames()
+ {
+ if (request == null)
+ {
+ return (null);
+ }
+
+ return request.getParameterNames();
+ }
+
+
+ /**
+ * Gets the parameterValues attribute of the ParameterParser object
+ *
+ *@param name Description of the Parameter
+ *@return The parameterValues value
+ */
+ public String[] getParameterValues(String name)
+ {
+ if (request == null)
+ {
+ return (null);
+ }
+
+ return request.getParameterValues(name);
+ }
+
+
+ /**
+ * Gets the rawParameter attribute of the ParameterParser object
+ *
+ *@param name Description of the Parameter
+ *@param def Description of the Parameter
+ *@return The rawParameter value
+ */
+ public String getRawParameter(String name, String def)
+ {
+ try
+ {
+ return getRawParameter(name);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Gets the rawParameter attribute of the ParameterParser object
+ *
+ *@param name Description of the Parameter
+ *@return The rawParameter value
+ *@exception ParameterNotFoundException 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]);
+ }
+
+
+ /**
+ * Gets the named parameter value as a short
+ *
+ *@param name the parameter name
+ *@return the parameter value as a short
+ *@exception ParameterNotFoundException if the parameter was not found
+ *@exception NumberFormatException if the parameter could not be
+ * converted to a short
+ */
+ public short getShortParameter(String name) throws ParameterNotFoundException, NumberFormatException
+ {
+ return Short.parseShort(getStringParameter(name));
+ }
+
+
+ /**
+ * Gets the named parameter value as a short, with a default. Returns the
+ * default value if the parameter is not found.
+ *
+ *@param name the parameter name
+ *@param def the default parameter value
+ *@return the parameter value as a short, or the default
+ */
+ public short getShortParameter(String name, short def)
+ {
+ try
+ {
+ return getShortParameter(name);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Gets the named parameter value as a String
+ *
+ *@param name the parameter name
+ *@return the parameter value as a String
+ *@exception ParameterNotFoundException if the parameter was not found or was
+ * the empty string
+ */
+ public String getStringParameter(String name) throws ParameterNotFoundException
+ {
+ String[] values = request.getParameterValues(name);
+ String value;
+
+ if (values == null)
+ {
+ throw new ParameterNotFoundException(name + " not found");
+ }
+ else if (values[0].length() == 0)
+ {
+ throw new ParameterNotFoundException(name + " was empty");
+ }
+ else
+ {
+ // trim illegal characters
+ value = clean(values[0].trim());
+
+ if (value.indexOf("&") > 0)
+ {
+ // truncate additional parameters that follow &
+ value = value.substring(0, value.indexOf("&"));
+ }
+
+ return value;
+ }
+ }
+
+
+ /**
+ * Gets the named parameter value as a String, with a default. Returns the
+ * default value if the parameter is not found or is the empty string.
+ *
+ *@param name the parameter name
+ *@param def the default parameter value
+ *@return the parameter value as a String, or the default
+ */
+ public String getStringParameter(String name, String def)
+ {
+ try
+ {
+ return getStringParameter(name);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Gets the subParameter attribute of the ParameterParser object
+ *
+ *@param first Description of the Parameter
+ *@param next Description of the Parameter
+ *@param def Description of the Parameter
+ *@return The subParameter value
+ */
+ public String getSubParameter(String first, String next, String def)
+ {
+ try
+ {
+ return getSubParameter(first, next);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+
+ /**
+ * Gets the parameter named 'next' following the parameter 'first'. Presumes
+ * the structure: first=firstvalue&next=nextValue
+ *
+ *@param first Description of the Parameter
+ *@param next Description of the Parameter
+ *@return The subParameter value
+ *@exception ParameterNotFoundException Description of the Exception
+ */
+ public String getSubParameter(String first, String next) throws ParameterNotFoundException
+ {
+ String[] values = request.getParameterValues(first);
+ String value;
+
+ if (values == null)
+ {
+ throw new ParameterNotFoundException(first + " not found");
+ }
+ else if (values[0].length() == 0)
+ {
+ throw new ParameterNotFoundException(first + " was empty");
+ }
+ else
+ {
+ value = clean(values[0].trim());
+
+ int idx = value.indexOf("&") + 1;
+
+ // index of first char of first sub-param name
+ if (idx == 0)
+ {
+ throw new ParameterNotFoundException("No subparameter key");
+ }
+
+ value = value.substring(idx);
+
+ //System.out.println("= = = = = =Parameter parser looking for " + next + " in " + value );
+ int nextValueIndex = value.indexOf(next + "=");
+
+ //System.out.println("= = = = = =Parameter parser nextValueIndex = " + nextValueIndex );
+ if (nextValueIndex < 0)
+ {
+ throw new ParameterNotFoundException("No subparameter value");
+ }
+
+ nextValueIndex += (next.length() + 1);
+
+ if (nextValueIndex >= 0)
+ {
+ value = value.substring(nextValueIndex);
+ }
+ else
+ {
+ throw new ParameterNotFoundException(next + " not found");
+ }
+ }
+
+ if (value.indexOf("&") > 0)
+ {
+ // truncate additional parameters that follow &
+ value = value.substring(0, value.indexOf("&"));
+ }
+
+ //System.out.println("=-=-=-=-=ParameterParser returning value " + value );
+ return value;
+ }
+
+
+ /**
+ * Gets the wordParameter attribute of the ParameterParser object
+ *
+ *@param name Description of the Parameter
+ *@return The wordParameter value
+ */
+ public String getWordParameter(String name) throws ParameterNotFoundException
+ {
+ String p = getStringParameter(name);
+ StringTokenizer st = new StringTokenizer(p);
+
+ return (st.nextToken().trim());
+ }
+
+
+ // FIXME: check for [a-zA-Z]
+
+ /**
+ * Gets the wordParameter attribute of the ParameterParser object
+ *
+ *@param name Description of the Parameter
+ *@param def Description of the Parameter
+ *@return The wordParameter value
+ */
+ public String getWordParameter(String name, String def)
+ {
+ try
+ {
+ return getWordParameter(name);
+ }
+ catch (Exception e)
+ {
+ return def;
+ }
+ }
+
+ /**
+ * Gets the specified parameter from the request and validates it against the provided regular expression.
+ * If the regular expression check fails, the default value is returned instead.
+ *
+ *@param name The name of the parameter to retrieve from the request.
+ *@param def The default value of the parameter.
+ *@param regexpattern The precompiled regular expression to be used to validate the parameter.
+ *@return The validated parameter value, or the default value if validation failed.
+ */
+ private String getRegexParameter(String name, String def, Pattern regexpattern) throws ValidationException
+ {
+ try
+ {
+ return getRegexParameter(name, regexpattern);
+ }
+ catch (Exception e)
+ {
+ //System.out.println("Exception occured in defined pattern match");
+ //e.printStackTrace();
+ return def;
+ }
+ }
+
+ /**
+ * Gets the specified parameter from the request and validates it against the provided regular expression.
+ * If the regular expression check fails, the default value is returned instead.
+ *
+ *@param name The name of the parameter to retrieve from the request.
+ *@param def The default value of the parameter.
+ *@param regexpattern The precompiled regular expression to be used to validate the parameter.
+ *@return The validated parameter value, or the default value if validation failed.
+ */
+ private String getRegexParameter(String name, Pattern regexpattern)
+ throws ParameterNotFoundException, ValidationException
+ {
+ String param = getStringParameter( name );
+
+ if ( regexpattern.matcher( param ).matches() )
+ {
+ return param;
+ }
+ else
+ {
+ //System.out.println(param + " didn't match defined pattern.");
+ throw new ValidationException(name + " contained an invalid value");
+ }
+ }
+
+
+
+ public String getStrictAlphaParameter(String name, int maxLength)
+ throws ParameterNotFoundException, ValidationException
+ {
+ String alphaRegEx = "^[a-zA-Z\\s]{0," + maxLength + "}$";
+ Pattern alphaPattern = Pattern.compile(alphaRegEx);
+
+ return getRegexParameter(name, alphaPattern);
+ }
+
+
+
+ public String getStrictNumericParameter(String name, int maxLength)
+ throws ParameterNotFoundException, ValidationException
+ {
+ String numericRegEx = "^\\d{0," + maxLength + "}$";
+ Pattern numericPattern = Pattern.compile(numericRegEx);
+
+ return getRegexParameter(name, numericPattern);
+ }
+
+
+
+ private static final String SSNREGEX = "^\\d{3}-\\d{2}-\\d{4}$";
+ private static final Pattern Ssnpattern = Pattern.compile(SSNREGEX);
+
+ public String getSsnParameter(String name) throws ParameterNotFoundException, ValidationException
+ {
+ return getRegexParameter(name, Ssnpattern);
+ }
+
+
+ // Validates format for major brands of credit card.
+ //private static final String CCNREGEX = "^(?:(?4\\d{3})|(?5[1-5]\\d{2})|(?6011)|(?(?:3[68]\\d{2})|(?:30[0-5]\\d))|(?3[47]\\d{2}))([ -]?)(?(DinersClub)(?:\\d{6}\\1\\d{4})|(?(AmericanExpress)(?:\\d{6}\\1\\d{5})|(?:\\d{4}\\1\\d{4}\\1\\d{4})))$";
+ private static final String CCNREGEX = "^\\d{16}$";
+ private static final Pattern Ccnpattern = Pattern.compile(CCNREGEX);
+
+ public String getCcnParameter(String name) throws ParameterNotFoundException, ValidationException
+ {
+ return getRegexParameter(name, Ccnpattern);
+ }
+
+
+ private static final String ZIPREGEX = "^\\d{5}(-\\d{4})?$";
+ private static final Pattern Zippattern = Pattern.compile( ZIPREGEX );
+
+ public String getZipParameter(String name) throws ParameterNotFoundException, ValidationException
+ {
+ return getZipParameter(name, null);
+ }
+
+ public String getZipParameter(String name, String def) throws ValidationException
+ {
+ return getRegexParameter(name, def, Zippattern);
+ }
+
+
+ private static final String PHONEREGEX = "^\\(?[\\d]{3}\\)?[\\s-]?[\\d]{3}[\\s-]?[\\d]{4}$";
+ // Or this more forgiving pattern:
+ //private static final String PHONEREGEX = "^([\\-()+ 0-9x])+$";
+ private static final Pattern phonepattern = Pattern.compile( PHONEREGEX );
+
+ public String getPhoneParameter(String name) throws ParameterNotFoundException, ValidationException
+ {
+ return getPhoneParameter(name, null);
+ }
+
+ public String getPhoneParameter(String name, String def) throws ValidationException
+ {
+ return getRegexParameter(name, def, phonepattern);
+ }
+
+
+ private static final String EMAILREGEX = "^[\\w-]+(?:\\.[\\w-]+)*@(?:[\\w-]+\\.)+[a-zA-Z]{2,7}$";
+ private static final Pattern emailpattern = Pattern.compile( EMAILREGEX );
+
+ public String getEMailParameter(String name) throws ParameterNotFoundException, ValidationException
+ {
+ return getEMailParameter(name, null);
+ }
+
+ public String getEMailParameter(String name, String def) throws ValidationException
+ {
+ return getRegexParameter(name, def, emailpattern);
+ }
+
+
+ private static final String DATEREGEX = "([\\/ .,:0-9a-zA-Z])+$";
+ private static final Pattern datepattern = Pattern.compile( DATEREGEX );
+
+ public String getDateParameter(String name) throws ParameterNotFoundException, ValidationException
+ {
+ return getDateParameter(name, null);
+ }
+
+ public String getDateParameter(String name, String def) throws ValidationException
+ {
+ return getRegexParameter(name, def, datepattern);
+ }
+
+
+ private static final String URLREGEX = "^(((https?)://)([-()_.!~*';/?:@&=+$,A-Za-z0-9])+)([).!';/?:,][[:blank:]])?$";
+ private static final Pattern URLpattern = Pattern.compile( URLREGEX );
+
+ public String getURLParameter(String name) throws ParameterNotFoundException, ValidationException
+ {
+ return getURLParameter(name, null);
+ }
+
+ public String getURLParameter(String name, String def) throws ValidationException
+ {
+ return getRegexParameter(name, def, URLpattern);
+ }
+
+
+ protected static String htmlEncode(String s)
+ {
+ return HtmlEncoder.encode(s);
+ }
+
+ /**
+ * Description of the Method
+ *
+ *@return Description of the Return Value
+ */
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer("[");
+ Enumeration e = getParameterNames();
+
+ while (e.hasMoreElements())
+ {
+ String key = (String) e.nextElement();
+ s.append(key + "=" + getParameterValues(key)[0]);
+
+ // FIXME: Other values?
+ if (e.hasMoreElements())
+ {
+ s.append(",");
+ }
+ }
+
+ s.append("]");
+
+ return (s.toString());
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ *@param request Description of the Parameter
+ */
+ public void update(ServletRequest request)
+ {
+ this.request = request;
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/Screen.java b/ webgoat/main/project/org/owasp/webgoat/session/Screen.java
new file mode 100644
index 000000000..023f9788c
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/Screen.java
@@ -0,0 +1,328 @@
+package org.owasp.webgoat.session;
+
+import java.io.PrintWriter;
+import java.util.Properties;
+
+import org.apache.ecs.Element;
+import org.apache.ecs.HtmlColor;
+import org.apache.ecs.StringElement;
+import org.apache.ecs.html.A;
+import org.apache.ecs.html.B;
+import org.apache.ecs.html.Font;
+import org.apache.ecs.html.IMG;
+import org.apache.ecs.html.TD;
+import org.owasp.webgoat.lessons.AbstractLesson;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public abstract class Screen
+{
+ /**
+ * Description of the Field
+ */
+ public static int MAIN_SIZE = 375;
+
+
+ //private Head head;
+ private Element content;
+ private LessonTracker lessonTracker;
+ final static IMG logo = new IMG( "images/aspectlogo-horizontal-small.jpg" ).setAlt( "Aspect Security" ).setBorder( 0 ).setHspace( 0 ).setVspace( 0 );
+
+
+ /**
+ * Constructor for the Screen object
+ */
+
+ public Screen() { }
+
+
+ // FIXME: Each lesson should have a role assigned to it. Each user/student
+ // should also have a role(s) assigned. The user would only be allowed
+ // to see lessons that correspond to their role. Eventually these roles
+ // will be stored in the internal database. The user will be able to hack
+ // into the database and change their role. This will allow the user to
+ // see the admin screens, once they figure out how to turn the admin switch on.
+ public abstract String getRole();
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ protected abstract Element createContent( WebSession s );
+
+
+
+ /**
+ * Gets the credits attribute of the Screen object
+ *
+ * @return The credits value
+ */
+ public abstract Element getCredits();
+
+
+ /**
+ * Creates a new lessonTracker object.
+ *
+ * @param props The properties file that was used to persist the user data.
+ * @return Description of the Return Value
+ */
+
+ public LessonTracker createLessonTracker( Properties props )
+ {
+
+ // If the lesson had any specialized properties in the user persisted properties,
+ // now would be the time to pull them out.
+
+ lessonTracker = createLessonTracker();
+ return lessonTracker;
+ }
+
+
+ /**
+ * This allows the screens to provide a custom LessonTracker object if needed.
+ *
+ * @return Description of the Return Value
+ */
+ public LessonTracker createLessonTracker()
+ {
+ lessonTracker = new LessonTracker();
+ return lessonTracker;
+ }
+
+
+
+ /**
+ * Gets the lessonTracker attribute of the AbstractLesson object
+ *
+ * @param userName Description of the Parameter
+ * @return The lessonTracker value
+ */
+
+ public LessonTracker getLessonTracker( WebSession s )
+ {
+ UserTracker userTracker = UserTracker.instance();
+ return userTracker.getLessonTracker( s, this );
+ }
+
+ public LessonTracker getLessonTracker( WebSession s, String userNameOverride )
+ {
+ UserTracker userTracker = UserTracker.instance();
+ return userTracker.getLessonTracker( s, userNameOverride, this );
+ }
+
+
+ public LessonTracker getLessonTracker( WebSession s, AbstractLesson lesson )
+ {
+ UserTracker userTracker = UserTracker.instance();
+ return userTracker.getLessonTracker( s, lesson );
+ }
+
+ /**
+ * Fill in a descriptive title for this lesson
+ *
+ * @return The title value
+ */
+ public abstract String getTitle();
+
+
+ protected void setContent(Element content)
+ {
+ this.content = content;
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @return Description of the Return Value
+ */
+
+ protected Element makeLogo()
+ {
+
+ return new A("http://www.aspectsecurity.com/webgoat.html", logo);
+ }
+
+ public String getSponsor()
+ {
+ return "Aspect Security";
+ }
+
+ public String getSponsorLogoResource()
+ {
+ return "images/aspectlogo-horizontal-small.jpg";
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param text Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ protected TD makeMenuCategory_DELETE_ME( String text )
+ {
+ return ( new TD().setWidth( "100%" ).addElement( new Font().setColor( HtmlColor.WHITE ).addElement( new B().addElement( text ) ) ) );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ protected Element makeMessages( WebSession s )
+ {
+
+ if ( s == null )
+ {
+
+ return ( new StringElement( "" ) );
+ }
+
+ Font f = new Font().setColor( HtmlColor.RED );
+
+ String message = s.getMessage();
+
+ f.addElement( message );
+
+ return ( f );
+ }
+
+
+
+ /**
+ * Returns the content length of the the html.
+ *
+ */
+
+ public int getContentLength()
+ {
+ return content.toString().length();
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param out Description of the Parameter
+ */
+
+ public void output( PrintWriter out )
+ {
+
+ // format output -- then send to printwriter
+
+ // otherwise we're doing way too much SSL encryption work
+
+ out.print( content.toString() );
+
+ }
+
+ public String getContent()
+ {
+ return (content == null) ? "" : content.toString();
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param x Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ protected static String pad( int x )
+ {
+
+ StringBuffer sb = new StringBuffer();
+
+ if ( x < 10 )
+ {
+
+ sb.append( " " );
+
+ }
+
+ if ( x < 100 )
+ {
+
+ sb.append( " " );
+
+ }
+
+ sb.append( x );
+
+ return ( sb.toString() );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param token Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected static String convertMetachars( String token )
+ {
+
+ int mci = 0;
+
+ /*
+ * meta char array
+ *
+ * FIXME: Removed the conversion of whitespace " " to " " in order for the
+ * html to be automatically wrapped in client browser. It is better to add line
+ * length checking and only do " " conversion in lines that won't exceed
+ * screen size, say less than 80 characters.
+ */
+ String[] metaChar = {"&", "<", ">", "\"", "\t", System.getProperty("line.separator")};
+
+ String[] htmlCode = {"&", "<", ">", """, " ", "
"};
+
+ String replacedString = token;
+ for ( ; mci < metaChar.length; mci += 1 )
+ {
+ replacedString = replacedString.replaceAll( metaChar[mci], htmlCode[mci] );
+ }
+ return ( replacedString );
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @param token Description of the Parameter
+ * @return Description of the Return Value
+ */
+ protected static String convertMetacharsJavaCode( String token )
+ {
+ return( convertMetachars(token).replaceAll(" ", " ") );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param s Description of the Parameter
+ * @return Description of the Return Value
+ */
+
+ //protected abstract Element wrapForm( WebSession s );
+
+}
+
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/UnauthenticatedException.java b/ webgoat/main/project/org/owasp/webgoat/session/UnauthenticatedException.java
new file mode 100644
index 000000000..290b3c987
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/UnauthenticatedException.java
@@ -0,0 +1,6 @@
+package org.owasp.webgoat.session;
+
+public class UnauthenticatedException extends Exception
+{
+
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/UnauthorizedException.java b/ webgoat/main/project/org/owasp/webgoat/session/UnauthorizedException.java
new file mode 100644
index 000000000..4e1b7a128
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/UnauthorizedException.java
@@ -0,0 +1,6 @@
+package org.owasp.webgoat.session;
+
+public class UnauthorizedException extends Exception
+{
+
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/UserTracker.java b/ webgoat/main/project/org/owasp/webgoat/session/UserTracker.java
new file mode 100644
index 000000000..2389c979c
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/UserTracker.java
@@ -0,0 +1,243 @@
+package org.owasp.webgoat.session;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.catalina.Role;
+import org.apache.catalina.User;
+import org.apache.catalina.users.MemoryUserDatabase;
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 29, 2003
+ */
+
+public class UserTracker
+{
+
+ private static UserTracker instance;
+
+ // FIXME: persist this somehow!
+
+ private static HashMap storage = new HashMap();
+
+ private static MemoryUserDatabase usersDB = new MemoryUserDatabase();
+
+
+ /**
+ * Constructor for the UserTracker object
+ */
+ private UserTracker() { }
+
+
+
+ /**
+ * Gets the completed attribute of the UserTracker object
+ *
+ * @param userName Description of the Parameter
+ * @return The completed value
+ */
+ public int getCompleted( String userName )
+ {
+
+ HashMap usermap = getUserMap( userName );
+
+ Iterator i = usermap.entrySet().iterator();
+
+ int count = 0;
+
+ while ( i.hasNext() )
+ {
+
+ Map.Entry entry = (Map.Entry) i.next();
+
+ int value = ( (Integer) entry.getValue() ).intValue();
+
+ if ( value > 5 )
+ {
+ count++;
+ }
+
+ }
+
+ return count;
+ }
+
+
+ /**
+ * Gets the users attribute of the UserTracker object
+ *
+ * @return The users value
+ */
+ public Collection getUsers()
+ {
+ return storage.keySet();
+ }
+
+ public Collection getAllUsers(String roleName)
+ {
+ synchronized ( usersDB ) {
+ Collection allUsers = new ArrayList();
+ try {
+ usersDB.open();
+ Iterator users = usersDB.getUsers();
+ while (users.hasNext())
+ {
+ User user = (User) users.next();
+ Iterator roles = user.getRoles();
+ while( roles.hasNext() )
+ {
+ Role role = (Role)roles.next();
+ if ( role.getRolename().trim().equals(roleName))
+ {
+ allUsers.add( user.getUsername() );
+ }
+ }
+ }
+ usersDB.close();
+ }
+ catch ( Exception e )
+ {}
+ return allUsers;
+ }
+ }
+
+ public void deleteUser( String user )
+ {
+ synchronized ( usersDB ) {
+ try
+ {
+ usersDB.open();
+ Iterator users = usersDB.getUsers();
+ while (users.hasNext())
+ {
+ User tomcatUser = (User) users.next();
+ if ( tomcatUser.getUsername().equals( user ) )
+ {
+ usersDB.removeUser(tomcatUser);
+ // FIXME: delete all the lesson tracking property files
+ break;
+ }
+ }
+ usersDB.close();
+
+ }
+ catch ( Exception e )
+ {}
+ }
+ }
+
+ /**
+ * Gets the lessonTracker attribute of the UserTracker object
+ *
+ * @param screen Description of the Parameter
+ * @param userName Description of the Parameter
+ * @return The lessonTracker value
+ */
+ public LessonTracker getLessonTracker( WebSession s, Screen screen )
+ {
+ return getLessonTracker(s, s.getUserName(), screen );
+ }
+
+ public LessonTracker getLessonTracker( WebSession s, String user, Screen screen )
+ {
+ HashMap usermap = getUserMap( user );
+ LessonTracker tracker = (LessonTracker) usermap.get( screen.getTitle() );
+ if ( tracker == null )
+ {
+ // Creates a new lesson tracker, if one does not exist on disk.
+ tracker = LessonTracker.load( s, user, screen );
+ usermap.put( screen.getTitle(), tracker );
+ }
+ //System.out.println( "User: [" + userName + "] UserTracker:getLessonTracker() LTH " + tracker.hashCode() + " for " + screen );
+ return tracker;
+ }
+
+
+ /**
+ * Gets the status attribute of the UserTracker object
+ *
+ * @param screen Description of the Parameter
+ * @param userName Description of the Parameter
+ * @return The status value
+ */
+ public String getStatus( WebSession s, Screen screen )
+ {
+ return ( "User [" + s.getUserName() + "] has accessed " + screen + " UserTracker:getStatus()LTH = " + getLessonTracker( s, screen ).hashCode() );
+ }
+
+
+
+ /**
+ * Gets the userMap attribute of the UserTracker object
+ *
+ * @param userName Description of the Parameter
+ * @return The userMap value
+ */
+ private HashMap getUserMap( String userName )
+ {
+
+ HashMap usermap = (HashMap) storage.get( userName );
+
+ if ( usermap == null )
+ {
+
+ usermap = new HashMap();
+
+ storage.put( userName, usermap );
+
+ }
+
+ return ( usermap );
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @return Description of the Return Value
+ */
+ public static synchronized UserTracker instance()
+ {
+
+ if ( instance == null )
+ {
+
+ instance = new UserTracker();
+
+ }
+
+ return instance;
+ }
+
+
+
+ /**
+ * Description of the Method
+ *
+ * @param screen Description of the Parameter
+ * @param s Description of the Parameter
+ */
+ public void update( WebSession s, Screen screen )
+ {
+
+ LessonTracker tracker = getLessonTracker( s, screen );
+
+ //System.out.println( "User [" + s.getUserName() + "] TRACKER: updating " + screen + " LTH " + tracker.hashCode() );
+ tracker.store( s, screen );
+
+ HashMap usermap = getUserMap( s.getUserName() );
+ usermap.put( screen.getTitle(), tracker );
+
+ }
+
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/ValidationException.java b/ webgoat/main/project/org/owasp/webgoat/session/ValidationException.java
new file mode 100644
index 000000000..6e7a0b419
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/ValidationException.java
@@ -0,0 +1,14 @@
+package org.owasp.webgoat.session;
+
+public class ValidationException extends Exception
+{
+ public ValidationException()
+ {
+ super();
+ }
+
+ public ValidationException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/WebSession.java b/ webgoat/main/project/org/owasp/webgoat/session/WebSession.java
new file mode 100644
index 000000000..d92b15090
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/WebSession.java
@@ -0,0 +1,1185 @@
+package org.owasp.webgoat.session;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.Category;
+import org.owasp.webgoat.lessons.admin.RefreshDBScreen;
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is
+ * published by OWASP under the GPL. You should read and accept the LICENSE before you use, modify
+ * and/or redistribute this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public class WebSession
+{
+ /**
+ * Description of the Field
+ */
+ public final static String ADMIN = "admin";
+
+ /**
+ * Tomcat role for a webgoat user
+ */
+ public final static String WEBGOAT_USER = "webgoat_user";
+
+ /**
+ * Tomcat role for a webgoat admin
+ */
+ public final static String WEBGOAT_ADMIN = "webgoat_admin";
+
+ /**
+ * Description of the Field
+ */
+ public final static String CHALLENGE = "Challenge";
+
+ /**
+ * Description of the Field
+ */
+ public final static String COLOR = "color";
+
+ /**
+ * Description of the Field
+ */
+ public final static String DATABASE_CONNECTION_STRING = "DatabaseConnectionString";
+
+ /**
+ * Description of the Field
+ */
+ public final static String DATABASE_DRIVER = "DatabaseDriver";
+
+ /**
+ * Description of the Field
+ */
+ public final static int ERROR = 0;
+
+ public static final String STAGE = "stage";
+
+ /**
+ * Description of the Field
+ */
+ public final static String JSESSION_ID = "jsessionid";
+
+ /**
+ * Description of the Field
+ */
+ public final static String LOGOUT = "Logout";
+
+ /**
+ * Description of the Field
+ */
+ public final static String RESTART = "Restart";
+
+
+ /**
+ * Description of the Field
+ */
+ public final static String MENU = "menu";
+
+ /**
+ * Description of the Field
+ */
+ public final static String SCREEN = "Screen";
+
+ /**
+ * Description of the Field
+ */
+ public final static String SESSION = "Session";
+
+ /**
+ * Description of the Field
+ */
+ public final static String ENTERPRISE = "Enterprise";
+
+ /**
+ * Description of the Field
+ */
+ public final static String SHOWCOOKIES = "ShowCookies";
+
+ /**
+ * Description of the Field
+ */
+ public final static String SHOWPARAMS = "ShowParams";
+
+ /**
+ * Description of the Field
+ */
+ public final static String SHOWREQUEST = "ShowRequest";
+
+ /**
+ * Description of the Field
+ */
+ public final static String SHOWSOURCE = "ShowSource";
+
+ public final static String SHOWHINTS = "ShowHints";
+
+ public final static String SHOW = "show";
+
+ public final static String SHOW_NEXTHINT = "NextHint";
+
+ public final static String SHOW_PREVIOUSHINT = "PreviousHint";
+
+ public final static String SHOW_PARAMS = "Params";
+
+ public final static String SHOW_COOKIES = "Cookies";
+
+ public final static String SHOW_SOURCE = "Source";
+
+ /**
+ * Description of the Field
+ */
+ public final static String DEFUSEOSCOMMANDS = "DefuseOSCommands";
+
+ /**
+ * Description of the Field
+ */
+ public final static String FEEDBACK_ADDRESS = "FeedbackAddress";
+
+ /**
+ * Description of the Field
+ */
+ public final String DEBUG = "debug";
+
+ /**
+ * Description of the Field
+ */
+ public final static int WELCOME = -1;
+
+ private ServletContext context = null;
+
+ private Course course;
+
+ private int currentScreen = WELCOME;
+
+ private int previousScreen = ERROR;
+
+ private static boolean databaseBuilt = false;
+
+ private String databaseConnectionString;
+
+ private String databaseDriver;
+
+ private static Connection connection = null;
+
+ private int hintNum = -1;
+
+ private boolean isAdmin = false;
+
+ private boolean isHackedAdmin = false;
+
+ private boolean isAuthenticated = false;
+
+ private boolean isColor = false;
+
+ private boolean isDebug = false;
+
+ private boolean hasHackedHackableAdmin = false;
+
+ private StringBuffer message = new StringBuffer( "" );
+
+ private ParameterParser myParser;
+
+ private HttpServletRequest request = null;
+
+ private HttpServletResponse response = null;
+
+ private String servletName;
+
+ private HashMap session = new HashMap();
+
+ private boolean showCookies = false;
+
+ private boolean showParams = false;
+
+ private boolean showRequest = false;
+
+ private boolean showSource = false;
+
+ private boolean defuseOSCommands = false;
+
+ private boolean enterprise = false;
+
+ private String feedbackAddress = "webgoat@aspectsecurity.com";
+
+ private boolean completedHackableAdmin = false;
+
+ private int currentMenu;
+
+ /**
+ * Constructor for the WebSession object
+ *
+ * @param servlet Description of the Parameter
+ * @param context Description of the Parameter
+ */
+ public WebSession( HttpServlet servlet, ServletContext context )
+ {
+ // initialize from web.xml
+ showParams = "true".equals( servlet.getInitParameter( SHOWPARAMS ) );
+ showCookies = "true".equals( servlet.getInitParameter( SHOWCOOKIES ) );
+ showSource = "true".equals( servlet.getInitParameter( SHOWSOURCE ) );
+ defuseOSCommands = "true".equals( servlet.getInitParameter( DEFUSEOSCOMMANDS ) );
+ enterprise = "true".equals( servlet.getInitParameter( ENTERPRISE ) );
+ feedbackAddress = servlet.getInitParameter( FEEDBACK_ADDRESS ) != null ? servlet
+ .getInitParameter( FEEDBACK_ADDRESS ) : feedbackAddress;
+ showRequest = "true".equals( servlet.getInitParameter( SHOWREQUEST ) );
+ isDebug = "true".equals( servlet.getInitParameter( DEBUG ) );
+ databaseConnectionString = servlet.getInitParameter( DATABASE_CONNECTION_STRING );
+ databaseDriver = servlet.getInitParameter( DATABASE_DRIVER );
+ servletName = servlet.getServletName();
+ this.context = context;
+ course = new Course();
+ course.loadCourses( enterprise, context, "/" );
+
+ // FIXME: hack to save context for web service calls
+ DatabaseUtilities.servletContextRealPath = context.getRealPath("/");
+ System.out.println("Context Path: " + DatabaseUtilities.servletContextRealPath);
+ // FIXME: need to solve concurrency problem here -- make tables for this user
+ if ( !databaseBuilt )
+ {
+ new RefreshDBScreen().refreshDB( this );
+ databaseBuilt = true;
+ }
+ }
+
+ public static synchronized Connection getConnection(WebSession s)
+ throws SQLException, ClassNotFoundException
+ {
+ if ( connection == null )
+ {
+ connection = DatabaseUtilities.makeConnection( s );
+ }
+
+ return connection;
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param key Description of the Parameter
+ * @param value Description of the Parameter
+ */
+ public void add( String key, Object value )
+ {
+ session.put( key, value );
+ }
+
+ /**
+ * Description of the Method
+ */
+ public void clearMessage()
+ {
+ message.setLength( 0 );
+ }
+
+ /**
+ * Description of the Method
+ */
+ public void eatCookies()
+ {
+ Cookie[] cookies = request.getCookies();
+
+ for ( int loop = 0; loop < cookies.length; loop++ )
+ {
+ if ( !cookies[loop].getName().startsWith( "JS" ) )
+ {// skip jsessionid cookie
+ cookies[loop].setMaxAge( 0 );// mark for deletion by browser
+ response.addCookie( cookies[loop] );
+ }
+ }
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @param key Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public Object get( String key )
+ {
+ return ( session.get( key ) );
+ }
+
+ /**
+ * Gets the context attribute of the WebSession object
+ *
+ * @return The context value
+ */
+ public ServletContext getContext()
+ {
+ return context;
+ }
+
+ public List getRoles()
+ {
+ List roles = new ArrayList();
+
+ roles.add(AbstractLesson.USER_ROLE);
+ if (isAdmin())
+ {
+ roles.add(AbstractLesson.ADMIN_ROLE);
+ }
+
+ return roles;
+ }
+
+ public String getRole()
+ {
+
+ String role = "";
+ if (isAdmin())
+ {
+ role = AbstractLesson.ADMIN_ROLE;
+ }
+ else if (isHackedAdmin())
+ {
+ role = AbstractLesson.HACKED_ADMIN_ROLE;
+ }
+ else if (isChallenge())
+ {
+ role = AbstractLesson.CHALLENGE_ROLE;
+ }
+ else
+ {
+ role = AbstractLesson.USER_ROLE;
+ }
+
+ return role;
+ }
+
+ /**
+ * Gets the course attribute of the WebSession object
+ *
+ * @return The course value
+ */
+ public Course getCourse()
+ {
+ return course;
+ }
+
+ public void setCourse( Course course )
+ {
+ this.course = course;
+ }
+
+ /**
+ * Gets the currentScreen attribute of the WebSession object
+ *
+ * @return The currentScreen value
+ */
+ public int getCurrentScreen()
+ {
+ return ( currentScreen );
+ }
+
+ public void setCurrentScreen( int screen )
+ {
+ currentScreen = screen;
+ }
+
+ /**
+ * returns the connection string with the real path to the database directory inserted at the
+ * word PATH
+ *
+ * @return The databaseConnectionString value
+ */
+ public String getDatabaseConnectionString()
+ {
+ try
+ {
+ String path = context.getRealPath( "/database" ).replace( '\\', '/' );
+ System.out.println( "PATH: " + path );
+ String realConnectionString = databaseConnectionString.replaceAll( "PATH", path );
+ System.out.println( "Database Connection String: " + realConnectionString );
+
+ return realConnectionString;
+ }
+ catch ( Exception e )
+ {
+ System.out.println( "Couldn't open database: check web.xml database parameters" );
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets the databaseDriver attribute of the WebSession object
+ *
+ * @return The databaseDriver value
+ */
+ public String getDatabaseDriver()
+ {
+ return ( databaseDriver );
+ }
+
+ public String getRestartLink()
+ {
+ List parameters = new ArrayList();
+
+ String screenValue = request.getParameter(SCREEN);
+ if (screenValue != null)
+ parameters.add(SCREEN + "=" + screenValue);
+
+ String menuValue = request.getParameter(MENU);
+ if (menuValue != null)
+ parameters.add(MENU + "=" + menuValue);
+
+ parameters.add(RESTART + "=" + currentScreen);
+
+ return makeQuery("attack", parameters);
+ }
+
+ private String makeQuery(String resource, List parameters)
+ {
+ StringBuffer query = new StringBuffer(resource);
+
+ boolean isFirstParameter = true;
+ Iterator i = parameters.iterator();
+
+ while (i.hasNext())
+ {
+ String parameter = (String) i.next();
+ if (isFirstParameter)
+ {
+ query.append("?");
+ isFirstParameter = false;
+ }
+ else
+ query.append("&");
+ query.append(parameter);
+ }
+
+ return query.toString();
+ }
+
+ public String getCurrentLink()
+ {
+ String thisLink = "attack";
+ Enumeration e = request.getParameterNames();
+ boolean isFirstParameter = true;
+ while (e.hasMoreElements())
+ {
+ String name = (String) e.nextElement();
+ if (isFirstParameter)
+ {
+ isFirstParameter = false;
+ thisLink += "?";
+ }
+ else
+ {
+ thisLink += "&";
+ }
+ thisLink = thisLink + name + "=" + request.getParameter(name);
+ }
+
+ return thisLink;
+ }
+
+ public AbstractLesson getCurrentLesson()
+ {
+ return getCourse().getLesson( this, getCurrentScreen(), getRoles() );
+ }
+
+ public AbstractLesson getLesson(int id)
+ {
+ return getCourse().getLesson( this, id, getRoles() );
+ }
+
+ public List getLessons(Category category)
+ {
+ return getCourse().getLessons( this, category, getRoles() );
+ }
+
+ /**
+ * Gets the hint1 attribute of the WebSession object
+ *
+ * @return The hint1 value
+ */
+ private int getHintNum()
+ {
+ return ( hintNum );
+ }
+
+ public String getHint()
+ {
+ String hint = null;
+
+ if ( getHintNum() >= 0 )
+ // FIXME
+ hint = getCurrentLesson().getHint( getHintNum() );
+
+ return hint;
+ }
+
+ public List getParams()
+ {
+ Vector params = null;
+
+ if ( showParams() && getParser() != null )
+ {
+ params = new Vector();
+
+ Enumeration e = getParser().getParameterNames();
+
+ while ( ( e != null ) && e.hasMoreElements() )
+ {
+ String name = (String) e.nextElement();
+ String[] values = getParser().getParameterValues( name );
+
+ for ( int loop = 0; ( values != null ) && ( loop < values.length ); loop++ )
+ {
+ params.add( new Parameter( name, values[loop] ) );
+ // params.add( name + " -> " + values[loop] );
+ }
+ }
+
+ Collections.sort( params );
+ }
+
+ return params;
+ }
+
+ public List getCookies()
+ {
+ List cookies = null;
+
+ if ( showCookies() )
+ cookies = Arrays.asList( request.getCookies() );
+
+ /*
+ * List cookies = new Vector();
+ *
+ * HttpServletRequest request = getRequest(); Cookie[] cookies = request.getCookies();
+ *
+ * if ( cookies.length == 0 ) { list.addElement( new LI( "No Cookies" ) ); }
+ *
+ * for ( int i = 0; i < cookies.length; i++ ) { Cookie cookie = cookies[i];
+ * cookies.add(cookie); //list.addElement( new LI( cookie.getName() + " -> " +
+ * cookie.getValue() ) ); }
+ */
+
+ return cookies;
+ }
+
+ /**
+ * Gets the cookie attribute of the CookieScreen object
+ *
+ * @param s Description of the Parameter
+ * @return The cookie value
+ */
+ public String getCookie( String cookieName )
+ {
+ Cookie[] cookies = getRequest().getCookies();
+
+ for ( int i = 0; i < cookies.length; i++ )
+ {
+ if ( cookies[i].getName().equalsIgnoreCase( cookieName ) )
+ {
+ return ( cookies[i].getValue() );
+ }
+ }
+
+ return ( null );
+ }
+
+ public String getSource()
+ {
+ return "Sorry. No Java Source viewing available.";
+ //return getCurrentLesson().getSource(this);
+ }
+
+ public String getInstructions()
+ {
+ return getCurrentLesson().getInstructions(this);
+ }
+
+ /**
+ * Gets the message attribute of the WebSession object
+ *
+ * @return The message value
+ */
+ public String getMessage()
+ {
+ return ( message.toString() );
+ }
+
+ /**
+ * Gets the parser attribute of the WebSession object
+ *
+ * @return The parser value
+ */
+ public ParameterParser getParser()
+ {
+ return ( myParser );
+ }
+
+ /**
+ * Gets the previousScreen attribute of the WebSession object
+ *
+ * @return The previousScreen value
+ */
+ public int getPreviousScreen()
+ {
+ return ( previousScreen );
+ }
+
+ /**
+ * Gets the request attribute of the WebSession object
+ *
+ * @return The request value
+ */
+ public HttpServletRequest getRequest()
+ {
+ return request;
+ }
+
+ public void setRequest( HttpServletRequest request )
+ {
+ this.request = request;
+ }
+
+ /**
+ * Gets the response attribute of the WebSession object
+ *
+ * @return The response value
+ */
+ public HttpServletResponse getResponse()
+ {
+ return response;
+ }
+
+ /**
+ * Gets the servletName attribute of the WebSession object
+ *
+ * @return The servletName value
+ */
+ public String getServletName()
+ {
+ return ( servletName );
+ }
+
+ /**
+ * Gets the sourceFile attribute of the WebSession object
+ *
+ * @param screen Description of the Parameter
+ * @return The sourceFile value
+ */
+ public String getWebResource( String fileName )
+ {
+ // Note: doesn't work for admin path! Maybe with a ../ attack
+ return ( context.getRealPath( fileName ));
+ }
+
+ /**
+ * Gets the admin attribute of the WebSession object
+ *
+ * @return The admin value
+ */
+ public boolean isAdmin()
+ {
+ return ( isAdmin );
+ }
+
+ /**
+ * Gets the hackedAdmin attribute of the WebSession object
+ *
+ * @return The hackedAdmin value
+ */
+ public boolean isHackedAdmin()
+ {
+ return ( isHackedAdmin );
+ }
+
+ /**
+ * Has the user ever hacked the hackable admin
+ *
+ * @return The hackedAdmin value
+ */
+ public boolean completedHackableAdmin()
+ {
+ return ( completedHackableAdmin );
+ }
+
+ /**
+ * Gets the authenticated attribute of the WebSession object
+ *
+ * @return The authenticated value
+ */
+ public boolean isAuthenticated()
+ {
+ return ( isAuthenticated );
+ }
+
+ private Map lessonSessions = new Hashtable();
+
+
+ public boolean isAuthenticatedInLesson(AbstractLesson lesson)
+ {
+ boolean authenticated = false;
+
+ LessonSession lessonSession = getLessonSession(lesson);
+ if (lessonSession != null)
+ {
+ authenticated = lessonSession.isAuthenticated();
+ }
+ //System.out.println("Authenticated for lesson " + lesson + "? " + authenticated);
+
+ return authenticated;
+ }
+
+ public boolean isAuthorizedInLesson(int employeeId, String functionId)
+ {
+ return getCurrentLesson().isAuthorized(this, employeeId, functionId);
+ }
+
+ public boolean isAuthorizedInLesson(String role, String functionId)
+ {
+ return getCurrentLesson().isAuthorized(this, role, functionId);
+ }
+
+ public int getUserIdInLesson() throws ParameterNotFoundException
+ {
+ return getCurrentLesson().getUserId(this);
+ }
+
+ public String getUserNameInLesson() throws ParameterNotFoundException
+ {
+ return getCurrentLesson().getUserName(this);
+ }
+
+ public void openLessonSession(AbstractLesson lesson)
+ {
+ System.out.println("Opening new lesson session for lesson " + lesson);
+ LessonSession lessonSession = new LessonSession();
+ lessonSessions.put(lesson, lessonSession);
+ }
+
+ public void closeLessonSession(AbstractLesson lesson)
+ {
+ lessonSessions.remove(lesson);
+ }
+
+ public LessonSession getLessonSession(AbstractLesson lesson)
+ {
+ return (LessonSession) lessonSessions.get(lesson);
+ }
+
+ /**
+ * Gets the challenge attribute of the WebSession object
+ *
+ * @return The challenge value
+ */
+ public boolean isChallenge()
+ {
+ if ( getCurrentLesson() != null )
+ {
+ return ( AbstractLesson.CHALLENGE.equals(getCurrentLesson().getCategory()));
+ }
+ return false;
+ }
+
+ /**
+ * Gets the color attribute of the WebSession object
+ *
+ * @return The color value
+ */
+ public boolean isColor()
+ {
+ return ( isColor );
+ }
+
+ /**
+ * Gets the screen attribute of the WebSession object
+ *
+ * @param value Description of the Parameter
+ * @return The screen value
+ */
+ public boolean isScreen( int value )
+ {
+ return ( getCurrentScreen() == value );
+ }
+
+ /**
+ * Gets the user attribute of the WebSession object
+ *
+ * @return The user value
+ */
+ public boolean isUser()
+ {
+ return ( !isAdmin && !isChallenge() );
+ }
+
+ /**
+ * Sets the message attribute of the WebSession object
+ *
+ * @param text The new message value
+ */
+ public void setMessage( String text )
+ {
+ message.append( "
" + " * " + text);
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @return Description of the Return Value
+ */
+ public boolean showCookies()
+ {
+ return ( showCookies );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @return Description of the Return Value
+ */
+ public boolean showParams()
+ {
+ return ( showParams );
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @return Description of the Return Value
+ */
+ public boolean showRequest()
+ {
+ return ( showRequest );
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @return Description of the Return Value
+ */
+ public boolean showSource()
+ {
+ return ( showSource );
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @return Description of the Return Value
+ */
+ public boolean isDefuseOSCommands()
+ {
+ return ( defuseOSCommands );
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @return Description of the Return Value
+ */
+ public boolean isEnterprise()
+ {
+ return ( enterprise );
+ }
+
+ /**
+ * Description of the Method
+ *
+ * @return Description of the Return Value
+ */
+ public String getFeedbackAddress()
+ {
+ return ( feedbackAddress );
+ }
+
+ /**
+ * Gets the userName attribute of the WebSession object
+ *
+ * @return The userName value
+ */
+ public String getUserName()
+ {
+ // System.out.println("Request: " + getRequest() );
+ // System.out.println("Principal: " + getRequest().getUserPrincipal() );
+ // System.out.println("Name: " + getRequest().getUserPrincipal().getName( ) );
+ return getRequest().getUserPrincipal().getName();
+ }
+
+ /**
+ * Parse parameters from the given request, handle any servlet commands, and update this session
+ * based on the parameters.
+ *
+ * @param request Description of the Parameter
+ * @param response Description of the Parameter
+ * @param name Description of the Parameter
+ */
+ public void update( HttpServletRequest request, HttpServletResponse response, String name )
+ throws IOException
+ {
+ String content = null;
+
+ clearMessage();
+ this.request = request;
+ this.response = response;
+ this.servletName = name;
+
+ if ( myParser == null )
+ {
+ myParser = new ParameterParser( request );
+ }
+ else
+ {
+ myParser.update( request );
+ }
+
+ // System.out.println("Current Screen 1: " + currentScreen );
+ // System.out.println("Previous Screen 1: " + previousScreen );
+ // FIXME: requires ?Logout=true
+ // FIXME: doesn't work right -- no reauthentication
+ if ( myParser.getRawParameter( LOGOUT, null ) != null )
+ {
+ System.out.println( "Logout " + request.getUserPrincipal() );
+ eatCookies();
+ request.getSession().invalidate();
+ currentScreen = WELCOME;
+ previousScreen = ERROR;
+ }
+
+ // There are several scenarios where we want the first lesson to be loaded
+ // 1) Previous screen is Welcome - Start of the course
+ // 2) After a logout and after the session has been reinitialized
+ if ( ( this.getPreviousScreen() == WebSession.WELCOME ) || ( getRequest().getSession( false ) != null &&
+ // getRequest().getSession(false).isNew() &&
+ this.getCurrentScreen() == WebSession.WELCOME && this.getPreviousScreen() == WebSession.ERROR ) )
+ {
+ currentScreen = course.getFirstLesson().getScreenId();
+ hintNum = -1;
+ }
+
+ // System.out.println("Current Screen 2: " + currentScreen );
+ // System.out.println("Previous Screen 2: " + previousScreen );
+ // update the screen variables
+ previousScreen = currentScreen;
+
+ try
+ {
+ // If the request is new there should be no parameters.
+ // This can occur from a session timeout or a the starting of a new course.
+ if ( !request.getSession().isNew() )
+ {
+ currentScreen = myParser.getIntParameter( SCREEN, currentScreen );
+ }
+ else
+ {
+ if ( !myParser.getRawParameter( SCREEN, "NULL" ).equals( "NULL" ) )
+ {
+ this.setMessage( "Session Timeout - Starting new Session." );
+ }
+ }
+ }
+ catch ( Exception e )
+ {
+ }
+
+ // clear variables when switching screens
+ if ( this.getCurrentScreen() != this.getPreviousScreen() )
+ {
+ if ( isDebug )
+ {
+ setMessage( "Changed to a new screen, clearing cookies and hints" );
+ }
+ eatCookies();
+ hintNum = -1;
+ }
+
+ // else update global variables for the current screen
+ else
+ {
+ // Handle "restart" commands
+ int lessonId = myParser.getIntParameter( RESTART, -1 );
+ if ( lessonId != -1 )
+ {
+ restartLesson(lessonId);
+ }
+ //if ( myParser.getBooleanParameter( RESTART, false ) )
+ //{
+ // getCurrentLesson().getLessonTracker( this ).getLessonProperties().setProperty( CHALLENGE_STAGE, "1" );
+ //}
+
+ // Handle "show" commands
+ String showCommand = myParser.getStringParameter( SHOW, null );
+ if ( showCommand != null )
+ {
+ if ( showCommand.equalsIgnoreCase( SHOW_PARAMS ) )
+ {
+ showParams = !showParams;
+ }
+ else if ( showCommand.equalsIgnoreCase( SHOW_COOKIES ) )
+ {
+ showCookies = !showCookies;
+ }
+ else if ( showCommand.equalsIgnoreCase( SHOW_SOURCE ) )
+ {
+ content = getSource();
+ //showSource = true;
+ }
+ else if ( showCommand.equalsIgnoreCase( SHOW_NEXTHINT ) )
+ {
+ getNextHint();
+ }
+ else if ( showCommand.equalsIgnoreCase( SHOW_PREVIOUSHINT ) )
+ {
+ getPreviousHint();
+ }
+ }
+
+ }
+
+ isAdmin = request.isUserInRole( WEBGOAT_ADMIN );
+ isHackedAdmin = myParser.getBooleanParameter( ADMIN, isAdmin );
+ if ( isHackedAdmin )
+ {
+ System.out.println("Hacked admin");
+ hasHackedHackableAdmin = true;
+ }
+ isColor = myParser.getBooleanParameter( COLOR, isColor );
+ isDebug = myParser.getBooleanParameter( DEBUG, isDebug );
+
+ // System.out.println( "showParams:" + showParams );
+ // System.out.println( "showSource:" + showSource );
+ // System.out.println( "showCookies:" + showCookies );
+ // System.out.println( "showRequest:" + showRequest );
+
+ if (content != null)
+ {
+ response.setContentType("text/html");
+ PrintWriter out = new PrintWriter(response.getOutputStream());
+ out.print(content);
+ out.flush();
+ out.close();
+ }
+ }
+
+ private void restartLesson(int lessonId)
+ {
+ System.out.println("Restarting lesson: " + getLesson(lessonId));
+ getCurrentLesson().getLessonTracker( this ).setStage(1);
+ getCurrentLesson().getLessonTracker( this ).setCompleted(false);
+ }
+
+ /**
+ * @param string
+ */
+ public void setHasHackableAdmin( String role )
+ {
+ hasHackedHackableAdmin = ( AbstractLesson.HACKED_ADMIN_ROLE.equals( role ) & hasHackedHackableAdmin );
+
+ // if the user got the Admin=true parameter correct AND they accessed an admin screen
+ if ( hasHackedHackableAdmin )
+ {
+ completedHackableAdmin = true;
+ }
+ }
+
+ /**
+ * @return Returns the isDebug.
+ */
+ public boolean isDebug()
+ {
+ return isDebug;
+ }
+
+ /**
+ * @param header - request header value to return
+ * @return
+ */
+ public String getHeader( String header )
+ {
+ return getRequest().getHeader( header );
+ }
+
+ public String getNextHint()
+ {
+ String hint = null;
+
+ // FIXME
+ int maxHints = getCurrentLesson().getHintCount();
+ if ( hintNum < maxHints - 1 )
+ {
+ hintNum++;
+
+ // Hints are indexed from 0
+ getCurrentLesson().getLessonTracker( this ).setMaxHintLevel( getHintNum() + 1 );
+
+ hint = (String) getCurrentLesson().getHint( getHintNum() );
+ }
+
+ return hint;
+ }
+
+ public String getPreviousHint()
+ {
+ String hint = null;
+
+ if ( hintNum > 0 )
+ {
+ hintNum--;
+
+ // Hints are indexed from 0
+ getCurrentLesson().getLessonTracker( this ).setMaxHintLevel( getHintNum() + 1 );
+
+ hint = (String) getCurrentLesson().getHint( getHintNum() );
+ }
+
+ return hint;
+ }
+
+ public void setCurrentMenu(Integer ranking)
+ {
+ currentMenu = ranking.intValue();
+ }
+
+ public int getCurrentMenu()
+ {
+ return currentMenu;
+ }
+
+ public String htmlEncode(String s)
+ {
+ //System.out.println("Testing for stage 4 completion in lesson " + getCurrentLesson().getName());
+ if (getCurrentLesson().getName().equals("CrossSiteScripting"))
+ {
+ if (getCurrentLesson().getStage(this) == 4 &&
+ s.indexOf("") > -1)
+ {
+ setMessage( "Welcome to stage 5 -- exploiting the data layer" );
+ // Set a phantom stage value to setup for the 4-5 transition
+ getCurrentLesson().setStage(this, 1005);
+ }
+ }
+
+ return ParameterParser.htmlEncode(s);
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/session/WebgoatProperties.java b/ webgoat/main/project/org/owasp/webgoat/session/WebgoatProperties.java
new file mode 100644
index 000000000..49b585cce
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/session/WebgoatProperties.java
@@ -0,0 +1,91 @@
+package org.owasp.webgoat.session;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+public class WebgoatProperties extends Properties
+{
+ public WebgoatProperties(String propertiesFileName) throws IOException
+ {
+ try
+ {
+ FileInputStream in = new FileInputStream(propertiesFileName);
+ load(in);
+ }
+ catch ( IOException e )
+ {
+ System.out.println("Warning: Unable to open webgoat.properties file");
+ }
+ }
+
+ public int getIntProperty(String key, int defaultValue)
+ {
+ int value = defaultValue;
+
+ String s = getProperty(key);
+ if (s != null)
+ {
+ value = Integer.parseInt(s);
+ }
+
+ return value;
+ }
+
+ public boolean getBooleanProperty(String key, boolean defaultValue)
+ {
+ boolean value = defaultValue;
+ key = this.trimLesson(key);
+
+ String s = getProperty(key);
+ if (s != null)
+ {
+ if (s.equalsIgnoreCase("true"))
+ value = true;
+ else if (s.equalsIgnoreCase("yes"))
+ value = true;
+ else if (s.equalsIgnoreCase("on"))
+ value = true;
+ else if (s.equalsIgnoreCase("false"))
+ value = false;
+ else if (s.equalsIgnoreCase("no"))
+ value = false;
+ else if (s.equalsIgnoreCase("off"))
+ value = false;
+ }
+
+ return value;
+ }
+
+ private String trimLesson(String lesson)
+ {
+ String result = "";
+
+ if(lesson.startsWith("org.owasp.webgoat.lessons."))
+ {
+ result = lesson.substring("org.owasp.webgoat.lessons.".length(), lesson.length());
+ }
+ else
+ {
+ result = lesson;
+ }
+
+ return result;
+ }
+
+ public static void main(String[] args)
+ {
+ WebgoatProperties properties = null;
+ try
+ {
+ properties = new WebgoatProperties("C:\\webgoat.properties");
+ }
+ catch (IOException e)
+ {
+ System.out.println("Error loading properties");
+ e.printStackTrace();
+ }
+ System.out.println(properties.getProperty("CommandInjection.category"));
+ }
+
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/util/Exec.java b/ webgoat/main/project/org/owasp/webgoat/util/Exec.java
new file mode 100644
index 000000000..abd43f3e7
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/util/Exec.java
@@ -0,0 +1,508 @@
+package org.owasp.webgoat.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.BitSet;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
+ * Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
+ * under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
+ * this software.
+ *
+ * @author Jeff Williams Aspect Security
+ * @created October 28, 2003
+ */
+public class Exec
+{
+ /**
+ * Description of the Method
+ *
+ * @param command Description of the Parameter
+ * @param input Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static ExecResults execInput( String command, String input )
+ {
+ return ( execOptions( command, input, 0, 0, false ) );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param command Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static ExecResults execLazy( String command )
+ {
+ return ( execOptions( command, "", 0, 0, true ) );
+ }
+
+
+ /*
+ * Execute an OS command and capture the output in an ExecResults.
+ * All exceptions are caught and stored in the ExecResults.
+ * @param String command is the OS command to execute
+ * @param String input is piped into the OS command
+ * @param int successCode is the expected return code if the command completes successfully
+ * @param int timeout is the number of milliseconds to wait before interrupting the command
+ * @param boolean quit tells the method to exit when there is no more output waiting
+ */
+ /**
+ * Description of the Method
+ *
+ * @param command Description of the Parameter
+ * @param input Description of the Parameter
+ * @param successCode Description of the Parameter
+ * @param timeout Description of the Parameter
+ * @param lazy Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static ExecResults execOptions( String[] command, String input, int successCode, int timeout, boolean lazy )
+ {
+ Process child = null;
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ ByteArrayOutputStream errors = new ByteArrayOutputStream();
+ ExecResults results = new ExecResults( command[0], input, successCode, timeout );
+ BitSet interrupted = new BitSet( 1 );
+ boolean lazyQuit = false;
+ ThreadWatcher watcher;
+
+ try
+ {
+ // start the command
+ child = Runtime.getRuntime().exec( command );
+
+ // get the streams in and out of the command
+ InputStream processIn = child.getInputStream();
+ InputStream processError = child.getErrorStream();
+ OutputStream processOut = child.getOutputStream();
+
+ // start the clock running
+ if ( timeout > 0 )
+ {
+ watcher = new ThreadWatcher( child, interrupted, timeout );
+ new Thread( watcher ).start();
+ }
+
+ // Write to the child process' input stream
+ if ( ( input != null ) && !input.equals( "" ) )
+ {
+ try
+ {
+ processOut.write( input.getBytes() );
+ processOut.flush();
+ processOut.close();
+ }
+ catch ( IOException e1 )
+ {
+ results.setThrowable( e1 );
+ }
+ }
+
+ // Read from the child process' output stream
+ // The process may get killed by the watcher at any time
+ int c = 0;
+
+ try
+ {
+ while ( true )
+ {
+ if ( interrupted.get( 0 ) || lazyQuit )
+ {
+ break;
+ }
+
+ // interrupted
+ c = processIn.read();
+
+ if ( c == -1 )
+ {
+ break;
+ }
+
+ // end of stream
+ output.write( c );
+
+ if ( lazy && ( processIn.available() < 1 ) )
+ {
+ lazyQuit = true;
+ }
+
+ // if lazy and nothing then quit (after at least one read)
+ }
+
+ processIn.close();
+ }
+ catch ( IOException e2 )
+ {
+ results.setThrowable( e2 );
+ }
+ finally
+ {
+ if ( interrupted.get( 0 ) )
+ {
+ results.setInterrupted();
+ }
+
+ results.setOutput( output.toString() );
+ }
+
+ // Read from the child process' error stream
+ // The process may get killed by the watcher at any time
+ try
+ {
+ while ( true )
+ {
+ if ( interrupted.get( 0 ) || lazyQuit )
+ {
+ break;
+ }
+
+ // interrupted
+ c = processError.read();
+
+ if ( c == -1 )
+ {
+ break;
+ }
+
+ // end of stream
+ output.write( c );
+
+ if ( lazy && ( processError.available() < 1 ) )
+ {
+ lazyQuit = true;
+ }
+
+ // if lazy and nothing then quit (after at least one read)
+ }
+
+ processError.close();
+ }
+ catch ( IOException e3 )
+ {
+ results.setThrowable( e3 );
+ }
+ finally
+ {
+ if ( interrupted.get( 0 ) )
+ {
+ results.setInterrupted();
+ }
+
+ results.setErrors( errors.toString() );
+ }
+
+ // wait for the return value of the child process.
+ if ( !interrupted.get( 0 ) && !lazyQuit )
+ {
+ int returnCode = child.waitFor();
+ results.setReturnCode( returnCode );
+
+ if ( returnCode != successCode )
+ {
+ results.setError( ExecResults.BADRETURNCODE );
+ }
+ }
+ }
+ catch ( InterruptedException i )
+ {
+ results.setInterrupted();
+ }
+ catch ( Throwable t )
+ {
+ results.setThrowable( t );
+ }
+ finally
+ {
+ if ( child != null )
+ {
+ child.destroy();
+ }
+ }
+
+ return ( results );
+ }
+
+
+ /*
+ * Execute an OS command and capture the output in an ExecResults.
+ * All exceptions are caught and stored in the ExecResults.
+ * @param String command is the OS command to execute
+ * @param String input is piped into the OS command
+ * @param int successCode is the expected return code if the command completes successfully
+ * @param int timeout is the number of milliseconds to wait before interrupting the command
+ * @param boolean quit tells the method to exit when there is no more output waiting
+ */
+ /**
+ * Description of the Method
+ *
+ * @param command Description of the Parameter
+ * @param input Description of the Parameter
+ * @param successCode Description of the Parameter
+ * @param timeout Description of the Parameter
+ * @param lazy Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static ExecResults execOptions( String command, String input, int successCode, int timeout, boolean lazy )
+ {
+ Process child = null;
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ ByteArrayOutputStream errors = new ByteArrayOutputStream();
+ ExecResults results = new ExecResults( command, input, successCode, timeout );
+ BitSet interrupted = new BitSet( 1 );
+ boolean lazyQuit = false;
+ ThreadWatcher watcher;
+
+ try
+ {
+ // start the command
+ child = Runtime.getRuntime().exec( command );
+
+ // get the streams in and out of the command
+ InputStream processIn = child.getInputStream();
+ InputStream processError = child.getErrorStream();
+ OutputStream processOut = child.getOutputStream();
+
+ // start the clock running
+ if ( timeout > 0 )
+ {
+ watcher = new ThreadWatcher( child, interrupted, timeout );
+ new Thread( watcher ).start();
+ }
+
+ // Write to the child process' input stream
+ if ( ( input != null ) && !input.equals( "" ) )
+ {
+ try
+ {
+ processOut.write( input.getBytes() );
+ processOut.flush();
+ processOut.close();
+ }
+ catch ( IOException e1 )
+ {
+ results.setThrowable( e1 );
+ }
+ }
+
+ // Read from the child process' output stream
+ // The process may get killed by the watcher at any time
+ int c = 0;
+
+ try
+ {
+ while ( true )
+ {
+ if ( interrupted.get( 0 ) || lazyQuit )
+ {
+ break;
+ }
+
+ // interrupted
+ c = processIn.read();
+
+ if ( c == -1 )
+ {
+ break;
+ }
+
+ // end of stream
+ output.write( c );
+
+ if ( lazy && ( processIn.available() < 1 ) )
+ {
+ lazyQuit = true;
+ }
+
+ // if lazy and nothing then quit (after at least one read)
+ }
+
+ processIn.close();
+ }
+ catch ( IOException e2 )
+ {
+ results.setThrowable( e2 );
+ }
+ finally
+ {
+ if ( interrupted.get( 0 ) )
+ {
+ results.setInterrupted();
+ }
+
+ results.setOutput( output.toString() );
+ }
+
+ // Read from the child process' error stream
+ // The process may get killed by the watcher at any time
+ try
+ {
+ while ( true )
+ {
+ if ( interrupted.get( 0 ) || lazyQuit )
+ {
+ break;
+ }
+
+ // interrupted
+ c = processError.read();
+
+ if ( c == -1 )
+ {
+ break;
+ }
+
+ // end of stream
+ output.write( c );
+
+ if ( lazy && ( processError.available() < 1 ) )
+ {
+ lazyQuit = true;
+ }
+
+ // if lazy and nothing then quit (after at least one read)
+ }
+
+ processError.close();
+ }
+ catch ( IOException e3 )
+ {
+ results.setThrowable( e3 );
+ }
+ finally
+ {
+ if ( interrupted.get( 0 ) )
+ {
+ results.setInterrupted();
+ }
+
+ results.setErrors( errors.toString() );
+ }
+
+ // wait for the return value of the child process.
+ if ( !interrupted.get( 0 ) && !lazyQuit )
+ {
+ int returnCode = child.waitFor();
+ results.setReturnCode( returnCode );
+
+ if ( returnCode != successCode )
+ {
+ results.setError( ExecResults.BADRETURNCODE );
+ }
+ }
+ }
+ catch ( InterruptedException i )
+ {
+ results.setInterrupted();
+ }
+ catch ( Throwable t )
+ {
+ results.setThrowable( t );
+ }
+ finally
+ {
+ if ( child != null )
+ {
+ child.destroy();
+ }
+ }
+
+ return ( results );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param command Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static ExecResults execSimple( String[] command )
+ {
+ return ( execOptions( command, "", 0, 0, false ) );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param command Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static ExecResults execSimple( String command )
+ {
+ return ( execOptions( command, "", 0, 0, false ) );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param command Description of the Parameter
+ * @param args Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static ExecResults execSimple( String command, String args )
+ {
+ return ( execOptions( command, args, 0, 0, false ) );
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param command Description of the Parameter
+ * @param timeout Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static ExecResults execTimeout( String command, int timeout )
+ {
+ return ( execOptions( command, "", 0, timeout, false ) );
+ }
+
+
+ /**
+ * The main program for the Exec class
+ *
+ * @param args The command line arguments
+ */
+ public static void main( String[] args )
+ {
+ ExecResults results;
+ String sep = System.getProperty( "line.separator" );
+ System.out.println( "-------------------------------------------" + sep + "TEST 1: execSimple" );
+ results = Exec.execSimple( "c:/swarm-2.1.1/bin/whoami.exe" );
+ System.out.println( results );
+ System.out.println( "-------------------------------------------" + sep + "TEST 2: execSimple (with search)" );
+ results = Exec.execSimple( "netstat -r" );
+ System.out.println( results );
+
+ if ( results.outputContains( "localhost:1031" ) )
+ {
+ System.out.println( "ERROR: listening on 1031" );
+ }
+
+ System.out.println( "-------------------------------------------" + sep + "TEST 3: execInput" );
+ results = Exec.execInput( "find \"cde\"", "abcdefg1\nhijklmnop\nqrstuv\nabcdefg2" );
+ System.out.println( results );
+ System.out.println( "-------------------------------------------" + sep + "TEST 4:execTimeout" );
+ results = Exec.execTimeout( "ping -t 127.0.0.1", 5 * 1000 );
+ System.out.println( results );
+ System.out.println( "-------------------------------------------" + sep + "TEST 5:execLazy" );
+ results = Exec.execLazy( "ping -t 127.0.0.1" );
+ System.out.println( results );
+ System.out.println( "-------------------------------------------" + sep + "TEST 6:ExecTimeout process never outputs" );
+ results = Exec.execTimeout( "c:/swarm-2.1.1/bin/sleep.exe 20", 5 * 1000 );
+ System.out.println( results );
+ System.out.println( "-------------------------------------------" + sep + "TEST 7:ExecTimeout process waits for input" );
+ results = Exec.execTimeout( "c:/swarm-2.1.1/bin/cat", 5 * 1000 );
+ System.out.println( results );
+ }
+}
+
diff --git a/ webgoat/main/project/org/owasp/webgoat/util/ExecResults.java b/ webgoat/main/project/org/owasp/webgoat/util/ExecResults.java
new file mode 100644
index 000000000..eb8fb2fa1
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/util/ExecResults.java
@@ -0,0 +1,320 @@
+package org.owasp.webgoat.util;
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of
+ * the Open Web Application Security Project (http://www.owasp.org) This
+ * software package org.owasp.webgoat.is published by OWASP under the GPL. You should read and
+ * accept the LICENSE before you use, modify and/or redistribute this software.
+ *
+ * @author Jeff Williams Aspect Security
+ */
+public class ExecResults
+{
+ /**
+ * Description of the Field
+ */
+ public final static int BADRETURNCODE = 2;
+
+ /**
+ * Description of the Field
+ */
+ public final static int THROWABLE = 1;
+ private String myCommand;
+ private boolean myError = false;
+ private int myErrorType = 0;
+ private String myErrors = null;
+ private String myInput;
+ private boolean myInterrupted = false;
+ private String myOutput = null;
+ private int myReturnCode = 0;
+ private int mySuccessCode;
+ private Throwable myThrowable = null;
+ private int myTimeout;
+
+ /**
+ * Constructor for the ExecResults object
+ *
+ *@param command Description of the Parameter
+ *@param input Description of the Parameter
+ *@param successCode Description of the Parameter
+ *@param timeout Description of the Parameter
+ */
+ public ExecResults(String command, String input, int successCode, int timeout)
+ {
+ myCommand = command.trim();
+ myInput = input.trim();
+ mySuccessCode = successCode;
+ myTimeout = timeout;
+ }
+
+ /**
+ * Description of the Method
+ *
+ *@param haystack Description of the Parameter
+ *@param needle Description of the Parameter
+ *@param fromIndex Description of the Parameter
+ *@return Description of the Return Value
+ */
+ private boolean contains(String haystack, String needle, int fromIndex)
+ {
+ return (haystack.trim().toLowerCase().indexOf(needle.trim().toLowerCase(), fromIndex) != -1);
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ *@param value Description of the Parameter
+ *@return Description of the Return Value
+ */
+ public boolean errorsContains(String value)
+ {
+ return (errorsContains(value, 0));
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ *@param value Description of the Parameter
+ *@param fromIndex Description of the Parameter
+ *@return Description of the Return Value
+ */
+ public boolean errorsContains(String value, int fromIndex)
+ {
+ return (contains(myErrors, value, fromIndex));
+ }
+
+
+ /**
+ * Gets the error attribute of the ExecResults object
+ *
+ *@return The error value
+ */
+ public boolean getError()
+ {
+ return (myError);
+ }
+
+
+ /**
+ * Gets the errorMessage attribute of the ExecResults object
+ *
+ *@return The errorMessage value
+ */
+ public String getErrorMessage()
+ {
+ switch (getErrorType())
+ {
+ case THROWABLE:
+ return ("Exception: " + myThrowable.getMessage());
+
+ case BADRETURNCODE:
+ return ("Bad return code (expected " + mySuccessCode + ")");
+
+ default:
+ return ("Unknown error");
+ }
+ }
+
+
+ /**
+ * Gets the errorType attribute of the ExecResults object
+ *
+ *@return The errorType value
+ */
+ public int getErrorType()
+ {
+ return (myErrorType);
+ }
+
+
+ /**
+ * Gets the errors attribute of the ExecResults object
+ *
+ *@return The errors value
+ */
+ public String getErrors()
+ {
+ return (myErrors);
+ }
+
+
+ /**
+ * Gets the interrupted attribute of the ExecResults object
+ *
+ *@return The interrupted value
+ */
+ public boolean getInterrupted()
+ {
+ return (myInterrupted);
+ }
+
+
+ /**
+ * Gets the output attribute of the ExecResults object
+ *
+ *@return The output value
+ */
+ public String getOutput()
+ {
+ return (myOutput);
+ }
+
+
+ /**
+ * Gets the returnCode attribute of the ExecResults object
+ *
+ *@return The returnCode value
+ */
+ public int getReturnCode()
+ {
+ return (myReturnCode);
+ }
+
+
+ /**
+ * Gets the throwable attribute of the ExecResults object
+ *
+ *@return The throwable value
+ */
+ public Throwable getThrowable()
+ {
+ return (myThrowable);
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ *@param value Description of the Parameter
+ *@return Description of the Return Value
+ */
+ public boolean outputContains(String value)
+ {
+ return (outputContains(value, 0));
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ *@param value Description of the Parameter
+ *@param fromIndex Description of the Parameter
+ *@return Description of the Return Value
+ */
+ public boolean outputContains(String value, int fromIndex)
+ {
+ return (contains(myOutput, value, fromIndex));
+ }
+
+
+ /**
+ * Sets the error attribute of the ExecResults object
+ *
+ *@param value The new error value
+ */
+ public void setError(int value)
+ {
+ myError = true;
+ myErrorType = value;
+ }
+
+
+ /**
+ * Sets the errors attribute of the ExecResults object
+ *
+ *@param errors The new errors value
+ */
+ public void setErrors(String errors)
+ {
+ myErrors = errors.trim();
+ }
+
+
+ /**
+ * Sets the interrupted attribute of the ExecResults object
+ */
+ public void setInterrupted()
+ {
+ myInterrupted = true;
+ }
+
+
+ /**
+ * Sets the output attribute of the ExecResults object
+ *
+ *@param value The new output value
+ */
+ public void setOutput(String value)
+ {
+ myOutput = value.trim();
+ }
+
+
+ /**
+ * Sets the returnCode attribute of the ExecResults object
+ *
+ *@param value The new returnCode value
+ */
+ public void setReturnCode(int value)
+ {
+ myReturnCode = value;
+ }
+
+
+ /**
+ * Sets the throwable attribute of the ExecResults object
+ *
+ *@param value The new throwable value
+ */
+ public void setThrowable(Throwable value)
+ {
+ setError(THROWABLE);
+ myThrowable = value;
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ *@return Description of the Return Value
+ */
+ public String toString()
+ {
+ String sep = System.getProperty("line.separator");
+ StringBuffer value = new StringBuffer();
+ value.append("ExecResults for \'" + myCommand + "\'" + sep);
+
+ if ((myInput != null) && !myInput.equals(""))
+ {
+ value.append(sep + "Input..." + sep + myInput + sep);
+ }
+
+ if ((myOutput != null) && !myOutput.equals(""))
+ {
+ value.append(sep + "Output..." + sep + myOutput + sep);
+ }
+
+ if ((myErrors != null) && !myErrors.equals(""))
+ {
+ value.append(sep + "Errors..." + sep + myErrors + sep);
+ }
+
+ value.append(sep);
+
+ if (myInterrupted)
+ {
+ value.append("Command timed out after " + (myTimeout / 1000) + " seconds " + sep);
+ }
+
+ value.append("Returncode: " + myReturnCode + sep);
+
+ if (myError)
+ {
+ value.append(getErrorMessage() + sep);
+ }
+
+ return (value.toString());
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/util/ExecutionException.java b/ webgoat/main/project/org/owasp/webgoat/util/ExecutionException.java
new file mode 100644
index 000000000..e01c00f31
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/util/ExecutionException.java
@@ -0,0 +1,31 @@
+package org.owasp.webgoat.util;
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of
+ * the Open Web Application Security Project (http://www.owasp.org) This
+ * software package org.owasp.webgoat.is published by OWASP under the GPL. You should read and
+ * accept the LICENSE before you use, modify and/or redistribute this software.
+ *
+ * @author Jeff Williams Aspect Security
+ */
+public class ExecutionException extends Exception
+{
+ /**
+ * Constructor for the ExecutionException object
+ */
+ public ExecutionException()
+ {
+ super();
+ }
+
+
+ /**
+ * Constructor for the ExecutionException object
+ *
+ *@param msg Description of the Parameter
+ */
+ public ExecutionException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/util/HtmlEncoder.java b/ webgoat/main/project/org/owasp/webgoat/util/HtmlEncoder.java
new file mode 100644
index 000000000..09401378a
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/util/HtmlEncoder.java
@@ -0,0 +1,195 @@
+package org.owasp.webgoat.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class HtmlEncoder
+{
+ static Map e2i = new HashMap();
+ static Map i2e = new HashMap();
+
+ // html entity list
+ private static Object[][] entities =
+ {
+ {"quot", new Integer( 34 )}, // " - double-quote
+ {"amp", new Integer( 38 )}, // & - ampersand
+ {"lt", new Integer( 60 )}, // < - less-than
+ {"gt", new Integer( 62 )}, // > - greater-than
+ {"nbsp", new Integer( 160 )}, // non-breaking space
+ {"copy", new Integer( 169 )}, // © - copyright
+ {"reg", new Integer( 174 )}, // ® - registered trademark
+ {"Agrave", new Integer( 192 )}, // À - uppercase A, grave accent
+ {"Aacute", new Integer( 193 )}, // Á - uppercase A, acute accent
+ {"Acirc", new Integer( 194 )}, // Â - uppercase A, circumflex accent
+ {"Atilde", new Integer( 195 )}, // Ã - uppercase A, tilde
+ {"Auml", new Integer( 196 )}, // Ä - uppercase A, umlaut
+ {"Aring", new Integer( 197 )}, // Å - uppercase A, ring
+ {"AElig", new Integer( 198 )}, // Æ - uppercase AE
+ {"Ccedil", new Integer( 199 )}, // Ç - uppercase C, cedilla
+ {"Egrave", new Integer( 200 )}, // È - uppercase E, grave accent
+ {"Eacute", new Integer( 201 )}, // É - uppercase E, acute accent
+ {"Ecirc", new Integer( 202 )}, // Ê - uppercase E, circumflex accent
+ {"Euml", new Integer( 203 )}, // Ë - uppercase E, umlaut
+ {"Igrave", new Integer( 204 )}, // Ì - uppercase I, grave accent
+ {"Iacute", new Integer( 205 )}, // Í - uppercase I, acute accent
+ {"Icirc", new Integer( 206 )}, // Î - uppercase I, circumflex accent
+ {"Iuml", new Integer( 207 )}, // Ï - uppercase I, umlaut
+ {"ETH", new Integer( 208 )}, // Ð - uppercase Eth, Icelandic
+ {"Ntilde", new Integer( 209 )}, // Ñ - uppercase N, tilde
+ {"Ograve", new Integer( 210 )}, // Ò - uppercase O, grave accent
+ {"Oacute", new Integer( 211 )}, // Ó - uppercase O, acute accent
+ {"Ocirc", new Integer( 212 )}, // Ô - uppercase O, circumflex accent
+ {"Otilde", new Integer( 213 )}, // Õ - uppercase O, tilde
+ {"Ouml", new Integer( 214 )}, // Ö - uppercase O, umlaut
+ {"Oslash", new Integer( 216 )}, // Ø - uppercase O, slash
+ {"Ugrave", new Integer( 217 )}, // Ù - uppercase U, grave accent
+ {"Uacute", new Integer( 218 )}, // Ú - uppercase U, acute accent
+ {"Ucirc", new Integer( 219 )}, // Û - uppercase U, circumflex accent
+ {"Uuml", new Integer( 220 )}, // Ü - uppercase U, umlaut
+ {"Yacute", new Integer( 221 )}, // Ý - uppercase Y, acute accent
+ {"THORN", new Integer( 222 )}, // Þ - uppercase THORN, Icelandic
+ {"szlig", new Integer( 223 )}, // ß - lowercase sharps, German
+ {"agrave", new Integer( 224 )}, // à - lowercase a, grave accent
+ {"aacute", new Integer( 225 )}, // á - lowercase a, acute accent
+ {"acirc", new Integer( 226 )}, // â - lowercase a, circumflex accent
+ {"atilde", new Integer( 227 )}, // ã - lowercase a, tilde
+ {"auml", new Integer( 228 )}, // ä - lowercase a, umlaut
+ {"aring", new Integer( 229 )}, // å - lowercase a, ring
+ {"aelig", new Integer( 230 )}, // æ - lowercase ae
+ {"ccedil", new Integer( 231 )}, // ç - lowercase c, cedilla
+ {"egrave", new Integer( 232 )}, // è - lowercase e, grave accent
+ {"eacute", new Integer( 233 )}, // é - lowercase e, acute accent
+ {"ecirc", new Integer( 234 )}, // ê - lowercase e, circumflex accent
+ {"euml", new Integer( 235 )}, // ë - lowercase e, umlaut
+ {"igrave", new Integer( 236 )}, // ì - lowercase i, grave accent
+ {"iacute", new Integer( 237 )}, // í - lowercase i, acute accent
+ {"icirc", new Integer( 238 )}, // î - lowercase i, circumflex accent
+ {"iuml", new Integer( 239 )}, // ï - lowercase i, umlaut
+ {"igrave", new Integer( 236 )}, // ì - lowercase i, grave accent
+ {"iacute", new Integer( 237 )}, // í - lowercase i, acute accent
+ {"icirc", new Integer( 238 )}, // î - lowercase i, circumflex accent
+ {"iuml", new Integer( 239 )}, // ï - lowercase i, umlaut
+ {"eth", new Integer( 240 )}, // ð - lowercase eth, Icelandic
+ {"ntilde", new Integer( 241 )}, // ñ - lowercase n, tilde
+ {"ograve", new Integer( 242 )}, // ò - lowercase o, grave accent
+ {"oacute", new Integer( 243 )}, // ó - lowercase o, acute accent
+ {"ocirc", new Integer( 244 )}, // ô - lowercase o, circumflex accent
+ {"otilde", new Integer( 245 )}, // õ - lowercase o, tilde
+ {"ouml", new Integer( 246 )}, // ö - lowercase o, umlaut
+ {"oslash", new Integer( 248 )}, // ø - lowercase o, slash
+ {"ugrave", new Integer( 249 )}, // ù - lowercase u, grave accent
+ {"uacute", new Integer( 250 )}, // ú - lowercase u, acute accent
+ {"ucirc", new Integer( 251 )}, // û - lowercase u, circumflex accent
+ {"uuml", new Integer( 252 )}, // ü - lowercase u, umlaut
+ {"yacute", new Integer( 253 )}, // ý - lowercase y, acute accent
+ {"thorn", new Integer( 254 )}, // þ - lowercase thorn, Icelandic
+ {"yuml", new Integer( 255 )}, // ÿ - lowercase y, umlaut
+ {"euro", new Integer( 8364 )},// Euro symbol
+ };
+
+
+ public HtmlEncoder()
+ {
+ for(int i=0; i
+ *
+ * e.g. "bread" & "butter" => "bread" &
+ * "butter" . Update: supports nearly all HTML entities, including funky
+ * accents. See the source code for more detail. Adapted from
+ * http://www.purpletech.com/code/src/com/purpletech/util/Utils.java.
+ *
+ * @param s1 Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static String encode( String s1 )
+ {
+ StringBuffer buf = new StringBuffer();
+
+ int i;
+ for ( i = 0; i < s1.length(); ++i )
+ {
+ char ch = s1.charAt( i );
+
+ String entity = (String) i2e.get( new Integer( (int) ch ) );
+
+ if ( entity == null )
+ {
+ if ( ( (int) ch ) > 128 )
+ {
+ buf.append( "" + ( (int) ch ) + ";" );
+ }
+ else
+ {
+ buf.append( ch );
+ }
+ }
+ else
+ {
+ buf.append( "&" + entity + ";" );
+ }
+ }
+
+ return buf.toString();
+ }
+
+
+ /**
+ * Given a string containing entity escapes, returns a string containing the actual Unicode
+ * characters corresponding to the escapes. Adapted from
+ * http://www.purpletech.com/code/src/com/purpletech/util/Utils.java.
+ *
+ * @param s1 Description of the Parameter
+ * @return Description of the Return Value
+ */
+ public static String decode( String s1 )
+ {
+ StringBuffer buf = new StringBuffer();
+
+ int i;
+ for ( i = 0; i < s1.length(); ++i )
+ {
+ char ch = s1.charAt( i );
+
+ if ( ch == '&' )
+ {
+ int semi = s1.indexOf( ';', i + 1 );
+ if ( semi == -1 )
+ {
+ buf.append( ch );
+ continue;
+ }
+ String entity = s1.substring( i + 1, semi );
+ Integer iso;
+ if ( entity.charAt( 0 ) == '#' )
+ {
+ iso = new Integer( entity.substring( 1 ) );
+ }
+ else
+ {
+ iso = (Integer) e2i.get( entity );
+ }
+ if ( iso == null )
+ {
+ buf.append( "&" + entity + ";" );
+ }
+ else
+ {
+ buf.append( (char) ( iso.intValue() ) );
+ }
+ i = semi;
+ }
+ else
+ {
+ buf.append( ch );
+ }
+ }
+
+ return buf.toString();
+ }
+}
diff --git a/ webgoat/main/project/org/owasp/webgoat/util/ThreadWatcher.java b/ webgoat/main/project/org/owasp/webgoat/util/ThreadWatcher.java
new file mode 100644
index 000000000..3a5b46b64
--- /dev/null
+++ b/ webgoat/main/project/org/owasp/webgoat/util/ThreadWatcher.java
@@ -0,0 +1,90 @@
+package org.owasp.webgoat.util;
+
+import java.util.BitSet;
+
+
+/**
+ * Copyright (c) 2002 Free Software Foundation developed under the custody of
+ * the Open Web Application Security Project (http://www.owasp.org) This
+ * software package org.owasp.webgoat.is published by OWASP under the GPL. You should read and
+ * accept the LICENSE before you use, modify and/or redistribute this software.
+ *
+ *@author jwilliams@aspectsecurity.com
+ *@created November 6, 2002
+ */
+public class ThreadWatcher implements Runnable
+{
+ // time to live in milliseconds
+ private BitSet myInterrupted;
+ private Process myProcess;
+ private int myTimeout;
+
+ /**
+ * Constructor for the ThreadWatcher object
+ *
+ *@param p Description of the Parameter
+ *@param interrupted Description of the Parameter
+ *@param timeout Description of the Parameter
+ */
+ public ThreadWatcher(Process p, BitSet interrupted, int timeout)
+ {
+ myProcess = p;
+
+ // thread used by whoever constructed this watcher
+ myTimeout = timeout;
+ myInterrupted = interrupted;
+ }
+
+ /*
+ * Interrupt the thread by marking the interrupted bit and killing the process
+ */
+
+ /**
+ * Description of the Method
+ */
+ public void interrupt()
+ {
+ myInterrupted.set(0);
+
+ // set interrupted bit (bit 0 of the bitset) to 1
+ myProcess.destroy();
+
+ /*
+ * try
+ * {
+ * myProcess.getInputStream().close();
+ * }
+ * catch( IOException e1 )
+ * {
+ * / do nothing -- input streams are probably already closed
+ * }
+ * try
+ * {
+ * myProcess.getErrorStream().close();
+ * }
+ * catch( IOException e2 )
+ * {
+ * / do nothing -- input streams are probably already closed
+ * }
+ * myThread.interrupt();
+ */
+ }
+
+
+ /**
+ * Main processing method for the ThreadWatcher object
+ */
+ public void run()
+ {
+ try
+ {
+ Thread.sleep(myTimeout);
+ }
+ catch (InterruptedException e)
+ {
+ // do nothing -- if watcher is interrupted, so is thread
+ }
+
+ interrupt();
+ }
+}