After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 787203 - Correctly quote and escape arguments of external programs passed to execute_command()
Correctly quote and escape arguments of external programs passed to execute_c...
Status: RESOLVED FIXED
Product: gparted
Classification: Other
Component: application
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gparted maintainers alias
gparted maintainers alias
: 649509 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2017-09-03 08:17 UTC by Pali
Modified: 2017-10-10 17:25 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
[PATCH] Correctly quote and escape arguments of external program (65.52 KB, patch)
2017-09-03 08:17 UTC, Pali
none Details | Review
Correctly quote and escape arguments of external programs (v2) (70.89 KB, patch)
2017-09-21 13:19 UTC, Mike Fleetwood
none Details | Review

Description Pali 2017-09-03 08:17:47 UTC
Created attachment 359013 [details] [review]
[PATCH] Correctly quote and escape arguments of external program

The whole command string is parsed and split to argv array via function
Glib::shell_parse_argv() which calls internal glib function
tokenize_command_line() for shell tokenization. It excepts command string to
be properly quoted and escaped shell fragment and after tokenization it
calls g_shell_unquote() on every parsed argument.

So to prevent composing incorrect command execution arguments, every
non-static string needs to be properly quoted and escaped.

This could be probably security related issue, as e.g. label argument for
filesystem comes from user input and may contain any Unicode string.

At least specifying following label caused confusion and error from the
external tools for changing filesystem labels.

 " --help "

GParted only put label into quotes, but have not escaped special characters
in label itself.

This patch should fix all these problems and calls Glib::shell_quote() on
every place where needed.

Probably better solution would be to create and use a new function which
would take argv array instead of one string with concatenated of all
(correctly quoted and escaped) arguments.
Comment 1 Pali 2017-09-03 08:20:21 UTC
Note that on 3 places is called "sh -c" so there also ';' is problematic and can lead to execution of another command. This problem is fixed in first part of attached patch. Second part fixes other problems.
Comment 2 Pali 2017-09-03 08:21:44 UTC
Related patch https://bugzilla.gnome.org/show_bug.cgi?id=787202
Comment 3 Mike Fleetwood 2017-09-12 20:11:21 UTC
Hi Pali,

Do you know a way to get an arbitrary device name into GParted so that
it might execute an unsafe command using that device name if not quoted?

Using the command line I get:
    # gpartedbin '/dev/sdb ; date > /tmp/log'
    Could not stat device /dev/sdb ; date > /tmp/log - No such file or directory.

Udev seems to make names safely:
    # btrfs filesystem label /dev/sdb31 '" ; date > /tmp/log'
    # ls -l /dev/disk/by-label
    ...
    lrwxrwxrwx. 1 root root 11 Sep 12 20:54 \x22\x20\x3b\x20date\x20\x3e\x20\x2ftmp\x2flog -> ../../sdb31

So far not found a way to get an unsafe path into GParted.
Comment 4 Pali 2017-09-12 21:16:15 UTC
> Do you know a way to get an arbitrary device name into GParted so that
it might execute an unsafe command using that device name if not quoted?

Yes, here is one:

$ printf '#!/bin/sh\necho test > out\n' > script.sh; chmod +x script.sh

$ truncate -s 20M 'jfs;script.sh'
$ mkfs.jfs -q 'jfs;script.sh'

$ ls -l out
ls: cannot access out: No such file or directory

$ sudo PATH=$PWD:$PATH ./gpartedbin 'jfs;script.sh'
$ sudo PATH=$PWD:$PATH ./gpartedbin 'jfs;script.sh'

$ ls -l out
-rw-r--r-- 1 root root 5 Sep 12 23:11 out
$ cat out 
test

Looks like that file is created after second run of gpartedbin.

Basically filename is interpreted as shell fragment. You can replace script.sh by any other executable binary in PATH.
Comment 5 Mike Fleetwood 2017-09-14 18:35:38 UTC
For the record the unsafe execution in comment 4 above works like this:

    jfs::set_used_sectors()
        partition.get_path() -> "jfs.script.sh"
        Utils::execute_command("sh -c 'echo dm | jfs_debugfs " +
                               partition.get_path() + "'", ...)
            command = "sh -c 'echo dm | jfs_debugfs jfs;script.sh'"
            Glib::shell_parse_argv(command) ->
                ["sh","-c","echo dm | jfs_debugfs jfs;script.sh"]
            Glib::spawn_async_with_pipes(...,
                Glib::shell_parse_argv(command), ...)

So FS image named 'jfs;script.sh' is passed to the shell where semicolon
separates the two commands, getting the following run via the shell:
    echo md | jfs_debugfs jfs
    script.sh


Pali,

Do you know of an attach that doesn't use one of the "sh -c" strings in
the code base?
Comment 6 Pali 2017-09-14 22:35:39 UTC
Fix for this problem is in attached patch. It is needed to correctly escape all passed parameters and for such thing there is glib function.
Comment 7 Mike Fleetwood 2017-09-15 07:58:08 UTC
Typo in the above question.  s/attach/attack/.

Do you know of an attack that doesn't use one of the "sh -c" strings in
the code base?
Comment 8 Pali 2017-09-16 08:08:20 UTC
(In reply to Mike Fleetwood from comment #7)
> Do you know of an attack that doesn't use one of the "sh -c" strings in
> the code base?

I do not see any other yet, but I have not looked at it more deeply.

Current implementation which executes external commands is not correct as it does not quote ans escape parameters correctly which can lead in undefined behavior.

What I see is incorrect usage of those "sh -c" strings and missing escaping in labels strings which comes from user UI. Via label user can pass arbitrary parameter to *label executables (e.g. xfs_admin).

And I suspect this is a security related problem as in future any external commands can be extended to support other new options which can cause problems.

Input field for label should set label and not trying to parse also any other parameters for the external command. If user specify that want to have disk labeled '" --param "' then disk should be labeled '" --param "' and not --param parsed and passed as parameter to *label executable.
Comment 9 Mike Fleetwood 2017-09-21 13:19:24 UTC
Created attachment 360196 [details] [review]
Correctly quote and escape arguments of external programs (v2)

Sorry it took so long, there was quite a bit to review and test and I
didn't have extra time for GParted.

Testing:
Debugged the string passed to execute_command() and what
Glib::shell_parse_argv() produced from it.  Then tested (almost)
everything.
* Query every type of recognised file system with and without blkid
  being available.  (without uses FS specific read UUID external
  commands too).
* Exercise every supported file system operation which involves an
  external command.
* Mount/activate/swapon and unmount/deactivate/swapoff.
* Refresh, create and delete partitions on a fake DMRaid array.
* etc.
All worked successfully.

I've made the following changes to patchset v1 from comment 0:
1) Updated the commit messages somewhat.
2) Added Glib::shell_quote() to missing case in
   Win_GParted::activate_mount_partition().
3) White space changes.

I'll commit in a day or so unless I hear otherwise.
Comment 10 Curtis Gedak 2017-09-21 17:08:51 UTC
Hi Mike and Pali,

Patch set v2 in comment #9 looks good to me and ready to commit.

I did some very basic testing and did not encounter any issues.

Thanks for your work in this area.

Curtis
Comment 11 Mike Fleetwood 2017-09-21 19:02:19 UTC
The following changes from patchset v2 have been pushed upstream to the
public GParted git repo:

Correctly quote and escape command line argument passed to "sh -c" (#787203)
https://git.gnome.org/browse/gparted/commit/?id=f422052356ab594bac044dbd34fca894d2774625

Correctly quote and escape arguments passed to external commands (#787203)
https://git.gnome.org/browse/gparted/commit/?id=8fdc2c21a60cf8999b4328632b18e2bbbf13f9a4
Comment 12 Mike Fleetwood 2017-09-21 21:38:20 UTC
*** Bug 649509 has been marked as a duplicate of this bug. ***
Comment 13 Curtis Gedak 2017-10-10 17:25:39 UTC
This enhancement was included in the GParted 0.30.0 release on October 10, 2017.