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 ); } }