From 3a740851af343344eacb7b5735fb30d82550e28f Mon Sep 17 00:00:00 2001 From: nishfath <81247855+nishfath@users.noreply.github.com> Date: Thu, 1 May 2025 13:19:19 -0400 Subject: [PATCH 01/12] Fixing src/main/java/io/shiftleft/controller/CustomerController.java for finding 4 --- .../java/io/shiftleft/controller/CustomerController.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/shiftleft/controller/CustomerController.java b/src/main/java/io/shiftleft/controller/CustomerController.java index 40e1c49..287d8b2 100644 --- a/src/main/java/io/shiftleft/controller/CustomerController.java +++ b/src/main/java/io/shiftleft/controller/CustomerController.java @@ -277,7 +277,7 @@ public void saveSettings(HttpServletResponse httpResponse, WebRequest request) t * @return String * @throws IOException */ - @RequestMapping(value = "/debug", method = RequestMethod.GET) +@RequestMapping(value = "/debug", method = RequestMethod.GET) public String debug(@RequestParam String customerId, @RequestParam int clientId, @RequestParam String firstName, @@ -303,9 +303,11 @@ ssn, socialSecurityNum, tin, phoneNumber, new Address("Debug str", httpResponse.setHeader("Location", String.format("%s/customers/%s", request.getContextPath(), customer1.getId())); - return customer1.toString().toLowerCase().replace("script",""); + // Properly encode the customer data to prevent XSS + return Encode.forHtml(customer1.toString()); } + /** * Debug test for saving and reading a customer * From 2952ca3e190349d099374288e188968c80b0327f Mon Sep 17 00:00:00 2001 From: nishfath <81247855+nishfath@users.noreply.github.com> Date: Thu, 1 May 2025 13:19:20 -0400 Subject: [PATCH 02/12] Fixing src/main/java/io/shiftleft/controller/CustomerController.java for finding 34 --- .../controller/CustomerController.java | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/main/java/io/shiftleft/controller/CustomerController.java b/src/main/java/io/shiftleft/controller/CustomerController.java index 287d8b2..627f581 100644 --- a/src/main/java/io/shiftleft/controller/CustomerController.java +++ b/src/main/java/io/shiftleft/controller/CustomerController.java @@ -109,32 +109,36 @@ private void dispatchEventToSalesForce(String event) * @param customerId * @return retrieved customer */ - @RequestMapping(value = "/customers/{customerId}", method = RequestMethod.GET) - public Customer getCustomer(@PathVariable("customerId") Long customerId) { +@RequestMapping(value = "/customers/{customerId}", method = RequestMethod.GET) +public Customer getCustomer(@PathVariable("customerId") Long customerId) { - /* validate customer Id parameter */ - if (null == customerId) { + /* validate customer Id parameter */ + if (null == customerId) { throw new InvalidCustomerRequestException(); - } - - Customer customer = customerRepository.findOne(customerId); - if (null == customer) { - throw new CustomerNotFoundException(); - } + } - Account account = new Account(4242l,1234, "savings", 1, 0); - log.info("Account Data is {}", account); - log.info("Customer Data is {}", customer); + Customer customer = customerRepository.findOne(customerId); + if (null == customer) { + throw new CustomerNotFoundException(); + } - try { - dispatchEventToSalesForce(String.format(" Customer %s Logged into SalesForce", customer)); - } catch (Exception e) { - log.error("Failed to Dispatch Event to SalesForce . Details {} ", e.getLocalizedMessage()); + Account account = new Account(4242l, 1234, "savings", 1, 0); + + // Log only non-sensitive information like IDs instead of entire objects + log.info("Processing account ID: null", account.getId()); + log.info("Retrieved customer ID: null", customer.getId()); + + try { + // Avoid logging sensitive customer information in the SalesForce event + dispatchEventToSalesForce(String.format("Customer ID %s logged into SalesForce", customer.getId())); + } catch (Exception e) { + // Don't include exception details in logs that might contain sensitive data + log.error("Failed to dispatch event to SalesForce. Error type: null", e.getClass().getName()); + } - } + return customer; +} - return customer; - } /** * Handler for / loads the index.tpl From 5c7a3b1ded84fcf89ecde50c914c1e50d37590e2 Mon Sep 17 00:00:00 2001 From: nishfath <81247855+nishfath@users.noreply.github.com> Date: Thu, 1 May 2025 13:19:25 -0400 Subject: [PATCH 03/12] Fixing src/main/java/io/shiftleft/controller/SearchController.java for finding 6 --- .../controller/SearchController.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/shiftleft/controller/SearchController.java b/src/main/java/io/shiftleft/controller/SearchController.java index faa4097..bcb38b0 100644 --- a/src/main/java/io/shiftleft/controller/SearchController.java +++ b/src/main/java/io/shiftleft/controller/SearchController.java @@ -17,16 +17,21 @@ @Controller public class SearchController { - @RequestMapping(value = "/search/user", method = RequestMethod.GET) - public String doGetSearch(@RequestParam String foo, HttpServletResponse response, HttpServletRequest request) { - java.lang.Object message = new Object(); - try { - ExpressionParser parser = new SpelExpressionParser(); - Expression exp = parser.parseExpression(foo); - message = (Object) exp.getValue(); - } catch (Exception ex) { - System.out.println(ex.getMessage()); +@RequestMapping(value = "/search/user", method = RequestMethod.GET) +@ResponseBody +public String doGetSearch(@RequestParam String foo, HttpServletResponse response, HttpServletRequest request) { + // Validate input parameter + if (foo == null || foo.isEmpty()) { + return "No search term provided"; } + + // Instead of evaluating user input as SpEL expression, just use it as a search term + String message = "Search results for: " + Encode.forHtml(foo); + + // Return HTML-encoded message to prevent XSS + return message; +} + return message.toString(); } } From 6ae626b827086e1cadeb86f6712d4a17b0b766b3 Mon Sep 17 00:00:00 2001 From: nishfath <81247855+nishfath@users.noreply.github.com> Date: Thu, 1 May 2025 13:19:28 -0400 Subject: [PATCH 04/12] Fixing src/main/java/io/shiftleft/controller/CustomerController.java for finding 14 --- .../controller/CustomerController.java | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/shiftleft/controller/CustomerController.java b/src/main/java/io/shiftleft/controller/CustomerController.java index 627f581..f963e0b 100644 --- a/src/main/java/io/shiftleft/controller/CustomerController.java +++ b/src/main/java/io/shiftleft/controller/CustomerController.java @@ -220,7 +220,7 @@ public void loadSettings(HttpServletResponse httpResponse, WebRequest request) t * @param request * @throws Exception */ - @RequestMapping(value = "/saveSettings", method = RequestMethod.GET) +@RequestMapping(value = "/saveSettings", method = RequestMethod.GET) public void saveSettings(HttpServletResponse httpResponse, WebRequest request) throws Exception { // "Settings" will be stored in a cookie // schema: base64(filename,value1,value2...), md5sum(base64(filename,value1,value2...)) @@ -232,8 +232,8 @@ public void saveSettings(HttpServletResponse httpResponse, WebRequest request) t String settingsCookie = request.getHeader("Cookie"); String[] cookie = settingsCookie.split(","); - if(cookie.length<2) { - httpResponse.getOutputStream().println("Malformed cookie"); + if(cookie.length<2) { + httpResponse.getOutputStream().println("Malformed cookie"); throw new Exception("cookie is incorrect"); } @@ -242,7 +242,7 @@ public void saveSettings(HttpServletResponse httpResponse, WebRequest request) t // Check md5sum String cookieMD5sum = cookie[1]; String calcMD5Sum = DigestUtils.md5Hex(base64txt); - if(!cookieMD5sum.equals(calcMD5Sum)) + if(!cookieMD5sum.equals(calcMD5Sum)) { httpResponse.getOutputStream().println("Wrong md5"); throw new Exception("Invalid MD5"); @@ -250,9 +250,35 @@ public void saveSettings(HttpServletResponse httpResponse, WebRequest request) t // Now we can store on filesystem String[] settings = new String(Base64.getDecoder().decode(base64txt)).split(","); - // storage will have ClassPathResource as basepath + if (settings.length == 0 || settings[0] == null || settings[0].isEmpty()) { + httpResponse.getOutputStream().println("Invalid filename"); + throw new Exception("Invalid filename"); + } + + // Sanitize filename and prevent directory traversal + String fileName = FilenameUtils.getName(settings[0]); + + // Extra validation to ensure no path traversal + if (!fileName.equals(settings[0]) || fileName.contains("..")) { + httpResponse.getOutputStream().println("Invalid file path"); + throw new Exception("Directory traversal attempt detected"); + } + + // storage will have ClassPathResource as basepath ClassPathResource cpr = new ClassPathResource("./static/"); - File file = new File(cpr.getPath()+settings[0]); + + // Construct safe file path within base directory + Path basePath = Paths.get(cpr.getPath()).normalize(); + Path resolvedPath = basePath.resolve(fileName).normalize(); + + // Validate that the final path is still within the intended base directory + if (!resolvedPath.startsWith(basePath)) { + httpResponse.getOutputStream().println("Invalid file path"); + throw new Exception("Path traversal detected"); + } + + File file = resolvedPath.toFile(); + if(!file.exists()) { file.getParentFile().mkdirs(); } @@ -260,13 +286,14 @@ public void saveSettings(HttpServletResponse httpResponse, WebRequest request) t FileOutputStream fos = new FileOutputStream(file, true); // First entry is the filename -> remove it String[] settingsArr = Arrays.copyOfRange(settings, 1, settings.length); - // on setting at a linez + // on setting at a line fos.write(String.join("\n",settingsArr).getBytes()); fos.write(("\n"+cookie[cookie.length-1]).getBytes()); fos.close(); httpResponse.getOutputStream().println("Settings Saved"); } + /** * Debug test for saving and reading a customer * From 3bd6188f2d53bcb8b4c24431cc9009a42475cd8f Mon Sep 17 00:00:00 2001 From: nishfath <81247855+nishfath@users.noreply.github.com> Date: Thu, 1 May 2025 13:19:29 -0400 Subject: [PATCH 05/12] Fixing src/main/java/io/shiftleft/controller/AdminController.java for finding 13 --- .../shiftleft/controller/AdminController.java | 105 +++++++++++------- 1 file changed, 63 insertions(+), 42 deletions(-) diff --git a/src/main/java/io/shiftleft/controller/AdminController.java b/src/main/java/io/shiftleft/controller/AdminController.java index 296c265..688caf9 100644 --- a/src/main/java/io/shiftleft/controller/AdminController.java +++ b/src/main/java/io/shiftleft/controller/AdminController.java @@ -29,17 +29,25 @@ public class AdminController { // helper private boolean isAdmin(String auth) - { +// Secure JWT key - in production, this should be stored securely, not hardcoded +private static final Key JWT_SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256); + +private boolean isAdmin(String authToken) { try { - ByteArrayInputStream bis = new ByteArrayInputStream(Base64.getDecoder().decode(auth)); - ObjectInputStream objectInputStream = new ObjectInputStream(bis); - Object authToken = objectInputStream.readObject(); - return ((AuthToken) authToken).isAdmin(); + // Verify and parse the JWT token + Claims claims = Jwts.parserBuilder() + .setSigningKey(JWT_SECRET_KEY) + .build() + .parseClaimsJws(authToken) + .getBody(); + + // Check if the role is ADMIN + return "ADMIN".equals(claims.get("role", String.class)); } catch (Exception ex) { - System.out.println(" cookie cannot be deserialized: "+ex.getMessage()); - return false; + System.out.println("Invalid authentication token: " + ex.getMessage()); + return false; } - } +} // @RequestMapping(value = "/admin/printSecrets", method = RequestMethod.POST) @@ -81,47 +89,60 @@ public String doGetPrintSecrets(@CookieValue(value = "auth", defaultValue = "not * @return redirect to company numbers * @throws Exception */ - @RequestMapping(value = "/admin/login", method = RequestMethod.POST) - public String doPostLogin(@CookieValue(value = "auth", defaultValue = "notset") String auth, @RequestBody String password, HttpServletResponse response, HttpServletRequest request) throws Exception { +@RequestMapping(value = "/admin/login", method = RequestMethod.POST) +public String doPostLogin(@CookieValue(value = "auth", defaultValue = "notset") String auth, + @RequestBody String password, + HttpServletResponse response, + HttpServletRequest request) throws Exception { String succ = "redirect:/admin/printSecrets"; + String fail = "redirect:/admin/login"; try { - // no cookie no fun - if (!auth.equals("notset")) { - if(isAdmin(auth)) { - request.getSession().setAttribute("auth",auth); - return succ; + // Check if user is already authenticated via cookie + if (!auth.equals("notset")) { + if (isAdmin(auth)) { + request.getSession().setAttribute("auth", auth); + return succ; + } } - } - // split password=value - String[] pass = password.split("="); - if(pass.length!=2) { + // Parse the password from request body + String[] pass = password.split("="); + if (pass.length != 2) { + return fail; + } + + // Verify password (consider using a more secure password handling mechanism) + if (pass[1] != null && pass[1].length() > 0 && pass[1].equals("shiftleftsecret")) { + // Generate JWT token instead of serialized object + String jwtToken = Jwts.builder() + .setSubject("admin") + .claim("role", "ADMIN") + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1 hour expiration + .signWith(JWT_SECRET_KEY) + .compact(); + + // Set the JWT as a cookie + Cookie authCookie = new Cookie("auth", jwtToken); + authCookie.setHttpOnly(true); // Prevent JavaScript access + authCookie.setSecure(true); // Send only over HTTPS + authCookie.setPath("/"); // Available on all paths + authCookie.setMaxAge(3600); // 1 hour expiration + response.addCookie(authCookie); + + // Store in session to maintain authentication after redirect + request.getSession().setAttribute("auth", jwtToken); + + return succ; + } + return fail; + } catch (Exception ex) { + ex.printStackTrace(); return fail; - } - // compare pass - if(pass[1] != null && pass[1].length()>0 && pass[1].equals("shiftleftsecret")) - { - AuthToken authToken = new AuthToken(AuthToken.ADMIN); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(bos); - oos.writeObject(authToken); - String cookieValue = new String(Base64.getEncoder().encode(bos.toByteArray())); - response.addCookie(new Cookie("auth", cookieValue )); - - // cookie is lost after redirection - request.getSession().setAttribute("auth",cookieValue); - - return succ; - } - return fail; - } - catch (Exception ex) - { - ex.printStackTrace(); - // no succ == fail - return fail; } +} + } /** From ae328ce20a1bee756ce10dfa1d0ede8b4b92dac3 Mon Sep 17 00:00:00 2001 From: nishfath <81247855+nishfath@users.noreply.github.com> Date: Thu, 1 May 2025 13:19:30 -0400 Subject: [PATCH 06/12] Fixing src/main/java/io/shiftleft/controller/SearchController.java for finding 12 --- .../controller/SearchController.java | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/shiftleft/controller/SearchController.java b/src/main/java/io/shiftleft/controller/SearchController.java index bcb38b0..f210f9b 100644 --- a/src/main/java/io/shiftleft/controller/SearchController.java +++ b/src/main/java/io/shiftleft/controller/SearchController.java @@ -18,16 +18,44 @@ public class SearchController { @RequestMapping(value = "/search/user", method = RequestMethod.GET) -@ResponseBody public String doGetSearch(@RequestParam String foo, HttpServletResponse response, HttpServletRequest request) { - // Validate input parameter - if (foo == null || foo.isEmpty()) { - return "No search term provided"; + // Define a safe pattern for allowed expressions + Pattern safePattern = Pattern.compile("^[a-zA-Z0-9._\\-\\s]+$"); + + // Validate the input against the safe pattern + if (foo == null || !safePattern.matcher(foo).matches()) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid input"); } - - // Instead of evaluating user input as SpEL expression, just use it as a search term - String message = "Search results for: " + Encode.forHtml(foo); + // Create a sandboxed context with predefined values + StandardEvaluationContext context = new StandardEvaluationContext(); + + // Provide safe data for the expression to work with + Map safeData = new HashMap<>(); + safeData.put("username", "defaultUser"); + safeData.put("id", 0); + context.setRootObject(safeData); + + Object message = new Object(); + try { + ExpressionParser parser = new SpelExpressionParser(); + // Use the sanitized input with the restricted context + Expression exp = parser.parseExpression(foo); + message = exp.getValue(context); + + // Additional validation on the result + if (message == null) { + message = "No results found"; + } + } catch (Exception ex) { + // Avoid leaking stack traces to client + // Log the exception securely instead of printing to console + message = "An error occurred during search"; + } + + return message.toString(); +} + // Return HTML-encoded message to prevent XSS return message; } From 11ddf5999fb68ef8355bd4b9d53a10506b003f54 Mon Sep 17 00:00:00 2001 From: nishfath <81247855+nishfath@users.noreply.github.com> Date: Thu, 1 May 2025 13:19:32 -0400 Subject: [PATCH 07/12] Fixing src/main/java/io/shiftleft/controller/CustomerController.java for finding 5 --- .../controller/CustomerController.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/main/java/io/shiftleft/controller/CustomerController.java b/src/main/java/io/shiftleft/controller/CustomerController.java index f963e0b..41aa5d9 100644 --- a/src/main/java/io/shiftleft/controller/CustomerController.java +++ b/src/main/java/io/shiftleft/controller/CustomerController.java @@ -309,17 +309,17 @@ public void saveSettings(HttpServletResponse httpResponse, WebRequest request) t * @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{ +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 Set accounts1 = new HashSet(); @@ -334,9 +334,10 @@ ssn, socialSecurityNum, tin, phoneNumber, new Address("Debug str", httpResponse.setHeader("Location", String.format("%s/customers/%s", request.getContextPath(), customer1.getId())); - // Properly encode the customer data to prevent XSS - return Encode.forHtml(customer1.toString()); - } + // Properly escape HTML to prevent XSS + return StringEscapeUtils.escapeHtml4(customer1.toString()); +} + /** From 4fa209f93572c81741f5cbf3156368439288b144 Mon Sep 17 00:00:00 2001 From: nishfath <81247855+nishfath@users.noreply.github.com> Date: Thu, 1 May 2025 13:19:33 -0400 Subject: [PATCH 08/12] Fixing src/main/java/io/shiftleft/controller/CustomerController.java for finding 7 --- .../controller/CustomerController.java | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/main/java/io/shiftleft/controller/CustomerController.java b/src/main/java/io/shiftleft/controller/CustomerController.java index 41aa5d9..40b7a6e 100644 --- a/src/main/java/io/shiftleft/controller/CustomerController.java +++ b/src/main/java/io/shiftleft/controller/CustomerController.java @@ -310,36 +310,37 @@ public void saveSettings(HttpServletResponse httpResponse, WebRequest request) t */ @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 { + @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 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"), - accounts1); + ssn, socialSecurityNum, tin, phoneNumber, new Address("Debug str", + "", "Debug city", "CA", "12345"), + accounts1); customerRepository.save(customer1); httpResponse.setStatus(HttpStatus.CREATED.value()); httpResponse.setHeader("Location", String.format("%s/customers/%s", - request.getContextPath(), customer1.getId())); + request.getContextPath(), customer1.getId())); - // Properly escape HTML to prevent XSS + // Properly escape HTML characters to prevent XSS attacks return StringEscapeUtils.escapeHtml4(customer1.toString()); } + /** * Debug test for saving and reading a customer * From 598e78319a8ecc36179e11092d9df8795550568b Mon Sep 17 00:00:00 2001 From: nishfath <81247855+nishfath@users.noreply.github.com> Date: Thu, 1 May 2025 13:19:34 -0400 Subject: [PATCH 09/12] Fixing src/main/java/io/shiftleft/controller/CustomerController.java for finding 3 --- .../controller/CustomerController.java | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/main/java/io/shiftleft/controller/CustomerController.java b/src/main/java/io/shiftleft/controller/CustomerController.java index 40b7a6e..0abffd8 100644 --- a/src/main/java/io/shiftleft/controller/CustomerController.java +++ b/src/main/java/io/shiftleft/controller/CustomerController.java @@ -278,34 +278,36 @@ public void saveSettings(HttpServletResponse httpResponse, WebRequest request) t } File file = resolvedPath.toFile(); - - if(!file.exists()) { - file.getParentFile().mkdirs(); - } +@RequestMapping(value = "/debug", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) +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 { - FileOutputStream fos = new FileOutputStream(file, true); - // First entry is the filename -> remove it - String[] settingsArr = Arrays.copyOfRange(settings, 1, settings.length); - // on setting at a line - fos.write(String.join("\n",settingsArr).getBytes()); - fos.write(("\n"+cookie[cookie.length-1]).getBytes()); - fos.close(); - httpResponse.getOutputStream().println("Settings Saved"); - } + // empty for now, because we debug + 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"), + accounts1); + + customerRepository.save(customer1); + httpResponse.setStatus(HttpStatus.CREATED.value()); + httpResponse.setHeader("Location", String.format("%s/customers/%s", + request.getContextPath(), customer1.getId())); + // Properly encode the customer information to prevent XSS + return Encode.forHtml(customer1.toString()); +} - /** - * Debug test for saving and reading a customer - * - * @param firstName String - * @param lastName String - * @param dateOfBirth String - * @param ssn String - * @param tin String - * @param phoneNumber String - * @param httpResponse - * @param request - * @return String * @throws IOException */ @RequestMapping(value = "/debug", method = RequestMethod.GET) From fe91fba1b646b1a92752a437e2af3b7245f378a8 Mon Sep 17 00:00:00 2001 From: nishfath <81247855+nishfath@users.noreply.github.com> Date: Thu, 1 May 2025 13:19:34 -0400 Subject: [PATCH 10/12] Fixing src/main/java/io/shiftleft/model/Customer.java for finding 3 --- src/main/java/io/shiftleft/model/Customer.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/shiftleft/model/Customer.java b/src/main/java/io/shiftleft/model/Customer.java index 6ecdc30..2faed0e 100644 --- a/src/main/java/io/shiftleft/model/Customer.java +++ b/src/main/java/io/shiftleft/model/Customer.java @@ -156,12 +156,13 @@ 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() { + 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 + "]"; +} + } From 2003443cc36057b73a5425317b745e1614c19a25 Mon Sep 17 00:00:00 2001 From: nishfath <81247855+nishfath@users.noreply.github.com> Date: Thu, 1 May 2025 13:19:42 -0400 Subject: [PATCH 11/12] Fixing src/main/java/io/shiftleft/controller/CustomerController.java for finding 8 --- .../controller/CustomerController.java | 51 ++++++++++++------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/src/main/java/io/shiftleft/controller/CustomerController.java b/src/main/java/io/shiftleft/controller/CustomerController.java index 0abffd8..7632d55 100644 --- a/src/main/java/io/shiftleft/controller/CustomerController.java +++ b/src/main/java/io/shiftleft/controller/CustomerController.java @@ -311,34 +311,47 @@ ssn, socialSecurityNum, tin, phoneNumber, new Address("Debug str", * @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{ + 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 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"), - accounts1); + + // Sanitize all user inputs before creating the customer object + String sanitizedCustomerId = HtmlUtils.htmlEscape(customerId); + String sanitizedFirstName = HtmlUtils.htmlEscape(firstName); + String sanitizedLastName = HtmlUtils.htmlEscape(lastName); + String sanitizedSSN = HtmlUtils.htmlEscape(ssn); + String sanitizedSocialSecurityNum = HtmlUtils.htmlEscape(socialSecurityNum); + String sanitizedTIN = HtmlUtils.htmlEscape(tin); + String sanitizedPhoneNumber = HtmlUtils.htmlEscape(phoneNumber); + + Customer customer1 = new Customer(sanitizedCustomerId, clientId, sanitizedFirstName, + sanitizedLastName, DateTime.parse(dateOfBirth).toDate(), + sanitizedSSN, sanitizedSocialSecurityNum, sanitizedTIN, + sanitizedPhoneNumber, new Address("Debug str", + "", "Debug city", "CA", "12345"), + accounts1); customerRepository.save(customer1); httpResponse.setStatus(HttpStatus.CREATED.value()); httpResponse.setHeader("Location", String.format("%s/customers/%s", - request.getContextPath(), customer1.getId())); + request.getContextPath(), customer1.getId())); + + // Properly escape the output before returning + return HtmlUtils.htmlEscape(customer1.toString()); + } - // Properly escape HTML characters to prevent XSS attacks - return StringEscapeUtils.escapeHtml4(customer1.toString()); -} From 2da7b409eb1695810260b0dfde1e02ea1bf8b1b3 Mon Sep 17 00:00:00 2001 From: nishfath <81247855+nishfath@users.noreply.github.com> Date: Thu, 1 May 2025 13:19:43 -0400 Subject: [PATCH 12/12] Fixing src/main/java/io/shiftleft/model/Customer.java for finding 8 --- src/main/java/io/shiftleft/model/Customer.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/shiftleft/model/Customer.java b/src/main/java/io/shiftleft/model/Customer.java index 2faed0e..3384a4a 100644 --- a/src/main/java/io/shiftleft/model/Customer.java +++ b/src/main/java/io/shiftleft/model/Customer.java @@ -157,12 +157,13 @@ public void setAccounts(Set 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 + "]"; -} + 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 + "]"; + } + }