I have following url to call my application:
http://machine.domain.com:8383/eqube70/BuildNPlay
This works great and it calles index.jsp as per my expectations.
But if my request url is changed as:
http://machine.domain.com:8383/eqube70/BuildNPlay/?--%3E%3C/script%3E%3Cscript%3Ealert('you got hacked')%3C/script%3E
Then I get the alert and I am not able to get my application working.
This is because through request URI some request params are passed.
In order to remove this I wrote requiest wrapper to scan param values.
If param value contain character such as <, > then I am replacing them with <, > respectively.
Now this works great if my request param values. But if newly passed request param names contain any of these chars then I am getting alert.
I want some way to scan request param names and remove/modify or skip the param names with malicious chars.
Is there anything I can do to achieve this?
Following is my code which I wrote so far.
public class eQIndexServlet implements Filter
{
static class RequestWrapper extends HttpServletRequestWrapper
{
char[] ESCAPECHARS = { '&', '<', '>'};
public RequestWrapper(ServletRequest request)
{
super((HttpServletRequest)request);
}
public String getParameter(String paramName)
{
//if(paramName.contains(ESCAPECHARS))
String value = super.getParameter(paramName);
value = eQUtil.escapeHtmlCharArray(value, ESCAPECHARS);
return value;
}
public String[] getParameterValues(String paramName)
{
String values[] = super.getParameterValues(paramName);
for(int i=0; i<values.length; i++)
{
values[i] = eQUtil.escapeHtmlCharArray(values[i], ESCAPECHARS);
}
return values;
}
}
After adding following code in getparameter method it worked
if(paramName.contains(">") || paramName.contains("<"))
return null;
it seems that if value is null then chain.doFilter ignores the paramter.
Related
I have my application.properties:
test.md5.params=something1,something4
In my java class I am getting this particular value :
and need to create same strings as present in the property file, such as
public String calculate(RequestClass request)
{
List<String> params= //I am getting the values from application.prop
**(above part id done)**
My Question is below ::
now in my params list I have [something1,something4]
so I need to concatenate both the String values like below:
String finalString=request.getSomething1()+request.getSomething4();
return finalString;
}
My Question is how to do this dynamically and in my properties file I might receive "n" of something values.
Note : I need to make the code such that my class remains constant, if in future I am adding 10 more values in properties files, my final string should be returning like
String finalString=request.getSomething1()+request.getSomething4()+....all the values.;
Through reflection this is possible, below is one implementation.
public String calculate(RequestClass request) throws InvocationTargetException, IllegalAccessException {
List<String> params = Arrays.asList("something1", "something4");
// Do your logic to get the method Names from params, below is an simple example - paramsUpdated
List<String> paramsUpdated = Arrays.asList("getSomething1", "getSomething4");
// Reflection to get the methods of request class
Method[] methods = request.getClass().getMethods();
StringBuilder sb = new StringBuilder();
for (String param : paramsUpdated) {
for (Method method : methods) {
if (param.equals(method.getName())) {
sb.append(method.invoke(request));
}
}
}
return sb.toString();
}
Since
public static String requestMethodExecution(String objectName, String className, String methodName, Object...
params) {
return String.format("%s,%s,%s,%s", objectName, className, methodName, Arrays.toString(params));
}
returns a String, and if you would, for example, call the method like this:
requestMethodExecution("foo","bar","fooBar",2.0,3.0,"Hello");
You'd get a String like this: foo,bar,fooBar,[2.0,3.0,Hello]
I would love to iterate over that Array, but I can't since it is a String.
Reason behind this is this method: (I just started with reflection, so I do not know how else to do it)
public static Class[] getParameterType(String ...params) throws ClassNotFoundException {
Class[] paramTypes = new Class[params.length];
for(int i=0; i<params.length;i++){
Class paramClass = Class.forName(params[i]);
if (paramClass == Double.class) {
paramTypes[i] = (double.class);
} else if (paramClass == Integer.class) {
paramTypes[i] = (int.class);
} else {
paramTypes[i] = paramClass;
}
}
return paramTypes;
}
So far I have only come up with a very dirty way:
public static String[] getParams(String message){
int indexOfParamStart = message.indexOf("[");
int indexOfParamEnd = message.indexOf("]")+1;
String[] splitMessage = message.substring(indexOfParamStart, indexOfParamEnd).replaceAll("\\[", "")
.replaceAll("]", "").replaceAll(" ","").split(",");
return splitMessage;
}
Edit: Thanks for looking into this! Since some of you are asking what I am trying to achieve, here is a bit more explanation:
I want to implement a simple request/reply protocol which allows remote method invocation (and I do not want to use java RMI...)
So I listen for requests whose structure can be seen at the requestMethodExecution example.
There I have all the relevant information to call the Method upon my class, so to invoke the method I need it's arguments (and their value) and I do not know how to access them from the given String.
The others are easy with Class c = Class.forName(className); etc..
Edit#2:
My question is not about a simple regex, so why close it? The title already states a different subject, I am getting a bit salty here...
See this this question for using RegEx to extract the array body from the outer string (by the square brackets), and then you can simply use String.split(",") to split the array body into array items.
I do have to write a unit test case for a method which returns a URL,
I've to verify all the values of the parameters in the URL, is there any API or better way to work around this..
Any suggestions would be appreciated.
Java Method:
class Sample{
public String returnURL(){
return "http://localhost:9080/sample?a=12-a&b=param2&c=param3&d=param_4&e=param5"
}
}
Junit:
#Test
public void returnURLTest(){
String url = new Sample().returnURL()
// Parse the url
assert url['a'] == "param1"
assert url['b'] == "param2"
}
Thanks
If you use AssertJ, you can create the URI (or URL) object and use the assertions on it, as shown in those examples: https://github.com/joel-costigliola/assertj-examples/blob/master/assertions-examples/src/test/java/org/assertj/examples/UriAssertionsExamples.java
assertThat(new URI("http://www.helloworld.org/index.html?happy=very")).hasParameter("happy", "very");
You'll just have to parse the URL and compare the individual pieces you pull out.
Something like:
int indexOfNextParameter = url.indexOf("=");
List<String> parameters = new ArrayList<>();
while(youAreParsingTheURL){
int indexOfParameter = url.indexOf("=", indexOfNextParameter);
String parameter = url.substring("=", indexOfParameter);
parameters.add(parameter);
}
Then just go through that parameters List and validate each item.
These two urls should be the same:
http://localhost?asdf=1&qwer=2
http://localhost?qwer=2&asdf=1
But using 'equals()' from the URL class, I get that they're different. How can I compare them?
EDIT: Some background on this question
I'm creating a Selenium test for some url mapping. I have old url, url it should get mapped to and the actual url. I need to compare the should-be url to the actual url. List of urls is created by client. Urls with the same parameters and values are considered valid if the list of parameters is the same, and they all have the right values (order of those parameters is irrelevant)
So if I get it right, you want to compare two URL's, regardless of the order of the query part.
There does not seem to be a method for this in the URL class, so you'll have to write your own.
Also, URL is final, you cannot override URL.equals(Object).
Your method could start with calling sameFile().
If that evaluates to true, you then call getQuery(), and split it into it's components - probably with String.split("\&"). From there on, you evaluate if the parameters are the same.
Also, don't forget to check if the "#fragment" is equal, if that is important to your application.
I don't think you're going to like it, but you could do something like
URL url = new URL("http://localhost?asdf=1&qwer=2");
URL url2 = new URL("http://localhost?qwer=2&asdf=1");
System.out.println(isEqual(url, url2));
public static boolean isEqual(URL url1, URL url2) {
boolean isEqual = url1.getAuthority().equals(url2.getAuthority()) &&
url1.getPort() == url2.getPort() &&
url1.getHost().equals(url2.getHost()) &&
url1.getProtocol().equals(url2.getProtocol());
if (isEqual) {
String query1 = url1.getQuery();
String query2 = url2.getQuery();
if (query1 != null && query2 != null) {
if (query1.length() == query2.length()) {
List<String> list1 = getParameters(query1);
List<String> list2 = getParameters(query2);
for (int index = 0; index < list1.size(); index++) {
String value1 = list1.get(index);
String value2 = list2.get(index);
if (!value1.equals(value2)) {
isEqual = false;
break;
}
}
} else {
isEqual = false;
}
} else {
isEqual = false;
}
}
return isEqual;
}
protected static List<String> getParameters(String value) {
List<String> parameters = new ArrayList<String>(25);
String[] values = value.split("&");
for (String par : values) {
if (!par.contains("=")) {
par += "=null";
}
parameters.add(par);
}
Collections.sort(parameters);
return parameters;
}
URL/URI equals method is broken. At least it doesn't provide results as you would expect.
There are a lot of weird things with it. You might be interested to read
Mr. Gosling – why did you make URL equals suck?!?
or maybe
How to compare two URLs in java?
So, don't expect it would be easy.
You can create your custom comparator for your particular case but in general you might have to parse the url string.
Hope this helps
You can accomplish this with functionality available in the String class.
This approach splits the URLs into two parts, the one before the "?" and the one after (it's fine if no "?" or parameters are present). If the URLs before the "?" are equivalent, the two are "equal" for our purposes.
public boolean urlsMatchWithoutQueryParameters(String firstUrl, secondUrl) {
// Get the portion of the URLs before the "?", and before all parameters.
String firstUrlWithoutParameters = firstUrl.split("\\?", 2)[0];
String secondUrlWithoutParameters = secondUrl.split("\\?", 2)[0];
return firstUrlWithoutParameters.equals(secondUrlWithoutParameters);
}
The code is a little crowded, so you could do something pull out the String logic into a helper like so:
public boolean urlsMatchWithoutQueryParameters(String firstUrl, secondUrl) {
return getUrlWithoutParameters(firstUrl).equals(getUrlWithoutParameters(secondUrl));
}
public String getUrlWithoutParameters(String url) {
// Get the portion of the URL before the "?", and before all parameters.
return url.split("\\?", 2)[0];
}
Note: This ignores URL anchors (e.g., #photos in the url www.example.com/profiles/user123#friends).
To for anchors, simply replace "\\?" with "#" in split("\\?", 2).
I like this question so I wrote this little demo. (Sorry, I used the StringUtils class for the substrings)
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang.StringUtils;
public class URLDemo
{
/**
* #param args
* #throws MalformedURLException
*/
public static void main(String[] args)
throws MalformedURLException
{
String url1 = "http://localhost?asdf=1&qwer=2";
String url2 = "http://localhost?qwer=2&asdf=1";
URL url11 = new URL(StringUtils.substringBefore(url1, "?"));
URL url22 = new URL(StringUtils.substringBefore(url2, "?"));
if (url11.equals(url22))
{
// url are equal but still need to check the parameters
List<String> params1 = Arrays.asList(StringUtils.split(StringUtils.substringAfter(url1, "?"), "&"));
List<String> params2 = Arrays.asList(StringUtils.split(StringUtils.substringAfter(url2, "?"), "&"));
// need to check both ways
if (params1.containsAll(params2) && params2.containsAll(params1))
{
System.out.println("URLs are the same");
}
else
{
System.out.println("URLs are different");
}
}
}
}
Well these two url are infact different
http://localhost?asdf=1&qwer=2
http://localhost?qwer=2&asdf=1
//////// EDITED PART //////////
Try this....
- Use openStream() on both the url.
- Save both of them as 2 String Objects, or StringBuilder instead.
- Now compare both of them using equals().
- This will solve the problem, i think so....
I have Spring MVC URL's define in Interfaces (just to hold the Constants) like:
String URL_X = "/my-url/{id:[0-9]*}";
String URL_Y = "/my-url/{id:[0-9]*}/blah-blah";
I have a method for my tests that replace the variables in an URL:
private static final String REGEX_PARAMETROS_DA_URL = "(\\{[^\\}]*\\})";
protected String replaceParametersOnURL(String urlSpring, String... params) {
String urlAtual = urlSpring;
for (String parametro : params) {
urlAtual = urlAtual.replaceFirst(REGEX_PARAMETROS_DA_URL, parametro);
}
return urlAtual;
}
I was using this regex: (\{[^\}]*\}) to match the variables and replace it.
But now i have some URL's that have {} on it and i can't find a properly regex to replace the variable with my value.
Is there any method on Spring that replaces the PathVariable value or can anyone help me with this regex?
Given this URL for instance:
/pessoajuridica/{cnpj:[0-9]{14}}-{slug:[a-zA-Z0-9-]+}/sancoes/resumo
The matches must be: {cnpj:[0-9]{14}}and {slug:[a-zA-Z0-9-]+}
Thanks #Matthew. I haven't noticed that the spring test itself can do this!
All i need to do is:
mockMvc.perform(get("/pessoajuridica/{cnpj:[0-9]{14}}-{slug:[a-zA-Z0-9-]+}/sancoes/resumo", var1, var2)) ...