Merge pull request #196 from span/xss-lab

Add stage parameter in the session to keep track of current stage
This commit is contained in:
mayhew64 2016-02-12 13:01:31 -05:00
commit 727e4ff56c
2 changed files with 272 additions and 189 deletions

View File

@ -33,32 +33,27 @@ import org.slf4j.LoggerFactory;
* ************************************************************************************************* * *************************************************************************************************
* *
* *
* This file is part of WebGoat, an Open Web Application Security Project * This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see
* utility. For details, please see http://www.owasp.org/ * http://www.owasp.org/
* *
* Copyright (c) 2002 - 20014 Bruce Mayhew * Copyright (c) 2002 - 20014 Bruce Mayhew
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
* the terms of the GNU General Public License as published by the Free Software * License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later
* Foundation; either version 2 of the License, or (at your option) any later
* version. * version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* 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 * You should have received a copy of the GNU General Public License along with this program; if not, write to the Free
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Place - Suite 330, Boston, MA 02111-1307, USA.
* *
* Getting Source ============== * Getting Source ==============
* *
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* for free software projects. * projects.
* *
* @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect * @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
* Security</a>
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a> * @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
* @since October 28, 2003 * @since October 28, 2003
* @version $Id: $Id * @version $Id: $Id
@ -96,7 +91,7 @@ public class WebSession {
public final static String COURSE = "course"; public final static String COURSE = "course";
/** /**
* Description of the Field * Error screen number
*/ */
public final static int ERROR = 0; public final static int ERROR = 0;
@ -104,27 +99,27 @@ public class WebSession {
public static final String STAGE = "stage"; public static final String STAGE = "stage";
/** /**
* Description of the Field * session id string
*/ */
public final static String JSESSION_ID = "jsessionid"; public final static String JSESSION_ID = "jsessionid";
/** /**
* Description of the Field * Logout parameter name
*/ */
public final static String LOGOUT = "Logout"; public final static String LOGOUT = "Logout";
/** /**
* Description of the Field * Restart parameter name
*/ */
public final static String RESTART = "Restart"; public final static String RESTART = "Restart";
/** /**
* Description of the Field * menu parameter name
*/ */
public final static String MENU = "menu"; public final static String MENU = "menu";
/** /**
* Description of the Field * Screen parameter name
*/ */
public final static String SCREEN = "Screen"; public final static String SCREEN = "Screen";
@ -184,6 +179,8 @@ public class WebSession {
private int previousScreen = ERROR; private int previousScreen = ERROR;
private int previousStage = -1;
private int hintNum = -1; private int hintNum = -1;
private boolean isAdmin = false; private boolean isAdmin = false;
@ -289,7 +286,7 @@ public class WebSession {
} }
/** /**
* Description of the Method * Marks all cookies but the JSESSIONID for deletion and adds them to the response.
*/ */
public void eatCookies() { public void eatCookies() {
Cookie[] cookies = request.getCookies(); Cookie[] cookies = request.getCookies();
@ -338,11 +335,9 @@ public class WebSession {
} }
/** /**
* Sets the admin flag - this routine is ONLY here to allow someone a * Sets the admin flag - this routine is ONLY here to allow someone a backdoor to setting the user up as an admin.
* backdoor to setting the user up as an admin.
* *
* This is also used by the WebSession to set the admin, but the method * This is also used by the WebSession to set the admin, but the method should be private
* should be private
* *
* @param state a boolean. * @param state a boolean.
*/ */
@ -539,11 +534,10 @@ public class WebSession {
} }
/* /*
* List cookies = new Vector(); HttpServletRequest request = getRequest(); Cookie[] cookies * List cookies = new Vector(); HttpServletRequest request = getRequest(); Cookie[] cookies =
* = request.getCookies(); if ( cookies.length == 0 ) { list.addElement( new LI( * request.getCookies(); if ( cookies.length == 0 ) { list.addElement( new LI( "No Cookies" ) ); } for ( int i =
* "No Cookies" ) ); } for ( int i = 0; i < cookies.length; i++ ) { Cookie cookie = * 0; i < cookies.length; i++ ) { Cookie cookie = cookies[i]; cookies.add(cookie); //list.addElement( new LI(
* cookies[i]; cookies.add(cookie); //list.addElement( new LI( cookie.getName() + " -> " + * cookie.getName() + " -> " + cookie.getValue() ) ); }
* cookie.getValue() ) ); }
*/ */
return cookies; return cookies;
} }
@ -918,8 +912,8 @@ public class WebSession {
} }
/** /**
* Parse parameters from the given request, handle any servlet commands, and * Parse parameters from the given request, handle any servlet commands, and update this session based on the
* update this session based on the parameters. * parameters.
* *
* @param request Description of the Parameter * @param request Description of the Parameter
* @param response Description of the Parameter * @param response Description of the Parameter
@ -929,22 +923,13 @@ public class WebSession {
public void update(HttpServletRequest request, HttpServletResponse response, String name) throws IOException { public void update(HttpServletRequest request, HttpServletResponse response, String name) throws IOException {
String content = null; String content = null;
clearMessage();
this.request = request; this.request = request;
this.response = response; this.response = response;
this.servletName = name; this.servletName = name;
if (myParser == null) { clearMessage();
myParser = new ParameterParser(request); updateParser(request);
} else { updateLocale(request);
myParser.update(request);
}
Locale locale = request.getLocale();
if(locale != null) {
LabelManager labelManager = BeanProvider.getBean("labelManager", LabelManager.class);
labelManager.setLocale(locale);
}
// System.out.println("Current Screen 1: " + currentScreen ); // System.out.println("Current Screen 1: " + currentScreen );
// System.out.println("Previous Screen 1: " + previousScreen ); // System.out.println("Previous Screen 1: " + previousScreen );
@ -952,78 +937,72 @@ public class WebSession {
// FIXME: doesn't work right -- no reauthentication // FIXME: doesn't work right -- no reauthentication
// REMOVED - we have explicit logout now via spriing security // REMOVED - we have explicit logout now via spriing security
/* /*
if (myParser.getRawParameter(LOGOUT, null) != null) { * if (myParser.getRawParameter(LOGOUT, null) != null) { System.out.println("Logout " +
System.out.println("Logout " + request.getUserPrincipal()); * request.getUserPrincipal()); eatCookies(); request.getSession().invalidate(); currentScreen = WELCOME;
eatCookies(); * previousScreen = ERROR; }
request.getSession().invalidate();
currentScreen = WELCOME;
previousScreen = ERROR;
}
*/ */
// There are several scenarios where we want the first lesson to be loaded updateScreenProperties(request);
// 1) Previous screen is Welcome - Start of the course
// 2) After a logout and after the session has been reinitialized
if ((this.getPreviousScreen() == WebSession.WELCOME) || (getRequest().getSession(false) != null
&& // getRequest().getSession(false).isNew() &&
this.getCurrentScreen() == WebSession.WELCOME && this.getPreviousScreen() == WebSession.ERROR)) {
currentScreen = course.getFirstLesson().getScreenId();
hintNum = -1;
}
// System.out.println("Current Screen 2: " + currentScreen );
// System.out.println("Previous Screen 2: " + previousScreen );
// update the screen variables
previousScreen = currentScreen;
try {
// If the request is new there should be no parameters.
// This can occur from a session timeout or a the starting of a new course.
if (!request.getSession().isNew()) {
currentScreen = myParser.getIntParameter(SCREEN, currentScreen);
} else {
if (!myParser.getRawParameter(SCREEN, "NULL").equals("NULL")) {
this.setMessage("Session Timeout - Starting new Session.");
}
}
} catch (Exception e) {
}
// clear variables when switching screens
if (this.getCurrentScreen() != this.getPreviousScreen()) { if (this.getCurrentScreen() != this.getPreviousScreen()) {
if (webgoatContext.isDebug()) { clearScreenProperties();
setMessage("Changed to a new screen, clearing cookies and hints");
}
eatCookies();
hintNum = -1;
} else if (myParser.getRawParameter(STAGE, null) != null) { } else if (myParser.getRawParameter(STAGE, null) != null) {
AbstractLesson al = getCurrentLesson(); updateCurrentScreenStage();
if (al instanceof SequentialLessonAdapter) {
SequentialLessonAdapter sla = (SequentialLessonAdapter) al;
int stage = myParser.getIntParameter(STAGE, sla.getStage(this));
if (stage > 0 && stage <= sla.getStageCount()) {
sla.setStage(this, stage);
}
} else if (al instanceof RandomLessonAdapter) {
try {
RandomLessonAdapter rla = (RandomLessonAdapter) al;
if (!myParser.getRawParameter(STAGE).equals("null")) {
int stage = myParser.getIntParameter(STAGE) - 1;
String[] stages = rla.getStages();
if (stages == null) {
stages = new String[0];
}
if (stage >= 0 && stage < stages.length) {
rla.setStage(this, stages[stage]);
}
} else { } else {
rla.setStage(this, null); content = updateCurrentScreen(content);
} }
} catch (ParameterNotFoundException pnfe) {
updateParameters(request);
updateContent(response, content);
}
/**
* Updates parameters isAdmin, isHackedAdmin, hasHackedHackableAdmin, isColor and isDebug
*
* @param request
*/
private void updateParameters(HttpServletRequest request) {
isAdmin = request.isUserInRole(WEBGOAT_ADMIN);
isHackedAdmin = myParser.getBooleanParameter(ADMIN, isAdmin);
if (isHackedAdmin) {
System.out.println("Hacked admin");
hasHackedHackableAdmin = true;
}
isColor = myParser.getBooleanParameter(COLOR, isColor);
isDebug = myParser.getBooleanParameter(DEBUG, isDebug);
}
/**
* If the content is not already set we get the response and sends it on its way
*
* @param response
* @param content to send
* @throws IOException
*/
private void updateContent(HttpServletResponse response, String content) throws IOException {
// System.out.println( "showParams:" + showParams );
// System.out.println( "showSource:" + showSource );
// System.out.println( "showSolution:" + showSolution );
// System.out.println( "showCookies:" + showCookies );
// System.out.println( "showRequest:" + showRequest );
if (content != null) {
response.setContentType("text/html");
PrintWriter out = new PrintWriter(response.getOutputStream());
out.print(content);
out.flush();
out.close();
} }
} }
} // else update global variables for the current screen
else { /**
* Checks to see if the lesson should be restarted. Also handles parsing of "show" commands for getting hints,
* params, cookies, source and solution.
*
* @param content
* @return the updated content
*/
private String updateCurrentScreen(String content) {
// else update global variables for the current screen
// Handle "restart" commands // Handle "restart" commands
int lessonId = myParser.getIntParameter(RESTART, -1); int lessonId = myParser.getIntParameter(RESTART, -1);
if (lessonId != -1) { if (lessonId != -1) {
@ -1054,29 +1033,134 @@ public class WebSession {
getPreviousHint(); getPreviousHint();
} }
} }
return content;
} }
isAdmin = request.isUserInRole(WEBGOAT_ADMIN); /**
isHackedAdmin = myParser.getBooleanParameter(ADMIN, isAdmin); * Checks to see what kind of lesson we are viewing and parses the "stage" parameter accordingly. Sets the stage for
if (isHackedAdmin) { * the lesson using setStage on the lesson object.
System.out.println("Hacked admin"); */
hasHackedHackableAdmin = true; private void updateCurrentScreenStage() {
AbstractLesson al = getCurrentLesson();
if (al instanceof SequentialLessonAdapter) {
updateSlaStage((SequentialLessonAdapter) al);
} else if (al instanceof RandomLessonAdapter) {
updateRlaStage((RandomLessonAdapter) al);
}
} }
isColor = myParser.getBooleanParameter(COLOR, isColor);
isDebug = myParser.getBooleanParameter(DEBUG, isDebug);
// System.out.println( "showParams:" + showParams ); /**
// System.out.println( "showSource:" + showSource ); * Updates the stage for a RandomLessonAdapter
// System.out.println( "showSolution:" + showSolution ); *
// System.out.println( "showCookies:" + showCookies ); * @param al
// System.out.println( "showRequest:" + showRequest ); */
if (content != null) { private void updateRlaStage(RandomLessonAdapter rla) {
response.setContentType("text/html"); try {
PrintWriter out = new PrintWriter(response.getOutputStream()); if (!myParser.getRawParameter(STAGE).equals("null")) {
out.print(content); int currentStage = myParser.getIntParameter(STAGE) - 1;
out.flush(); if (previousStage != currentStage) {
out.close(); previousStage = currentStage;
String[] stages = rla.getStages();
if (stages == null) {
stages = new String[0];
}
if (currentStage >= 0 && currentStage < stages.length) {
rla.setStage(this, stages[currentStage]);
}
}
} else {
rla.setStage(this, null);
}
} catch (ParameterNotFoundException pnfe) {
logger.warn("ParameterNotFoundException when updating stage for RandomLessonAdapter: " + pnfe.getMessage() + " " + pnfe.getCause());
}
}
/**
* Updates the stage for a SequentialLessonAdapter
*
* @param al
*/
private void updateSlaStage(SequentialLessonAdapter sla) {
int stage = myParser.getIntParameter(STAGE, sla.getStage(this));
if (stage > 0 && stage <= sla.getStageCount()) {
sla.setStage(this, stage);
}
}
/**
* Eats all the cookies and resets hintNum and previousStage
*/
private void clearScreenProperties() {
if (webgoatContext.isDebug()) {
setMessage("Changed to a new screen, clearing cookies and hints");
}
eatCookies();
hintNum = -1;
previousStage = -1;
}
/**
* Updates the properties currentScreen, previousScreen and hintNum depending on which scenario is being handled.
*
* @param request
*/
private void updateScreenProperties(HttpServletRequest request) {
// There are several scenarios where we want the first lesson to be loaded
// 1) Previous screen is Welcome - Start of the course
// 2) After a logout and after the session has been reinitialized
if ((this.getPreviousScreen() == WebSession.WELCOME) ||
(getRequest().getSession(false) != null &&
// getRequest().getSession(false).isNew() &&
this.getCurrentScreen() == WebSession.WELCOME &&
this.getPreviousScreen() == WebSession.ERROR)) {
currentScreen = course.getFirstLesson().getScreenId();
hintNum = -1;
}
// System.out.println("Current Screen 2: " + currentScreen );
// System.out.println("Previous Screen 2: " + previousScreen );
// update the screen variables
previousScreen = currentScreen;
try {
// If the request is new there should be no parameters.
// This can occur from a session timeout or a the starting of a new course.
if (!request.getSession().isNew()) {
currentScreen = myParser.getIntParameter(SCREEN, currentScreen);
} else {
if (!myParser.getRawParameter(SCREEN, "NULL").equals("NULL")) {
this.setMessage("Session Timeout - Starting new Session.");
}
}
} catch (Exception e) {
logger.warn("Exception when updating properties in updateScreenProperties: " + e.getMessage() + " " + e.getCause());
}
}
/**
* Updates the labelmanager local based on the labelManager bean
*
* @param request
*/
private void updateLocale(HttpServletRequest request) {
Locale locale = request.getLocale();
if (locale != null) {
LabelManager labelManager = BeanProvider.getBean("labelManager", LabelManager.class);
labelManager.setLocale(locale);
}
}
/**
* Creates a new parser if not created yet. Sets the request on the parser for later use.
*
* @param request
*/
private void updateParser(HttpServletRequest request) {
if (myParser == null) {
myParser = new ParameterParser(request);
} else {
myParser.update(request);
} }
} }

View File

@ -16,7 +16,6 @@ lesson.SilentTransactions.hidden=true
lesson.WeakAuthenticationCookie.hidden=true lesson.WeakAuthenticationCookie.hidden=true
lesson.TraceXSS.hidden=true lesson.TraceXSS.hidden=true
lesson.DBSQLInjection.hidden=true lesson.DBSQLInjection.hidden=true
lesson.CrossSiteScripting.hidden=true
lesson.DBCrossSiteScripting.hidden=true lesson.DBCrossSiteScripting.hidden=true
lesson.XPATHInjection.hidden=true lesson.XPATHInjection.hidden=true
lesson.ForcedBrowsing.hidden=true lesson.ForcedBrowsing.hidden=true