Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In 2.5, the script module fails with privilege escalation, due to permission issues #36398

Closed
ephesused opened this issue Feb 19, 2018 · 1 comment · Fixed by #36401
Closed
Assignees
Labels
affects_2.5 This issue/PR affects Ansible v2.5 bug This issue/PR relates to a bug. module This issue/PR relates to a module. support:core This issue/PR relates to code supported by the Ansible Engineering Team.

Comments

@ephesused
Copy link

ISSUE TYPE
  • Bug Report
COMPONENT NAME

Privilege escalation and the script module

ANSIBLE VERSION
$ PYTHONPATH=~/ansible-2.5.0b2/lib ~/ansible-2.5.0b2/bin/ansible --version
ansible 2.5.0b2
  config file = /home/centos/ansible.cfg
  configured module search path = [u'/home/centos/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /home/centos/ansible-2.5.0b2/lib/ansible
  executable location = /home/centos/ansible-2.5.0b2/bin/ansible
  python version = 2.7.5 (default, Aug  4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
$
CONFIGURATION

DEFAULT_ROLES_PATH(/etc/ansible/ansible.cfg) = [u'/etc/ansible/roles', u'/usr/share/ansible/roles']

OS / ENVIRONMENT

CentOS 7.4

SUMMARY

Prior to 2.5, script tasks run with privilege escalation applied setfacl to both the housing directory and the target host script. With 2.5, setfacl is applying solely to the target host script. The housing directory is not opened to the become_user, so the task fails with permissions issues.

#35666 is possibly related, where there were permission failures for tasks with privilege escalation and deep remote_tmp directories.

STEPS TO REPRODUCE

ansible-playbook -i inventory.ini playbook.yml -vvv

inventory.ini

target ansible_connection=local

playbook.yml

---
- hosts: all
  tasks:
  - debug:
      var: ansible_version.full
  - name: By default user
    script: /home/centos/test.sh
  - name: By another user
    become: true
    become_user: another
    script: /home/centos/test.sh
#!/bin/bash

echo "Hi there, $(whoami)"
EXPECTED RESULTS

I expected the playbook to run to completion, as it does in 2.4.2. The setfacl call in the "By another user" task applies to both the housing directory and the script.

$ ansible-playbook -i inventory.ini playbook.yml -vvv
ansible-playbook 2.4.2.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/centos/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.7.5 (default, Aug  4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
Using /etc/ansible/ansible.cfg as config file
Parsed /home/centos/inventory.ini inventory source with ini plugin

PLAYBOOK: playbook.yml ******************************************************************************************************************************
1 plays in playbook.yml

PLAY [all] ******************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************
Using module file /usr/lib/python2.7/site-packages/ansible/modules/system/setup.py
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c 'echo ~ && sleep 0'
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/centos/.ansible/tmp/ansible-tmp-1519056612.13-105399086177092 `" && echo ansible-tmp-1519056612.13-105399086177092="` echo /home/centos/.ansible/tmp/ansible-tmp-1519056612.13-105399086177092 `" ) && sleep 0'
<target> PUT /tmp/tmpL2Iqku TO /home/centos/.ansible/tmp/ansible-tmp-1519056612.13-105399086177092/setup.py
<target> EXEC /bin/sh -c 'chmod u+x /home/centos/.ansible/tmp/ansible-tmp-1519056612.13-105399086177092/ /home/centos/.ansible/tmp/ansible-tmp-1519056612.13-105399086177092/setup.py && sleep 0'
<target> EXEC /bin/sh -c '/usr/bin/python /home/centos/.ansible/tmp/ansible-tmp-1519056612.13-105399086177092/setup.py; rm -rf "/home/centos/.ansible/tmp/ansible-tmp-1519056612.13-105399086177092/" > /dev/null 2>&1 && sleep 0'
ok: [target]
META: ran handlers

TASK [debug] ****************************************************************************************************************************************
task path: /home/centos/playbook.yml:4
ok: [target] => {
    "ansible_version.full": "2.4.2.0"
}

TASK [By default user] ******************************************************************************************************************************
task path: /home/centos/playbook.yml:6
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c 'echo ~ && sleep 0'
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/centos/.ansible/tmp/ansible-tmp-1519056612.49-257402348266617 `" && echo ansible-tmp-1519056612.49-257402348266617="` echo /home/centos/.ansible/tmp/ansible-tmp-1519056612.49-257402348266617 `" ) && sleep 0'
<target> PUT /home/centos/test.sh TO /home/centos/.ansible/tmp/ansible-tmp-1519056612.49-257402348266617/test.sh
<target> EXEC /bin/sh -c 'chmod u+x /home/centos/.ansible/tmp/ansible-tmp-1519056612.49-257402348266617/ /home/centos/.ansible/tmp/ansible-tmp-1519056612.49-257402348266617/test.sh && sleep 0'
<target> EXEC /bin/sh -c ' /home/centos/.ansible/tmp/ansible-tmp-1519056612.49-257402348266617/test.sh && sleep 0'
<target> EXEC /bin/sh -c 'rm -f -r /home/centos/.ansible/tmp/ansible-tmp-1519056612.49-257402348266617/ > /dev/null 2>&1 && sleep 0'
changed: [target] => {
    "changed": true,
    "rc": 0,
    "stderr": "",
    "stdout": "Hi there, centos\n",
    "stdout_lines": [
        "Hi there, centos"
    ]
}

TASK [By another user] ******************************************************************************************************************************
task path: /home/centos/playbook.yml:8
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c 'echo ~ && sleep 0'
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /tmp/ansible-tmp-1519056612.57-242465962454810 `" && echo ansible-tmp-1519056612.57-242465962454810="` echo /tmp/ansible-tmp-1519056612.57-242465962454810 `" ) && sleep 0'
<target> PUT /home/centos/test.sh TO /tmp/ansible-tmp-1519056612.57-242465962454810/test.sh
<target> EXEC /bin/sh -c 'setfacl -m u:another:r-x /tmp/ansible-tmp-1519056612.57-242465962454810/ /tmp/ansible-tmp-1519056612.57-242465962454810/test.sh && sleep 0'
<target> EXEC /bin/sh -c 'sudo -H -S -n -u another /bin/sh -c '"'"'echo BECOME-SUCCESS-livmgqbneomtrzkguocdhrslwpxwfetg;  /tmp/ansible-tmp-1519056612.57-242465962454810/test.sh'"'"' && sleep 0'
<target> EXEC /bin/sh -c 'rm -f -r /tmp/ansible-tmp-1519056612.57-242465962454810/ > /dev/null 2>&1 && sleep 0'
changed: [target] => {
    "changed": true,
    "rc": 0,
    "stderr": "",
    "stdout": "Hi there, another\n",
    "stdout_lines": [
        "Hi there, another"
    ]
}
META: ran handlers
META: ran handlers

PLAY RECAP ******************************************************************************************************************************************
target                     : ok=4    changed=2    unreachable=0    failed=0

$
ACTUAL RESULTS

2.5.0b2 fails, complaining about permissions issues. The setfacl call in the "By another user" task targets only the script, leaving the housing directory unaltered.

$ PYTHONPATH=~/ansible-2.5.0b2/lib ~/ansible-2.5.0b2/bin/ansible-playbook -i inventory.ini playbook.yml -vvv
ansible-playbook 2.5.0b2
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/centos/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /home/centos/ansible-2.5.0b2/lib/ansible
  executable location = /home/centos/ansible-2.5.0b2/bin/ansible-playbook
  python version = 2.7.5 (default, Aug  4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
Using /etc/ansible/ansible.cfg as config file
Parsed /home/centos/inventory.ini inventory source with ini plugin

PLAYBOOK: playbook.yml ******************************************************************************************************************************
1 plays in playbook.yml

PLAY [all] ******************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************
task path: /home/centos/playbook.yml:2
Using module file /home/centos/ansible-2.5.0b2/lib/ansible/modules/system/setup.py
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c 'echo ~ && sleep 0'
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/centos/.ansible/tmp/ansible-tmp-1519056718.23-110145123590191 `" && echo ansible-tmp-1519056718.23-110145123590191="` echo /home/centos/.ansible/tmp/ansible-tmp-1519056718.23-110145123590191 `" ) && sleep 0'
<target> PUT /home/centos/.ansible/tmp/ansible-local-10853yBdDa0/tmpSAIhCG TO /home/centos/.ansible/tmp/ansible-tmp-1519056718.23-110145123590191/setup.py
<target> EXEC /bin/sh -c 'chmod u+x /home/centos/.ansible/tmp/ansible-tmp-1519056718.23-110145123590191/ /home/centos/.ansible/tmp/ansible-tmp-1519056718.23-110145123590191/setup.py && sleep 0'
<target> EXEC /bin/sh -c '/usr/bin/python /home/centos/.ansible/tmp/ansible-tmp-1519056718.23-110145123590191/setup.py && sleep 0'
<target> EXEC /bin/sh -c 'rm -f -r /home/centos/.ansible/tmp/ansible-tmp-1519056718.23-110145123590191/ > /dev/null 2>&1 && sleep 0'
ok: [target]
META: ran handlers

TASK [debug] ****************************************************************************************************************************************
task path: /home/centos/playbook.yml:4
ok: [target] => {
    "ansible_version.full": "2.5.0b2",
    "failed": false
}

TASK [By default user] ******************************************************************************************************************************
task path: /home/centos/playbook.yml:6
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c 'echo ~ && sleep 0'
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/centos/.ansible/tmp/ansible-tmp-1519056718.64-9784177752591 `" && echo ansible-tmp-1519056718.64-9784177752591="` echo /home/centos/.ansible/tmp/ansible-tmp-1519056718.64-9784177752591 `" ) && sleep 0'
<target> PUT /home/centos/test.sh TO /home/centos/.ansible/tmp/ansible-tmp-1519056718.64-9784177752591/test.sh
<target> EXEC /bin/sh -c 'chmod u+x /home/centos/.ansible/tmp/ansible-tmp-1519056718.64-9784177752591/test.sh && sleep 0'
<target> EXEC /bin/sh -c ' /home/centos/.ansible/tmp/ansible-tmp-1519056718.64-9784177752591/test.sh && sleep 0'
<target> EXEC /bin/sh -c 'rm -f -r /home/centos/.ansible/tmp/ansible-tmp-1519056718.64-9784177752591/ > /dev/null 2>&1 && sleep 0'
changed: [target] => {
    "changed": true,
    "failed": false,
    "rc": 0,
    "stderr": "",
    "stdout": "Hi there, centos\n",
    "stdout_lines": [
        "Hi there, centos"
    ]
}

TASK [By another user] ******************************************************************************************************************************
task path: /home/centos/playbook.yml:8
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c 'echo ~ && sleep 0'
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /var/tmp/ansible-tmp-1519056718.73-151571114285502 `" && echo ansible-tmp-1519056718.73-151571114285502="` echo /var/tmp/ansible-tmp-1519056718.73-151571114285502 `" ) && sleep 0'
<target> PUT /home/centos/test.sh TO /var/tmp/ansible-tmp-1519056718.73-151571114285502/test.sh
<target> EXEC /bin/sh -c 'setfacl -m u:another:r-x /var/tmp/ansible-tmp-1519056718.73-151571114285502/test.sh && sleep 0'
<target> EXEC /bin/sh -c 'sudo -H -S -n -u another /bin/sh -c '"'"'echo BECOME-SUCCESS-zejjjxnnwejptupoeojbilzghhckrtbr;  /var/tmp/ansible-tmp-1519056718.73-151571114285502/test.sh'"'"' && sleep 0'
<target> EXEC /bin/sh -c 'rm -f -r /var/tmp/ansible-tmp-1519056718.73-151571114285502/ > /dev/null 2>&1 && sleep 0'
fatal: [target]: FAILED! => {
    "changed": true,
    "failed": true,
    "msg": "non-zero return code",
    "rc": 126,
    "stderr": "/bin/sh: /var/tmp/ansible-tmp-1519056718.73-151571114285502/test.sh: Permission denied\n",
    "stdout": "",
    "stdout_lines": []
}
        to retry, use: --limit @/home/centos/playbook.retry

PLAY RECAP ******************************************************************************************************************************************
target                     : ok=3    changed=1    unreachable=0    failed=1

$
@ansibot
Copy link
Contributor

ansibot commented Feb 19, 2018

Files identified in the description:

If these files are inaccurate, please update the component name section of the description or use the !component bot command.

click here for bot help

@ansibot ansibot added affects_2.5 This issue/PR affects Ansible v2.5 bug_report module This issue/PR relates to a module. needs_triage Needs a first human triage before being processed. support:core This issue/PR relates to code supported by the Ansible Engineering Team. labels Feb 19, 2018
@abadger abadger added this to To Do in 2.5.x blocker list Feb 19, 2018
@bcoca bcoca removed the needs_triage Needs a first human triage before being processed. label Feb 19, 2018
abadger added a commit to abadger/ansible that referenced this issue Feb 19, 2018
Unified tmp accidentally removed the containing tmpdir from the list of
files to fix the permissions on when we're becoming a different
unprivileged user.  This resulted in a visible bug for script but not
for patch.  This is because patch also uploads the module to the same
temporary directory and the uploaded module also ends up calling
fixup_perms2() which includes the temporary directory.  So by the time
patch needs to access the temporary patch file, the directory is
appropriately set.

script's breakage was visible because script does not upload a module
(it's akin to raw in this way).  Therefore, we only call fixup_perms2()
once in script and so leaving out the tmpdir in script means that the
containing directory never has its permissions set appropriately.

Fixing both because it does not cause an extra round trip for patch so
any speedup would be minimal and it's better to fix the perms as close
as possible to where we know we need it.  Otherwise, changes to
seemingly unrelated code later could end up breaking it.

Fixes ansible#36398
abadger added a commit that referenced this issue Feb 19, 2018
Unified tmp accidentally removed the containing tmpdir from the list of
files to fix the permissions on when we're becoming a different
unprivileged user.  This resulted in a visible bug for script but not
for patch.  This is because patch also uploads the module to the same
temporary directory and the uploaded module also ends up calling
fixup_perms2() which includes the temporary directory.  So by the time
patch needs to access the temporary patch file, the directory is
appropriately set.

script's breakage was visible because script does not upload a module
(it's akin to raw in this way).  Therefore, we only call fixup_perms2()
once in script and so leaving out the tmpdir in script means that the
containing directory never has its permissions set appropriately.

Fixing both because it does not cause an extra round trip for patch so
any speedup would be minimal and it's better to fix the perms as close
as possible to where we know we need it.  Otherwise, changes to
seemingly unrelated code later could end up breaking it.

Fixes #36398

(cherry picked from commit edaeb69)
abadger added a commit that referenced this issue Feb 19, 2018
Unified tmp accidentally removed the containing tmpdir from the list of
files to fix the permissions on when we're becoming a different
unprivileged user.  This resulted in a visible bug for script but not
for patch.  This is because patch also uploads the module to the same
temporary directory and the uploaded module also ends up calling
fixup_perms2() which includes the temporary directory.  So by the time
patch needs to access the temporary patch file, the directory is
appropriately set.

script's breakage was visible because script does not upload a module
(it's akin to raw in this way).  Therefore, we only call fixup_perms2()
once in script and so leaving out the tmpdir in script means that the
containing directory never has its permissions set appropriately.

Fixing both because it does not cause an extra round trip for patch so
any speedup would be minimal and it's better to fix the perms as close
as possible to where we know we need it.  Otherwise, changes to
seemingly unrelated code later could end up breaking it.

Fixes #36398
@nitzmahone nitzmahone moved this from To Do to Done in 2.5.x blocker list Feb 23, 2018
@ansibot ansibot added bug This issue/PR relates to a bug. and removed bug_report labels Mar 7, 2018
@ansible ansible locked and limited conversation to collaborators Apr 27, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affects_2.5 This issue/PR affects Ansible v2.5 bug This issue/PR relates to a bug. module This issue/PR relates to a module. support:core This issue/PR relates to code supported by the Ansible Engineering Team.
Projects
No open projects
Development

Successfully merging a pull request may close this issue.

4 participants