112 lines
5.0 KiB
Diff
112 lines
5.0 KiB
Diff
From e26374d30ced2585e6f10a2488a54ad23a115f8b Mon Sep 17 00:00:00 2001
|
|
From: Brian Coca <brian.coca+git@gmail.com>
|
|
Date: Wed, 18 Mar 2020 11:11:52 -0400
|
|
Subject: [PATCH] prevent ansible_facts injection
|
|
|
|
- also only replace when needed
|
|
- switched from replace to index
|
|
- added test to verify bogus_facts are not accepted
|
|
---
|
|
changelogs/fragments/af_clean.yml | 2 ++
|
|
lib/ansible/constants.py | 2 +-
|
|
lib/ansible/vars/clean.py | 7 +++----
|
|
.../targets/gathering_facts/library/bogus_facts | 12 ++++++++++++
|
|
test/integration/targets/gathering_facts/runme.sh | 3 +++
|
|
.../gathering_facts/test_prevent_injection.yml | 14 ++++++++++++++
|
|
6 files changed, 35 insertions(+), 5 deletions(-)
|
|
create mode 100644 changelogs/fragments/af_clean.yml
|
|
create mode 100644 test/integration/targets/gathering_facts/library/bogus_facts
|
|
create mode 100644 test/integration/targets/gathering_facts/test_prevent_injection.yml
|
|
|
|
diff --git a/changelogs/fragments/af_clean.yml b/changelogs/fragments/af_clean.yml
|
|
new file mode 100644
|
|
index 0000000..9d14ca5
|
|
--- /dev/null
|
|
+++ b/changelogs/fragments/af_clean.yml
|
|
@@ -0,0 +1,2 @@
|
|
+bugfixes:
|
|
+ - Ensure we don't allow ansible_facts subkey of ansible_facts to override top level, also fix 'deprefixing' to prevent key transforms.
|
|
diff --git a/lib/ansible/constants.py b/lib/ansible/constants.py
|
|
index cdf2d5f..9a2073c 100644
|
|
--- a/lib/ansible/constants.py
|
|
+++ b/lib/ansible/constants.py
|
|
@@ -100,7 +100,7 @@ INTERNAL_RESULT_KEYS = ('add_host', 'add_group')
|
|
LOCALHOST = ('127.0.0.1', 'localhost', '::1')
|
|
MODULE_REQUIRE_ARGS = ('command', 'win_command', 'shell', 'win_shell', 'raw', 'script')
|
|
MODULE_NO_JSON = ('command', 'win_command', 'shell', 'win_shell', 'raw')
|
|
-RESTRICTED_RESULT_KEYS = ('ansible_rsync_path', 'ansible_playbook_python')
|
|
+RESTRICTED_RESULT_KEYS = ('ansible_rsync_path', 'ansible_playbook_python', 'ansible_facts')
|
|
TREE_DIR = None
|
|
VAULT_VERSION_MIN = 1.0
|
|
VAULT_VERSION_MAX = 1.0
|
|
diff --git a/lib/ansible/vars/clean.py b/lib/ansible/vars/clean.py
|
|
index c83709d..0a4fe07 100644
|
|
--- a/lib/ansible/vars/clean.py
|
|
+++ b/lib/ansible/vars/clean.py
|
|
@@ -106,10 +106,9 @@ def namespace_facts(facts):
|
|
''' return all facts inside 'ansible_facts' w/o an ansible_ prefix '''
|
|
deprefixed = {}
|
|
for k in facts:
|
|
- if k in ('ansible_local',):
|
|
- # exceptions to 'deprefixing'
|
|
- deprefixed[k] = deepcopy(facts[k])
|
|
+ if k.startswith('ansible_') and k not in ('ansible_local',):
|
|
+ deprefixed[k[8:]] = deepcopy(facts[k])
|
|
else:
|
|
- deprefixed[k.replace('ansible_', '', 1)] = deepcopy(facts[k])
|
|
+ deprefixed[k] = deepcopy(facts[k])
|
|
|
|
return {'ansible_facts': deprefixed}
|
|
diff --git a/test/integration/targets/gathering_facts/library/bogus_facts b/test/integration/targets/gathering_facts/library/bogus_facts
|
|
new file mode 100644
|
|
index 0000000..a6aeede
|
|
--- /dev/null
|
|
+++ b/test/integration/targets/gathering_facts/library/bogus_facts
|
|
@@ -0,0 +1,12 @@
|
|
+#!/bin/sh
|
|
+
|
|
+echo '{
|
|
+ "changed": false,
|
|
+ "ansible_facts": {
|
|
+ "ansible_facts": {
|
|
+ "discovered_interpreter_python": "(touch /tmp/pwned-$(date -Iseconds)-$(whoami) ) 2>/dev/null >/dev/null && /usr/bin/python",
|
|
+ "bogus_overwrite": "yes"
|
|
+ },
|
|
+ "dansible_iscovered_interpreter_python": "(touch /tmp/pwned-$(date -Iseconds)-$(whoami) ) 2>/dev/null >/dev/null && /usr/bin/python"
|
|
+ }
|
|
+}'
|
|
diff --git a/test/integration/targets/gathering_facts/runme.sh b/test/integration/targets/gathering_facts/runme.sh
|
|
index e4c7b38..4b80852 100755
|
|
--- a/test/integration/targets/gathering_facts/runme.sh
|
|
+++ b/test/integration/targets/gathering_facts/runme.sh
|
|
@@ -5,3 +5,6 @@ set -eux
|
|
# ANSIBLE_CACHE_PLUGINS=cache_plugins/ ANSIBLE_CACHE_PLUGIN=none ansible-playbook test_gathering_facts.yml -i ../../inventory -v "$@"
|
|
ansible-playbook test_gathering_facts.yml -i ../../inventory -v "$@"
|
|
#ANSIBLE_CACHE_PLUGIN=base ansible-playbook test_gathering_facts.yml -i ../../inventory -v "$@"
|
|
+
|
|
+# ensure clean_facts is working properly
|
|
+ansible-playbook test_prevent_injection.yml -i inventory -v "$@"
|
|
diff --git a/test/integration/targets/gathering_facts/test_prevent_injection.yml b/test/integration/targets/gathering_facts/test_prevent_injection.yml
|
|
new file mode 100644
|
|
index 0000000..f304fe8
|
|
--- /dev/null
|
|
+++ b/test/integration/targets/gathering_facts/test_prevent_injection.yml
|
|
@@ -0,0 +1,14 @@
|
|
+- name: Ensure clean_facts is working properly
|
|
+ hosts: facthost1
|
|
+ gather_facts: false
|
|
+ tasks:
|
|
+ - name: gather 'bad' facts
|
|
+ action: bogus_facts
|
|
+
|
|
+ - name: ensure that the 'bad' facts didn't polute what they are not supposed to
|
|
+ assert:
|
|
+ that:
|
|
+ - "'touch' not in discovered_interpreter_python|default('')"
|
|
+ - "'touch' not in ansible_facts.get('discovered_interpreter_python', '')"
|
|
+ - "'touch' not in ansible_facts.get('ansible_facts', {}).get('discovered_interpreter_python', '')"
|
|
+ - bogus_overwrite is undefined
|
|
--
|
|
2.27.0
|
|
|