Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pushing test for Persistent XSS in HTML #455

Merged
merged 4 commits into from
Nov 29, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,379 @@
package org.sasanlabs.service.vulnerability.xss.reflected;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;

import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.sasanlabs.service.vulnerability.xss.persistent.PersistentXSSInHTMLTagVulnerability;
import org.sasanlabs.service.vulnerability.xss.persistent.Post;
import org.sasanlabs.service.vulnerability.xss.persistent.PostRepository;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

public class PersistentXSSInHTMLTagVulnerabilityTest {
@Mock private PostRepository postRepository;

private PersistentXSSInHTMLTagVulnerability vulnerability;

@BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
vulnerability = new PersistentXSSInHTMLTagVulnerability(postRepository);
}

@Test
public void testGetVulnerablePayloadLevel1() {
// Prepare test data
Map<String, String> queryParams =
Collections.singletonMap("comment", "<script>alert('XSS')</script>");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel1(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall we also assert on the arguments passed to the postRepository?


// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the content of the post being saved
assertEquals("<script>alert('XSS')</script>", postCaptor.getValue().getContent());

// Assert on the HTTP response status code
assertEquals(200, response.getStatusCodeValue());
}

@Test
public void testGetVulnerablePayloadLevel1WithXSSInAttributeValue() {
// Prepare test data
Map<String, String> queryParams =
Collections.singletonMap("comment", "<a href='javascript:alert(1)'>Click me</a>");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel1(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());

// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the content of the post being saved
assertEquals(
"<a href='javascript:alert(1)'>Click me</a>", postCaptor.getValue().getContent());

// Assert on the HTTP response status code
assertEquals(200, response.getStatusCodeValue());
}

@Test
public void testGetVulnerablePayloadLevel2() {
// Prepare test data
Map<String, String> queryParams =
Collections.singletonMap("comment", "<img src='x' onerror='alert(1)'>");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel2(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());

// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the content of the post being saved
assertEquals("<img src='x' onerror='alert(1)'>", postCaptor.getValue().getContent());

// Assert on the HTTP response status code
assertEquals(200, response.getStatusCodeValue());
}

@Test
public void testGetVulnerablePayloadLevel3() {
// Prepare test data
Map<String, String> queryParams =
Collections.singletonMap("comment", "<script>alert('XSS')</script>");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel3(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());

// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the modified content of the post being saved
assertEquals("<script>alert('XSS')</script>", postCaptor.getValue().getContent());

// Assert on the HTTP response status code
assertEquals(200, response.getStatusCodeValue());
}

@Test
public void testGetVulnerablePayloadLevel4() {
// Prepare test data
Map<String, String> queryParams =
Collections.singletonMap("comment", "<img src='x' onerror='alert(1)'>");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel4(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to add a few more granular level of assertions then just verifying the call to postRepository.


// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the modified content of the post being saved
assertEquals("<img src='x' onerror='alert(1)'>", postCaptor.getValue().getContent());

// Assert on the HTTP response status code
assertEquals(200, response.getStatusCodeValue());
}

@Test
public void testGetVulnerablePayloadLevel5() {
// Prepare test data
Map<String, String> queryParams =
Collections.singletonMap("comment", "<script>alert('XSS')</script>");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel5(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());

// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the modified content of the post being saved
assertEquals("<script>alert('XSS')</script>", postCaptor.getValue().getContent());

// Assert on the HTTP response status code
assertEquals(200, response.getStatusCodeValue());
}

@Test
public void testGetVulnerablePayloadLevel6() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think adding a few tests would help here like input having NullByte and its impact on level 6 and level 5.

// Prepare test data
Map<String, String> queryParams =
Collections.singletonMap("comment", "<img src='x' onerror='alert(1)'>");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel6(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());

// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the modified content of the post being saved
assertEquals("<img src='x' onerror='alert(1)'>", postCaptor.getValue().getContent());

// Assert on the HTTP response status code
assertEquals(200, response.getStatusCodeValue());
}

@Test
public void testGetVulnerablePayloadLevel7() {
// Prepare test data
Map<String, String> queryParams =
Collections.singletonMap("comment", "<script>alert('XSS')</script>");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel7(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());

// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the modified content of the post being saved
assertEquals("<script>alert('XSS')</script>", postCaptor.getValue().getContent());

// Assert on the HTTP response status code
assertEquals(200, response.getStatusCodeValue());
}

@Test
public void testGetVulnerablePayloadLevel5WithNullByte() {
// Prepare test data with NullByte
Map<String, String> queryParams =
Collections.singletonMap("comment", "<script>\u0000alert('XSS')</script>");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel5(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());

// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the modified content of the post being saved (assuming it's not modified)
assertEquals("<script>\u0000alert('XSS')</script>", postCaptor.getValue().getContent());

// Assert on the HTTP response status code
assertEquals(200, response.getStatusCodeValue());
}

@Test
public void testGetVulnerablePayloadLevel6WithNullByte() {
// Prepare test data with NullByte
Map<String, String> queryParams =
Collections.singletonMap("comment", "<img src='x' onerror='alert(1)'>\u0000");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel6(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());

// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the modified content of the post being saved (assuming it's not modified)
assertEquals("<img src='x' onerror='alert(1)'>\u0000", postCaptor.getValue().getContent());

// Assert on the HTTP response status code
assertEquals(200, response.getStatusCodeValue());
}

@Test
public void testGetVulnerablePayloadLevel4WithResponseStatusAssertions() {
// Prepare test data
Map<String, String> queryParams =
Collections.singletonMap("comment", "<img src='x' onerror='alert(1)'>");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel4(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());

// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the modified content of the post being saved
assertEquals("<img src='x' onerror='alert(1)'>", postCaptor.getValue().getContent());

// Assert on the HTTP response status code
assertEquals(HttpStatus.OK, response.getStatusCode());
}

@Test
public void testGetVulnerablePayloadLevel6WithHtmlEscaping() {
Post post = new Post();
post.setContent("<img src='x' onerror='alert(1)'>");

when(postRepository.findByLevelIdentifier("LEVEL_6")).thenReturn(Arrays.asList(post));

// Prepare test data
Map<String, String> queryParams =
Collections.singletonMap("comment", "<img src='x' onerror='alert(1)'>");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel6(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());

// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the content of the post being saved
assertEquals("<img src='x' onerror='alert(1)'>", postCaptor.getValue().getContent());

// Assert on the modified content of the post being saved (HTML escaped)
assertEquals(
"<div id=\"comments\">&lt;img src='x' onerror='alert(1)'&gt;</div>",
response.getBody());

// Assert on the HTTP response status code
assertEquals(HttpStatus.OK, response.getStatusCode());
}

@Test
public void testGetVulnerablePayloadLevel2_WithPatternReplacement() {
Post post = new Post();
post.setContent("<img src='x' onerror='alert(1)'>");

when(postRepository.findByLevelIdentifier("LEVEL_2")).thenReturn(Arrays.asList(post));

// Prepare test data
Map<String, String> queryParams =
Collections.singletonMap("comment", "<img src='x' onerror='alert(1)'>");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel2(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());

// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the content of the post being saved
assertEquals("<img src='x' onerror='alert(1)'>", postCaptor.getValue().getContent());

// Assert on the modified content of the post being saved (pattern replaced)
assertEquals("<div id=\"comments\"> src='x' onerror='alert(1)'></div>", response.getBody());

// Assert on the HTTP response status code
assertEquals(HttpStatus.OK, response.getStatusCode());
}

@Test
public void testGetVulnerablePayloadLevel3_WithResponseContentAssertions() {
Post post = new Post();
post.setContent("<script>alert('XSS')</script>");

when(postRepository.findByLevelIdentifier("LEVEL_3")).thenReturn(Arrays.asList(post));

// Prepare test data
Map<String, String> queryParams =
Collections.singletonMap("comment", "<script>alert('XSS')</script>");

// Perform the test
ResponseEntity<String> response = vulnerability.getVulnerablePayloadLevel3(queryParams);

// Verify that the save method is called once
verify(postRepository, times(1)).save(any());

// Capture the argument passed to the save method
ArgumentCaptor<Post> postCaptor = ArgumentCaptor.forClass(Post.class);
verify(postRepository).save(postCaptor.capture());

// Assert on the modified content of the post being saved
assertEquals("<script>alert('XSS')</script>", postCaptor.getValue().getContent());

// Assert on the content of the response
assertEquals("<div id=\"comments\">>alert('XSS')</script></div>", response.getBody());

// Assert on the HTTP response status code
assertEquals(HttpStatus.OK, response.getStatusCode());
}
}
Loading