diff --git a/ webgoat/main/project/JavaSource/org/owasp/webgoat/lessons/HttpSplitting.java b/ webgoat/main/project/JavaSource/org/owasp/webgoat/lessons/HttpSplitting.java index a064f77b8..15bfce6eb 100644 --- a/ webgoat/main/project/JavaSource/org/owasp/webgoat/lessons/HttpSplitting.java +++ b/ webgoat/main/project/JavaSource/org/owasp/webgoat/lessons/HttpSplitting.java @@ -1,6 +1,8 @@ package org.owasp.webgoat.lessons; import java.io.PrintWriter; import java.net.URLDecoder; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.*; import org.apache.ecs.*; @@ -22,6 +24,8 @@ import org.owasp.webgoat.session.WebSession; public class HttpSplitting extends LessonAdapter { private final static String LANGUAGE = "language"; + private final static String REDIRECT = "fromRedirect"; + private static String STAGE = "stage"; /** * Description of the Method @@ -41,35 +45,19 @@ public class HttpSplitting extends LessonAdapter { setContent(form); } - protected Element createContent(WebSession s) + protected Element doHTTPSplitting(WebSession s) { ElementContainer ec = new ElementContainer(); String lang = null; try { - //add the text - ec.addElement( new StringElement( "Search by country : " ) ); - - 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(); - } + ec.addElement(createAttackEnvironment(s)); + lang = URLDecoder.decode(s.getParser().getRawParameter( LANGUAGE, "" ), "UTF-8") ; //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 ) { //Split by the line separator line.separator is platform independant @@ -81,26 +69,117 @@ public class HttpSplitting extends LessonAdapter { if (Arrays.binarySearch(arrTokens, "CONTENT-LENGTH: 0") >= 0 && Arrays.binarySearch(arrTokens, "HTTP/1.1 200 OK") >= 0 ) { - try - { - PrintWriter out = new PrintWriter(s.getResponse().getOutputStream()); - out.print(lang.substring(lang.indexOf("HTTP/1.1"))); - out.flush(); - out.close(); - - //we gotta set it manually here so that we don't throw an exception - getLessonTracker(s).setCompleted(true); - } - catch(Exception e) - { - e.printStackTrace(); - } - makeSuccess( s ); + PrintWriter out = new PrintWriter(s.getResponse().getOutputStream()); + out.print(lang.substring(lang.indexOf("HTTP/1.1"))); + out.flush(); + out.close(); + + //we gotta set it manually here so that we don't throw an exception + 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) + { + s.setMessage( "Error generating " + this.getClass().getName() ); + e.printStackTrace(); + } 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.

"); + 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() { return AbstractLesson.GENERAL; @@ -113,7 +192,7 @@ public class HttpSplitting extends LessonAdapter { 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( "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%0ahahahahaha" ); return hints; } diff --git a/ webgoat/main/project/WebContent/lesson_plans/HttpSplitting.html b/ webgoat/main/project/WebContent/lesson_plans/HttpSplitting.html index 46caba040..fd29eac68 100644 --- a/ webgoat/main/project/WebContent/lesson_plans/HttpSplitting.html +++ b/ webgoat/main/project/WebContent/lesson_plans/HttpSplitting.html @@ -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) 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, -but also allows them to create additional responses entirely under their control +but also allows them to create additional responses entirely under their control.
+The effect of an HTTP Splitting attack is maximized when accompanied with a Cache Poisining. The goal of
+Cache Poisining attack is to poison the cache of the victim by fooling the cache to believe that the page
+hijacked using the HTTP splitting is a good one and it is indeed the server's copy.
+The attack happens using the HTTP Splitting attack plus adding the Last-Modified: header and setting it
+to a future date. This will force the browser to send If-Modified-Since request header, which gives the attacker
+the chance to intercept the server's reply and replace it with a '304 Not Modified' reply. A sample of a 304 response is:
+HTTP/1.1 304 Not Modified +Date: Fri, 30 Dec 2005 17:32:47 GMT + + +

General Goal(s):

@@ -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.
* Your excercise should be to force the server to send a 200 OK.
* 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. +