diff --git a/src/main/java/io/shiftleft/controller/CustomerController.java b/src/main/java/io/shiftleft/controller/CustomerController.java index 40e1c49..d7ccb35 100644 --- a/src/main/java/io/shiftleft/controller/CustomerController.java +++ b/src/main/java/io/shiftleft/controller/CustomerController.java @@ -277,34 +277,55 @@ public void saveSettings(HttpServletResponse httpResponse, WebRequest request) t * @return String * @throws IOException */ - @RequestMapping(value = "/debug", method = RequestMethod.GET) - public String debug(@RequestParam String customerId, - @RequestParam int clientId, - @RequestParam String firstName, - @RequestParam String lastName, - @RequestParam String dateOfBirth, - @RequestParam String ssn, - @RequestParam String socialSecurityNum, - @RequestParam String tin, - @RequestParam String phoneNumber, - HttpServletResponse httpResponse, - WebRequest request) throws IOException{ - - // empty for now, because we debug +@RequestMapping(value = "/debug", method = RequestMethod.GET, produces = "application/json") +@ResponseBody +public ResponseEntity debug(@RequestParam String customerId, + @RequestParam int clientId, + @RequestParam String firstName, + @RequestParam String lastName, + @RequestParam String dateOfBirth, + @RequestParam String ssn, + @RequestParam String socialSecurityNum, + @RequestParam String tin, + @RequestParam String phoneNumber, + HttpServletResponse httpResponse, + WebRequest request) throws IOException{ + + // Input validation - validate date format + try { + DateTime.parse(dateOfBirth); + } catch (IllegalArgumentException e) { + return ResponseEntity.badRequest().body("{\"error\": \"Invalid date format\"}"); + } + + // Create customer object with validated inputs Set accounts1 = new HashSet(); - //dateofbirth example -> "1982-01-10" - Customer customer1 = new Customer(customerId, clientId, firstName, lastName, DateTime.parse(dateOfBirth).toDate(), - ssn, socialSecurityNum, tin, phoneNumber, new Address("Debug str", - "", "Debug city", "CA", "12345"), + Customer customer1 = new Customer(customerId, clientId, firstName, lastName, + DateTime.parse(dateOfBirth).toDate(), + ssn, socialSecurityNum, tin, phoneNumber, + new Address("Debug str", "", "Debug city", "CA", "12345"), accounts1); customerRepository.save(customer1); + + // Create a safe JSON response instead of returning raw toString() + String safeResponse = String.format( + "{\"id\": \"%s\", \"customerId\": \"%s\", \"clientId\": %d, \"firstName\": \"%s\", \"lastName\": \"%s\", \"status\": \"created\"}", + Encode.forJavaScript(customer1.getId() != null ? customer1.getId().toString() : ""), + Encode.forJavaScript(customer1.getCustomerId()), + customer1.getClientId(), + Encode.forJavaScript(customer1.getFirstName()), + Encode.forJavaScript(customer1.getLastName()) + ); + httpResponse.setStatus(HttpStatus.CREATED.value()); httpResponse.setHeader("Location", String.format("%s/customers/%s", request.getContextPath(), customer1.getId())); + httpResponse.setContentType("application/json"); + + return ResponseEntity.status(HttpStatus.CREATED).body(safeResponse); +} - return customer1.toString().toLowerCase().replace("script",""); - } /** * Debug test for saving and reading a customer diff --git a/src/main/java/io/shiftleft/model/Customer.java b/src/main/java/io/shiftleft/model/Customer.java index 6ecdc30..8faa84f 100644 --- a/src/main/java/io/shiftleft/model/Customer.java +++ b/src/main/java/io/shiftleft/model/Customer.java @@ -16,21 +16,32 @@ public class Customer { public Customer() { } - public Customer(String customerId, int clientId, String firstName, String lastName, Date dateOfBirth, String ssn, +public Customer(String customerId, int clientId, String firstName, String lastName, Date dateOfBirth, String ssn, String socialInsurancenum, String tin, String phoneNumber, Address address, Set accounts) { super(); + // Sanitize all string inputs to prevent XSS attacks this.clientId = clientId; - this.customerId = customerId; - this.firstName = firstName; - this.lastName = lastName; + this.customerId = sanitizeInput(customerId); + this.firstName = sanitizeInput(firstName); + this.lastName = sanitizeInput(lastName); this.dateOfBirth = dateOfBirth; - this.ssn = ssn; - this.socialInsurancenum = socialInsurancenum; - this.tin = tin; - this.phoneNumber = phoneNumber; + this.ssn = sanitizeInput(ssn); + this.socialInsurancenum = sanitizeInput(socialInsurancenum); + this.tin = sanitizeInput(tin); + this.phoneNumber = sanitizeInput(phoneNumber); this.address = address; this.accounts = accounts; - } +} + +private String sanitizeInput(String input) { + // Remove null values and sanitize the input + if (input == null) { + return ""; + } + // Use OWASP encoder to sanitize HTML entities + return Encode.forHtml(input.trim()); +} + @Id @GeneratedValue(strategy = GenerationType.AUTO) @@ -156,12 +167,22 @@ public void setAccounts(Set accounts) { this.accounts = accounts; } - @Override - public String toString() { - return "Customer [id=" + id + ", customerId=" + customerId + ", clientId=" + clientId + ", firstName=" + firstName - + ", lastName=" + lastName + ", dateOfBirth=" + dateOfBirth + ", ssn=" + ssn + ", socialInsurancenum=" - + socialInsurancenum + ", tin=" + tin + ", phoneNumber=" + phoneNumber + ", address=" + address + ", accounts=" - + accounts + "]"; - } +@Override +public String toString() { + // HTML-encode all user-controlled data to prevent XSS + return "Customer [id=" + Encode.forHtml(String.valueOf(id)) + + ", customerId=" + Encode.forHtml(customerId) + + ", clientId=" + clientId + + ", firstName=" + Encode.forHtml(firstName) + + ", lastName=" + Encode.forHtml(lastName) + + ", dateOfBirth=" + Encode.forHtml(String.valueOf(dateOfBirth)) + + ", ssn=" + Encode.forHtml(ssn) + + ", socialInsurancenum=" + Encode.forHtml(socialInsurancenum) + + ", tin=" + Encode.forHtml(tin) + + ", phoneNumber=" + Encode.forHtml(phoneNumber) + + ", address=" + (address != null ? Encode.forHtml(address.toString()) : "null") + + ", accounts=" + (accounts != null ? Encode.forHtml(accounts.toString()) : "null") + "]"; +} + }