-
-
Notifications
You must be signed in to change notification settings - Fork 400
/
BlindSQLInjectionVulnerability.java
157 lines (144 loc) · 7.08 KB
/
BlindSQLInjectionVulnerability.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package org.sasanlabs.service.vulnerability.sqlInjection;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
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.vulnerability.types.VulnerabilityType;
import org.sasanlabs.vulnerability.utils.Constants;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.ResponseEntity.BodyBuilder;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.RequestParam;
/**
* This is the most difficult and slowest attack which is done only if Error Based and Union Based
* SQLInjections are not possible. In this attack response from the API is just {@code true} or
* {@code false} and to get the data from the API time based/condition based attacks are done like
* Wait for 10 seconds if 5 users are there in the data based and this way if query starts following
* those conditions then this attack is possible.
*
* @author [email protected] KSASAN
*/
@VulnerableAppRestController(
descriptionLabel = "SQL_INJECTION_VULNERABILITY",
value = "BlindSQLInjectionVulnerability")
public class BlindSQLInjectionVulnerability {
@PersistenceContext private EntityManager entityManager;
private JdbcTemplate applicationJdbcTemplate;
static final String CAR_IS_PRESENT_RESPONSE = "{ \"isCarPresent\": true}";
public BlindSQLInjectionVulnerability(
@Qualifier("applicationJdbcTemplate") JdbcTemplate applicationJdbcTemplate) {
this.applicationJdbcTemplate = applicationJdbcTemplate;
}
@AttackVector(
vulnerabilityExposed = VulnerabilityType.BLIND_SQL_INJECTION,
description = "BLIND_SQL_INJECTION_URL_PARAM_APPENDED_DIRECTLY_TO_QUERY",
payload = "BLIND_SQL_INJECTION_PAYLOAD_LEVEL_1")
@VulnerableAppRequestMapping(
value = LevelConstants.LEVEL_1,
htmlTemplate = "LEVEL_1/SQLInjection_Level1")
public ResponseEntity<String> getCarInformationLevel1(
@RequestParam Map<String, String> queryParams) {
String id = queryParams.get(Constants.ID);
BodyBuilder bodyBuilder = ResponseEntity.status(HttpStatus.OK);
return applicationJdbcTemplate.query(
"select * from cars where id=" + id,
(rs) -> {
if (rs.next()) {
return bodyBuilder.body(CAR_IS_PRESENT_RESPONSE);
}
return bodyBuilder.body(
ErrorBasedSQLInjectionVulnerability.CAR_IS_NOT_PRESENT_RESPONSE);
});
}
@AttackVector(
vulnerabilityExposed = VulnerabilityType.BLIND_SQL_INJECTION,
description =
"BLIND_SQL_INJECTION_URL_PARAM_WRAPPED_WITH_SINGLE_QUOTE_APPENDED_TO_QUERY",
payload = "BLIND_SQL_INJECTION_PAYLOAD_LEVEL_2")
@VulnerableAppRequestMapping(
value = LevelConstants.LEVEL_2,
htmlTemplate = "LEVEL_1/SQLInjection_Level1")
public ResponseEntity<String> getCarInformationLevel2(
@RequestParam Map<String, String> queryParams) {
String id = queryParams.get(Constants.ID);
BodyBuilder bodyBuilder = ResponseEntity.status(HttpStatus.OK);
bodyBuilder.body(ErrorBasedSQLInjectionVulnerability.CAR_IS_NOT_PRESENT_RESPONSE);
return applicationJdbcTemplate.query(
"select * from cars where id='" + id + "'",
(rs) -> {
if (rs.next()) {
return bodyBuilder.body(CAR_IS_PRESENT_RESPONSE);
}
return bodyBuilder.body(
ErrorBasedSQLInjectionVulnerability.CAR_IS_NOT_PRESENT_RESPONSE);
});
}
@VulnerableAppRequestMapping(
value = LevelConstants.LEVEL_3,
variant = Variant.SECURE,
htmlTemplate = "LEVEL_1/SQLInjection_Level1")
public ResponseEntity<String> getCarInformationLevel3(
@RequestParam Map<String, String> queryParams) {
String id = queryParams.get(Constants.ID);
BodyBuilder bodyBuilder = ResponseEntity.status(HttpStatus.OK);
bodyBuilder.body(ErrorBasedSQLInjectionVulnerability.CAR_IS_NOT_PRESENT_RESPONSE);
return applicationJdbcTemplate.query(
(conn) -> conn.prepareStatement("select * from cars where id=?"),
(prepareStatement) -> {
prepareStatement.setString(1, id);
},
(rs) -> {
if (rs.next()) {
return bodyBuilder.body(CAR_IS_PRESENT_RESPONSE);
}
return bodyBuilder.body(
ErrorBasedSQLInjectionVulnerability.CAR_IS_NOT_PRESENT_RESPONSE);
});
}
// Input Validation - Ensure that the input data is valid and of the expected type.
@VulnerableAppRequestMapping(
value = LevelConstants.LEVEL_4,
variant = Variant.SECURE,
htmlTemplate = "LEVEL_1/SQLInjection_Level1")
public ResponseEntity<String> getCarInformationLevel4(
@RequestParam Map<String, String> queryParams) {
String id = queryParams.get(Constants.ID);
// Validate numeric ID
if (!id.matches("\\d+")) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Invalid ID format.");
}
BodyBuilder bodyBuilder = ResponseEntity.status(HttpStatus.OK);
bodyBuilder.body(ErrorBasedSQLInjectionVulnerability.CAR_IS_NOT_PRESENT_RESPONSE);
return applicationJdbcTemplate.query(
"select * from cars where id=" + id,
(rs) -> {
if (rs.next()) {
return bodyBuilder.body(CAR_IS_PRESENT_RESPONSE);
}
return bodyBuilder.body(
ErrorBasedSQLInjectionVulnerability.CAR_IS_NOT_PRESENT_RESPONSE);
});
}
// Implementation Level 5 - Hibernate
@VulnerableAppRequestMapping(
value = LevelConstants.LEVEL_5,
variant = Variant.SECURE,
htmlTemplate = "LEVEL_1/SQLInjection_Level1")
public ResponseEntity<String> getCarInformationLevel5(
@RequestParam Map<String, String> queryParams) {
int id = Integer.parseInt(queryParams.get(Constants.ID));
CarInformation car = entityManager.find(CarInformation.class, id);
if (car != null) {
return ResponseEntity.ok(CAR_IS_PRESENT_RESPONSE);
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(ErrorBasedSQLInjectionVulnerability.CAR_IS_NOT_PRESENT_RESPONSE);
}
}
}