Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 77 additions & 43 deletions src/main/java/io/shiftleft/controller/AdminController.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,34 @@ public class AdminController {
private String fail = "redirect:/";

// helper
private boolean isAdmin(String auth)
{
private boolean isAdmin(String auth) {
try {
ByteArrayInputStream bis = new ByteArrayInputStream(Base64.getDecoder().decode(auth));
ObjectInputStream objectInputStream = new ObjectInputStream(bis);
Object authToken = objectInputStream.readObject();
return ((AuthToken) authToken).isAdmin();
// Use JWT tokens instead of serialized objects to prevent deserialization attacks
// Parse and validate the JWT token
Claims claims = Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(auth)
.getBody();

// Verify the token hasn't expired
if (claims.getExpiration().before(new Date())) {
return false;
}

// Check if the role claim indicates admin privileges
String role = claims.get("role", String.class);
return "ADMIN".equals(role);

} catch (JwtException ex) {
System.out.println("Invalid JWT token: " + ex.getMessage());
return false;
} catch (Exception ex) {
System.out.println(" cookie cannot be deserialized: "+ex.getMessage());
return false;
System.out.println("Error validating token: " + ex.getMessage());
return false;
}
}

}

//
Expand Down Expand Up @@ -81,47 +98,64 @@ 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";

try {
// no cookie no fun
if (!auth.equals("notset")) {
if(isAdmin(auth)) {
request.getSession().setAttribute("auth",auth);
return succ;
// Check if valid auth token already exists
if (!auth.equals("notset")) {
if(isAdmin(auth)) {
request.getSession().setAttribute("auth", auth);
return succ;
}
}

// Validate password input format
String[] pass = password.split("=");
if(pass.length != 2) {
return fail;
}

// Verify password with constant-time comparison to prevent timing attacks
if(pass[1] != null && pass[1].length() > 0 &&
MessageDigest.isEqual(pass[1].getBytes(StandardCharsets.UTF_8),
"shiftleftsecret".getBytes(StandardCharsets.UTF_8))) {

// Generate JWT token instead of serializing objects
String jwtToken = Jwts.builder()
.setSubject("admin")
.claim("role", "ADMIN")
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1 hour expiration
.signWith(getSigningKey(), SignatureAlgorithm.HS256)
.compact();

// Set secure cookie attributes
Cookie authCookie = new Cookie("auth", jwtToken);
authCookie.setHttpOnly(true); // Prevent XSS attacks
authCookie.setSecure(true); // Only transmit over HTTPS
authCookie.setPath("/");
authCookie.setMaxAge(3600); // 1 hour
response.addCookie(authCookie);

// Store token in session
request.getSession().setAttribute("auth", jwtToken);

return succ;
}
}

// split password=value
String[] pass = password.split("=");
if(pass.length!=2) {
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;
catch (Exception ex) {
// Log error securely without exposing sensitive information
System.err.println("Authentication error occurred");
return fail;
}
}

}

/**
Expand Down
Loading