- Added testcases for bypassing frontend validation.

- Improved layout of the lesson
- Fixed JavaScript issues with 'let'
This commit is contained in:
Nanne Baars 2017-06-16 01:16:31 +02:00
parent bf210de013
commit edceba73fe
5 changed files with 105 additions and 48 deletions

View File

@ -8,27 +8,4 @@
<artifactId>webgoat-lessons-parent</artifactId> <artifactId>webgoat-lessons-parent</artifactId>
<version>8.0-SNAPSHOT</version> <version>8.0-SNAPSHOT</version>
</parent> </parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>4.1.3.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<type>jar</type>
<scope>test</scope>
</dependency>
</dependencies>
</project> </project>

View File

@ -52,63 +52,63 @@
enctype="application/json;charset=UTF-8" enctype="application/json;charset=UTF-8"
onsubmit="return validate()"> onsubmit="return validate()">
<div> <div>
Field1: exactly three lowercase characters(^[a-z]{3}$) <strong>Field 1:</strong> exactly three lowercase characters(^[a-z]{3}$)
</div> </div>
<div> <div>
<textarea cols="25" name="field1" rows="1">abc</textarea> <textarea cols="25" name="field1" rows="1">abc</textarea>
</div> </div>
<p></p> <p></p>
<div>Field2: exactly three digits(^[0-9]{3}$)</div> <div><strong>Field 2:</strong> exactly three digits(^[0-9]{3}$)</div>
<div> <div>
<textarea cols="25" name="field2" rows="1">123</textarea> <textarea cols="25" name="field2" rows="1">123</textarea>
</div> </div>
<p></p> <p></p>
<div>Field3: letters, numbers, and space only(^[a-zA-Z0-9 ]*$)</div> <div><strong>Field 3:</strong> letters, numbers, and space only(^[a-zA-Z0-9 ]*$)</div>
<div> <div>
<textarea cols="25" name="field3" rows="1">abc 123 ABC</textarea> <textarea cols="25" name="field3" rows="1">abc 123 ABC</textarea>
</div> </div>
<p></p> <p></p>
<div>Field4: enumeration of numbers (^(one|two|three|four|five|six|seven|eight|nine)$)</div> <div><strong>Field 4:</strong> enumeration of numbers (^(one|two|three|four|five|six|seven|eight|nine)$)</div>
<div> <div>
<textarea cols="25" name="field4" rows="1">seven</textarea> <textarea cols="25" name="field4" rows="1">seven</textarea>
</div> </div>
<p></p> <p></p>
<div>Field5: simple zip code (^\d{5}$)</div> <div><strong>Field 5:</strong> simple zip code (^\d{5}$)</div>
<div> <div>
<textarea cols="25" name="field5" rows="1">01101</textarea> <textarea cols="25" name="field5" rows="1">01101</textarea>
</div> </div>
<p></p> <p></p>
<div>Field6: zip with optional dash four (^\d{5}(-\d{4})?$)</div> <div><strong>Field 6:</strong> zip with optional dash four (^\d{5}(-\d{4})?$)</div>
<div> <div>
<textarea cols="25" name="field6" rows="1">90210-1111</textarea> <textarea cols="25" name="field6" rows="1">90210-1111</textarea>
</div> </div>
<p></p> <p></p>
<div>Field7: US phone number with or without dashes (^[2-9]\d{2}-?\d{3}-?\d{4}$)</div> <div><strong>Field 7:</strong> US phone number with or without dashes (^[2-9]\d{2}-?\d{3}-?\d{4}$)</div>
<div> <div>
<textarea cols="25" name="field7" rows="1">301-604-4882</textarea> <textarea cols="25" name="field7" rows="1">301-604-4882</textarea>
</div> </div>
<input type="hidden" value="" name="error" /> <input type="hidden" value="" name="error" />
<p><input type="submit" value="Submit" /></p> <p><button type="submit" class="btn btn-primary">Submit</button></p>
</form> </form>
<script> <script>
let regex1=/^[a-z]{3}$/; var regex1=/^[a-z]{3}$/;
let regex2=/^[0-9]{3}$/; var regex2=/^[0-9]{3}$/;
let regex3=/^[a-zA-Z0-9 ]*$/; var regex3=/^[a-zA-Z0-9 ]*$/;
let regex4=/^(one|two|three|four|five|six|seven|eight|nine)$/; var regex4=/^(one|two|three|four|five|six|seven|eight|nine)$/;
let regex5=/^\d{5}$/; var regex5=/^\d{5}$/;
let regex6=/^\d{5}(-\d{4})?$/; var regex6=/^\d{5}(-\d{4})?$/;
let regex7=/^[2-9]\d{2}-?\d{3}-?\d{4}$/; var regex7=/^[2-9]\d{2}-?\d{3}-?\d{4}$/;
var validate = function() { var validate = function() {
let msg='JavaScript found form errors'; var msg='JavaScript found form errors';
let err=0; var err=0;
if (!regex1.test(document.frontendValidation.field1.value)) {err+=1; msg+='\n bad field1';} if (!regex1.test(document.frontendValidation.field1.value)) {err+=1; msg+='\n Value entered for field 1 is not correct';}
if (!regex2.test(document.frontendValidation.field2.value)) {err+=1; msg+='\n bad field2';} if (!regex2.test(document.frontendValidation.field2.value)) {err+=1; msg+='\n Value entered for field 2 is not correct';}
if (!regex3.test(document.frontendValidation.field3.value)) {err+=1; msg+='\n bad field3';} if (!regex3.test(document.frontendValidation.field3.value)) {err+=1; msg+='\n Value entered for field 3 is not correct';}
if (!regex4.test(document.frontendValidation.field4.value)) {err+=1; msg+='\n bad field4';} if (!regex4.test(document.frontendValidation.field4.value)) {err+=1; msg+='\n Value entered for field 4 is not correct';}
if (!regex5.test(document.frontendValidation.field5.value)) {err+=1; msg+='\n bad field5';} if (!regex5.test(document.frontendValidation.field5.value)) {err+=1; msg+='\n Value entered for field 5 is not correct';}
if (!regex6.test(document.frontendValidation.field6.value)) {err+=1; msg+='\n bad field6';} if (!regex6.test(document.frontendValidation.field6.value)) {err+=1; msg+='\n Value entered for field 6 is not correct';}
if (!regex7.test(document.frontendValidation.field7.value)) {err+=1; msg+='\n bad field7';} if (!regex7.test(document.frontendValidation.field7.value)) {err+=1; msg+='\n Value entered for field 7 is not correct';}
document.frontendValidation.error.value = err document.frontendValidation.error.value = err
if ( err > 0 ) { if ( err > 0 ) {
alert(msg) alert(msg)
@ -117,6 +117,8 @@
return true; return true;
} }
</script> </script>
<br/>
<br/>
<div class="attack-feedback"></div> <div class="attack-feedback"></div>
<div class="attack-output"></div> <div class="attack-output"></div>
</div> </div>

View File

@ -1,4 +1,5 @@
== Validation == Validation
Often, there is some mechanism in place to prevent users from sending altered Often, there is some mechanism in place to prevent users from sending altered
field values to server, such as validation before sending. Most of popular browsers field values to server, such as validation before sending. Most of popular browsers
such as Chrome don't allow editing scripts during runtime. We will have to circumvent such as Chrome don't allow editing scripts during runtime. We will have to circumvent

View File

@ -1,10 +1,11 @@
== Concept == Concept
Users have a great degree of control over the front-end of the web application. Users have a great degree of control over the front-end of the web application.
They can alter HTML code, sometimes also scripts. This is why They can alter HTML code, sometimes also scripts. This is why
apps that require certain format of input should also validate on server-side. apps that require certain format of input should also validate on server-side.
== Goals == Goals
* The user should have a basic knowledge of HTML * The user should have a basic knowledge of HTML
* The user should be able to tamper a request before sending (with proxy or other tool) * The user should be able to tamper a request before sending (with proxy or other tool)
* The user will be able to tamper with field restrictions and bypass client-side validation * The user will be able to tamper with field restrictions and bypass client-side validation

View File

@ -0,0 +1,76 @@
package org.owasp.webgoat.plugin;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.owasp.webgoat.plugins.LessonTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author nbaars
* @since 6/16/17.
*/
@RunWith(SpringJUnit4ClassRunner.class)
public class BypassRestrictionsFrontendValidationTest extends LessonTest {
@Before
public void setup() throws Exception {
when(webSession.getCurrentLesson()).thenReturn(new BypassRestrictions());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void noChangesShouldNotPassTheLesson() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation")
.param("field1", "abc")
.param("field2", "123")
.param("field3", "abc ABC 123")
.param("field4", "seven")
.param("field5", "01101")
.param("field6", "90201 1111")
.param("field7", "301-604-4882")
.param("error", "2"))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false)));
}
@Test
public void bypassAllFieldShouldPass() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation")
.param("field1", "abcd")
.param("field2", "1234")
.param("field3", "abc $ABC 123")
.param("field4", "ten")
.param("field5", "01101AA")
.param("field6", "90201 1111AA")
.param("field7", "301-604-4882$$")
.param("error", "0"))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
public void notBypassingAllFieldShouldNotPass() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation")
.param("field1", "abc")
.param("field2", "1234")
.param("field3", "abc $ABC 123")
.param("field4", "ten")
.param("field5", "01101AA")
.param("field6", "90201 1111AA")
.param("field7", "301-604-4882AA")
.param("error", "0"))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false)));
}
}