Bug 998223 - (CVE-2013-4259) CVE-2013-4259 ansible: insecure location for ssh ControlMaster socket
CVE-2013-4259 ansible: insecure location for ssh ControlMaster socket
Product: Security Response
Classification: Other
Component: vulnerability (Show other bugs)
Unspecified Unspecified
medium Severity medium
: ---
: ---
Assigned To: Red Hat Product Security
: Security
Depends On: 999621 1001454
Blocks: 998712
  Show dependency treegraph
Reported: 2013-08-18 07:40 EDT by Michael Scherer
Modified: 2017-05-12 03:04 EDT (History)
7 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2017-05-12 03:04:19 EDT
Type: Bug
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)
better patch (2.05 KB, patch)
2013-08-18 10:24 EDT, Michael Scherer
no flags Details | Diff

  None (edit)
Description Michael Scherer 2013-08-18 07:40:22 EDT
by default, ansible try to create a ControlMaster file in a predictible location in /tmp. This is vulnerable to a ssh socket injection attack like this :

~ $ sudo ln -s /tmp/ansible-ssh-elspeth.example.org-22-misc /tmp/ansible-ssh-sisay.example.org-22-misc

~ $ ansible -i 'elspeth.example.org,sisay.example.org' all -m shell -u misc -a hostname
elspeth.example.org | success | rc=0 >>

sisay.example.org | success | rc=0 >>

I also did a test without using root, that's the same.
Based on this attack, someone could divert the ssh connexion to another server, make it connect to a server under the control of attacker, and steal configuration file ( with passwords ), or steal password with a fake sudo ( since ansible can also use sudo )

Please note that you need to :
- disable selinux
# setenforce 0

- disable latest protection from the kernel 

# sysctl -w fs.protected_symlinks=0
# sysctl -w fs.protected_hardlinks=0

to make sure this work.
I didn't found how/where ssh control the socket file for suitability, maybe it should

I am not sure what could be a good fix. I do have a patch that put the socket in $XDG_RUNTIME_DIR but it is a very weak mitigation technique that do not work on older platform such as RHEL 6. 

Another solution would be to make sure the socket is created in specific temporary directory, but this could make the software much slower.

And checking if the socket exist first is prone to race condition.

Upstream was not contacted yet, and plan to release 1.3 around 2 weeks. Issue is not public ( but quite easy to spot )
Comment 1 Michael Scherer 2013-08-18 07:45:04 EDT
The issue is in https://github.com/ansible/ansible/blob/devel/lib/ansible/runner/connection_plugins/ssh.py#L59

Possible fix :

commit d06eaae5fa32ae24e8076f846bdf3f04e6090384
Author: Michael Scherer <misc@zarb.org>
Date:   Sun Aug 18 13:19:01 2013 +0200

    Try to mitigate symlink attacks on newer platform
    A attacker could pre create a socket in /tmp and so divert
    the ssh connexion to another server. However, newer platform
    are protected against this since kernel 3.10 and surely with
    a proper selinux policy.

diff --git a/lib/ansible/runner/connection_plugins/ssh.py b/lib/ansible/runner/connection_plugins/ssh.py
index abbffcf..be8289e 100644
--- a/lib/ansible/runner/connection_plugins/ssh.py
+++ b/lib/ansible/runner/connection_plugins/ssh.py
@@ -51,12 +51,15 @@ class Connection(object):
         self.common_args = []
         extra_args = C.ANSIBLE_SSH_ARGS
+        control_path_dir = '/tmp'
+        if 'XDG_RUNTIME_DIR' in os.environ:
+            control_path_dir = os.environ['XDG_RUNTIME_DIR']
         if extra_args is not None:
             self.common_args += shlex.split(extra_args)
             self.common_args += ["-o", "ControlMaster=auto",
                                  "-o", "ControlPersist=60s",
-                                 "-o", "ControlPath=/tmp/ansible-ssh-%h-%p-%r"]
+                                 "-o", "ControlPath=%s/ansible-ssh-%%h-%%p-%%r" % control_path_dir]
         if not C.HOST_KEY_CHECKING:
             self.common_args += ["-o", "StrictHostKeyChecking=no"]
Comment 2 Michael Scherer 2013-08-18 10:24:40 EDT
Created attachment 787788 [details]
better patch

So here is a proper patch, using a temporary directory shared during the playbook run. 

However, it could be written more cleanly without using global, and using proper object lifecycle, but I consider that being minor when compared to the security fix.
Comment 3 Vincent Danen 2013-08-19 16:12:46 EDT
Hi, Michael.  The best thing to do here would be to alert upstream to this.  We can assign a CVE for this that you can pass along as well, and then we can open this bug up and get fixes into Fedora and EPEL6 once the issue is fixed upstream.
Comment 4 Vincent Danen 2013-08-19 16:28:31 EDT

Red Hat would like to thank Michael Scherer for reporting this issue.
Comment 5 Vincent Danen 2013-08-19 16:29:09 EDT
Michael, when you report this to upstream can you also note that it was assigned CVE-2013-4259?

Comment 6 Michael Scherer 2013-08-19 17:35:39 EDT
Yep, will do. I keep you in CC to see how we organize the embargo, if upstream want one.
Comment 7 Vincent Danen 2013-08-21 13:58:33 EDT
Created ansible tracking bugs for this issue:

Affects: fedora-all [bug 999621]
Comment 8 Vincent Danen 2013-08-21 14:01:10 EDT
This is public now:

Comment 9 Vincent Danen 2013-08-27 01:51:32 EDT
Created ansible tracking bugs for this issue:

Affects: epel-6 [bug 1001454]
Comment 10 Fedora Update System 2013-08-28 12:43:55 EDT
ansible-1.2.3-2.el6 has been pushed to the Fedora EPEL 6 stable repository.  If problems still persist, please make note of it in this bug report.
Comment 11 Fedora Update System 2013-08-30 18:58:23 EDT
ansible-1.2.3-2.fc18 has been pushed to the Fedora 18 stable repository.  If problems still persist, please make note of it in this bug report.
Comment 12 Fedora Update System 2013-08-30 19:03:27 EDT
ansible-1.2.3-2.fc19 has been pushed to the Fedora 19 stable repository.  If problems still persist, please make note of it in this bug report.

Note You need to log in before you can comment on or make changes to this bug.