package org.owasp.webgoat.lessons;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.net.Socket;
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 java.util.StringTokenizer;
import java.util.Vector;
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.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.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.session.DatabaseUtilities;
import org.owasp.webgoat.session.ECSFactory;
import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.util.Exec;
import org.owasp.webgoat.util.ExecResults;
/**
* Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
* Application Security Project (http://www.owasp.org) This software package 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 Challenge2Screen extends LessonAdapter
{
private static final String USER_COOKIE = "user";
private static final String JSP = ".jsp";
private static final String WEBGOAT_CHALLENGE = "webgoat_challenge";
private static final String WEBGOAT_CHALLENGE_JSP = WEBGOAT_CHALLENGE + JSP;
private static final String PROCEED_TO_NEXT_STAGE = "Proceed to the next stage...";
/**
* Description of the Field
*/
protected final static String CREDIT = "Credit";
/**
* Description of the Field
*/
protected final static String PROTOCOL = "File";
/**
* Description of the Field
*/
protected final static String MESSAGE = "Message";
/**
* Description of the Field
*/
protected final static String PARAM = "p";
/**
* Description of the Field
*/
protected final static String PASSWORD = "Password";
/**
* Description of the Field
*/
protected final static String USER = "s";
/**
* Description of the Field
*/
protected final static String USERNAME = "Username";
private static Connection connection = null;
private String pass = "goodbye";
private String user = "youaretheweakestlink";
/**
* Description of the Method
*
* @param s Description of the Parameter
* @return Description of the Return Value
*/
protected Element createContent( WebSession s )
{
return super.createStagedContent(s);
}
/**
* Determine the username and password
*
* @param s Description of the Parameter
* @return Description of the Return Value
* @exception Exception Description of the Exception
*/
protected Element doStage1( WebSession s ) throws Exception
{
setStage( s, 1 );
String username = s.getParser().getStringParameter( USERNAME, "" );
String password = s.getParser().getStringParameter( PASSWORD, "" );
if ( username.equals( user ) && password.equals( pass ) )
{
s.setMessage( "Welcome to stage 2 -- get credit card numbers!" );
setStage( s, 2 );
return ( doStage2( s ) );
}
s.setMessage( "Invalid login" );
ElementContainer ec = new ElementContainer();
ec.addElement( makeLogin(s) );
//
// these are red herrings for the first stage
Input input = new Input( Input.HIDDEN, USER, "White" );
ec.addElement( input );
Cookie newCookie = new Cookie( USER_COOKIE, "White" );
s.getResponse().addCookie( newCookie );
//
return ( ec );
}
// get creditcards from database
/**
* Description of the Method
*
* @param s Description of the Parameter
* @return Description of the Return Value
* @exception Exception Description of the Exception
*/
protected Element doStage2( WebSession s ) throws Exception
{
//
Cookie newCookie = new Cookie( USER_COOKIE, "White" );
s.getResponse().addCookie( newCookie );
ElementContainer ec = new ElementContainer();
if ( s.getParser().getStringParameter(Input.SUBMIT, "").equals(PROCEED_TO_NEXT_STAGE + "(3)"))
{
s.setMessage( "Welcome to stage 3 -- deface the site" );
setStage( s, 3 );
// Reset the defaced webpage so the lesson can start over
resetWebPage(s);
return doStage3(s);
}
if ( connection == null )
{
connection = DatabaseUtilities.makeConnection( s );
}
Statement statement3 = connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );
// pull the USER_COOKIE from the cookies
String user = getCookie(s);
String query = "SELECT * FROM user_data WHERE last_name = '" + user +"'";
Vector v = new Vector();
try
{
ResultSet results = statement3.executeQuery( query );
while ( results.next() )
{
String type = results.getString( "cc_type" );
String num = results.getString( "cc_number" );
v.addElement( type + "-" + num );
}
if ( v.size() > 2 )
{
ResultSetMetaData resultsMetaData = results.getMetaData();
ec.addElement( DatabaseUtilities.writeTable( results, resultsMetaData ) );
ec.addElement(ECSFactory.makeButton(PROCEED_TO_NEXT_STAGE + "(3)"));
}
else
{
s.setMessage("Try to get all the credit card numbers");
ec.addElement( buildCart(s));
//Table t = ECSFactory.makeTable( s.isColor(), HtmlColor.ALICEBLUE );
Table t = new Table().setCellSpacing( 0 ).setCellPadding( 2 ).setBorder( 0 ).setWidth( "90%" ).setAlign(
"center" );
ec.addElement( new BR() );
TR tr = new TR();
tr.addElement( new TD().addElement( "Please select credit card for this purchase: " ) );
Element p = ECSFactory.makePulldown( CREDIT, v );
tr.addElement( new TD().addElement( p ).setAlign( "right" ));
t.addElement( tr );
tr = new TR();
Element b = ECSFactory.makeButton( "Buy Now!" );
tr.addElement( new TD().addElement( b ) );
t.addElement( tr );
ec.addElement(t);
ec.addElement( new BR() );
Input input = new Input( Input.HIDDEN, USER, "White" );
ec.addElement( input );
}
}
catch ( Exception e )
{
s.setMessage("An error occurred in the woods");
}
return ( ec );
//
}
/**
* Description of the Method
*
* @param s Description of the Parameter
* @return Description of the Return Value
* @exception Exception Description of the Exception
*/
/* (non-Javadoc)
* @see lessons.LessonAdapter#doStage3(session.WebSession)
*/
protected Element doStage3( WebSession s ) throws Exception
{
//
ElementContainer ec = new ElementContainer();
if ( s.getParser().getStringParameter(Input.SUBMIT, "").equals(PROCEED_TO_NEXT_STAGE +"(4)"))
{
setStage( s, 4 );
// Reset the defaced webpage so the lesson can start over
resetWebPage(s);
return doStage4(s);
}
// execute the possible attack first to determine if site is defaced.
ElementContainer netstatResults = getNetstatResults(s);
if (isDefaced(s))
{
ec.addElement( new HR() );
s.setMessage( "CONGRATULATIONS - You have defaced the site!" );
Table t = new Table().setCellSpacing( 0 ).setCellPadding( 2 ).setWidth("90%").setAlign("center");
if ( s.isColor() )
{
t.setBorder( 1 );
}
TR tr = new TR();
tr.addElement( new TD().setAlign("center").addElement(ECSFactory.makeButton(PROCEED_TO_NEXT_STAGE + "(4)")));
t.addElement(tr);
tr = new TR();
tr.addElement( new TD().addElement( showDefaceAttempt(s) ));
t.addElement(tr);
ec.addElement( t );
return ec;
}
else
{
// Setup the screen content
try
{
ec.addElement( new H1("Current Network Status:") );
ec.addElement( netstatResults );
Table t = new Table().setCellSpacing( 0 ).setCellPadding( 2 ).setWidth("90%").setAlign("center");
if ( s.isColor() )
{
t.setBorder( 1 );
}
String[] list = {"TCP", "TCPv6", "IP", "IPv6", "UDP", "UDPv6"};
TR tr = new TR();
tr.addElement( new TD().addElement( ECSFactory.makeButton( "View Network" )));
tr.addElement( new TD().setWidth("35%").addElement( ECSFactory.makePulldown( PROTOCOL, list, "", 5 )));
t.addElement(tr);
ec.addElement( t );
}
catch ( Exception e )
{
ec.addElement( new P().addElement( "Select a message to read from the Message List below" ) );
}
ec.addElement( new HR() );
Table t = new Table().setCellSpacing( 0 ).setCellPadding( 2 ).setWidth("90%").setAlign("center");
if ( s.isColor() )
{
t.setBorder( 1 );
}
TR tr = new TR();
tr.addElement( new TD().addElement( showDefaceAttempt(s) ));
t.addElement(tr);
ec.addElement( t );
}
return ( ec );
//
}
private boolean isDefaced(WebSession s)
{
//
boolean defaced = false;
try
{
// get current text and compare to the new text
String origpath = s.getContext(). getRealPath( WEBGOAT_CHALLENGE + "_" + s.getUserName() + JSP );
String masterFilePath = s.getContext().getRealPath( WEBGOAT_CHALLENGE_JSP );
String defacedText = getFileText( new BufferedReader( new FileReader( origpath ) ), false );
String origText = getFileText( new BufferedReader( new FileReader( masterFilePath ) ), false );
defaced = ( !origText.equals(defacedText) );
}
catch ( Exception e )
{
e.printStackTrace();
}
return defaced;
//
}
private Element showDefaceAttempt( WebSession s ) throws Exception
{
ElementContainer ec = new ElementContainer();
// get current text and compare to the new text
String origpath = s.getContext(). getRealPath( WEBGOAT_CHALLENGE + "_" + s.getUserName() + JSP );
String defaced = getFileText( new BufferedReader( new FileReader( origpath ) ), false );
String origText = getFileText( new BufferedReader( new FileReader( s.getContext(). getRealPath( WEBGOAT_CHALLENGE_JSP ))), false);
// show webgoat.jsp text
ec.addElement( new H1().addElement( "Original Website Text" ) );
ec.addElement( new P().addElement( origText ) );
ec.addElement( new HR() );
ec.addElement( new H1().addElement( "Defaced Website Text" ) );
ec.addElement( new P().addElement( defaced ) );
ec.addElement( new HR() );
return ec;
}
private void resetWebPage(WebSession s)
{
try
{
// get current text and compare to the new text
String defacedpath = s.getContext(). getRealPath( WEBGOAT_CHALLENGE + "_" + s.getUserName() + JSP );
String masterFilePath = s.getContext().getRealPath( WEBGOAT_CHALLENGE_JSP );
// replace the defaced text with the original
File usersFile = new File( defacedpath );
FileWriter fw = new FileWriter( usersFile );
fw.write( getFileText( new BufferedReader( new FileReader( masterFilePath ) ), false ) );
fw.close();
// System.out.println("webgoat_guest replaced: " + getFileText( new BufferedReader( new FileReader( defacedpath ) ), false ) );
}
catch (Exception e)
{
e.printStackTrace();
}
}
protected Category getDefaultCategory()
{
return CHALLENGE;
}
/**
* Description of the Method
*
* @param s Description of the Parameter
* @return Description of the Return Value
* @exception Exception Description of the Exception
*/
protected Element doStage4( WebSession s ) throws Exception
{
makeSuccess( s );
ElementContainer ec = new ElementContainer();
ec.addElement(new H1().addElement( "Thanks for coming!" ));
ec.addElement(new BR());
ec.addElement(new H1().addElement( "Please remember that you will be caught and fired if you use these techniques for evil." ));
return ( ec ) ;
}
/**
* Description of the Method
*
* @param s Description of the Parameter
* @return Description of the Return Value
* @exception Exception Description of the Exception
*/
protected Element doStage5( WebSession s ) throws Exception
{
//
ElementContainer ec = new ElementContainer();
return ( ec );
//
}
/**
* Description of the Method
*
* @param s Description of the Parameter
* @return Description of the Return Value
* @exception Exception Description of the Exception
*/
protected Element doStage6( WebSession s ) throws Exception
{
return ( new StringElement( "not yet" ) );
}
/**
* Gets the hints attribute of the ChallengeScreen object
*
* @return The hints value
*/
protected List getHints(WebSession s)
{
//
List hints = new ArrayList();
hints.add( "You need to gain access to the Java source code for this lesson." );
hints.add( "Seriously, no more hints -- it's a CHALLENGE!" );
hints.add( "Come on -- give it a rest!" );
if (getStage(s) != 1);
{
hints.add("Persistance is always rewarded");
}
return hints;
//
}
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 );
}
/**
* Gets the instructions attribute of the ChallengeScreen object
*
* @return The instructions value
*/
public String getInstructions(WebSession s)
{
String instructions = "Your mission is to break the authentication scheme, " +
"steal all the credit cards from the database, and then deface the website. " +
"You will have to use many of the techniques you have learned in the other lessons. " +
"The main webpage for this site is 'webgoat_challenge_<username>.jsp'";
return ( instructions );
}
/**
* Gets the ranking attribute of the ChallengeScreen object
*
* @return The ranking value
*/
protected Integer getDefaultRanking()
{
return new Integer( 130 );
}
/**
* Gets the title attribute of the ChallengeScreen object
*
* @return The title value
*/
public String getTitle()
{
return ( "The CHALLENGE!" );
}
/**
* Description of the Method
*
* @param text Description of the Parameter
* @return Description of the Return Value
*/
protected ElementContainer getNetstatResults( WebSession s )
{
//
ElementContainer ec = new ElementContainer();
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("Protocol").setWidth("7%"));
tr.addElement( new TH().addElement("Local Address").setWidth("80%"));
tr.addElement( new TH().addElement("Foreign Address").setWidth("10%"));
tr.addElement( new TH().addElement("State").setWidth("3%"));
t.addElement( tr );
String protocol = s.getParser().getRawParameter( PROTOCOL, "tcp" );
String osName = System.getProperty( "os.name" );
ExecResults er = null;
if ( osName.indexOf( "Windows" ) != -1 )
{
String cmd = "cmd.exe /c netstat -a -p " + protocol;
er = Exec.execSimple( cmd );
}
else
{
String[] cmd = {"/bin/sh", "-c", "netstat -a -p " + protocol};
er = Exec.execSimple( cmd );
}
String results = er.getOutput();
StringTokenizer lines = new StringTokenizer( results, "\n");
String line = lines.nextToken();
//System.out.println(line);
int start = 0;
while ( start == 0 && lines.hasMoreTokens() )
{
if (( line.indexOf("Proto") != -1 ) )
{
start++;
}
else
{
line = lines.nextToken();
}
}
while ( start > 0 && lines.hasMoreTokens() )
{
// in order to avoid a ill-rendered screen when the user performs
// command injection, we will wrap the screen at 4 columns
int columnCount = 4;
tr = new TR();
StringTokenizer tokens = new StringTokenizer( lines.nextToken(), "\t ");
while( tokens.hasMoreTokens() && columnCount-- > 0 )
{
tr.addElement( new TD().addElement(tokens.nextToken()));
}
t.addElement( tr );
}
// parse the results
ec.addElement( t );
return ( ec );
//
}
/**
* Description of the Method
*
* @param s Description of the Parameter
* @return Description of the Return Value
*/
protected Element makeClues( WebSession s )
{
return new StringElement( "Clues not Available :)" );
}
protected Element makeHints( WebSession s )
{
return new StringElement("Hint: Find the hints");
}
/**
* Description of the Method
*
* @param s Description of the Parameter
* @param message Description of the Parameter
*/
protected void sendMessage( Socket s, String message )
{
try
{
OutputStreamWriter osw = new OutputStreamWriter( s.getOutputStream() );
osw.write( message );
}
catch ( Exception e )
{
System.out.println( "Couldn't write " + message + " to " + s );
e.printStackTrace();
}
}
protected Element buildCart( WebSession s )
{
ElementContainer ec = new ElementContainer();
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("Sympathy Bouquet"));
tr.addElement( new TD().addElement("59.99").setAlign("right"));
tr.addElement( new TD().addElement(" 1 ").setAlign( "right" ));
tr.addElement( new TD().addElement("59.99"));
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( "59.99"));
t.addElement( tr );
ec.addElement(t);
return ( ec );
}
public boolean canHaveClues()
{
return false;
}
/**
* 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( USER_COOKIE ) )
{
return ( cookies[i].getValue() );
}
}
return ( null );
}
}