package org.owasp.webgoat.lessons;
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.IMG;
import org.apache.ecs.html.Input;
import org.apache.ecs.html.TD;
import org.apache.ecs.html.TR;
import org.apache.ecs.html.Table;
import org.apache.ecs.xhtml.br;
import org.owasp.webgoat.session.ECSFactory;
import org.owasp.webgoat.session.ParameterNotFoundException;
import org.owasp.webgoat.session.ValidationException;
import org.owasp.webgoat.session.WebSession;
/***************************************************************************************************
*
*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* Copyright (c) 2002 - 20014 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
*
* For details, please see http://webgoat.github.io
*
* @author Yiannis Pavlosoglou <a href="http://code.google.com/p/webgoat">WebGoat</a>
* @created December 05, 2009
*/
public class OffByOne extends LessonAdapter
{
private final static String[] price_plans = { "$1.99 - 1 hour ", "$5.99 - 12 hours", "$9.99 - 24 hours"};
private final static String ROOM_NUMBER = "room_no";
private final static String FIRST_NAME = "first_name";
private final static String LAST_NAME = "last_name";
private final static String PRICE_PLAN = "price_plan";
private final static IMG LOGO = new IMG("images/logos/seleucus.png").setAlt("Seleucus Ltd")
.setBorder(0).setHspace(0).setVspace(0);
/**
* <p>The main method for creating content, implemented
* from the the LessonAdapter class.</p>
*
* <p>This particular "Off-by-One" lesson belonging in
* the category of "Buffer Overflows" carries three
* steps.</p>
*
* @param s
* WebSession
* @return Description of the Return Value
*/
protected Element createContent(WebSession s)
{
ElementContainer ec = new ElementContainer();
try
{
if(isFirstStep(s))
{
ec.addElement(makeFirstStep(s));
}
else
{
if (isSecondStep(s))
{
ec.addElement(makeSecondStep(s));
}
else
{
ec.addElement(makeThirdStep(s));
}
}
} catch (Exception e)
{
s.setMessage("Error generating " + this.getClass().getName());
e.printStackTrace();
}
return (ec);
}
/**
* <p>Returns the Buffer Overflow category for this
* lesson.</p>
*
* @return The category value
*/
protected Category getDefaultCategory()
{
return Category.BUFFER_OVERFLOW;
}
/**
* <p>Returns the hints as a List of Strings
* for this lesson.</p>
*
* @return The hints values
*/
public List<String> getHints(WebSession s)
{
List<String> hints = new ArrayList<String>();
hints.add("While registering for Internet usage, see where else your details are used during the registration process.");
hints.add("See which fields during the registration process, allow for really long input to be submitted.");
hints.add("Check for hidden form fields during registration");
hints.add("Typically, web-based buffer overflows occur just above the value of 2 to the power of a number. E.g. 1024 + 1, 2048 + 1, 4096 + 1");
hints.add("Overflow the room number field with 4096+1 characters and look for hidden fields");
hints.add("Enter the VIP name in the first and last name fields");
return hints;
}
/**
* <p>Get the default ranking within the "Buffer
* Overflow" category.</p>
*
* <p>Currently ranked to be the first lesson in
* this category.</p>
*
* @return The value of 5 as an Integer Object
*/
protected Integer getDefaultRanking()
{
return new Integer(5);
}
/**
* <p>Gets the title attribute for this lesson.</p>
*
* @return "Off-by-One Overflows"
*/
public String getTitle()
{
return ("Off-by-One Overflows");
}
/**
* yada, yada...
*/
public Element getCredits()
{
return super.getCustomCredits("Created by Yiannis Pavlosoglou ", LOGO);
}
/**
* <p>Based on the parameters currently with values, this method
* returns true if we are in the first step of this lesson.</p>
*
* @param s
* @return true if we are in the first step of the lesson.
*/
protected boolean isFirstStep(WebSession s)
{
String room = s.getParser().getRawParameter(ROOM_NUMBER, "");
String name = s.getParser().getRawParameter(FIRST_NAME, "");
String last = s.getParser().getRawParameter(LAST_NAME, "");
return (room.isEmpty() && name.isEmpty() && last.isEmpty() );
}
/**
* <p>Based on the parameters currently with values, this method
* returns true if we are in the second step of this lesson.</p>
*
* @param s
* @return true if we are in the second step of the lesson
*/
protected boolean isSecondStep(WebSession s)
{
String price = s.getParser().getRawParameter(PRICE_PLAN, "");
return price.isEmpty();
}
/**
* <p>Method for constructing the first step and returning it as
* an Element.</p>
*
* @param s
* @return The Element that is the first step.
*/
private Element makeFirstStep(WebSession s)
{
ElementContainer ec = new ElementContainer();
String param = "";
// Header
ec.addElement(new StringElement("In order to access the Internet, you need to provide us the following information:"));
ec.addElement(new br());
ec.addElement(new br());
ec.addElement(new StringElement("Step 1/2"));
ec.addElement(new br());
ec.addElement(new br());
ec.addElement(new StringElement("Ensure that your first and last names are entered exactly as they appear in the hotel's registration system."));
ec.addElement(new br());
ec.addElement(new br());
// Table
Table t = new Table().setCellSpacing(0).setCellPadding(2).setBorder(0).setWidth("90%").setAlign("center");
if (s.isColor())
{
t.setBorder(1);
}
// First Name
try {
param = s.getParser().getStrictAlphaParameter(FIRST_NAME, 25);
} catch (ParameterNotFoundException e) {
param = "";
} catch (ValidationException e) {
param = "";
}
Input input = new Input(Input.TEXT, FIRST_NAME, param);
TR tr = new TR();
tr.addElement(new TD().addElement("First Name: "));
tr.addElement(new TD().addElement(input));
tr.addElement(new TD().addElement("*"));
t.addElement(tr);
tr = new TR();
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
t.addElement(tr);
// Last Name
try {
param = s.getParser().getStrictAlphaParameter(LAST_NAME, 25);
} catch (ParameterNotFoundException e) {
param = "";
} catch (ValidationException e) {
param = "";
}
input = new Input(Input.TEXT, LAST_NAME, param);
tr = new TR();
tr.addElement(new TD().addElement("Last Name: "));
tr.addElement(new TD().addElement(input));
tr.addElement(new TD().addElement("*"));
t.addElement(tr);
tr = new TR();
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
t.addElement(tr);
// Room Number
try {
param = s.getParser().getStrictAlphaParameter(ROOM_NUMBER, 25);
} catch (ParameterNotFoundException e) {
param = "";
} catch (ValidationException e) {
param = "";
}
input = new Input(Input.TEXT, ROOM_NUMBER, param);
tr = new TR();
tr.addElement(new TD().addElement("Room Number: "));
tr.addElement(new TD().addElement(input));
tr.addElement(new TD().addElement("*"));
t.addElement(tr);
tr = new TR();
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
t.addElement(tr);
// Submit
tr = new TR();
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(ECSFactory.makeButton("Submit")));
tr.addElement(new TD().addElement(" "));
t.addElement(tr);
ec.addElement(t);
// Footer
ec.addElement(new br());
ec.addElement(new br());
ec.addElement(new StringElement("* The above fields are required for login."));
ec.addElement(new br());
ec.addElement(new br());
return ec;
}
/**
* <p>Method for constructing the second step and returning it as
* an Element.</p>
*
* @param s
* @return The Element that is the second step.
*/
private Element makeSecondStep(WebSession s)
{
ElementContainer ec = new ElementContainer();
String param = "";
// Header
ec.addElement(new StringElement("Please select from the following available price plans:"));
ec.addElement(new br());
ec.addElement(new br());
ec.addElement(new StringElement("Step 2/2"));
ec.addElement(new br());
ec.addElement(new br());
ec.addElement(new StringElement("Ensure that your selection matches the hours of usage, as no refunds are given for this service."));
ec.addElement(new br());
ec.addElement(new br());
// Table
Table t = new Table().setCellSpacing(0).setCellPadding(2).setBorder(0).setWidth("90%").setAlign("center");
if (s.isColor())
{
t.setBorder(1);
}
// First Empty Row
TR tr = new TR();
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
t.addElement(tr);
// Price Plans
tr = new TR();
tr.addElement(new TD().addElement("Available Price Plans:"));
tr.addElement(new TD().addElement(ECSFactory.makePulldown(PRICE_PLAN, price_plans, price_plans[2], 1)));
tr.addElement(new TD().addElement(" "));
t.addElement(tr);
// Submit
tr = new TR();
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(ECSFactory.makeButton("Accept Terms")));
tr.addElement(new TD().addElement(" "));
t.addElement(tr);
ec.addElement(t);
ec.addElement("\r\n");
// Hidden Form Fields
param = s.getParser().getStringParameter(LAST_NAME, "");
Input input = new Input(Input.HIDDEN, LAST_NAME, param);
ec.addElement(input);
ec.addElement("\r\n");
param = s.getParser().getStringParameter(FIRST_NAME, "");
input = new Input(Input.HIDDEN, FIRST_NAME, param);
ec.addElement(input);
ec.addElement("\r\n");
param = s.getParser().getStringParameter(ROOM_NUMBER, "");
input = new Input(Input.HIDDEN, ROOM_NUMBER, param);
ec.addElement(input);
ec.addElement("\r\n");
// Footer
ec.addElement(new br());
ec.addElement(new br());
ec.addElement(new StringElement("By Clicking on the above you accept the terms and conditions."));
ec.addElement(new br());
ec.addElement(new br());
return ec;
}
/**
* <p>Method for constructing the third step and returning it as
* an Element.</p>
*
* @param s
* @return The Element that is the third step.
*/
private Element makeThirdStep(WebSession s)
{
ElementContainer ec = new ElementContainer();
String param1 = "";
String param2 = "";
String param3 = "";
// Header
ec.addElement(new StringElement("You have now completed the 2 step process and have access to the Internet"));
ec.addElement(new br());
ec.addElement(new br());
ec.addElement(new StringElement("Process complete"));
ec.addElement(new br());
ec.addElement(new br());
ec.addElement(new StringElement("Your connection will remain active for the time allocated for starting now."));
ec.addElement(new br());
ec.addElement(new br());
// Table
Table t = new Table().setCellSpacing(0).setCellPadding(2).setBorder(0).setWidth("90%").setAlign("center");
if (s.isColor())
{
t.setBorder(1);
}
// First Empty Row
TR tr = new TR();
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
t.addElement(tr);
// Price Plans
tr = new TR();
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
t.addElement(tr);
// Submit
tr = new TR();
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
tr.addElement(new TD().addElement(" "));
t.addElement(tr);
ec.addElement(t);
ec.addElement("\r\n");
// Hidden Form Fields
param1 = s.getParser().getStringParameter(LAST_NAME, "");
Input input = new Input(Input.HIDDEN, "a", param1);
ec.addElement(input);
ec.addElement("\r\n");
param2 = s.getParser().getStringParameter(FIRST_NAME, "");
input = new Input(Input.HIDDEN, "b", param2);
ec.addElement(input);
ec.addElement("\r\n");
param3 = s.getParser().getStringParameter(ROOM_NUMBER, "");
input = new Input(Input.HIDDEN, "c", param3);
ec.addElement(input);
ec.addElement("\r\n");
// And finally the check...
if(param3.length() > 4096)
{
ec.addElement(new Input(Input.hidden, "d", "Johnathan"));
ec.addElement("\r\n");
ec.addElement(new Input(Input.hidden, "e", "Ravern"));
ec.addElement("\r\n");
ec.addElement(new Input(Input.hidden, "f", "4321"));
ec.addElement("\r\n");
ec.addElement(new Input(Input.hidden, "g", "John"));
ec.addElement("\r\n");
ec.addElement(new Input(Input.hidden, "h", "Smith"));
ec.addElement("\r\n");
ec.addElement(new Input(Input.hidden, "i", "56"));
ec.addElement("\r\n");
ec.addElement(new Input(Input.hidden, "j", "Ana"));
ec.addElement("\r\n");
ec.addElement(new Input(Input.hidden, "k", "Arneta"));
ec.addElement("\r\n");
ec.addElement(new Input(Input.hidden, "l", "78"));
ec.addElement("\r\n");
ec.addElement(new Input(Input.hidden, "m", "Lewis"));
ec.addElement("\r\n");
ec.addElement(new Input(Input.hidden, "n", "Hamilton"));
ec.addElement("\r\n");
ec.addElement(new Input(Input.hidden, "o", "9901"));
ec.addElement("\r\n");
s.setMessage("To complete the lesson, restart lesson and enter VIP first/last name");
}
if (("Johnathan".equalsIgnoreCase(param2) || "John".equalsIgnoreCase(param2)
|| "Ana".equalsIgnoreCase(param2) ||"Lewis".equalsIgnoreCase(param2))
&& ("Ravern".equalsIgnoreCase(param1) || "Smith".equalsIgnoreCase(param1)
|| "Arneta".equalsIgnoreCase(param1) ||"Hamilton".equalsIgnoreCase(param1)))
{
// :)
// Allows for mixed VIP names, but that's not really the point
makeSuccess(s);
}
// Footer
ec.addElement(new br());
ec.addElement(new br());
ec.addElement(new StringElement("We would like to thank you for your payment."));
ec.addElement(new br());
ec.addElement(new br());
return ec;
}
}