Is escaping the Accept header necessary? - java

I have a Jersey app that has been run through our corporations website vulnerability tool. It came back with a vulnerability that is quite odd. If you send in this header:
"*/*'"!#$^*\/:;.,?{}[]`~-_<sCrIpT>alert(81363)</sCrIpT>"
you actually get it back in the response and it is not escaped. Anyone think this is a problem?
Here is the actual response:
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Accept: */*'"!#$^*\/:;.,?{}[]`~-_<sCrIpT>alert(81363)</sCrIpT>
Pragma: no-cache
...
And one more thing. I just upgraded to jersey 1.14 and it still does this...

You mean in produced error message? Something like:
< HTTP/1.1 400 Bad Request
< Content-Type: text/plain
< Date: Thu, 27 Sep 2012 14:30:30 GMT
< Connection: close
< Transfer-Encoding: chunked
<
* Closing connection #0
The HTTP header field "Accept" with value "..." could not be parsed
?
If so, we can definitely do something about it, please report this as a new RFE at http://java.net/jira/browse/JERSEY. (I wasn't able to reproduce anything else related to this issue).
Thanks!

Related

How to print the whole response on the console

I can't print the whole response from the server on the console!
,
There are 3 ways to bypass this matter,
Add this header Connection: close
Replace HTTP/1.1 to HTTP/1.0
Add this s.close(); // Socket.close();
I can't close the connection because I want to send more than once at the same connection,
I just want to print the whole response without closing the connection.
String content = "GET /Zuck HTTP/1.1\r\nHost: www.facebook.com\r\nuser-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36\r\n\r\n";
Executing your code returns the following:
HTTP/1.1 302 Found
Location: https://www.facebook.com/zuck
Strict-Transport-Security: max-age=15552000; preload
Content-Type: text/html; charset="utf-8"
X-FB-Debug: NHDnNLmTeg5PBPiSL7++1dz/ZdRbnlnKy1gpdfBbLFkvrhbJMJT+nLJd1VYpmEkkkUtmvXsjgLvFEeML/82WUA==
Date: Thu, 18 Jun 2020 15:36:24 GMT
Alt-Svc: h3-27=":443"; ma=3600
Connection: keep-alive
Content-Length: 0
HTTP reponse status code 302 indicates a redirect to the Location: https://www.facebook.com/zuck. Either handle redirects in your code or - to get your example running - simply replace Zuck with zuck in your content string.
Since your operating on raw socket you actually cannot determine when you have received whole response. You can however do it with protocols like http in same cases.
In your example you receive Content-Length: 0 which tells the number (0) of bytes the body of message have.
You can also pass header Connection: close which closes connection after sending full response, but I think it is not what you're looking for.
You can also just do read/write operations on two separate threads.

jsoup request returns wrong status code

I have a Twitter shortened URL (t.co) and I'm trying to use jsoup to send a request and parse its response. There should be three redirect hops before reaching the final URL. This is not the case when using jsoup, even after setting followRedirects to true.
My code:
public static void main(String[] args) {
try {
Response response = Jsoup.connect("https://t. co/sLMy6zi4Yw").followRedirects(true).execute(); // Space intentional to avoid SOF shortened errors
System.out.println(response.statusCode()); // prints 200
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
However, using Python's Request library, I can get the right response:
response = requests.get('https://t. co/sLMy6zi4Yw', allow_redirects=False)
print(response.status_code)
301
I'm using jsoup version 1.11.2 and Requests version 2.18.4 with Python 3.5.2.
Anybody have any insight on the matter?
To overcome this special case you can remove the User-Agent header which Jsoup sets by default (for some unknown/undocument reason)
Connection connection = Jsoup.connect(url).followRedirects(true);
connection.request().removeHeader("User-Agent");
Let's examine the raw requests & view the server behavior
Request with user agent (to simulate a browser) returns
status code 200
Meta refresh which is a method of instructing a web browser to automatically refresh the current web page or frame after a given time interval, this case 0 seconds and url http://bit. ly/2n3VDpo
Javascript code which replaces location to the same url (google "meta refresh is depercated" / "drawbacks using meta refresh")
Curl example
curl --include --raw "https://t. co/sLMy6zi4Yw" --user-agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
Response
Chrome/63.0.3239.132 Safari/537.36"
HTTP/1.1 200 OK
cache-control: private,max-age=300
content-length: 257
content-security-policy: referrer always;
content-type: text/html; charset=utf-8
referrer-policy: unsafe-url
server: tsa_b
strict-transport-security: max-age=0
vary: Origin
x-response-time: 20
x-xss-protection: 1; mode=block; report=https://twitter.com/i/xss_report
<head><meta name="referrer" content="always"><noscript><META http-equiv="refresh" content="0;URL=http://bit. ly/2n3VDpo"></noscript><title>http://bit. ly/2n3VDpo</title></head><script>window.opener = null;location.replace("http:\/\/bit. ly\/2n3VDpo")</script>
Request without user agent returns
status code 301
header "location" with the redirect url
Curl example
curl --include --raw "https://t. co/sLMy6zi4Yw"
HTTP/1.1 301 Moved Permanently
cache-control: private,max-age=300
content-length: 0
location: http://bit. ly/2n3VDpo
server: tsa_b
strict-transport-security: max-age=0
vary: Origin
x-response-time: 9

Analyze HTTP-header before body is transmitted in apache tomcat

Is it possible to analyze the header of a HTTP-(POST)-Request before the body is transmitted?
I would like to send an error to a client if the file he is trying to upload via an HTTP-POST is to large to handle for the server. To improve the user experience (and safe traffic) I would prefer to send the error response before he uploads the whole file, by analyzing the content-length-header.
I thought about implementing a javax.servlet.filter like this:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request.getContentLength() > MAX_DOCUMENT_SIZE) {
ObjectMapper jsonMapper = new ObjectMapper();
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("messageCode", 1234);
jsonMap.put("messageDescription", "error message");
response.reset();
response.setStatus(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE);
jsonMapper.writeValue(response.getWriter(), jsonMap);
return;
}
}
chain.doFilter(request, response);
}
but I am not sure if the tomcat is able to analyze the headers before the hole request was transmitted.
EDIT: curl
> CONNECT myserver.com:443 HTTP/1.1
> Host: myserver.com:443
> Proxy-Connection: Keep-Alive
> user-agent: my-test
>
< HTTP/1.0 200 Connection established
<
* Proxy replied OK to CONNECT request
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
* Server certificate: myserver.com
> POST /uploads HTTP/1.1
> Host: myserver
> Accept: */*
> user-agent: my-test
> Content-Length: 51951089
> Content-Type: application/x-www-form-urlencoded
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
< HTTP/1.1 404 Not Found
< Date: Tue, 01 Sep 2015 09:49:01 GMT
* Server WEB is not blacklisted
< Server: WEB
< X-XSS-Protection: 1; mode=block
< X-DNS-Prefetch-Control: off
< X-Content-Type-Options: nosniff
< X-Frame-Options: sameorigin
< Strict-Transport-Security: max-age=15768000 ; includeSubDomains
< Cache-Control: private
< Expires: Thu, 01 Jan 1970 01:00:00 GMT
< Content-Type: text/plain;charset=utf-8
< Content-Length: 0
< Vary: Accept-Encoding
< Connection: close
<
Yes, this is possible and I am actually doing this in Tomcat 6. I have not tried a Filter but a Tomcat-specific Valve. If this solution works as a Vavle, feel free to port it to a Filter.
Have Tomcat to invoke your valve. Your demo code looks just the way it should look, make sure that you send a 400 (or better 413) to indicate that the input is not appropriate. You may close the connection too. Now here comes the very important part: to make this work, the client has to POST or PUT the request, additionally the client must send a Expect: 100-continue header. The server will analyze all incoming headers and signal the client that the request is inappropriate. With that, the client will receive a 400 (or better 413) before it sends off its payload (request will be aborted). You'll exchange headers only and save resources. But beware, your clients must properly implement Expect: 100-continue. .NET clients don't. I would strongly recommend to verify the proper working of your valve with curl because it does the stuff right. If you'd like to see wire headers for this, no problem.
Caveat: your content length limit won't work if the client streams its payload in chunks.
You write a java script function and bind it onchange event on input type="file" files[0].size will give u size of the file.So u can check if it is uploadable.
Thx

http: conditional get does not give a chance to refresh headers without sending body again

I don't know if this is a bug or a feature in the http spec, or I am not understanding things ok.
I have a resource that changes at most once a week, at the week's beginning. If it didn't change, then the previous week's resource continues to be valid for the whole week.
(For all our tests we have modified the one week period for five minutes, but I think our observations are still valid).
First we send the resource with the header Expires: next Monday. The whole week the browser retrieves from the cache. If on Monday we have a new resource then it is retrieved with its new headers and everything is ok.
The problem occurs when the resource is not renewed. In response to the conditional get our app (Java+Tomcat) sends new headers with Expires: next Monday but without the body. But our frontend server (apache) removes this header, because the spec says you should not send new headers if the resource did not change. So now forever (until the resource changes) the browser will send a conditional get when we would like it to continue serving straight from the cache.
Is there a spec compliant way to update the headers without updating the body? (or sending it again)
And subquestion: how to make apache pass along tomcat's headers?
Just a Expires header is not enough. According to RFC 2616 section 13.3.4, a server needs to respond with two headers, Last-Modified and ETag, to do conditional GET right:
In other words, the preferred behavior for an HTTP/1.1 origin server is to send both a strong entity tag and a Last-Modified value.
And if the client is HTTP/1.1 compliant, it should send If-Modified-Since. Then the server is supposed to respond as following (quoted from Roy Fielding's proposal to add conditional GET):
If resource is inaccessible (for whatever reason), then the server should return a 4XX message just like it does now.
If resource no longer exists, the server should return a 404 Not Found response (i.e. same as now).
If resource is accessible but its last modification date is earlier (less than) or equal to the date passed, the server should return a 304 Not Modified message (with no body).
If resource is accessible and its last modification date is later than the date passed, the server should return a 200 OK message (i.e. same as now) with body.
So, I guess you don't need to configure Apache and/or Tomcat the way you described. You need to make your application HTTP/1.1 compliant.
Try sending a valid HTTP-Date for the Expires header?
One way to solve the problem is using separate URIs for each week. The canonical url redirects to the appropriate url for the week, and instructs the browser to cache the redirect for a week. Also, URLs that have a date in them will instruct the browser to cache forever.
Canonical URL : /path/to/resource
Status Code : 301
Location : /path/to/resource/12-dec or /path/to/resource/19-dec
Expires : Next Monday
Week 1 : /path/to/resource/12-dec
Status code : 200
Expires : Never
Week 2 : /path/to/resource/19-dec
Status code : 200
Expires : Never
When the cache expires on Monday, you just send a redirect response. You either send last weeks URL or this weeks, but you never send the entire response body.
With this approach, you have eliminated conditional gets. You have also made your resources "unmodifiable-once-published", and you also get versioned resources.
The only caveat - redirects aren't cached by all browsers even though the http spec requires them to do so. Notably IE8 and below don't cache. For details, look at the column "cache browser redirects" in browserscope.
The Expires header was basically deprecated with HTTP 1.1; use Cache-Control: max-age instead.
Make sure you are including Last-Modified.
It's optional, but you may also want to specify Cache-Control: must-revalidate, to make sure intermediate proxies don't deliver potentially stale content.
You don't need to set ETag.
Example request:
GET http://localhost/images/logo.png HTTP/1.1
Accept: image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5
Referer: http://localhost/default.aspx
Accept-Language: en-US
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost
Connection: Keep-Alive
The response includes the requested content:
HTTP/1.1 200 OK
Cache-Control: max-age=10
Content-Type: image/png
Last-Modified: Sat, 21 Feb 2009 11:28:18 GMT
Accept-Ranges: bytes
Date: Sun, 18 Dec 2011 05:48:34 GMT
Content-Length: 2245
Requests made before the 10 second timeout are resolved from cache, with no HTTP request. After the timeout:
GET http://localhost/images/logo.png HTTP/1.1
Accept: image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5
Referer: http://localhost/default.aspx
Accept-Language: en-US
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
If-Modified-Since: Sat, 21 Feb 2009 11:28:18 GMT
Host: localhost
The response is just headers, without content:
HTTP/1.1 304 Not Modified
Cache-Control: max-age=10
Last-Modified: Sat, 21 Feb 2009 11:28:18 GMT
Accept-Ranges: bytes
Date: Sun, 18 Dec 2011 05:49:04 GMT
Subsequent requests are again resolved from the browser's cache until the specified cache expiration time.

App Engine HTTP Status Code message

I found an inconsistency between Java's dev_appserver and the live App Engine server.
On my local development server I have a Servlet which returns:
return response.sendError(response.SC_BAD_REQUEST, "Please log in to comment");
When I access the page I get back a Status Code message in the header which is:
Status Code:400 Please log in to comment
The issue comes when I deploy this to App Engine. When accessing that same servlet I get this "Bad Request" instead of "Please log in to comment":
Status Code:400 Bad Request
The Please log in to comment Status Code message appears in the content HTML, but not in the header as it does in the development environment.
Why is this?
Edit
Here's the curl -vvvv traces for both dev_appserver and production:
dev_appserver curl trace:
> POST /add-comment HTTP/1.1
> User-Agent: Mozilla/4.0
> Host: localhost:8080
> Accept: */*
> Content-Length: 9
> Content-Type: application/x-www-form-urlencoded
>
< HTTP/1.1 400 Please log in to comment
< Content-Type: text/html; charset=iso-8859-1
< Cache-Control: must-revalidate,no-cache,no-store
< Content-Length: 1406
< Server: Jetty(6.1.x)
Production curl trace:
> POST /add-comment HTTP/1.1
> User-Agent: Mozilla/4.0
> Host: www.xxx.org
> Accept: */*
> Content-Length: 9
> Content-Type: application/x-www-form-urlencoded
>
< HTTP/1.1 400 Bad Request
< Content-Type: text/html; charset=utf-8
< Vary: Accept-Encoding
< Date: Thu, 18 Aug 2011 14:04:26 GMT
< Server: Google Frontend
< Cache-Control: private
< Transfer-Encoding: chunked
I would say the prod system is the correct implementation. The javadocs for sendError() say:
Sends an error response to the client using the specified status. The
server defaults to creating the response to look like an
HTML-formatted server error page containing the specified message,
setting the content type to "text/html", leaving cookies and other
headers unmodified. If an error-page declaration has been made for the
web application corresponding to the status code passed in, it will be
served back in preference to the suggested msg parameter.
If the response has already been committed, this method throws an
IllegalStateException. After using this method, the response should be
considered to be committed and should not be written to.
I highlighted a part. This says it just returns a html page with the message when possible. It doesn't say it uses it in the HTTP Status code (which I personally haven't seen anywhere as well :()
It isn't specifically a problem with sendError. The setStatus method will behave the same way. Under normal Java, both sendError and setStatus do set the status description. The issue is that the production App Engine server always sets the status description to the standard description for each code.

Categories