diff --git a/src/main/java/org/sasanlabs/service/vulnerability/sampleVulnerability/SampleVulnerability.java b/src/main/java/org/sasanlabs/service/vulnerability/sampleVulnerability/SampleVulnerability.java
new file mode 100644
index 00000000..3f15c150
--- /dev/null
+++ b/src/main/java/org/sasanlabs/service/vulnerability/sampleVulnerability/SampleVulnerability.java
@@ -0,0 +1,108 @@
+package org.sasanlabs.service.vulnerability.sampleVulnerability;
+
+import org.sasanlabs.internal.utility.LevelConstants;
+import org.sasanlabs.internal.utility.Variant;
+import org.sasanlabs.internal.utility.annotations.AttackVector;
+import org.sasanlabs.internal.utility.annotations.VulnerableAppRequestMapping;
+import org.sasanlabs.internal.utility.annotations.VulnerableAppRestController;
+import org.sasanlabs.service.vulnerability.bean.GenericVulnerabilityResponseBean;
+import org.sasanlabs.vulnerability.types.VulnerabilityType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * This is a sample vulnerability for helping developers in adding a new Vulnerability for
+ * VulnerableApp
+ *
+ * @author KSASAN preetkaran20@gmail.com
+ */
+/**
+ * {@code VulnerableAppRestController} annotation is similar to {@link
+ * org.springframework.stereotype.Controller} Annotation
+ */
+@VulnerableAppRestController(
+ /**
+ * "descriptionLabel" parameter of annotation is i18n label stored in {@link
+ * /VulnerableApp/src/main/resources/i18n/}. This descriptionLabel
+ * will be shown in the UI as the description of the Vulnerability. It helps students to
+ * learn about the vulnerability and can also include some of the useful references etc.
+ */
+ descriptionLabel = "SAMPLE_VULNERABILITY",
+ /**
+ * "value" parameter of annotation is used to create the request mapping. e.g. for the below
+ * parameter value, /VulnerableApp/SampleVulnerability will be created as URI Path.
+ */
+ value = "SampleVulnerability")
+public class SampleVulnerability {
+
+ /**
+ * {@code AttackVector} annotation is used to create the Hints section in the User Interface.
+ * This annotation can be mentioned multiple times in case the same vulnerability level
+ */
+ @AttackVector(
+ /**
+ * "vulnerabilityExposed" parameter is used to depict the Vulnerability exposed by the
+ * level. For example say a level is exposing SQL_INJECTION.
+ */
+ vulnerabilityExposed = VulnerabilityType.SAMPLE_VULNERABILITY,
+ /**
+ * "description" parameter of annotation is i18n label stored in {@link
+ * /VulnerableApp/src/main/resources/i18n/}. This description
+ * will be shown in the UI as hint to give some indication on how the level is handling
+ * input to help user to crack the level.
+ */
+ description = "SAMPLE_VULNERABILITY_USER_INPUT_HANDLING_INJECTION",
+
+ /**
+ * "payload" parameter of annotation is i18n label stored in {@link
+ * /VulnerableApp/src/main/resources/attackvectors/*.properties}. This payload will be
+ * shown in UI to help users find/exploit the vulnerability
+ */
+ payload = "NOT_APPLICABLE")
+ /**
+ * This annotation is similar to {@link RequestMapping} SpringBoot annotation. It will map the
+ * endpoint to /VulnerableApp/SampleVulnerability/LEVEL_1 where LEVEL_1 is coming from the value
+ * parameter.
+ */
+ @VulnerableAppRequestMapping(
+ /**
+ * "value" parameter is used to map the level to URI path
+ * /VulnerableApp/SampleVulnerability/${value}.
+ */
+ value = LevelConstants.LEVEL_1,
+
+ /**
+ * "htmlTemplate" is used to load the UI for the level for taking input from the user.
+ * It points to files in directory
+ * src/main/resource/static/templates/${VulnerabilityName} e.g.
+ * src/main/resource/static/templates/SampleVulnerability as ${htmlTemplate}.js,
+ * ${htmlTemplate}.css, ${htmlTemplate}.html. e.g. in this case it will be:
+ * src/main/resource/static/templates/SampleVulnerability/LEVEL_1/SampleVulnerability_Level1.js
+ * etc
+ *
+ *
CSS, JS and HTML are all loaded to render the UI.
+ */
+ htmlTemplate = "LEVEL_1/SampleVulnerability")
+ public GenericVulnerabilityResponseBean sampleUnsecuredLevel(@RequestParam("name") String key) {
+ /** Add Business logic here */
+ return new GenericVulnerabilityResponseBean<>("Not Implemented", true);
+ }
+
+ /** For secured level there is no need for {@link AttackVector} annotation. */
+ @VulnerableAppRequestMapping(
+ value = LevelConstants.LEVEL_2,
+
+ // Can reuse the same UI template in case it doesn't change between levels
+ htmlTemplate = "LEVEL_1/SampleVulnerability",
+ /**
+ * "variant" parameter defines whether the level is secure or not and same is depicted
+ * in the UI as a closed lock and open lock icon. Default value of the variant is
+ * UNSECURE so in case a secure level is added, please add the variant as {@link
+ * Variant#SECURE}
+ */
+ variant = Variant.SECURE)
+ public GenericVulnerabilityResponseBean sampleSecuredLevel(@RequestParam("name") String key) {
+ /** Add Business logic here */
+ return new GenericVulnerabilityResponseBean<>("Not Implemented", true);
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/static/templates/SampleVulnerability/LEVEL_1/SampleVulnerability.css b/src/main/resources/static/templates/SampleVulnerability/LEVEL_1/SampleVulnerability.css
new file mode 100644
index 00000000..e5d57b25
--- /dev/null
+++ b/src/main/resources/static/templates/SampleVulnerability/LEVEL_1/SampleVulnerability.css
@@ -0,0 +1,16 @@
+#SampleVulnerability {
+ color: black;
+ text-align: center;
+}
+
+#fetchDetails {
+ background: blueviolet;
+ display: inline-block;
+ padding: 8px 8px;
+ margin: 10px;
+ border: 2px solid transparent;
+ border-radius: 3px;
+ transition: 0.2s opacity;
+ color: #FFF;
+ font-size: 12px;
+}
\ No newline at end of file
diff --git a/src/main/resources/static/templates/SampleVulnerability/LEVEL_1/SampleVulnerability.html b/src/main/resources/static/templates/SampleVulnerability/LEVEL_1/SampleVulnerability.html
new file mode 100644
index 00000000..dddeea7d
--- /dev/null
+++ b/src/main/resources/static/templates/SampleVulnerability/LEVEL_1/SampleVulnerability.html
@@ -0,0 +1,9 @@
+
+
+
+ This is a Sample Vulnerability. please add the UI components here.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/static/templates/SampleVulnerability/LEVEL_1/SampleVulnerability.js b/src/main/resources/static/templates/SampleVulnerability/LEVEL_1/SampleVulnerability.js
new file mode 100644
index 00000000..78641721
--- /dev/null
+++ b/src/main/resources/static/templates/SampleVulnerability/LEVEL_1/SampleVulnerability.js
@@ -0,0 +1,23 @@
+function addingEventListenerToFetchData() {
+ document
+ .getElementById("fetchDetails")
+ .addEventListener("click", function () {
+ /**
+ * getUrlForVulnerabilityLevel() method provides url to call the Vulnerability Level
+ * of Sample Vulnerability.
+ * e.g. /VulnerableApp/SampleVulnerability/LEVEL_1 for LEVEL_1
+ */
+ let url = getUrlForVulnerabilityLevel();
+ /**
+ * doGetAjaxCall() method is used to do the ajax get call to the Vulnerability Level
+ */
+ doGetAjaxCall(fetchDataCallback, url + "?name=dummyInput", true);
+ });
+}
+// Used to register event on the button or any other component
+addingEventListenerToFetchData();
+
+//Callback function to handle the response and render in the UI
+function fetchDataCallback(data) {
+ document.getElementById("response").innerHTML = data.content;
+}
diff --git a/src/test/java/org/sasanlabs/service/vulnerability/sqlInjection/ErrorBasedSQLInjectionVulnerabilityTest.java b/src/test/java/org/sasanlabs/service/vulnerability/sqlInjection/ErrorBasedSQLInjectionVulnerabilityTest.java
new file mode 100644
index 00000000..74079531
--- /dev/null
+++ b/src/test/java/org/sasanlabs/service/vulnerability/sqlInjection/ErrorBasedSQLInjectionVulnerabilityTest.java
@@ -0,0 +1,143 @@
+package org.sasanlabs.service.vulnerability.sqlInjection;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.sasanlabs.vulnerability.utils.Constants;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.PreparedStatementCreator;
+import org.springframework.jdbc.core.PreparedStatementSetter;
+import org.springframework.jdbc.core.ResultSetExtractor;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.verify;
+
+class ErrorBasedSQLInjectionVulnerabilityTest {
+
+ private ErrorBasedSQLInjectionVulnerability errorBasedSQLInjectionVulnerability;
+ private JdbcTemplate template;
+
+ @BeforeEach
+ void setUp() {
+ template = Mockito.mock(JdbcTemplate.class);
+
+ // Mock database
+ doReturn(null)
+ .when(template)
+ .query(anyString(), (ResultSetExtractor>) any());
+ doReturn(null)
+ .when(template)
+ .query(
+ anyString(),
+ (PreparedStatementSetter) any(),
+ (ResultSetExtractor>) any());
+
+ errorBasedSQLInjectionVulnerability = new ErrorBasedSQLInjectionVulnerability(template);
+ }
+
+ @Test
+ void doesCarInformationExistsLevel1_ExpectParamEscaped() {
+ // Act
+ final Map queryParams = Collections.singletonMap("id", "1");
+ errorBasedSQLInjectionVulnerability.doesCarInformationExistsLevel1(queryParams);
+
+ // Assert
+ verify(template)
+ .query(
+ eq("select * from cars where id=1"),
+ (ResultSetExtractor>) any());
+ }
+
+ @Test
+ void doesCarInformationExistsLevel2_ExpectParamEscaped() {
+ // Act
+ final Map queryParams = Collections.singletonMap("id", "1");
+ errorBasedSQLInjectionVulnerability.doesCarInformationExistsLevel2(queryParams);
+
+ // Assert
+ verify(template)
+ .query(
+ eq("select * from cars where id='1'"),
+ (ResultSetExtractor>) any());
+ }
+
+ @Test
+ void doesCarInformationExistsLevel3_ExpectParamEscaped() {
+ // Act
+ final Map queryParams = Collections.singletonMap("id", "1'");
+ errorBasedSQLInjectionVulnerability.doesCarInformationExistsLevel3(queryParams);
+
+ // Assert
+ verify(template)
+ .query(
+ eq("select * from cars where id='1'"),
+ (ResultSetExtractor>) any());
+ }
+
+ @Test
+ void doesCarInformationExistsLevel4_ExpectValidResponse() {
+ // Arrange
+ Map queryParams = new HashMap<>();
+ queryParams.put(Constants.ID, "1'");
+
+ // Mock the response entity
+ ResponseEntity mockResponseEntity = ResponseEntity.status(HttpStatus.OK).body("Sample response");
+ doReturn(mockResponseEntity)
+ .when(template)
+ .query(
+ Mockito.any(PreparedStatementCreator.class),
+ Mockito.any(PreparedStatementSetter.class),
+ Mockito.any(ResultSetExtractor.class));
+
+ // Act
+ ResponseEntity response = errorBasedSQLInjectionVulnerability.doesCarInformationExistsLevel4(queryParams);
+
+ // Assert
+ assertEquals(HttpStatus.OK, response.getStatusCode());
+ assertEquals("Sample response", response.getBody());
+ verify(template)
+ .query(
+ Mockito.any(PreparedStatementCreator.class),
+ Mockito.any(PreparedStatementSetter.class),
+ Mockito.any(ResultSetExtractor.class));
+ }
+
+ @Test
+ void doesCarInformationExistsLevel5_ExpectValidResponse() {
+ // Arrange
+ Map queryParams = new HashMap<>();
+ queryParams.put(Constants.ID, "1");
+
+ // Mock the response entity
+ ResponseEntity mockResponseEntity = ResponseEntity.status(HttpStatus.OK).body("Sample response");
+ doReturn(mockResponseEntity)
+ .when(template)
+ .query(
+ Mockito.any(PreparedStatementCreator.class),
+ Mockito.any(PreparedStatementSetter.class),
+ Mockito.any(ResultSetExtractor.class));
+
+ // Act
+ ResponseEntity response = errorBasedSQLInjectionVulnerability.doesCarInformationExistsLevel5(queryParams);
+
+ // Assert
+ assertEquals(HttpStatus.OK, response.getStatusCode());
+ assertEquals("Sample response", response.getBody());
+ verify(template)
+ .query(
+ Mockito.any(PreparedStatementCreator.class),
+ Mockito.any(PreparedStatementSetter.class),
+ Mockito.any(ResultSetExtractor.class));
+ }
+
+}
\ No newline at end of file