Otherwise, by default, tzinfo will use TZInfo::ZoneinfoDataSource, which does not seem to be affected.
https://github.com/tzinfo/tzinfo/blob/d9b289e1be30d29a2cb23b...
https://github.com/tzinfo/tzinfo/commit/b98c32efd61289fe6f00...
Edit: misread your comment, 1.x is vulnerable only if you have the tzinfo-data gem installed, or explicitly set TZInfo::DataSource to DataSources::RubyDataSource as you stated.
I'm guessing that's because the time zone is included in the "date modified" field, but that's just a hunch.
If anybody is able to quickly spin up a Ruby on Rails app with a file uploader, I bet somebody be happy to bang on it and see if they can get an exploit to trigger. (I'm headed to sleep now, but that will be a fun challenge to dig into tomorrow.)
If this turns out to be something impactful and widespread, I'll tweet/blog[0] about it and give a shout out to anybody that helps on a POC. Raising awareness so that people are aware of RCE vectors like this one is important for making sure people update.
(I'm guessing that somebody clever will figure out a "gadget-like" way to get RCE with this on a base Ruby install by loading in specific files from the disk. Ie, you will no longer need arbitrary file write access to the disk in order to turn this into RCE. That would scenario would make this CVE a much more widely exploitable attack, versus being fairly niche due to needing a more specific setup. I'm no Ruby expert, so maybe I'm totally wrong here.)
App in question has to allow file upload that writes to local disk. Attacker would have to upload his ruby payload via this method.
App in question has to allow arbitrary, user-entered time zone select, eg allowing a user to enter "EST", and then pass that directly, raw, to TZInfo::Timezone.get(). Attacker would have to know where in the target filesystem their uploaded payload is, and submit a crafted timezone payload with escape characters to the path of their uploaded payload file relative to where the TZInfo gem is.
So, lets say I upload nasty_ruby.py, and the app puts it in /temp/myappuploads/nasty_ruby.py And lets say the tzinfo gem is running in /myapp/gems/tzinfo-gem/ I would submit something like 'fake\n../../../temp/myappuploads/nasty_ruby.py' which would cause the impacted tzinfo-gem method to call require on '../../../temp/myappuploads/nasty_ruby.py' which would execute it.
In general, I don't think I've ever seen time zone selection available as freeform text vs, say, a dropdown, so that seems fairly rare. Assuming you do have a freeform text form submission for timezone, you have to ALSO have a file upload capability that would place files on the local disk on the same system. And then, the attacker would have to either know or traverse/explore to find the path to where those files are on the system - ostensibly possible but seemingly unlikely? And this is all predicated on you using an old version of tzinfo-gem.
That said, if your ruby app checks all these boxes and is running an outdated version of the gem then yeah, its a straightforward RCE and thus very bad (and i think why they rated the severity as they did)
> I don't think I've ever seen time zone selection available as freeform text vs, say, a dropdown, so that seems fairly rare.
HTML dropdowns are freeform text when submitted.
This is sometimes interesting, and occasionally important.
The file upload itself is only part of the exploit.
If we assume the exploit as "executing code that is written by the attacker"¹, then the requirements are:
1. ability to upload an arbitrary file to a filesystem accessible by the host
2. ability, for the attacker, to pass values that are ultimately sent to `TZInfo::Timezone.get()`
With those conditions in place, the attacker will attempt to figure out where the file is located (with multiple attempts or so), then make `Timezone.get()` load the file.
It's not clear to me if `Timezone.get()` is indirectly invoked by some common Rails API, or if this is an API that is commonly invoked by the user.
As a starting point, one should check if they're invoking such API in their app.
EDIT: at a brief check, ActiveSupport exposes a `TimeZone` wrapper, that invokes `TZInfo::Timezone`, and can be used for the exploit.
EDIT2: It seems that the instatiation is not user-initiated (I suppose it's automatic... and not obvious to track), so unless the app devs intentionally perform this instantiation, I think they won't trigger custom calls (but I don't want to give false assurances).
EDIT3: I wonder if this can be triggered by putting certain data in the database and triggering loading. I can't exclude this vector because... Rails is complicated :). Seems overly complex, though. I think Rails intimate knowledge is necessary in order assess with very high certainty which the possible attack vectors are.
[¹] I'm making this distinction because if point 2 applies, but not point 1, the attacker can still execute arbitrary files preexisting in the filesystem.
From reading the description it looks like the second line, if present, is just (somehow) loaded as a ruby file.
So this is exploitable on a file upload if you can find the destination location of the upload data. More generally if you can get a ruby script on the FS somehow, and this is accessible from the tzinfo-gem via a relative path, and you can probe the FS (but depending on the error feedback the vulnerability itself could provide the probing tool, if it lets you discriminate between EFILE and EEXIST… or if rails has a standard upload path and the average application will almost certainly be using that)
My guess is that it might be exploitable when parsing a user provided datetime with zone without any sanitization of the input. And only when using that get method. I might try to see if Rails is vunerable to this, but probably not from a cursory glance
The app doesn't know what is a "valid" or "invalid" timezone, it is tzinfo's responsibility to check it.
UPD: in fact tzinfo tried to validate a timezone identifier but did it the wrong way. It used a regular expression like /^...$/ and using ^ and $ is a mistake here. This allows to bypass validation by passing a multiline identifier.
Personally I love regex, but only because I'm good at it and I generally have a good memory for obscure trivia.
> Versions 2.0.0 and later are not vulnerable.
Was about to panic there for a second.
EDIT: Oops, I think I read it wrong, it's tzinfo version >2.0.0 that is not vulnerable, not ruby. Time to panic
[0] https://github.com/tzinfo/tzinfo/commit/01bcca5de920093b52fb...
So if you write a regexp like /^[0-9]$/, a string "Any characters\n12345\nAny characters" will match the regexp.
because Ruby has \A and \Z to match the boundaries of a string