Invalid date in HttpCookie.parse; What should be the behavior? - datetime

Today I changed the java I have been using on my desktop from the Oracle JDK 1.7 to the OpenJDK 1.7.
So I went from
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)
to
java version "1.7.0_65"
OpenJDK Runtime Environment (rhel-2.5.1.2.el6_5-x86_64 u65-b17)
OpenJDK 64-Bit Server VM (build 24.65-b04, mixed mode)
I then ran the unit tests for one of my projects and what has been running successfully before now failed.
The failing test in question did something like this:
List<HttpCookie> cookies =
HttpCookie.parse("FOO=BAR; expires=Thu, 01-Jan-2020 00:00:10 GMT");
HttpCookie cookie = cookies.get(0);
and then an assertion using the value from
cookie.getMaxAge();
The problem I found is that suddenly the cookie.getMaxAge() always returned a 0 instead of the expected 'big' value.
It turns out that I ask an invalid question: 01-Jan-2020 is a Wednesday, not a Thursday.
I fixed this error in my unit test (so now I ask for "Wed, 01-Jan-2020" and this now works).
For me the question remains: What 'should' be the behavior in case of 'not so good input'?
Both behaviors I see here have some validation.
Apparently:
Oracle: The date can be parsed so we return the value. The 'day of the week' is just a 'hint'.
OpenJDK: This date cannot exist as it was specified so we return a 0
Is there a specification on this point?

From the Oracle javadoc we see that the string must be a set-cookie (Netscape proposal) or set-cookie2 (RFC 2965). Your string is following the Netscape proposal.
From the Netscape proposal:
The date string is formatted as:
Wdy, DD-Mon-YYYY HH:MM:SS GMT
This is based on RFC 822, RFC 850, RFC 1036, and RFC 1123, with the variations that the only legal time zone is GMT and the separators between the elements of the date must be dashes.
From RFC 822:
5.2. SEMANTICS
If included, day-of-week must be the day implied by the date specification.
So your string is not a set-cookie string.
The parse method should throw an IllegalArgumentException if:
header string violates the cookie specification's syntax, or the cookie name contains illegal characters, or the cookie name is one of the tokens reserved for use by the cookie protocol
The day-of-week error is a semantic violation of the specification and not a syntactic one, so no exception has to be raised.
In conclusion, the behavior of the parse method encountering a date with a wrong day-of-week is not defined. The specification should either impose to raise an IllegalArgumentException, either impose to ignore the problem as the day-of-week is an optional redundant information.

Related

#PathVariable containing backslash quote returns 400 Bad Request

If you run this simple RestController with Spring Boot (2.5.3):
#RestController
public class SampleRestController {
#GetMapping("/search/{criteria}")
public String hello(#PathVariable(name = "criteria") String criteria) {
return "Hello: " + criteria;
}
}
And try to open this link in your browser:
http://localhost:8080/search/%22%5C%22bug%5C%22%22
Then you will get "400 Bad Request", returned by the embedded Tomcat.
I don't understand, is this a bug in Tomcat ? Is this not a valid URL ?
EDIT: As per some of the replies: I went step-by-step through the Tomcat 9.0.50 source-code and saw the line about ALLOW_BACKSLASH.
And neither of the values true or false is good for me, because with true it replaced \ with / and with false it returns 400 Bad Request.
What I needed was to allow backslash without replacing it with slash.
My question is really whether this is a bug in Tomcat, since for me the URL seems to be valid. I am not technically putting a \ into the URL, I am putting a %-encoded backslash. What is the purpose of the %-encoding if not to allow the user to send any character in the URL ?
Refer to Piotr P. Karwasz comments above for better explanation.
The tomcat version correspond to Spring Boot (2.5.3) is 9.0.50.
By checking the source code of CoyoteAdaptor and Tomcat System parameter documentation, the url checking is configured by a flag ALLOW_BACKSLASH through System Property org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH, with false as default value.
...
protected static final boolean ALLOW_BACKSLASH =
Boolean.parseBoolean(System.getProperty("org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH", "false"));
...
To allow backslash in the URL, we can add below when running the application.
-Dorg.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH=true
This property is replaced after tomcat 10.0.0-M4.
Remove org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH system property, replaced by the allowBackslash attribute on the Connector. (remm)
While samabcde's answer provides a solution for your problem, let me answer to your more general questions:
your URL is perfectly valid although RFC 3986, section 7.3 allows some restriction to be imposed for security reasons,
these restrictions are not a Tomcat bug, as they were introduced as an answer to CVE-2007-0450. Before Tomcat 6.0.10 the sequences /, %2F and %5C were used to split the request URI into components. If Tomcat was behind a proxy that forwarded only an application (let's say /app), you could use /app/%5C../manager/html to access Tomcat Manager.
If you set org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH=true you expose your system to the aforementioned vulnerability and all %5C sequences will appear as / in the servletPath and pathInfo ServletRequest properties. Since the requestURI property contains the undecoded URI path (cf. this question) your example will work.
Yes it seems like an invalid URL, you also get an error by Spring Boot refering to RFC 7230 and RFC 3986 specifications.
But you could use some query parameter to avoid this error, e.g.:
#GetMapping("/search")
public String hello(#RequestParam(name = "criteria", required = false) String criteria) {
return "Hello: " + criteria;
}
And call it like:
http://localhost:8080/search?criteria=%22%5C%22bug%5C%22%22

Not recognized as a valid DateTime

We utilised the CSVHelper to upload CSV file with date column and worked ok on dev machine till we published into Azure the following issue:
An unhandled exception occurred while processing the request.
FormatException: String '13/12/2018' was not recognized as a valid
DateTime. System.DateTimeParse.Parse(ReadOnlySpan s,
DateTimeFormatInfo dtfi, DateTimeStyles styles)
ReaderException: An unexpected error occurred.
CsvHelper.Configuration.ConfigurationFunctions.ReadingExceptionOccurred(CsvHelperException
exception)
The machine is using the Australian date which is dd/MM/yyyy format. It looks like Azure sets to American format one. How do we change this? Or how do force this into .Net core code configuration?
We also found that even we change the format of the date into ISO date: yyyy-MM-dd ... again worked OK on dev BUT not in Azure Production?
Any ideas?
Modified this and solved the problem:
var csvReader = new CsvReader(reader2);
csvReader.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-AU");
var records = csvReader.GetRecords<UploadBatchItem>();

Potentially dangerous characters in Request Parameters (not Request.Path!)

There are lots of questions on this topic but I didn't find one for our special case ...
We have a productive site running and once in a while - about 5 to 10 times a day - we receive error notifications about potentially dangerous Request.Path values. The strange thing here is, that the actual "dangerous" characters are not in the request path but in the parameters.
When looking into the request object we get values like these:
HttpContext.Current.Request.Url.AbsolutePath --> /relative/path/to/page
HttpContext.Current.Request.Url.Query --> ?param1=value&param2=value
ASP.NET is complaining about the ? in the params:
Message: A potentially dangerous Request.Path value was detected from the client (?). (System.Web.HttpException)
Stacktrace:
at System.Web.HttpRequest.ValidateInputIfRequiredByConfig()
at System.Web.HttpApplication.PipelineStepManager.ValidateHelper(HttpContext context)
But from my point of view everything seems to be fine (these are indeed valid urls and if I type them in the browser they do work).
We're also tracking the client IP and client user agent and they are mostly related to some crawlers. Is it possible, that they're building a erroneous request which triggers these errors?
You are probably using asp.net 4.0 or higher. It is more 'picky' then the previous versions. The following chars are filtered by default:
< > * % & : \ ?
You are able to change these in your web.config:
<httpRuntime requestPathInvalidCharacters="<,>,*,%,&,:,\,?" />
It could be that crawlers or some browsers do use escape chars which contain % like when sending a request. Some more reading on the subject: Experiments In Wackiness Allowing Percents Angle brackets And Other Naughty Things In The ASPNETIIS RequestURL

Set or read Date in HTTP header (Windows Phone 8)

Does anyone knows of a way to set or read the 'Date' HTTP header in an HTTP GET request on Windows Phone 8?
I need to be able to set the value of the Date header or at least read the value that will actually be sent in the request.
I have tried with something like:
var web_request = HttpWebRequest.CreateHttp(url);
web_request.Headers["Date"] = the_date;
But this produces an exception at run time:
System.ArgumentException: The 'Date' header must be modified using the appropriate property or method.
There's sample code here with HttpClient but this is apparently not available under Windows Phone 8:
How do you set the Content-Type header for an HttpClient request?
I have tried reading the date as well but after:
var web_request = HttpWebRequest.CreateHttp(url);
The date does not seem to be set yet.
That worked well after adding "Microsoft HTTP Client Libraries".
However there is still a problem in this library on WindowsPhone Platform.
PROBLEM:
I have a scenario where i want to add a "Date" header in a specific format, so i used
string customDate = "11/29/2013 7:46:25"
DefaultRequestHeaders.TryAddWithoutValidation("Date", customDate);
the above line adds the "Date" header, that means it does not throw any exception, but when i checked in fidler there is no "Date" header added. The same code works well in Windows8 store apps.
Looks like there is a bug in "Microsoft HTTP Client Libraries" for WindowsPhone8 platform.
By using "Microsoft HTTP Client Libraries" for Date header works well and good if Date is of DateTime object, however if i want to assign a value to Date header in a specific format as mentioned in earlier post then it does not get added.
Its a header with built-in support that you need to set/get explicitly;
web_request.Date = DateTime.UtcNow;
(Its default is 01/01/0001 00:00:00 which is not sent in the request)
The problem with:
web_request.Date
is that there is no "Date" property in the Windows Phone 8 version of HttpWebRequest.
See: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/5738e95a-5afe-4a49-929d-b51490a5480b/httpwebrequest-date-property-missing
In this link it is suggested to use HttpClient and HttpRequestMessage. Example:
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Date = DateTime.Now.Subtract(new TimeSpan(10, 0, 0));
HttpResponseMessage response = client.SendAsync(request).Result;
string resultCode = response.StatusCode.ToString();
I was stuck because HttpClient and HttpRequestMessage seem not to be available for Windows Phone 8 either. But it is possible to add them:
In Visual Studio (Express) 2012 for Windows Phone:
TOOLS -> Library Package Manager -> Manage NuGet Packages for Solution...
Then search for "Microsoft HTTP Client Libraries" and install it.
After that System.Net.Http is available and the HttpClient solution can be used.

Problem setting cookie expiration to DateTime.Max (December 31, 9999)?

We're supporting legacy code that is dropping a cookie and setting the expiration to DateTime.MaxValue:
HttpCookie cookie = new HttpCookie(cookieName, value);
cookie.Expires = DateTime.MaxValue;
It seems that on some browsers (which we are not logging), this cookie expires immediately--or may not even be getting dropped. According to MSDN, DateTime.MaxValue is December 31, 9999. Are there any browser-related issues with setting a cookie expiration to this date?
The correct answer would be to change the expiration date, but at this point, we can't change production code.
If I had to randomly guess why it's not working, I would say it has something to do with Unix epoch time. This value will technically overflow (on 32-bit machines) after January 19, 2038 at 3:14:07 AM GMT - so the next second after this would be interpreted as January 1, 1970 0:00:01 AM GMT.
It's possible that the future time you've supplied is actually converted into a past time.
Again, this is a complete guess and hopefully I can test it soon when VWD Express 2008 is downloaded on my home machine.
Edit:
Searching for this issue, I have found a similar error:
http://framework.zend.com/issues/browse/ZF-5690

Resources