Added Cache Poisining lesson as a staged lesson to HTTP Splitting lesson.
git-svn-id: http://webgoat.googlecode.com/svn/trunk@40 4033779f-a91e-0410-96ef-6bf7bf53c507
This commit is contained in:
parent
9f76aeb38f
commit
7acbacbe61
@ -1,6 +1,8 @@
|
|||||||
package org.owasp.webgoat.lessons;
|
package org.owasp.webgoat.lessons;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.apache.ecs.*;
|
import org.apache.ecs.*;
|
||||||
@ -22,6 +24,8 @@ import org.owasp.webgoat.session.WebSession;
|
|||||||
public class HttpSplitting extends LessonAdapter {
|
public class HttpSplitting extends LessonAdapter {
|
||||||
|
|
||||||
private final static String LANGUAGE = "language";
|
private final static String LANGUAGE = "language";
|
||||||
|
private final static String REDIRECT = "fromRedirect";
|
||||||
|
private static String STAGE = "stage";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description of the Method
|
* Description of the Method
|
||||||
@ -41,35 +45,19 @@ public class HttpSplitting extends LessonAdapter {
|
|||||||
setContent(form);
|
setContent(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Element createContent(WebSession s)
|
protected Element doHTTPSplitting(WebSession s)
|
||||||
{
|
{
|
||||||
ElementContainer ec = new ElementContainer();
|
ElementContainer ec = new ElementContainer();
|
||||||
String lang = null;
|
String lang = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//add the text
|
ec.addElement(createAttackEnvironment(s));
|
||||||
ec.addElement( new StringElement( "Search by country : " ) );
|
lang = URLDecoder.decode(s.getParser().getRawParameter( LANGUAGE, "" ), "UTF-8") ;
|
||||||
|
|
||||||
lang = URLDecoder.decode(s.getParser().getRawParameter( LANGUAGE, "" )) ;
|
|
||||||
|
|
||||||
//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 );
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
s.setMessage( "Error generating " + this.getClass().getName() );
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check if we are coming from the redirect page
|
//Check if we are coming from the redirect page
|
||||||
String fromRedirect = s.getParser().getStringParameter ( "fromRedirect" , "");
|
String fromRedirect = s.getParser().getStringParameter ( "fromRedirect" , "");
|
||||||
|
|
||||||
if ( lang.length() != 0 && fromRedirect.length() != 0 )
|
if ( lang.length() != 0 && fromRedirect.length() != 0 )
|
||||||
{
|
{
|
||||||
//Split by the line separator line.separator is platform independant
|
//Split by the line separator line.separator is platform independant
|
||||||
@ -80,8 +68,6 @@ public class HttpSplitting extends LessonAdapter {
|
|||||||
|
|
||||||
if (Arrays.binarySearch(arrTokens, "CONTENT-LENGTH: 0") >= 0 &&
|
if (Arrays.binarySearch(arrTokens, "CONTENT-LENGTH: 0") >= 0 &&
|
||||||
Arrays.binarySearch(arrTokens, "HTTP/1.1 200 OK") >= 0 )
|
Arrays.binarySearch(arrTokens, "HTTP/1.1 200 OK") >= 0 )
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
PrintWriter out = new PrintWriter(s.getResponse().getOutputStream());
|
PrintWriter out = new PrintWriter(s.getResponse().getOutputStream());
|
||||||
out.print(lang.substring(lang.indexOf("HTTP/1.1")));
|
out.print(lang.substring(lang.indexOf("HTTP/1.1")));
|
||||||
@ -90,16 +76,109 @@ public class HttpSplitting extends LessonAdapter {
|
|||||||
|
|
||||||
//we gotta set it manually here so that we don't throw an exception
|
//we gotta set it manually here so that we don't throw an exception
|
||||||
getLessonTracker(s).setCompleted(true);
|
getLessonTracker(s).setCompleted(true);
|
||||||
|
|
||||||
|
//makeSuccess( s );
|
||||||
|
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)
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
s.setMessage( "Error generating " + this.getClass().getName() );
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
makeSuccess( s );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ( ec );
|
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;
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
ec.addElement("Now that you have successfully performed an HTTP Splitting, now try to poison" +
|
||||||
|
" the victim's cache using. Type 'restart' in the input field if you wish to " +
|
||||||
|
" to return to the HTTP Splitting lesson.<br><br>");
|
||||||
|
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);
|
||||||
|
getLessonTracker(s).setStage(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ec.addElement( new P().addElement( ex.getMessage() ) );
|
||||||
|
}
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
|
||||||
protected Category getDefaultCategory()
|
protected Category getDefaultCategory()
|
||||||
{
|
{
|
||||||
@ -113,7 +192,7 @@ public class HttpSplitting extends LessonAdapter {
|
|||||||
hints.add( "Use CR (%0d) and LF (%0a) for a new line" );
|
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( "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( "A 200 OK message looks like this: HTTP/1.1 200 OK" );
|
||||||
hints.add( "Try French%0d%0aContent-Length: 0%0d%0aHTTP/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:%2019%0d%0a%0d%0a<html>hahahahaha</html>" );
|
||||||
return hints;
|
return hints;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,18 @@ The attacker passes malacious 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)
|
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
|
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,
|
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
|
but also allows them to create additional responses entirely under their control.<br>
|
||||||
|
The effect of an HTTP Splitting attack is maximized when accompanied with a Cache Poisining. The goal of<br>
|
||||||
|
Cache Poisining attack is to poison the cache of the victim by fooling the cache to believe that the page<br>
|
||||||
|
hijacked using the HTTP splitting is a good one and it is indeed the server's copy.<br>
|
||||||
|
The attack happens using the HTTP Splitting attack plus adding the <b>Last-Modified:</b> header and setting it<br>
|
||||||
|
to a future date. This will force the browser to send <b>If-Modified-Since</b> request header, which gives the attacker<br>
|
||||||
|
the chance to intercept the server's reply and replace it with a '304 Not Modified' reply. A sample of a 304 response is:<br>
|
||||||
|
HTTP/1.1 304 Not Modified
|
||||||
|
Date: Fri, 30 Dec 2005 17:32:47 GMT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p><b>General Goal(s):</b> </p>
|
<p><b>General Goal(s):</b> </p>
|
||||||
<!-- Start Instructions -->
|
<!-- Start Instructions -->
|
||||||
@ -22,4 +33,5 @@ but also allows them to create additional responses entirely under their control
|
|||||||
* You should be able to use the CR (%0d) and LF (%0a) to exploit the attack.<br>
|
* You should be able to use the CR (%0d) and LF (%0a) to exploit the attack.<br>
|
||||||
* Your excercise should be to force the server to send a 200 OK. <br>
|
* Your excercise should be to force the server to send a 200 OK. <br>
|
||||||
* If the screen changed as an effect to your attack, just go back to the homepage where you will find the lesson completed if you successfully exploited the attack.
|
* If the screen changed as an effect to your attack, just go back to the homepage where you will find the lesson completed if you successfully exploited the attack.
|
||||||
|
|
||||||
<!-- Stop Instructions -->
|
<!-- Stop Instructions -->
|
||||||
|
Loading…
x
Reference in New Issue
Block a user