WebGoat/ webgoat/main/project/org/owasp/webgoat/lessons/PathBasedAccessControl.java

263 lines
8.0 KiB
Java

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;
/**
* Copyright (c) 2002 Free Software Foundation developed under the custody of the Open Web
* Application Security Project (http://www.owasp.org) This software package org.owasp.webgoat.is published by OWASP
* under the GPL. You should read and accept the LICENSE before you use, modify and/or redistribute
* this software.
*
* @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
* @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 = " <p><B>Current Directory is:</B> " + Encoding.urlDecode( dir ) + "<br><br> Choose the file to view:</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( "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 = s.isDefuseOSCommands();
if ( s.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"),"<br>")
.replaceAll("(?s)<!DOCTYPE.*/head>","")
.replaceAll("<br><br>","<br>")
.replaceAll("<br>\\s<br>","<br>")
.replaceAll("<\\?", "&lt;")
.replaceAll("<(r|u|t)", "&lt;$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 AbstractLesson.A2;
}
/**
* Gets the hints attribute of the AccessControlScreen object
*
* @return The hints value
*/
protected List getHints()
{
List<String> hints = new ArrayList<String>();
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(120);
protected Integer getDefaultRanking()
{
return DEFAULT_RANKING;
}
/**
* Gets the title attribute of the AccessControlScreen object
*
* @return The title value
*/
public String getTitle()
{
return ( "How to Bypass a Path Based Access Control Scheme" );
}
}