|
3 | 3 | import java.sql.ResultSet;
|
4 | 4 | import java.sql.SQLException;
|
5 | 5 | import java.util.Map;
|
| 6 | +import java.util.Optional; |
| 7 | +import javax.persistence.EntityManager; |
| 8 | +import javax.persistence.TypedQuery; |
| 9 | +import javax.persistence.criteria.CriteriaBuilder; |
| 10 | +import javax.persistence.criteria.CriteriaQuery; |
| 11 | +import javax.persistence.criteria.Root; |
6 | 12 | import org.sasanlabs.internal.utility.LevelConstants;
|
7 | 13 | import org.sasanlabs.internal.utility.Variant;
|
8 | 14 | import org.sasanlabs.internal.utility.annotations.AttackVector;
|
|
12 | 18 | import org.springframework.beans.factory.annotation.Qualifier;
|
13 | 19 | import org.springframework.http.HttpStatus;
|
14 | 20 | import org.springframework.http.ResponseEntity;
|
| 21 | +import org.springframework.jdbc.core.BeanPropertyRowMapper; |
15 | 22 | import org.springframework.jdbc.core.JdbcTemplate;
|
| 23 | +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; |
| 24 | +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; |
| 25 | +import org.springframework.jdbc.core.namedparam.SqlParameterSource; |
16 | 26 | import org.springframework.web.bind.annotation.RequestParam;
|
17 | 27 |
|
18 | 28 | /**
|
|
28 | 38 | public class UnionBasedSQLInjectionVulnerability {
|
29 | 39 |
|
30 | 40 | private final JdbcTemplate applicationJdbcTemplate;
|
| 41 | + private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; |
| 42 | + private final CarInformationRepository carInformationRepository; |
| 43 | + private final EntityManager entityManager; |
31 | 44 |
|
32 | 45 | public UnionBasedSQLInjectionVulnerability(
|
33 |
| - @Qualifier("applicationJdbcTemplate") final JdbcTemplate applicationJdbcTemplate) { |
| 46 | + @Qualifier("applicationJdbcTemplate") final JdbcTemplate applicationJdbcTemplate, |
| 47 | + NamedParameterJdbcTemplate namedParameterJdbcTemplate, |
| 48 | + CarInformationRepository carInformationRepository, |
| 49 | + EntityManager entityManager) { |
34 | 50 | this.applicationJdbcTemplate = applicationJdbcTemplate;
|
| 51 | + this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; |
| 52 | + this.carInformationRepository = carInformationRepository; |
| 53 | + this.entityManager = entityManager; |
35 | 54 | }
|
36 | 55 |
|
37 | 56 | @AttackVector(
|
@@ -92,6 +111,83 @@ public ResponseEntity<CarInformation> getCarInformationLevel4(
|
92 | 111 | this::resultSetToResponse);
|
93 | 112 | }
|
94 | 113 |
|
| 114 | + @VulnerableAppRequestMapping( |
| 115 | + value = LevelConstants.LEVEL_5, |
| 116 | + variant = Variant.SECURE, |
| 117 | + htmlTemplate = "LEVEL_1/SQLInjection_Level1") |
| 118 | + public ResponseEntity<CarInformation> getCarInformationLevel5( |
| 119 | + @RequestParam final Map<String, String> queryParams) { |
| 120 | + final String id = queryParams.get("id"); |
| 121 | + SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("id", id); |
| 122 | + CarInformation s = |
| 123 | + namedParameterJdbcTemplate.queryForObject( |
| 124 | + "select * from cars where id=:id", |
| 125 | + namedParameters, |
| 126 | + new BeanPropertyRowMapper<>(CarInformation.class)); |
| 127 | + return new ResponseEntity<>(s, HttpStatus.OK); |
| 128 | + } |
| 129 | + |
| 130 | + @VulnerableAppRequestMapping( |
| 131 | + value = LevelConstants.LEVEL_6, |
| 132 | + variant = Variant.SECURE, |
| 133 | + htmlTemplate = "LEVEL_1/SQLInjection_Level1") |
| 134 | + public ResponseEntity<CarInformation> getCarInformationLevel6( |
| 135 | + @RequestParam final Map<String, String> queryParams) { |
| 136 | + final String id = queryParams.get("id"); |
| 137 | + String jql = "from CarInformation where id = :id"; |
| 138 | + TypedQuery<CarInformation> q = |
| 139 | + entityManager |
| 140 | + .createQuery(jql, CarInformation.class) |
| 141 | + .setParameter("id", Integer.valueOf(id)); |
| 142 | + return new ResponseEntity<>(q.getSingleResult(), HttpStatus.OK); |
| 143 | + } |
| 144 | + |
| 145 | + @VulnerableAppRequestMapping( |
| 146 | + value = LevelConstants.LEVEL_7, |
| 147 | + variant = Variant.SECURE, |
| 148 | + htmlTemplate = "LEVEL_1/SQLInjection_Level1") |
| 149 | + public ResponseEntity<CarInformation> getCarInformationLevel7( |
| 150 | + @RequestParam final Map<String, String> queryParams) { |
| 151 | + final String id = queryParams.get("id"); |
| 152 | + |
| 153 | + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); |
| 154 | + CriteriaQuery<CarInformation> cq = cb.createQuery(CarInformation.class); |
| 155 | + Root<CarInformation> root = cq.from(CarInformation.class); |
| 156 | + |
| 157 | + cq.select(root).where(cb.equal(root.get("id"), id)); |
| 158 | + |
| 159 | + TypedQuery<CarInformation> q = entityManager.createQuery(cq); |
| 160 | + return new ResponseEntity<>(q.getSingleResult(), HttpStatus.OK); |
| 161 | + } |
| 162 | + |
| 163 | + @VulnerableAppRequestMapping( |
| 164 | + value = LevelConstants.LEVEL_8, |
| 165 | + variant = Variant.SECURE, |
| 166 | + htmlTemplate = "LEVEL_1/SQLInjection_Level1") |
| 167 | + public ResponseEntity<CarInformation> getCarInformationLevel8( |
| 168 | + @RequestParam final Map<String, String> queryParams) { |
| 169 | + final String id = queryParams.get("id"); |
| 170 | + TypedQuery<CarInformation> q = |
| 171 | + entityManager |
| 172 | + .createNamedQuery("findById", CarInformation.class) |
| 173 | + .setParameter("id", Integer.valueOf(id)); |
| 174 | + return new ResponseEntity<>(q.getSingleResult(), HttpStatus.OK); |
| 175 | + } |
| 176 | + |
| 177 | + @VulnerableAppRequestMapping( |
| 178 | + value = LevelConstants.LEVEL_9, |
| 179 | + variant = Variant.SECURE, |
| 180 | + htmlTemplate = "LEVEL_1/SQLInjection_Level1") |
| 181 | + public ResponseEntity<CarInformation> getCarInformationLevel9( |
| 182 | + @RequestParam final Map<String, String> queryParams) { |
| 183 | + final String id = queryParams.get("id"); |
| 184 | + Optional<CarInformation> carInformation = |
| 185 | + carInformationRepository.findById(Integer.valueOf(id)); |
| 186 | + return carInformation |
| 187 | + .map(information -> new ResponseEntity<>(information, HttpStatus.OK)) |
| 188 | + .orElseGet(() -> new ResponseEntity<>(HttpStatus.NOT_FOUND)); |
| 189 | + } |
| 190 | + |
95 | 191 | private ResponseEntity<CarInformation> resultSetToResponse(final ResultSet rs)
|
96 | 192 | throws SQLException {
|
97 | 193 | final CarInformation carInformation = new CarInformation();
|
|
0 commit comments