I'm doing a file upload with Jersey, but I need only the filename. Internet Explorer sends the entire path, and based on what's in FormDataContentDisposition, Jersey parses out the slashes, so I can't even parse that. Thanks.
Sounds like a difficult issue. The ideal case of course is to grab the string containing the slashes and just use string.split!
Failing that, the only strategy i can begin to think of is to try iterating through the string seeing if folders exist for various lengths of the first part of the string etc. This can cause problems too though if you intend to find a folder "MyFolder (2)" and theres also a "MyFolder". I don't know alot about jersey but i would recommend trying to find a different way to grab the string you need.
Add a change event to the file input tag
Parse out the filename as it still has slashes at this point
Stick that value into a hidden input
That hidden input then gets submitted along with the rest of the form.
#kombat has found this solution and posted it as a comment. For better this is now reposted as a community wiki answer.
It is a bug in Jersey. In Nabble discussion http://jersey.576304.n2.nabble.com/Jersey-truncating-the-slashes-from-the-uploaded-file-name-td5984041.html the author of the bug reveals himself and acknowledges 'reusing the code' for parsing HTTP Headers to parse Content-Disposition. However, the cited RFC 2616 does not specify, that Content-Disposition fields are to be escaped according to the rules specified to HTTP headers. Just the opposite, there is written that:
Content-Disposition is not part of the HTTP standard, but since it
is widely implemented, we are documenting its use and risks for
implementors.
This bug has already an ugly workaround in the class org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide in actual version of Jersey, however it doesn't work with IE 11 and Edge because it checks User-Agent part which has changed. There is a pull request with fix: https://github.com/jersey/jersey/pull/233/files, but for almost 2 years nobody has cared to merge it.
You have 3 solutions:
1) Aplly a 'fix' on client side, which is IMHO a wrong approach, because there is no bug on client side, the bug is in Jersey!
2) Change Jersey to other framework, in which the developers take the compatibility issues more seriously instead of concentrating on maximizing code reuse etc.
3) Patch Jersey manually. Download the sources, apply pull request, compile and release with modified version number.
I was getting that error when I tried the Eclipse browser. When I tried my code on Chrome, the FormDataContentDisposition.getFileName() was fine.
Related
I'm working in a very bing and old software that works with servlets and includes accents and other strange characters in the URL. The software was upgraded from JDK7 to JDK11 a few weeks ago and the server was upgraded from Tomcat6 to Tomcat9.
I've tried:
- Using URLEncoder in the java part and encodeURI in the javascript part and it works fine, but there are hundreds of places that need this change and it's complicated because it's easy to make a mistake.
- Use the encodeURI in the server.xml of Tomcat but it doesn't change anything. And I've added the relaxedQueryChars tag, but it doesn't accept accents.
- The last thing that I've tried is to add a filter, to try to encode the params of the request, in the web.xml but it doesn't work when the error appears and there's no option to change the order. And another problem is that the ServletRequest has no setParameter so if I can solve the order filter problem I have this one...
I'm getting this error:
Estado HTTP 400 – Bad Request
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
The code worked perfectly in Tomcat6 but with the upgrade we get this problem. I'm trying to get a server config solution to avoid using code encoding but I don't know what more can I try...
Thank you!
Finally we decided to install Tomcat8 instead of 9 because the codification change was introduced in Tomcat8.5.
It's a workaround and it doesn't solve the real codification problem. But, actually, it's risky to try to use the encode function in every part of the code because it may generate other kind of problems.
Currently my java code uses
response.sendRedirect(request.getRequestUrl().toString());
Which is an open redirect.
I have to fix this but I can not white list it since there are too many URL's are associated with it.
I have tried the following solution with ESAPI but it wont work for me.
ESAPI.httpUtilities().setCurrentHTTP(req, resp);
ESAPI.httpUtilities().sendRedirect(location);
ESAPI.httpUtilities().clearCurrent();
I am new to ESAPI.
[Disclaimer]
I'm project co-lead on ESAPI.
I have to fix this but I can not white list it since there are too
many URL's are associated with it.
Essentially, "I have to fix the problem, but I am restricting myself from the easiest solution."
Here are the best practices enumerated by #jww:
Simply avoid using redirects and forwards.
If used, do not allow the url as user input for the destination. This can usually be done. In this case, you should have a method to validate URL.
If user input can’t be avoided, ensure that the supplied value is valid, appropriate for the application, and is authorized for the user.
It is recommended that any such destination input be mapped to a value, rather than the actual URL or portion of the URL, and that server side code translate this value to the target URL.
Sanitize input by creating a list of trusted URL's (lists of hosts or a regex).
Force all redirects to first go through a page notifying users that they are going off of your site, and have them click a link to confirm.
These are literally all the solutions available to you. Some web frameworks make this easy for you, like Spring MVC with Spring Security.
These lines:
ESAPI.httpUtilities().setCurrentHTTP(req, resp);
ESAPI.httpUtilities().sendRedirect(location);
ESAPI.httpUtilities().clearCurrent();
Don't work because you have to inspect the user input before performing the redirect.
You definitely are going to want to white-list this, at least at a minimum, based on domain names. Restrict it as much as possible. E.g., if your app is hosted at https://myApp.example.com/ redirecting to anywhere on your site is probably okay. (I write probably, because if it can be used as a way to bypass authorization checks, say on a multi-sequence page series, then it might not be okay. But as long as your regular authorization checks pick up and validate the redirect, you generally will be okay.) But what about redirects to https://anotherApp.example.com/? Would those be okay? What about anything in the "example.com" domain? Are their other 3rd party domains that you need to white-list? If so, be sure to list those URLs as well. But the one thing that you want to avoid are completely open redirects and for that you need some type of white-listing. You could build some custom validators using ESAPI to do this, but it's probably just easier to write it without ESAPI. If you have a bunch of URLs that you have to white-list, keep them in a configuration file that's not part of your .war / .ear file so you can easily update it without redeploying your application and just (re)read the config file when it gets updated.
Hope this helps.
-kevin
Thanks for all your suggestions and comments.
I found that the lines
ESAPI.httpUtilities().setCurrentHTTP(req, resp);
ESAPI.httpUtilities().sendRedirect(location);
ESAPI.httpUtilities().clearCurrent();
Is now working fine for me, after a long struggle I found that my code is using latest version of commons-configuration.jar but when I added Esapi as a dependency the Esapi used an old version of the same and that was not compatible with my code so I just excluded the this from Esapi dependency using the exclusion in pom and it worked for me.
We have a Tapestry-Spring-Hibernate webapp running on Tomcat 6, handing about a few 1000 requests a second. Randomly, for no apparent reason, a page just displays a bunch of random characters on the browser. However, when the page is refreshed, it displays fine. Here is a screen-shot of the source of the garbled page on Chrome:
Here is what I have found so far:
It doesn't seem to be browser specific. I have witnessed this on Chrome and Firefox, but users have also reported this on IE 7 and up.
Load on the server seems to have no correlation to when this happens.
Refreshing the page displays the page normally, as if nothing ever happened.
I don't see anything relevant in the server or the application logs
The content-type tag for the page is <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
There are a couple other webapps deployed on the same container, one being Alfresco, but they don't seem to exhibit this at all.
My question is, has someone run into this before, and if so, can they point me to where I should start looking? Is this a problem with the page having something like the incorrect content-type or the server not being able to handle it for some reason? Or could this be a framework bug in Tapestry or in the application itself? Any pointers are welcome. At this point, I am not sure where the problem is, so I wasn't sure if this goes on ServerFault or stays here.
It is most likely a bug in the application. (Most bugs are ... despite the natural tendency of programmers to blame something else.)
However, could be a bit tricky to track down this problem. I suggest that you start with the standard things:
Look at the server error logs to see if anything strange shows up at the time when one of these "events" occur.
Look at the server access logs to see if you can identify the request that produced the garbage data.
Enable your browser's debugger and see if you can track down the bad request that way.
If you can figure out what the request that produced the bad response was, you'll have more traction in finding the cause.
FWIW - that doesn't look like the result of a character encoding problem. That looks more like binary or compressed data.
Here's one situation that has led me to see a garbled page. On the error page Tapestry sets a response header called X-Tapestry-ErrorMessage. Evidently newlines aren't allowed in headers (at least on some browsers) so if that header has a newline in it, you get the gibberish. One error message we were setting happened to have a trailing new line. I changed it to remove any newlines before setting that header and then the error page showed correctly.
This seems to be related to gzip compression issues in the Tapestry framework (as suggested by #barnyr) and is possibly a regression bug in Tapestry 5.3. To quote Howard from a mailing list thread:
I believe this was a bug where under certain circumstances, a corrupt
GZIP stream of page content would be streamed to the client; this is
fixed in 5.2.6 for sure, but I thought it was fixed in 5.2.5 as well.
The quick fix is to add the following configuration symbol in the contributeApplicationDefaults method of the app's module class:
configuration.add(SymbolConstants.GZIP_COMPRESSION_ENABLED, "false");
This of course disables gzip compression, but might a trade-off worth making.
Possibly related issues:
GZip compression should be disabled if the request is over http 1.0
Is GZIP compression compatible with XmlHttpRequest?
I'd like to store then later display user-entered content securely with minimal effort (my goal is a web app not writing a bunch of security-related code).
EDIT: Google App Engine for Java
I'm working with the same issue myself; but I haven't had the chance to get it out into the real world yet; so please just keep in mind that MY ANSWER IS NOT BATTLE TESTED. USE AT YOUR OWN RISK.
First, you need to ask yourself if you're going to be allowing the user to use ANY html markup. So, for example, can the user enter a link? What about make bold text?
If the answer is NO, then it is fairly simple. Here is the idea of how to set the filter up:
http://greatwebguy.com/programming/java/simple-cross-site-scripting-xss-servlet-filter/
But personally, I don't like the filter being used in the first example; I just put it there to show you how to set the filter up.
I would recommend using this filter:
http://xss-html-filter.sourceforge.net/
So basically:
Setup the example from first link, get it working
Download the example from the second link, put it in your project in such a way you can access it from your code.
Rewrite the cleanXSS method to use what you downloaded from the second link. So probably something like:
private String cleanXSS(String value) {
return new HTMLInputFilter().filter( input );
}
If you do want to allow HTML (such as an anchor tag/etc) then it looks like the HTMLInputFilter has mechanisms to allow this; but it isn't documented so you'll have to figure it out by looking at the code yourself or provide your own way of filtering.
user-entered content securely with minimal effort (my goal is a web app not writing a bunch of security-related code).
How much security-related code you need to write depends on how much you are at risk (how likely is it someone would want to attack your site, which it self is related to how popular your site is).
For example if your writing a public notepad, which will have a total of 3 users, you can get away with the bare minimum, if however your writing a we hate China, Iran and all hackers/crackers app dealing with $1,000,000 worth of transactions an hour and 3 billion users, you may be a bit more of a target.
Simply put you shouldn't trust any data that comes from outside your app including from the datastore. All this data should be checked that it's what you expect.
I've not validated incoming Java Strings against XSS however removing HTML is normally good enough, and Jsoup looks interesting for this (See Remove HTML tags from a String )
Also to be sure you should ensure your outputting what you expect to be outputting and not the some JavaScript.
Most templating engines, including django's (which is bundled with App Engine), provide facilities to escape output to make it safe to print in HTML. In newer versions of Django, this is done automatically unless you tell it not to; in 0.9.6 (still the default in webapp), you pass your output values to |escape in the template.
Escaping on output is universally the best way to do this, because it means you have the original unmodified text; if you modify your escaping or output formatting later, you can still format text entered before that.
You can also use a service that will proxy all connections and block any XSS attempts. I know only one service like that - CloudFlare (but it doesn't mean there aren't others like that). Unfortunately security features goes in with Pro plan which is paid :(
I am trying to handle a file upload, and I'm using the
com.oreilly.servlet.multipart.MultipartParser class to parse the posted
data (in cos.jar). However, when I call the constructor for MultipartParser, I get this
exception:
java.io.IOException: Corrupt form data: premature ending
at com.oreilly.servlet.multipart.MultipartParser.<init>(MultipartParser.java:166)
at com.oreilly.servlet.multipart.MultipartParser.<init>(MultipartParser.java:94)
Has anyone seen this before? From what I read, this means that the
data ended before it found the boundary it was looking for. How can I
fix this?
I am using cos.jar version 1.0.
Thanks!
http://www.servlets.com/cos/faq.html
This indicates there was a problem
parsing the POST request submitted by
the client. There can be many causes
for the problem:
The client hit the STOP button (not really a problem, but it does cause a
premature ending)
A bug in the web form
A bug in the servlet
A bug in the web server
A bug in the browser
A bug in the com.oreilly.servlet library itself
History has shown the web server to be
the most frequent cause of problems
probably because there are so many
different servers and few vendors
appear to test their binary upload
capability.
First, make sure your client isn't
hitting the STOP button. Then, check
if your problem is already posted on
the "Servlet bugs you need to know
about" resource on this site. If it's
not well known, then you get to be
among the first to learn about it! And
you can share your discovery with us
here!
Second, see if the upload works using
the provided upload.html form and
DemoRequestUploadServlet.java class.
Some people have found bugs in their
form that caused problems. Testing
this combination will see if that's
the case. One user, Duke Takle, found
this exception was caused by a
redirect: I was experiencing the same
"premature ending" as Albert Smith.
What I've found is that the problem
was isolated to I.E. 5.0. The
application that troubled me was doing
a redirect after the construction of a
MultipartRequest. It looks like this
construction went well except on I.E.
5.0 the browser attempted to make the request again and by that time the
ServletInputStream was empty. I've
modified the application to simply
write the needed response instead of
redirecting. This problem was observed
and fixed as described in Tomcat 4.0
and Weblogic 6.1. Other users have
found bugs in their handling servlet
where they call request.getParameter()
instead of
multipartRequest.getParameter(), and
some servers falsely read the input
stream when their getParameter() is
called causing an "unexpected end of
part".
So, the problem was caused by me calling the MultipartParser constructor twice, by accident. It failed the second time, since the request had already been processed.