diff --git a/src/main/java/io/shiftleft/controller/AdminController.java b/src/main/java/io/shiftleft/controller/AdminController.java index 296c26573..ef55c1a97 100644 --- a/src/main/java/io/shiftleft/controller/AdminController.java +++ b/src/main/java/io/shiftleft/controller/AdminController.java @@ -7,19 +7,21 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Base64; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.core.io.ClassPathResource; -import org.springframework.stereotype.Controller; import org.springframework.util.FileCopyUtils; import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; - /** * Admin checks login */ @@ -31,7 +33,10 @@ public class AdminController { private boolean isAdmin(String auth) { try { - ByteArrayInputStream bis = new ByteArrayInputStream(Base64.getDecoder().decode(auth)); + String hmac = auth.split("\\|")[0]; + String base64 = auth.split("\\|")[1]; + String data = hmacBase64Decode(base64, "shiftleftsecretkey"); + ByteArrayInputStream bis = new ByteArrayInputStream(Base64.getDecoder().decode(data)); ObjectInputStream objectInputStream = new ObjectInputStream(bis); Object authToken = objectInputStream.readObject(); return ((AuthToken) authToken).isAdmin(); @@ -106,8 +111,13 @@ public String doPostLogin(@CookieValue(value = "auth", defaultValue = "notset") 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 )); + String data = Base64.getEncoder().encodeToString(bos.toByteArray()); + String hmac = hmacBase64Encode(data, "shiftleftsecretkey"); + String cookieValue = hmac + "|" + data; + Cookie cookie = new Cookie("auth", cookieValue); + cookie.setHttpOnly(true); + cookie.setSecure(true); + response.addCookie(cookie); // cookie is lost after redirection request.getSession().setAttribute("auth",cookieValue); @@ -134,4 +144,30 @@ public String doPostLogin(@CookieValue(value = "auth", defaultValue = "notset") public String doGetLogin(HttpServletResponse response, HttpServletRequest request) { return "redirect:/"; } + + private String hmacBase64Encode(String data, String key) { + try { + Mac mac = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "HmacSHA256"); + mac.init(secretKeySpec); + byte[] hmac = mac.doFinal(data.getBytes()); + return Base64.getEncoder().encodeToString(hmac); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + private String hmacBase64Decode(String hmac, String key) { + try { + Mac mac = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "HmacSHA256"); + mac.init(secretKeySpec); + byte[] hmacBytes = Base64.getDecoder().decode(hmac); + byte[] dataBytes = new byte[mac.getMacLength()]; + mac.doFinal(hmacBytes, 0, hmacBytes.length, dataBytes, 0); + return new String(Base64.getDecoder().decode(new String(dataBytes))); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } } diff --git a/src/main/java/io/shiftleft/controller/AppErrorController.java b/src/main/java/io/shiftleft/controller/AppErrorController.java index 68f4d669f..1468a5cbf 100644 --- a/src/main/java/io/shiftleft/controller/AppErrorController.java +++ b/src/main/java/io/shiftleft/controller/AppErrorController.java @@ -6,6 +6,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes; @@ -38,9 +39,8 @@ public AppErrorController(ErrorAttributes errorAttributes) { /** * Supports the HTML Error View * @param request - * @return */ - @RequestMapping(value = ERROR_PATH, produces = "text/html") + @RequestMapping(value = ERROR_PATH, method = RequestMethod.GET, produces = "text/html") public ModelAndView errorHtml(HttpServletRequest request) { return new ModelAndView("/errors/error", getErrorAttributes(request, false)); } @@ -48,9 +48,8 @@ public ModelAndView errorHtml(HttpServletRequest request) { /** * Supports other formats like JSON, XML * @param request - * @return */ - @RequestMapping(value = ERROR_PATH) + @RequestMapping(value = ERROR_PATH, method = RequestMethod.GET) @ResponseBody public ResponseEntity> error(HttpServletRequest request) { Map body = getErrorAttributes(request, getTraceParameter(request)); @@ -78,7 +77,7 @@ private boolean getTraceParameter(HttpServletRequest request) { } private Map getErrorAttributes(HttpServletRequest request, - boolean includeStackTrace) { + boolean includeStackTrace) { RequestAttributes requestAttributes = new ServletRequestAttributes(request); Map m = this.errorAttributes.getErrorAttributes(requestAttributes, includeStackTrace); @@ -102,4 +101,4 @@ private HttpStatus getStatus(HttpServletRequest request) { } return HttpStatus.INTERNAL_SERVER_ERROR; } -} \ No newline at end of file +} diff --git a/src/main/java/io/shiftleft/controller/SearchController.java b/src/main/java/io/shiftleft/controller/SearchController.java index faa409760..f98ac3bc0 100644 --- a/src/main/java/io/shiftleft/controller/SearchController.java +++ b/src/main/java/io/shiftleft/controller/SearchController.java @@ -10,7 +10,6 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; - /** * Search login */ @@ -20,12 +19,22 @@ 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()); + String whitelist = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + boolean isValid = true; + for (char c : foo.toCharArray()) { + if (whitelist.indexOf(c) == -1) { + isValid = false; + break; + } + } + if (isValid) { + try { + ExpressionParser parser = new SpelExpressionParser(); + Expression exp = parser.parseExpression(foo); + message = (Object) exp.getValue(); + } catch (Exception ex) { + System.out.println(ex.getMessage()); + } } return message.toString(); } diff --git a/src/main/resources/config/application-aws.properties b/src/main/resources/config/application-aws.properties index 6467531bd..1b7bdf374 100644 --- a/src/main/resources/config/application-aws.properties +++ b/src/main/resources/config/application-aws.properties @@ -1,3 +1,7 @@ -aws.accesskey=AKIAILQI6VLJU3HSCEQQ -aws.secretkey=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY -aws.bucket=mysaas/customerid/account/date \ No newline at end of file +aws.bucket=mysaas/customerid/account/date +``` + +Add environment variables: +``` +AWS_ACCESS_KEY_ID=AKIAILQI6VLJU3HSCEQQ +AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY