419 lines
14 KiB
Java
419 lines
14 KiB
Java
/*
|
|
* 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.sql.Connection;
|
|
import java.sql.PreparedStatement;
|
|
import java.sql.ResultSet;
|
|
import java.sql.SQLException;
|
|
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.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.owasp.webgoat.session.DatabaseUtilities;
|
|
import org.owasp.webgoat.session.ECSFactory;
|
|
import org.owasp.webgoat.session.ParameterNotFoundException;
|
|
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 SoapRequest extends LessonAdapter {
|
|
/* TEST CODE
|
|
private final static String ACCT_NUM = "account_number";
|
|
private static Connection connection = null;
|
|
private String accountNumber;
|
|
*/
|
|
|
|
//static boolean completed;
|
|
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";
|
|
|
|
//int instead of boolean to keep track of method invocation count
|
|
static int accessFirstName;
|
|
static int accessLastName;
|
|
static int accessCreditCard;
|
|
static int accessLoginCount;
|
|
|
|
protected Category getDefaultCategory()
|
|
{
|
|
return AbstractLesson.WEB_SERVICES;
|
|
}
|
|
|
|
protected List getHints()
|
|
{
|
|
List<String> hints = new ArrayList<String>();
|
|
hints.add("Accessible operations are delimited by the <operation> tag contained within the <portType> section of the WSDL. <BR> Below is an example of a typical operation (getFirstName): <br><br>" +
|
|
"<wsdl:portType name=\"SoapRequest\"> <br>" +
|
|
"<wsdl:<strong>operation name=\"getFirstName\"</strong>><br>" +
|
|
"<wsdl:input message=\"impl:getFirstNameRequest\" name=\"getFirstNameRequest\" /><br>" +
|
|
"<wsdl:output message=\"impl:getFirstNameResponse\" name=\"getFirstNameResponse\" /><br>" +
|
|
"<wsdlsoap:operation soapAction=\"\" />" +
|
|
"</wsdl:portType><br><br>" +
|
|
"The methods invoked are defined by the input and output message attributes. " +
|
|
"Example: <strong>\"getFirstNameRequest\"</strong>");
|
|
hints.add("There are several tags within a SOAP envelope. " +
|
|
"Each namespace is defined in the <definitions> section of the WSDL, and is declared using the (xmlns:namespace_name_here=\"namespace_reference_location_here\") format.<br><br>" +
|
|
"The following example defines a tag \"<xsd:\", whose attribute structure will reference the namespace location assigned to it in the declaration:<br>" +
|
|
"<strong>xmlns:xsd=\"http://www.w3.org/2001/XMLSchema</strong>");
|
|
hints.add("Determine what parameters and types are required by the message definition corresponding to the operation's request method. " +
|
|
"This example defines a parameter (id) of type (int) in the namespace (xsd) for the method (getFirstNameRequest):<br>" +
|
|
"<wsdl:message name=\"getFirstNameRequest\"<br><br>" +
|
|
"<wsdl:<strong>part name=\"id\" type=\"xsd:int\"</strong> /><br>" +
|
|
"</wsdl:message><br><br>" +
|
|
"Examples of other types:<br>" +
|
|
"{boolean, byte, base64Binary, double, float, int, long, short, unsignedInt, unsignedLong, unsignedShort, string}.<br>");
|
|
String soapEnv = "A SOAP request uses the following HTTP header: <br><br> " +
|
|
"SOAPAction: some action header, can be "" <br><br>" +
|
|
"The SOAP message body has the following format:<br>" +
|
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?> <br>" +
|
|
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" <br>" +
|
|
" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" <br>" +
|
|
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> <br>" +
|
|
" <SOAP-ENV:Body> <br>" +
|
|
" <ns1:getFirstName SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:ns1=\"http://lessons\"> <br>" +
|
|
" <id xsi:type=\"xsd:int\">101</id> <br>"+
|
|
" </ns1:getFirstName> <br>" +
|
|
" </SOAP-ENV:Body> <br>" +
|
|
"</SOAP-ENV:Envelope> <br><br>" +
|
|
"Intercept the HTTP request and try to create a SOAP request.";
|
|
soapEnv.replaceAll("(?s) "," ");
|
|
hints.add(soapEnv);
|
|
|
|
return hints;
|
|
}
|
|
|
|
private final static Integer DEFAULT_RANKING = new Integer(100);
|
|
|
|
protected Integer getDefaultRanking()
|
|
{
|
|
return DEFAULT_RANKING;
|
|
}
|
|
|
|
public String getTitle()
|
|
{
|
|
return "How to Create a SOAP Request";
|
|
}
|
|
|
|
protected Element makeOperationsLine( 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().addElement( "How many operations are defined in the WSDL: " ));
|
|
tr.addElement(new TD( new Input( Input.TEXT, "count", "")));
|
|
Element b = ECSFactory.makeButton( "Submit" );
|
|
tr.addElement( new TD(b).setAlign("LEFT") );
|
|
t1.addElement(tr);
|
|
|
|
ec.addElement(t1);
|
|
|
|
return ec;
|
|
}
|
|
|
|
protected Element makeTypeLine( 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().addElement( "Now, what is the type of the (id) parameter in the \"getFirstNameRequest\" method: " ));
|
|
tr.addElement(new TD( new Input( Input.TEXT, "type", "")));
|
|
Element b = ECSFactory.makeButton( "Submit" );
|
|
tr.addElement( new TD(b).setAlign("LEFT") );
|
|
t1.addElement(tr);
|
|
|
|
ec.addElement(t1);
|
|
|
|
return ec;
|
|
}
|
|
|
|
protected Element createContent( WebSession s )
|
|
{
|
|
return super.createStagedContent(s);
|
|
}
|
|
|
|
protected Element doStage1( WebSession s ) throws Exception
|
|
{
|
|
return viewWsdl( s );
|
|
}
|
|
|
|
protected Element doStage2( WebSession s ) throws Exception
|
|
{
|
|
return determineType( s);
|
|
}
|
|
|
|
protected Element doStage3( WebSession s ) throws Exception
|
|
{
|
|
return createSoapEnvelope( s);
|
|
}
|
|
|
|
protected Element viewWsdl(WebSession s)
|
|
{
|
|
ElementContainer ec = new ElementContainer();
|
|
|
|
//DEVNOTE: Test for stage completion.
|
|
try
|
|
{
|
|
int operationCount = 0;
|
|
operationCount = s.getParser().getIntParameter( "count" );
|
|
|
|
if (operationCount == 4)
|
|
{
|
|
getLessonTracker(s).setStage(2);
|
|
s.setMessage("Stage 1 completed.");
|
|
|
|
// Redirect user to Stage2 content.
|
|
ec.addElement(doStage2(s));
|
|
}
|
|
else
|
|
{
|
|
s.setMessage( "Sorry, that is an incorrect count. Try Again." );
|
|
}
|
|
}
|
|
catch (NumberFormatException nfe)
|
|
{
|
|
//DEVNOTE: Eat the exception.
|
|
//ec.addElement( new P().addElement( nfe.getMessage() ) );
|
|
s.setMessage("Sorry, that answer is invalid. Try again.");
|
|
}
|
|
catch (ParameterNotFoundException pnfe)
|
|
{
|
|
//DEVNOTE: Eat the exception.
|
|
// ec.addElement( new P().addElement( pnfe.getMessage() ) );
|
|
}
|
|
catch ( Exception e )
|
|
{
|
|
s.setMessage( "Error generating " + this.getClass().getName() );
|
|
e.printStackTrace();
|
|
}
|
|
|
|
//DEVNOTE: Conditionally display Stage1 content depending on whether stage is completed or not
|
|
if (getLessonTracker(s).getStage() == 1)
|
|
//if ( null == (getLessonTracker(s).getLessonProperties().getProperty(WebSession.STAGE)) ||
|
|
// (getLessonTracker(s).getLessonProperties().getProperty(WebSession.STAGE)).equals("1") )
|
|
{
|
|
ec.addElement( makeOperationsLine(s) );
|
|
|
|
A a = new A("services/SoapRequest?WSDL","WebGoat WSDL");
|
|
ec.addElement(new P().addElement("View the following WSDL and count available operations:"));
|
|
ec.addElement(new BR());
|
|
ec.addElement(a);
|
|
}
|
|
|
|
//getLessonTracker( s ).setCompleted( SoapRequest.completed );
|
|
|
|
return (ec);
|
|
}
|
|
|
|
protected Element determineType(WebSession s)
|
|
{
|
|
ElementContainer ec = new ElementContainer();
|
|
|
|
//DEVNOTE: Test for stage completion.
|
|
try
|
|
{
|
|
String paramType = "";
|
|
paramType = s.getParser().getStringParameter( "type" );
|
|
|
|
//if (paramType.equalsIgnoreCase("int"))
|
|
if (paramType.equals("int"))
|
|
{
|
|
getLessonTracker(s).setStage(3);
|
|
s.setMessage("Stage 2 completed. ");
|
|
//s.setMessage("Now, you'll craft a SOAP envelope for invoking a web service directly.");
|
|
|
|
// Redirect user to Stage2 content.
|
|
ec.addElement(doStage3(s));
|
|
}
|
|
else
|
|
{
|
|
s.setMessage( "Sorry, that is an incorrect type. Try Again." );
|
|
}
|
|
}
|
|
catch (ParameterNotFoundException pnfe)
|
|
{
|
|
//DEVNOTE: Eat the exception.
|
|
// ec.addElement( new P().addElement( pnfe.getMessage() ) );
|
|
}
|
|
catch ( Exception e )
|
|
{
|
|
s.setMessage( "Error generating " + this.getClass().getName() );
|
|
e.printStackTrace();
|
|
}
|
|
|
|
//DEVNOTE: Conditionally display Stage2 content depending on whether stage is completed or not
|
|
if (getLessonTracker(s).getStage() == 2)
|
|
//if ( null == (getLessonTracker(s).getLessonProperties().getProperty(WebSession.STAGE)) ||
|
|
// (getLessonTracker(s).getLessonProperties().getProperty(WebSession.STAGE)).equals("2") )
|
|
{
|
|
ec.addElement( makeTypeLine(s) );
|
|
|
|
A a = new A("services/SoapRequest?WSDL","WebGoat WSDL");
|
|
ec.addElement(new P().addElement("View the following WSDL and count available operations:"));
|
|
ec.addElement(new BR());
|
|
ec.addElement(a);
|
|
}
|
|
|
|
//getLessonTracker( s ).setCompleted( SoapRequest.completed );
|
|
|
|
return (ec);
|
|
}
|
|
|
|
protected Element createSoapEnvelope (WebSession s)
|
|
{
|
|
ElementContainer ec = new ElementContainer();
|
|
|
|
// Determine how many methods have been accessed. User needs to check at least two methods
|
|
// before completing the lesson.
|
|
if ((accessFirstName + accessLastName + accessCreditCard + accessLoginCount) >= 2)
|
|
{
|
|
//SoapRequest.completed = true;
|
|
makeSuccess(s);
|
|
}
|
|
else
|
|
{
|
|
|
|
// display Stage2 content
|
|
ec.addElement(new P().addElement( "Intercept the request and invoke any method by sending a valid SOAP request for a valid account. <br>" ));
|
|
Element b = ECSFactory.makeButton( "Press to generate an HTTP request" );
|
|
ec.addElement( b );
|
|
|
|
// conditionally display invoked methods
|
|
if ((accessFirstName + accessLastName + accessCreditCard + accessLoginCount) > 0)
|
|
{
|
|
ec.addElement("<br><br>Methods Invoked:<br>");
|
|
ec.addElement("<ul>");
|
|
if ( accessFirstName > 0 )
|
|
{
|
|
ec.addElement("<li>getFirstName</li>");
|
|
}
|
|
if ( accessLastName > 0 )
|
|
{
|
|
ec.addElement("<li>getLastName</li>");
|
|
}
|
|
if ( accessCreditCard > 0 )
|
|
{
|
|
ec.addElement("<li>getCreditCard</li>");
|
|
}
|
|
if ( accessLoginCount > 0 )
|
|
{
|
|
ec.addElement("<li>getLoginCount</li>");
|
|
}
|
|
ec.addElement("</ul>");
|
|
}
|
|
}
|
|
|
|
//getLessonTracker( s ).setCompleted( SoapRequest.completed );
|
|
return (ec);
|
|
}
|
|
|
|
public String getResults(int id, String field) {
|
|
try
|
|
{
|
|
Connection connection = DatabaseUtilities.makeConnection();
|
|
if (connection == null) {
|
|
return null;
|
|
}
|
|
PreparedStatement ps = connection.prepareStatement("SELECT * FROM user_data WHERE userid = ?");
|
|
ps.setInt(1, id);
|
|
try
|
|
{
|
|
ResultSet results = ps.executeQuery();
|
|
if ( ( results != null ) && ( results.next() == true ) )
|
|
{
|
|
return results.getString(field);
|
|
}
|
|
}
|
|
catch ( SQLException sqle )
|
|
{
|
|
}
|
|
}
|
|
catch ( Exception e )
|
|
{
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public String getCreditCard(int id) {
|
|
String result = getResults(id, "cc_number");
|
|
//SoapRequest.completed = true;
|
|
|
|
if (result != null)
|
|
{
|
|
//DEVNOTE: Always set method access counter to (1) no matter how many times it is accessed.
|
|
// This is intended to be used to determine how many methods have been accessed, not how often.
|
|
accessCreditCard = 1;
|
|
return result;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public String getFirstName(int id) {
|
|
String result = getResults(id, "first_name");
|
|
if (result != null)
|
|
{
|
|
//DEVNOTE: Always set method access counter to (1) no matter how many times it is accessed.
|
|
// This is intended to be used to determine how many methods have been accessed, not how often.
|
|
accessFirstName = 1;
|
|
return result;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public String getLastName(int id) {
|
|
String result = getResults(id, "last_name");
|
|
if (result != null)
|
|
{
|
|
//DEVNOTE: Always set method access counter to (1) no matter how many times it is accessed.
|
|
// This is intended to be used to determine how many methods have been accessed, not how often.
|
|
accessLastName = 1;
|
|
return result;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public String getLoginCount(int id) {
|
|
String result = getResults(id, "login_count");
|
|
if (result != null)
|
|
{
|
|
//DEVNOTE: Always set method access counter to (1) no matter how many times it is accessed.
|
|
// This is intended to be used to determine how many methods have been accessed, not how often.
|
|
accessLoginCount = 1;
|
|
return result;
|
|
}
|
|
return null;
|
|
}
|
|
}
|