Browse code

prevent templating of passwords from prompt (#59246) (#59554)

* prevent templating of passwords from prompt (#59246)

* prevent templating of passwords from prompt

fixes CVE-2019-10206

(cherry picked from commit e9a37f8e3171105941892a86a1587de18126ec5b)

* Improve performane of UnsafeProxy __new__

This adds an early return to the __new__ method of the UnsafeProxy object
which avoids creating the unsafe object if the incoming object is already
unsafe.

(cherry picked from commit c1e23c22a9fedafaaa88c2119b26dc123ff1392e)
(cherry picked from commit 490f17c7f959ce153765c1f033fdc30becf0faf7)

Brian Coca authored on 2019/08/13 10:06:01
Showing 3 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+bugfixes:
1
+    - resolves CVE-2019-10206, by avoiding templating passwords from prompt as it is probable they have special characters.
... ...
@@ -42,6 +42,7 @@ from ansible.parsing.dataloader import DataLoader
42 42
 from ansible.release import __version__
43 43
 from ansible.utils.path import unfrackpath
44 44
 from ansible.utils.vars import load_extra_vars, load_options_vars
45
+from ansible.utils.unsafe_proxy import AnsibleUnsafeBytes
45 46
 from ansible.vars.manager import VariableManager
46 47
 from ansible.parsing.vault import PromptVaultSecret, get_file_vault_secret
47 48
 
... ...
@@ -342,6 +343,13 @@ class CLI(with_metaclass(ABCMeta, object)):
342 342
         except EOFError:
343 343
             pass
344 344
 
345
+        # we 'wrap' the passwords to prevent templating as
346
+        # they can contain special chars and trigger it incorrectly
347
+        if sshpass:
348
+            sshpass = AnsibleUnsafeBytes(sshpass)
349
+        if becomepass:
350
+            becomepass = AnsibleUnsafeBytes(becomepass)
351
+
345 352
         return (sshpass, becomepass)
346 353
 
347 354
     def normalize_become_options(self):
... ...
@@ -55,7 +55,7 @@ __metaclass__ = type
55 55
 
56 56
 from collections import Mapping, MutableSequence, Set
57 57
 
58
-from ansible.module_utils.six import string_types, text_type
58
+from ansible.module_utils.six import string_types, text_type, binary_type
59 59
 from ansible.module_utils._text import to_text
60 60
 
61 61
 
... ...
@@ -70,15 +70,24 @@ class AnsibleUnsafeText(text_type, AnsibleUnsafe):
70 70
     pass
71 71
 
72 72
 
73
+class AnsibleUnsafeBytes(binary_type, AnsibleUnsafe):
74
+    pass
75
+
76
+
73 77
 class UnsafeProxy(object):
74 78
     def __new__(cls, obj, *args, **kwargs):
79
+        if isinstance(obj, AnsibleUnsafe):
80
+            # Already marked unsafe
81
+            return obj
82
+
75 83
         # In our usage we should only receive unicode strings.
76 84
         # This conditional and conversion exists to sanity check the values
77 85
         # we're given but we may want to take it out for testing and sanitize
78 86
         # our input instead.
87
+        # Note that this does the wrong thing if we're *intentionall* passing a byte string to this
88
+        # function.
79 89
         if isinstance(obj, string_types):
80
-            obj = to_text(obj, errors='surrogate_or_strict')
81
-            return AnsibleUnsafeText(obj)
90
+            obj = AnsibleUnsafeText(to_text(obj, errors='surrogate_or_strict'))
82 91
         return obj
83 92
 
84 93