-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29 from US-ELRR/elrr-improve-request-validation
Add try/catch, enhance error nmessages.
- Loading branch information
Showing
12 changed files
with
263 additions
and
274 deletions.
There are no files selected for viewing
22 changes: 7 additions & 15 deletions
22
src/main/java/com/deloitte/elrr/elrraggregator/exception/ResourceNotFoundException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,20 @@ | ||
/** | ||
* | ||
*/ | ||
package com.deloitte.elrr.elrraggregator.exception; | ||
|
||
import org.springframework.http.HttpStatus; | ||
import org.springframework.web.bind.annotation.ResponseStatus; | ||
|
||
/** | ||
* @author mnelakurti | ||
* | ||
*/ | ||
@ResponseStatus(value = HttpStatus.NOT_FOUND) | ||
public class ResourceNotFoundException extends Exception { | ||
|
||
/** | ||
* | ||
*/ | ||
private static final long serialVersionUID = 1L; | ||
private static final long serialVersionUID = 1L; | ||
|
||
/** | ||
* | ||
* @param message | ||
*/ | ||
public ResourceNotFoundException(final String message) { | ||
super(message); | ||
} | ||
/** | ||
* @param message | ||
*/ | ||
public ResourceNotFoundException(final String message) { | ||
super(message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
194 changes: 110 additions & 84 deletions
194
src/main/java/com/deloitte/elrr/elrrconsolidate/SanatizingFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,97 +1,123 @@ | ||
package com.deloitte.elrr.elrrconsolidate; | ||
|
||
import fr.spacefox.confusablehomoglyphs.Confusables; | ||
import jakarta.servlet.*; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.extern.slf4j.Slf4j; | ||
import java.io.IOException; | ||
import java.util.Iterator; | ||
|
||
import org.json.JSONException; | ||
import org.json.JSONObject; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.util.StringUtils; | ||
|
||
import java.io.IOException; | ||
import java.util.Iterator; | ||
|
||
import fr.spacefox.confusablehomoglyphs.Confusables; | ||
import jakarta.servlet.Filter; | ||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.ServletRequest; | ||
import jakarta.servlet.ServletResponse; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@Component | ||
@Slf4j | ||
public class SanatizingFilter implements Filter { | ||
|
||
|
||
private boolean invalidParam; | ||
|
||
@Override | ||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | ||
throws IOException, ServletException { | ||
|
||
HttpServletResponse httpResponse = (HttpServletResponse) response; | ||
WrappedHttp httpRequest; | ||
invalidParam = false; | ||
|
||
StringBuilder body = new StringBuilder(); | ||
for(String line : request.getReader().lines().toList()) { | ||
if(InputSanatizer.isValidInput(line)) { | ||
body.append(line); | ||
body.append('\n'); | ||
|
||
} | ||
else { | ||
log.error("Illegal line in request body: " + line); | ||
httpResponse.sendError(HttpStatus.BAD_REQUEST.value(), "Illegal line in request body: " + line); | ||
} | ||
} | ||
if(httpResponse.isCommitted()) | ||
return; | ||
|
||
|
||
httpRequest = new WrappedHttp((HttpServletRequest) request, body.toString()); | ||
httpRequest.getParameterMap(); //might help to cache parameters for future filter chain | ||
|
||
//below we check each parameter string for any invalid values | ||
httpRequest.getParameterNames().asIterator().forEachRemaining((param) -> { | ||
String paramVal = request.getParameter(param); | ||
if(!InputSanatizer.isValidInput(paramVal)) { | ||
invalidParam = true; | ||
} | ||
}); | ||
|
||
if(invalidParam) { | ||
log.error("Illegal Parameter Value"); | ||
httpResponse.sendError(HttpStatus.BAD_REQUEST.value(), "Illegal Parameter Value"); | ||
return; | ||
} | ||
|
||
if (hasHomoGlyphs(httpRequest)) | ||
{ | ||
log.error("Request body contains homoglyphs."); | ||
httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, "Request body contains homoglyphs."); | ||
return; | ||
} | ||
|
||
chain.doFilter(httpRequest, response); | ||
} | ||
|
||
private static boolean hasHomoGlyphs(WrappedHttp httpRequest) { | ||
if(!StringUtils.hasLength(httpRequest.getBody())) | ||
{ | ||
return false; | ||
} | ||
Confusables confusables = Confusables.fromInternal(); | ||
JSONObject jsonObject = new JSONObject(httpRequest.getBody()); | ||
Iterator keys = jsonObject.keys(); | ||
while (keys.hasNext()) { | ||
String key = (String) keys.next(); | ||
String value = (String) jsonObject.get(key); | ||
boolean dangerousKey = confusables.isDangerous(key); | ||
boolean dangerousValue = confusables.isDangerous(value); | ||
if (dangerousKey || dangerousValue) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
} | ||
private boolean invalidParam; | ||
|
||
@Override | ||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | ||
throws IOException, ServletException { | ||
HttpServletResponse httpResponse = (HttpServletResponse) response; | ||
WrappedHttp httpRequest; | ||
invalidParam = false; | ||
|
||
StringBuilder body = new StringBuilder(); | ||
try { | ||
for (String line : request.getReader().lines().toList()) { | ||
if (InputSanatizer.isValidInput(line)) { | ||
body.append(line); | ||
body.append('\n'); | ||
|
||
} else { | ||
// need to log bad request. Might be best to continue processing | ||
// and report all bad lines. / complete body | ||
httpResponse.sendError( | ||
HttpStatus.BAD_REQUEST.value(), "Illegal line in request body: " + line); | ||
} | ||
} | ||
} catch (IOException | IllegalStateException e) { | ||
log.error("Error: " + e.getMessage()); | ||
e.printStackTrace(); | ||
return; | ||
} | ||
|
||
if (httpResponse.isCommitted()) return; | ||
|
||
httpRequest = new WrappedHttp((HttpServletRequest) request, body.toString()); | ||
httpRequest.getParameterMap(); // might help to cache parameters for | ||
// future filter chain | ||
|
||
// Check each parameter string for any invalid values | ||
httpRequest | ||
.getParameterNames() | ||
.asIterator() | ||
.forEachRemaining( | ||
(param) -> { | ||
String paramVal = request.getParameter(param); | ||
if (!InputSanatizer.isValidInput(paramVal)) { | ||
invalidParam = true; | ||
log.error("Illegal Parameter Value " + paramVal); | ||
} | ||
}); | ||
|
||
if (invalidParam) { | ||
try { | ||
httpResponse.sendError(HttpStatus.BAD_REQUEST.value(), "Illegal Parameter Value"); | ||
return; | ||
} catch (IOException e) { | ||
log.error("Error: " + e.getMessage()); | ||
e.printStackTrace(); | ||
return; | ||
} | ||
} | ||
|
||
if (hasHomoGlyphs(httpRequest)) { | ||
try { | ||
log.error("Request body contains homoglyphs."); | ||
httpResponse.sendError( | ||
HttpServletResponse.SC_BAD_REQUEST, "Request body contains homoglyphs."); | ||
return; | ||
} catch (IOException | JSONException e) { | ||
log.error("Error: " + e.getMessage()); | ||
e.printStackTrace(); | ||
return; | ||
} | ||
} | ||
|
||
try { | ||
chain.doFilter(httpRequest, response); | ||
} catch (IOException | ServletException e) { | ||
log.error("Error: " + e.getMessage()); | ||
e.printStackTrace(); | ||
return; | ||
} | ||
} | ||
|
||
private static boolean hasHomoGlyphs(WrappedHttp httpRequest) { | ||
|
||
if (httpRequest.getBody().isEmpty()) return false; | ||
Confusables confusables = Confusables.fromInternal(); | ||
JSONObject jsonObject = new JSONObject(httpRequest.getBody()); | ||
Iterator<String> keys = jsonObject.keys(); | ||
while (keys.hasNext()) { | ||
String key = keys.next(); | ||
String value = (String) jsonObject.get(key); | ||
boolean dangerousKey = confusables.isDangerous(key); | ||
boolean dangerousValue = confusables.isDangerous(value); | ||
if (dangerousKey || dangerousValue) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.