From a90817f3325e7e1f3237c159c0698c23ba77c4d1 Mon Sep 17 00:00:00 2001 From: lawson89 Date: Fri, 20 Jun 2014 14:41:15 -0400 Subject: [PATCH] check in hint service which provides a list of hints for the current lesson --- .../owasp/webgoat/lessons/AbstractLesson.java | 1638 ++++++++--------- .../owasp/webgoat/service/HintService.java | 47 +- java/org/owasp/webgoat/session/Course.java | 15 +- .../org/owasp/webgoat/session/WebSession.java | 10 +- 4 files changed, 834 insertions(+), 876 deletions(-) diff --git a/java/org/owasp/webgoat/lessons/AbstractLesson.java b/java/org/owasp/webgoat/lessons/AbstractLesson.java index 804c1d0df..b6ae5d945 100644 --- a/java/org/owasp/webgoat/lessons/AbstractLesson.java +++ b/java/org/owasp/webgoat/lessons/AbstractLesson.java @@ -1,861 +1,777 @@ - -package org.owasp.webgoat.lessons; - -import java.io.BufferedReader; -import java.io.FileReader; -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.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -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; -import org.owasp.webgoat.util.WebGoatI18N; - - - -/*************************************************************************************************** - * - * - * 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 Map lessonPlanFileName = new HashMap(); - - private String lessonSolutionFileName; - - private WebgoatContext webgoatContext; - - private LinkedList availableLanguages = new LinkedList(); - - private String defaultLanguage = "English"; - - /** - * 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 "Hint: " + 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) - { - StringBuffer src = new StringBuffer(); - String lang = s.getCurrrentLanguage(); - - try - { - // System.out.println("Loading lesson plan file: " + - // getLessonPlanFileName()); - String filename = getLessonPlanFileName(lang); - if(filename==null){ - filename = getLessonPlanFileName(getDefaultLanguage()); - - } - - src.append(readFromFile(new BufferedReader(new FileReader(s.getWebResource(filename))), false)); - - } catch (Exception e) - { - // s.setMessage( "Could not find lesson plan for " + - // getLessonName()); - src = new StringBuffer("Could not find lesson plan for: " + getLessonName()+" and language "+lang); - - } - return src.toString(); - } - - /** - * 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 (Exception e) - { - s.setMessage("Could not find source file"); - src = ("Could not find the source file or source file does not exist.
" - + "Send this message to: " + s.getWebgoatContext().getFeedbackAddress() + ""); - } - - 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 - { - // System.out.println("Solution: " + getLessonSolutionFileName()); - src = readFromFile(new BufferedReader(new FileReader(s.getWebResource(getLessonSolutionFileName()))), false); - } catch (Exception e) - { - s.setMessage("Could not find the solution file"); - src = ("Could not find the solution file or solution file does not exist.
" - + "Send this message to: " + s.getWebgoatContext().getFeedbackAddress() + ""); - } - - // Solutions are html files - return src; - } - - - /** - *

Returns the default "path" portion of a lesson's URL.

- * - *

Legacy webgoat lesson links are of the form "attack?Screen=Xmenu=Ystage=Z". - * This method returns the path portion of the url, i.e., "attack" in the string above.

- * - *

Newer, Spring-Controller-based classes will override this method - * to return "*.do"-styled paths.

- */ - protected String getPath() { - return "attack"; - } - - /** - * Get the link that can be used to request this screen. - * - * @return - */ - public String getLink() - { - StringBuffer link = new StringBuffer(); - - // mvc update: - link.append(getPath()).append("?"); - 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 getDefaultLanguage(){ - return this.defaultLanguage; - } - - public String getLessonPlanFileName(String lang) - { - String ret = lessonPlanFileName.get(lang); - if(ret==null) ret = lessonPlanFileName.get(getDefaultLanguage()); - return ret; - } - - public void setLessonPlanFileName(String lang, String lessonPlanFileName) - { - this.lessonPlanFileName.put(lang,lessonPlanFileName); - this.availableLanguages.add(lang); - } - - public List getAvailableLanguages(){ - return this.availableLanguages; - } - - 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; - } -} +package org.owasp.webgoat.lessons; + +import java.io.BufferedReader; +import java.io.FileReader; +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.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +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 Map lessonPlanFileName = new HashMap(); + + private String lessonSolutionFileName; + + private WebgoatContext webgoatContext; + + private LinkedList availableLanguages = new LinkedList(); + + private String defaultLanguage = "English"; + + /** + * 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); + + // @TODO we need to restrict access at the service layer + // rather than passing session object around + public List getHintsPublic(WebSession s){ + List hints = getHints(s); + return hints; + } + + /** + * 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 "Hint: " + 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) { + StringBuffer src = new StringBuffer(); + String lang = s.getCurrrentLanguage(); + + try { + // System.out.println("Loading lesson plan file: " + + // getLessonPlanFileName()); + String filename = getLessonPlanFileName(lang); + if (filename == null) { + filename = getLessonPlanFileName(getDefaultLanguage()); + + } + + src.append(readFromFile(new BufferedReader(new FileReader(s.getWebResource(filename))), false)); + + } catch (Exception e) { + // s.setMessage( "Could not find lesson plan for " + + // getLessonName()); + src = new StringBuffer("Could not find lesson plan for: " + getLessonName() + " and language " + lang); + + } + return src.toString(); + } + + /** + * 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 (Exception e) { + s.setMessage("Could not find source file"); + src = ("Could not find the source file or source file does not exist.
" + + "Send this message to: " + s.getWebgoatContext().getFeedbackAddress() + ""); + } + + 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 { + // System.out.println("Solution: " + getLessonSolutionFileName()); + src = readFromFile(new BufferedReader(new FileReader(s.getWebResource(getLessonSolutionFileName()))), false); + } catch (Exception e) { + s.setMessage("Could not find the solution file"); + src = ("Could not find the solution file or solution file does not exist.
" + + "Send this message to: " + s.getWebgoatContext().getFeedbackAddress() + ""); + } + + // Solutions are html files + return src; + } + + /** + *

+ * Returns the default "path" portion of a lesson's URL.

+ * + *

+ * Legacy webgoat lesson links are of the form + * "attack?Screen=Xmenu=Ystage=Z". This method returns the path portion of + * the url, i.e., "attack" in the string above.

+ * + *

+ * Newer, Spring-Controller-based classes will override this method to + * return "*.do"-styled paths.

+ */ + protected String getPath() { + return "attack"; + } + + /** + * Get the link that can be used to request this screen. + * + * @return + */ + public String getLink() { + StringBuffer link = new StringBuffer(); + + // mvc update: + link.append(getPath()).append("?"); + 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 getDefaultLanguage() { + return this.defaultLanguage; + } + + public String getLessonPlanFileName(String lang) { + String ret = lessonPlanFileName.get(lang); + if (ret == null) { + ret = lessonPlanFileName.get(getDefaultLanguage()); + } + return ret; + } + + public void setLessonPlanFileName(String lang, String lessonPlanFileName) { + this.lessonPlanFileName.put(lang, lessonPlanFileName); + this.availableLanguages.add(lang); + } + + public List getAvailableLanguages() { + return this.availableLanguages; + } + + 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/java/org/owasp/webgoat/service/HintService.java b/java/org/owasp/webgoat/service/HintService.java index bf375c0f2..81544657b 100644 --- a/java/org/owasp/webgoat/service/HintService.java +++ b/java/org/owasp/webgoat/service/HintService.java @@ -5,7 +5,13 @@ */ package org.owasp.webgoat.service; +import java.util.ArrayList; +import java.util.List; +import javax.servlet.http.HttpSession; +import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.model.Hint; +import org.owasp.webgoat.session.Course; +import org.owasp.webgoat.session.WebSession; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @@ -16,14 +22,41 @@ import org.springframework.web.bind.annotation.ResponseBody; */ @Controller public class HintService extends BaseService { - + + /** + * Returns hints for current lesson + * + * @param session + * @return + */ @RequestMapping(value = "/hint.do", produces = "application/json") public @ResponseBody - Hint showHint() { - Hint h = new Hint(); - h.setHint("This is a test hint"); - h.setLesson("Some lesson"); - h.setNumber(1); - return h; + List showHint(HttpSession session) { + List listHints = new ArrayList(); + WebSession ws; + Object o = session.getAttribute(WebSession.SESSION); + if (o == null || !(o instanceof WebSession)) { + return null; + } + ws = (WebSession) o; + AbstractLesson l = ws.getCurrentLesson(); + if (l == null) { + return listHints; + } + List hints; + hints = l.getHintsPublic(ws); + if (hints == null) { + return listHints; + } + int idx = 0; + for (String h : hints) { + Hint hint = new Hint(); + hint.setHint(h); + hint.setLesson(l.getName()); + hint.setNumber(idx); + listHints.add(hint); + idx++; + } + return listHints; } } diff --git a/java/org/owasp/webgoat/session/Course.java b/java/org/owasp/webgoat/session/Course.java index 6430b409c..c39883976 100644 --- a/java/org/owasp/webgoat/session/Course.java +++ b/java/org/owasp/webgoat/session/Course.java @@ -170,7 +170,7 @@ public class Course { public AbstractLesson getFirstLesson() { List roles = new ArrayList(); roles.add(AbstractLesson.USER_ROLE); - // Category 0 is the admin function. We want the first real category + // Category 0 is the admin function. We want the first real category // to be returned. This is noramally the General category and the Http Basics lesson return ((AbstractLesson) getLessons((Category) getCategories().get(0), roles).get(0)); } @@ -269,6 +269,15 @@ public class Course { return getLessons(category, roles); } + public AbstractLesson getLesson(int lessonId) { + for (AbstractLesson l : lessons) { + if (l.getScreenId() == lessonId) { + return l; + } + } + return null; + } + /** * Load all of the filenames into a temporary cache * @@ -357,7 +366,7 @@ public class Course { if (absoluteFile.startsWith("/lesson_plans") && absoluteFile.endsWith(".html") && className.endsWith(fileName)) { - // System.out.println("DEBUG: setting lesson plan file " + absoluteFile + " for + // System.out.println("DEBUG: setting lesson plan file " + absoluteFile + " for // lesson " + // lesson.getClass().getName()); // System.out.println("fileName: " + fileName + " == className: " + className ); @@ -367,7 +376,7 @@ public class Course { } if (absoluteFile.startsWith("/lesson_solutions") && absoluteFile.endsWith(".html") && className.endsWith(fileName)) { - // System.out.println("DEBUG: setting lesson solution file " + absoluteFile + " + // System.out.println("DEBUG: setting lesson solution file " + absoluteFile + " // for lesson " + // lesson.getClass().getName()); // System.out.println("fileName: " + fileName + " == className: " + className ); diff --git a/java/org/owasp/webgoat/session/WebSession.java b/java/org/owasp/webgoat/session/WebSession.java index a32a76aa8..dcd1dc3e7 100644 --- a/java/org/owasp/webgoat/session/WebSession.java +++ b/java/org/owasp/webgoat/session/WebSession.java @@ -767,7 +767,7 @@ public class WebSession { WebGoatI18N.setCurrentLanguage(this.currentLanguage); } - // System.out.println("Current Screen 1: " + currentScreen ); + // System.out.println("Current Screen 1: " + currentScreen ); // System.out.println("Previous Screen 1: " + previousScreen ); // FIXME: requires ?Logout=true // FIXME: doesn't work right -- no reauthentication @@ -779,7 +779,7 @@ public class WebSession { previousScreen = ERROR; } - // There are several scenarios where we want the first lesson to be loaded + // 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 @@ -789,13 +789,13 @@ public class WebSession { hintNum = -1; } - // System.out.println("Current Screen 2: " + currentScreen ); + // 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. + // 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); @@ -880,7 +880,7 @@ public class WebSession { isColor = myParser.getBooleanParameter(COLOR, isColor); isDebug = myParser.getBooleanParameter(DEBUG, isDebug); - // System.out.println( "showParams:" + showParams ); + // System.out.println( "showParams:" + showParams ); // System.out.println( "showSource:" + showSource ); // System.out.println( "showSolution:" + showSolution ); // System.out.println( "showCookies:" + showCookies );