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