test_client.py (salt-3002.1) | : | test_client.py (salt-3002.2) | ||
---|---|---|---|---|
skipping to change at line 179 | skipping to change at line 179 | |||
"password": "saltdev", | "password": "saltdev", | |||
"eauth": "auto", | "eauth": "auto", | |||
} | } | |||
def setUp(self): | def setUp(self): | |||
""" | """ | |||
Set up a NetapiClient instance | Set up a NetapiClient instance | |||
""" | """ | |||
opts = AdaptedConfigurationTestCaseMixin.get_config("client_config").cop y() | opts = AdaptedConfigurationTestCaseMixin.get_config("client_config").cop y() | |||
self.netapi = salt.netapi.NetapiClient(opts) | self.netapi = salt.netapi.NetapiClient(opts) | |||
self.priv_file = os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "key_test") | self.priv_file = os.path.join(RUNTIME_VARS.TMP_SSH_CONF_DIR, "client_key ") | |||
self.rosters = os.path.join(RUNTIME_VARS.TMP_CONF_DIR) | self.rosters = os.path.join(RUNTIME_VARS.TMP_CONF_DIR) | |||
self.roster_file = os.path.join(self.rosters, "roster") | ||||
def tearDown(self): | def tearDown(self): | |||
del self.netapi | del self.netapi | |||
@classmethod | @classmethod | |||
def setUpClass(cls): | def setUpClass(cls): | |||
cls.post_webserver = Webserver(handler=SaveRequestsPostHandler) | cls.post_webserver = Webserver(handler=SaveRequestsPostHandler) | |||
cls.post_webserver.start() | cls.post_webserver.start() | |||
cls.post_web_root = cls.post_webserver.web_root | cls.post_web_root = cls.post_webserver.web_root | |||
cls.post_web_handler = cls.post_webserver.handler | cls.post_web_handler = cls.post_webserver.handler | |||
skipping to change at line 204 | skipping to change at line 205 | |||
cls.post_webserver.stop() | cls.post_webserver.stop() | |||
del cls.post_webserver | del cls.post_webserver | |||
@slowTest | @slowTest | |||
def test_ssh(self): | def test_ssh(self): | |||
low = { | low = { | |||
"client": "ssh", | "client": "ssh", | |||
"tgt": "localhost", | "tgt": "localhost", | |||
"fun": "test.ping", | "fun": "test.ping", | |||
"ignore_host_keys": True, | "ignore_host_keys": True, | |||
"roster_file": "roster", | "roster_file": self.roster_file, | |||
"rosters": [self.rosters], | "rosters": [self.rosters], | |||
"ssh_priv": self.priv_file, | "ssh_priv": self.priv_file, | |||
} | } | |||
low.update(self.eauth_creds) | low.update(self.eauth_creds) | |||
ret = self.netapi.run(low) | ret = self.netapi.run(low) | |||
self.assertIn("localhost", ret) | self.assertIn("localhost", ret) | |||
self.assertIn("return", ret["localhost"]) | self.assertIn("return", ret["localhost"]) | |||
skipping to change at line 295 | skipping to change at line 296 | |||
def test_shell_inject_ssh_priv(self): | def test_shell_inject_ssh_priv(self): | |||
""" | """ | |||
Verify CVE-2020-16846 for ssh_priv variable | Verify CVE-2020-16846 for ssh_priv variable | |||
""" | """ | |||
# ZDI-CAN-11143 | # ZDI-CAN-11143 | |||
path = "/tmp/test-11143" | path = "/tmp/test-11143" | |||
self.addCleanup(self.cleanup_file, path) | self.addCleanup(self.cleanup_file, path) | |||
self.addCleanup(self.cleanup_file, "aaa") | self.addCleanup(self.cleanup_file, "aaa") | |||
self.addCleanup(self.cleanup_file, "aaa.pub") | self.addCleanup(self.cleanup_file, "aaa.pub") | |||
self.addCleanup(self.cleanup_dir, "aaa|id>") | self.addCleanup(self.cleanup_dir, "aaa|id>") | |||
tgt = "www.zerodayinitiative.com" | ||||
low = { | low = { | |||
"roster": "cache", | "roster": "cache", | |||
"client": "ssh", | "client": "ssh", | |||
"tgt": "www.zerodayinitiative.com", | "tgt": tgt, | |||
"ssh_priv": "aaa|id>{} #".format(path), | "ssh_priv": "aaa|id>{} #".format(path), | |||
"fun": "test.ping", | "fun": "test.ping", | |||
"eauth": "auto", | "eauth": "auto", | |||
"username": "saltdev_auto", | "username": "saltdev_auto", | |||
"password": "saltdev", | "password": "saltdev", | |||
"roster_file": self.roster_file, | ||||
"rosters": self.rosters, | ||||
} | } | |||
ret = self.netapi.run(low) | ret = self.netapi.run(low) | |||
self.assertFalse(ret[tgt]["stdout"]) | ||||
self.assertTrue(ret[tgt]["stderr"]) | ||||
self.assertFalse(os.path.exists(path)) | self.assertFalse(os.path.exists(path)) | |||
@slowTest | @slowTest | |||
def test_shell_inject_tgt(self): | def test_shell_inject_tgt(self): | |||
""" | """ | |||
Verify CVE-2020-16846 for tgt variable | Verify CVE-2020-16846 for tgt variable | |||
""" | """ | |||
# ZDI-CAN-11167 | # ZDI-CAN-11167 | |||
path = "/tmp/test-11167" | path = "/tmp/test-11167" | |||
self.addCleanup(self.cleanup_file, path) | self.addCleanup(self.cleanup_file, path) | |||
low = { | low = { | |||
"roster": "cache", | "roster": "cache", | |||
"client": "ssh", | "client": "ssh", | |||
"tgt": "root|id>{} #@127.0.0.1".format(path), | "tgt": "root|id>{} #@127.0.0.1".format(path), | |||
"roster_file": "/tmp/salt-tests-tmpdir/config/roaster", | "roster_file": self.roster_file, | |||
"rosters": "/", | "rosters": "/", | |||
"fun": "test.ping", | "fun": "test.ping", | |||
"eauth": "auto", | "eauth": "auto", | |||
"username": "saltdev_auto", | "username": "saltdev_auto", | |||
"password": "saltdev", | "password": "saltdev", | |||
"ignore_host_keys": True, | ||||
} | } | |||
ret = self.netapi.run(low) | ret = self.netapi.run(low) | |||
self.assertFalse(ret["127.0.0.1"]["stdout"]) | ||||
self.assertTrue(ret["127.0.0.1"]["stderr"]) | ||||
self.assertFalse(os.path.exists(path)) | self.assertFalse(os.path.exists(path)) | |||
@slowTest | @slowTest | |||
def test_shell_inject_ssh_options(self): | def test_shell_inject_ssh_options(self): | |||
""" | """ | |||
Verify CVE-2020-16846 for ssh_options | Verify CVE-2020-16846 for ssh_options | |||
""" | """ | |||
# ZDI-CAN-11169 | # ZDI-CAN-11169 | |||
path = "/tmp/test-11169" | path = "/tmp/test-11169" | |||
self.addCleanup(self.cleanup_file, path) | self.addCleanup(self.cleanup_file, path) | |||
low = { | low = { | |||
"roster": "cache", | "roster": "cache", | |||
"client": "ssh", | "client": "ssh", | |||
"tgt": "127.0.0.1", | "tgt": "127.0.0.1", | |||
"renderer": "cheetah", | "renderer": "jinja|yaml", | |||
"fun": "test.ping", | "fun": "test.ping", | |||
"eauth": "auto", | "eauth": "auto", | |||
"username": "saltdev_auto", | "username": "saltdev_auto", | |||
"password": "saltdev", | "password": "saltdev", | |||
"roster_file": "/tmp/salt-tests-tmpdir/config/roaster", | "roster_file": self.roster_file, | |||
"rosters": "/", | "rosters": "/", | |||
"ssh_options": ["|id>{} #".format(path), "lol"], | "ssh_options": ["|id>{} #".format(path), "lol"], | |||
} | } | |||
ret = self.netapi.run(low) | ret = self.netapi.run(low) | |||
self.assertFalse(ret["127.0.0.1"]["stdout"]) | ||||
self.assertTrue(ret["127.0.0.1"]["stderr"]) | ||||
self.assertFalse(os.path.exists(path)) | self.assertFalse(os.path.exists(path)) | |||
@slowTest | @slowTest | |||
def test_shell_inject_ssh_port(self): | def test_shell_inject_ssh_port(self): | |||
""" | """ | |||
Verify CVE-2020-16846 for ssh_port variable | Verify CVE-2020-16846 for ssh_port variable | |||
""" | """ | |||
# ZDI-CAN-11172 | # ZDI-CAN-11172 | |||
path = "/tmp/test-11172" | path = "/tmp/test-11172" | |||
self.addCleanup(self.cleanup_file, path) | self.addCleanup(self.cleanup_file, path) | |||
low = { | low = { | |||
"roster": "cache", | "roster": "cache", | |||
"client": "ssh", | "client": "ssh", | |||
"tgt": "127.0.0.1", | "tgt": "127.0.0.1", | |||
"renderer": "cheetah", | "renderer": "jinja|yaml", | |||
"fun": "test.ping", | "fun": "test.ping", | |||
"eauth": "auto", | "eauth": "auto", | |||
"username": "saltdev_auto", | "username": "saltdev_auto", | |||
"password": "saltdev", | "password": "saltdev", | |||
"roster_file": "/tmp/salt-tests-tmpdir/config/roaster", | "roster_file": self.roster_file, | |||
"rosters": "/", | "rosters": "/", | |||
"ssh_port": "hhhhh|id>{} #".format(path), | "ssh_port": "hhhhh|id>{} #".format(path), | |||
"ignore_host_keys": True, | ||||
} | } | |||
ret = self.netapi.run(low) | ret = self.netapi.run(low) | |||
self.assertFalse(ret["127.0.0.1"]["stdout"]) | ||||
self.assertTrue(ret["127.0.0.1"]["stderr"]) | ||||
self.assertFalse(os.path.exists(path)) | self.assertFalse(os.path.exists(path)) | |||
@slowTest | @slowTest | |||
def test_shell_inject_remote_port_forwards(self): | def test_shell_inject_remote_port_forwards(self): | |||
""" | """ | |||
Verify CVE-2020-16846 for remote_port_forwards variable | Verify CVE-2020-16846 for remote_port_forwards variable | |||
""" | """ | |||
# ZDI-CAN-11173 | # ZDI-CAN-11173 | |||
path = "/tmp/test-1173" | path = "/tmp/test-1173" | |||
self.addCleanup(self.cleanup_file, path) | self.addCleanup(self.cleanup_file, path) | |||
low = { | low = { | |||
"roster": "cache", | "roster": "cache", | |||
"client": "ssh", | "client": "ssh", | |||
"tgt": "127.0.0.1", | "tgt": "127.0.0.1", | |||
"renderer": "cheetah", | "renderer": "jinja|yaml", | |||
"fun": "test.ping", | "fun": "test.ping", | |||
"roster_file": "/tmp/salt-tests-tmpdir/config/roaster", | "roster_file": self.roster_file, | |||
"rosters": "/", | "rosters": "/", | |||
"ssh_remote_port_forwards": "hhhhh|id>{} #, lol".format(path), | "ssh_remote_port_forwards": "hhhhh|id>{} #, lol".format(path), | |||
"eauth": "auto", | "eauth": "auto", | |||
"username": "saltdev_auto", | "username": "saltdev_auto", | |||
"password": "saltdev", | "password": "saltdev", | |||
"ignore_host_keys": True, | ||||
} | } | |||
ret = self.netapi.run(low) | ret = self.netapi.run(low) | |||
self.assertFalse(ret["127.0.0.1"]["stdout"]) | ||||
self.assertTrue(ret["127.0.0.1"]["stderr"]) | ||||
self.assertFalse(os.path.exists(path)) | self.assertFalse(os.path.exists(path)) | |||
@requires_sshd_server | @pytest.mark.requires_sshd_server | |||
class NetapiSSHClientAuthTest(SSHCase): | class NetapiSSHClientAuthTest(SSHCase): | |||
USERA = "saltdev" | USERA = "saltdev-auth" | |||
USERA_PWD = "saltdev" | USERA_PWD = "saltdev" | |||
def setUp(self): | def setUp(self): | |||
""" | """ | |||
Set up a NetapiClient instance | Set up a NetapiClient instance | |||
""" | """ | |||
opts = salt.config.client_config(os.path.join(TMP_CONF_DIR, "master")) | opts = salt.config.client_config( | |||
os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "master") | ||||
) | ||||
naopts = copy.deepcopy(opts) | naopts = copy.deepcopy(opts) | |||
naopts["ignore_host_keys"] = True | naopts["ignore_host_keys"] = True | |||
self.netapi = salt.netapi.NetapiClient(naopts) | self.netapi = salt.netapi.NetapiClient(naopts) | |||
self.priv_file = os.path.join(RUNTIME_VARS.TMP_SSH_CONF_DIR, "client_key ") | self.priv_file = os.path.join(RUNTIME_VARS.TMP_SSH_CONF_DIR, "client_key ") | |||
self.rosters = os.path.join(RUNTIME_VARS.TMP_CONF_DIR) | self.rosters = os.path.join(RUNTIME_VARS.TMP_CONF_DIR) | |||
self.roster_file = os.path.join(self.rosters, "roster") | ||||
# Initialize salt-ssh | # Initialize salt-ssh | |||
self.run_function("test.ping") | self.run_function("test.ping") | |||
self.mod_case = ModuleCase() | self.mod_case = ModuleCase() | |||
try: | try: | |||
add_user = self.mod_case.run_function( | add_user = self.mod_case.run_function( | |||
"user.add", [self.USERA], createhome=False | "user.add", [self.USERA], createhome=False | |||
) | ) | |||
self.assertTrue(add_user) | self.assertTrue(add_user) | |||
if salt.utils.platform.is_darwin(): | if salt.utils.platform.is_darwin(): | |||
hashed_password = self.USERA_PWD | hashed_password = self.USERA_PWD | |||
skipping to change at line 464 | skipping to change at line 484 | |||
@slowTest | @slowTest | |||
def test_ssh_auth_bypass(self): | def test_ssh_auth_bypass(self): | |||
""" | """ | |||
CVE-2020-25592 - Bogus eauth raises exception. | CVE-2020-25592 - Bogus eauth raises exception. | |||
""" | """ | |||
low = { | low = { | |||
"roster": "cache", | "roster": "cache", | |||
"client": "ssh", | "client": "ssh", | |||
"tgt": "127.0.0.1", | "tgt": "127.0.0.1", | |||
"renderer": "cheetah", | "renderer": "jinja|yaml", | |||
"fun": "test.ping", | "fun": "test.ping", | |||
"roster_file": "/tmp/salt-tests-tmpdir/config/roaster", | "roster_file": self.roster_file, | |||
"rosters": "/", | "rosters": "/", | |||
"eauth": "xx", | "eauth": "xx", | |||
"ignore_host_keys": True, | ||||
} | } | |||
with self.assertRaises(salt.exceptions.EauthAuthenticationError): | with self.assertRaises(salt.exceptions.EauthAuthenticationError): | |||
ret = self.netapi.run(low) | ret = self.netapi.run(low) | |||
@slowTest | @slowTest | |||
def test_ssh_auth_valid(self): | def test_ssh_auth_valid(self): | |||
""" | """ | |||
CVE-2020-25592 - Valid eauth works as expected. | CVE-2020-25592 - Valid eauth works as expected. | |||
""" | """ | |||
low = { | low = { | |||
"client": "ssh", | "client": "ssh", | |||
"tgt": "localhost", | "tgt": "localhost", | |||
"fun": "test.ping", | "fun": "test.ping", | |||
"roster_file": "roster", | "roster_file": "roster", | |||
"rosters": [self.rosters], | "rosters": [self.rosters], | |||
"ssh_priv": self.priv_file, | "ssh_priv": self.priv_file, | |||
"eauth": "pam", | "eauth": "pam", | |||
"username": "saltdev", | "username": self.USERA, | |||
"password": "saltdev", | "password": self.USERA_PWD, | |||
} | } | |||
ret = self.netapi.run(low) | ret = self.netapi.run(low) | |||
assert "localhost" in ret | assert "localhost" in ret | |||
assert ret["localhost"]["return"] is True | assert ret["localhost"]["return"] is True | |||
@slowTest | @slowTest | |||
def test_ssh_auth_invalid(self): | def test_ssh_auth_invalid(self): | |||
""" | """ | |||
CVE-2020-25592 - Wrong password raises exception. | CVE-2020-25592 - Wrong password raises exception. | |||
""" | """ | |||
low = { | low = { | |||
"client": "ssh", | "client": "ssh", | |||
"tgt": "localhost", | "tgt": "localhost", | |||
"fun": "test.ping", | "fun": "test.ping", | |||
"roster_file": "roster", | "roster_file": "roster", | |||
"rosters": [self.rosters], | "rosters": [self.rosters], | |||
"ssh_priv": self.priv_file, | "ssh_priv": self.priv_file, | |||
"eauth": "pam", | "eauth": "pam", | |||
"username": "saltdev", | "username": self.USERA, | |||
"password": "notvalidpassword", | "password": "notvalidpassword", | |||
} | } | |||
with self.assertRaises(salt.exceptions.EauthAuthenticationError): | with self.assertRaises(salt.exceptions.EauthAuthenticationError): | |||
ret = self.netapi.run(low) | ret = self.netapi.run(low) | |||
@slowTest | @slowTest | |||
def test_ssh_auth_invalid_acl(self): | def test_ssh_auth_invalid_acl(self): | |||
""" | """ | |||
CVE-2020-25592 - Eauth ACL enforced. | CVE-2020-25592 - Eauth ACL enforced. | |||
""" | """ | |||
low = { | low = { | |||
"client": "ssh", | "client": "ssh", | |||
"tgt": "localhost", | "tgt": "localhost", | |||
"fun": "at.at", | "fun": "at.at", | |||
"args": ["12:05am", "echo foo"], | "args": ["12:05am", "echo foo"], | |||
"roster_file": "roster", | "roster_file": "roster", | |||
"rosters": [self.rosters], | "rosters": [self.rosters], | |||
"ssh_priv": self.priv_file, | "ssh_priv": self.priv_file, | |||
"eauth": "pam", | "eauth": "pam", | |||
"username": "saltdev", | "username": self.USERA, | |||
"password": "notvalidpassword", | "password": "notvalidpassword", | |||
} | } | |||
with self.assertRaises(salt.exceptions.EauthAuthenticationError): | with self.assertRaises(salt.exceptions.EauthAuthenticationError): | |||
ret = self.netapi.run(low) | ret = self.netapi.run(low) | |||
@slowTest | @slowTest | |||
def test_ssh_auth_token(self): | def test_ssh_auth_token(self): | |||
""" | """ | |||
CVE-2020-25592 - Eauth tokens work as expected. | CVE-2020-25592 - Eauth tokens work as expected. | |||
""" | """ | |||
low = { | low = { | |||
"eauth": "pam", | "eauth": "pam", | |||
"username": "saltdev", | "username": self.USERA, | |||
"password": "saltdev", | "password": self.USERA_PWD, | |||
} | } | |||
ret = self.netapi.loadauth.mk_token(low) | ret = self.netapi.loadauth.mk_token(low) | |||
assert "token" in ret and ret["token"] | assert "token" in ret and ret["token"] | |||
low = { | low = { | |||
"client": "ssh", | "client": "ssh", | |||
"tgt": "localhost", | "tgt": "localhost", | |||
"fun": "test.ping", | "fun": "test.ping", | |||
"roster_file": "roster", | "roster_file": "roster", | |||
"rosters": [self.rosters], | "rosters": [self.rosters], | |||
"ssh_priv": self.priv_file, | "ssh_priv": self.priv_file, | |||
End of changes. 32 change blocks. | ||||
21 lines changed or deleted | 42 lines changed or added |