/** * 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 { Table t = new Table().setCellSpacing(0).setCellPadding(2).setWidth("90%").setAlign("center"); if (s.isColor()) { t.setBorder(1); } List<File> htmlFiles = findHtmlFiles(LessonUtil.getLessonDirectory(s, this).getParentFile()); List<String> htmlFilenames = Lists.newArrayList( Iterables.transform( htmlFiles, new Function<File, String>() { @Override public String apply(File input) { return input.getName(); } })); String[] list = htmlFilenames.toArray(new String[htmlFilenames.size()]); String listing = " <p><B>" + getLabelManager().get("CurrentDirectory") + "</B> " + Encoding.urlDecode(htmlFiles.get(0).getParent()) + "<br><br>" + getLabelManager().get("ChooseFileToView") + "</p>"; 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(getLabelManager().get("ViewFile")))); t.addElement(tr); ec.addElement(t); // FIXME: would be cool to allow encodings here -- hex, percent, // url, etc... final String file = s.getParser().getRawParameter(FILE, ""); if (!file.equals("")) // first time in or missing parameter - just kick out { // defuse file searching boolean illegalCommand = true; // 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(getLabelManager().get("AccessDenied")); s.setMessage(getLabelManager().get("ItAppears1")); } else { if (upDirCount(file) > 5) { s.setMessage(getLabelManager().get("AccessDenied")); s.setMessage(getLabelManager().get("ItAppears2")); } else { illegalCommand = false; } } // provide a little guidance to help them along. If the allowed file comes back as // null we have the potential for a real attack vector File allowedFile = guideTheAtack(s, file, htmlFiles); if (!illegalCommand) { File attemptedFile = new File(LessonUtil.getLessonDirectory(s, this) + "/lessonPlans/en/" + file); if (allowedFile == null) { // We have a potential attack if (file != null && attemptedFile.isFile() && attemptedFile.exists()) { // They have accessed something meaningful s.setMessage( getLabelManager().get("CongratsAccessToFileAllowed") + " ==> " + Encoding.urlDecode(attemptedFile.getCanonicalPath())); makeSuccess(s); } else if (file != null && file.length() != 0) { s.setMessage( getLabelManager().get("AccessToFileDenied1") + Encoding.urlDecode(file) + getLabelManager().get("AccessToFileDenied2")); } else { // do nothing, probably entry screen } } else { attemptedFile = allowedFile; } displayAttemptedFile(ec, attemptedFile); } } } catch (Exception e) { s.setMessage(getLabelManager().get("ErrorGenerating") + this.getClass().getName()); e.printStackTrace(); } return (ec); }
private File guideTheAtack(WebSession s, String fileName, List<File> htmlFiles) throws Exception { // Most people are going to start off with a simple test of // ./lesson.html or ../en/lesson.html where lesson is equal // to the name of the selection from the UI. // Example real path: plugin_extracted/plugin/CSRF/lessonPlans/en/CSRF.html // the URL input by default for CSRF is &File=CSRF.html // We need to see if this was a simple attempt and serve the file as an allowed // file. I don;t like this path hack, but it puts them in the right spot // on the file system... int lastSlash = fileName.lastIndexOf(System.getProperty("file.separator")); if (lastSlash == -1) lastSlash = 0; String lessonDir = fileName.substring(lastSlash); if (lessonDir.length() >= ".html".length()) // at least something semi valid is there { lessonDir = lessonDir.substring(0, lessonDir.length() - ".html".length()); } String attemptedFileName = LessonUtil.getLessonDirectory(s, this).getParent() + "/" + lessonDir + "/lessonPlans/en/" + fileName; File attemptedFile = new File(attemptedFileName); // Check access to an allowed file. if allowedFile != null, access is allowed // FIXME: This will incorrectly match ../lesson.html when it should be ../en/lesson.html File allowedFile = null; for (File htmlFile : htmlFiles) { if (htmlFile.getName().equals(fileName) || htmlFile.getName().equals(attemptedFile.getName())) { allowedFile = htmlFile; } } if (allowedFile != null && allowedFile.isFile() && allowedFile.exists()) { // Don't set completion if they are listing files in the // directory listing we gave them. if (upDirCount(fileName) >= 1) { s.setMessage( getLabelManager().get("OnTheRightPath") + " ==> " + Encoding.urlDecode(allowedFile.getCanonicalPath())); } else { s.setMessage( getLabelManager().get("FileInAllowedDirectory") + " ==> " + Encoding.urlDecode(allowedFile.getCanonicalPath())); } } if (s.isDebug()) { // f is only null if the "File" input was NOT a known lesson file s.setMessage(getLabelManager().get("File") + fileName); if (allowedFile != null) { s.setMessage(getLabelManager().get("Dir") + allowedFile.getParentFile()); s.setMessage(getLabelManager().get("IsFile") + allowedFile.isFile()); s.setMessage(getLabelManager().get("Exists") + allowedFile.exists()); } } return allowedFile; }