From 8cf4f4bfda968ab526c1a601ea1030bbaccaba17 Mon Sep 17 00:00:00 2001
From: Norbert Pocs <norbertpocs0@gmail.com>
Date: Tue, 10 Oct 2023 10:28:47 +0200
Subject: [PATCH 6/9] CVE-2023-6004: torture_proxycommand: Add test for
 proxycommand injection

Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>

Conflict: NA
Reference:https://git.libssh.org/projects/libssh.git/patch/?id=8cf4f4bfda968ab526c1a601ea1030bbaccaba17
---
 tests/client/torture_proxycommand.c | 53 +++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/tests/client/torture_proxycommand.c b/tests/client/torture_proxycommand.c
index c04ff2ab..dc17f3d8 100644
--- a/tests/client/torture_proxycommand.c
+++ b/tests/client/torture_proxycommand.c
@@ -161,6 +161,56 @@ static void torture_options_set_proxycommand_ssh_stderr(void **state)
     assert_int_equal(rc & O_RDWR, O_RDWR);
 }
 
+static void torture_options_proxycommand_injection(void **state)
+{
+    struct torture_state *s = *state;
+    struct passwd *pwd = NULL;
+    const char *malicious_host = "`echo foo > mfile`";
+    const char *command = "nc %h %p";
+    char *current_dir = NULL;
+    char *malicious_file_path = NULL;
+    int mfp_len;
+    int verbosity = torture_libssh_verbosity();
+    struct stat sb;
+    int rc;
+
+    pwd = getpwnam("bob");
+    assert_non_null(pwd);
+
+    rc = setuid(pwd->pw_uid);
+    assert_return_code(rc, errno);
+
+    s->ssh.session = ssh_new();
+    assert_non_null(s->ssh.session);
+
+    ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
+    // if we would be checking the rc, this should fail
+    ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, malicious_host);
+
+    ssh_options_set(s->ssh.session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
+
+    rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROXYCOMMAND, command);
+    assert_int_equal(rc, 0);
+    rc = ssh_connect(s->ssh.session);
+    assert_ssh_return_code_equal(s->ssh.session, rc, SSH_ERROR);
+
+    current_dir = torture_get_current_working_dir();
+    assert_non_null(current_dir);
+    mfp_len = strlen(current_dir) + 6;
+    malicious_file_path = malloc(mfp_len);
+    assert_non_null(malicious_file_path);
+    rc = snprintf(malicious_file_path, mfp_len,
+                  "%s/mfile", current_dir);
+    assert_int_equal(rc, mfp_len);
+    free(current_dir);
+    rc = stat(malicious_file_path, &sb);
+    assert_int_not_equal(rc, 0);
+
+    // cleanup
+    remove(malicious_file_path);
+    free(malicious_file_path);
+}
+
 int torture_run_tests(void) {
     int rc;
     struct CMUnitTest tests[] = {
@@ -176,6 +226,9 @@ int torture_run_tests(void) {
         cmocka_unit_test_setup_teardown(torture_options_set_proxycommand_ssh_stderr,
                                         session_setup,
                                         session_teardown),
+        cmocka_unit_test_setup_teardown(torture_options_proxycommand_injection,
+                                        NULL,
+                                        session_teardown),
     };
 
 
-- 
2.33.0

