zzinter


Checking for sudo privileges of the zzinter user on the target system after making the lateral movement

zzinter@ssg:~$ sudo -l
Matching Defaults entries for zzinter on ssg:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
 
User zzinter may run the following commands on ssg:
    (root) NOPASSWD: /opt/sign_key.sh

The zzinter user is able to execute /opt/sign_key.sh as the root user without getting prompted for password

/opt/sign_key.sh


zzinter@ssg:~$ cat /opt/sign_key.sh
#!/bin/bash
 
usage () {
    echo "Usage: $0 <ca_file> <public_key_file> <username> <principal> <serial>"
    exit 1
}
 
if [ "$#" -ne 5 ]; then
    usage
fi
 
ca_file="$1"
public_key_file="$2"
username="$3"
principal="$4"
serial="$5"
 
if [ ! -f "$ca_file" ]; then
    echo "Error: CA file '$ca_file' not found."
    usage
fi
 
if [[ $ca == "/etc/ssh/ca-it" ]]; then
    echo "Error: Use API for signing with this CA."
    usage
fi
 
itca=$(cat /etc/ssh/ca-it)
ca=$(cat "$ca_file")
if [[ $itca == $ca ]]; then
    echo "Error: Use API for signing with this CA."
    usage
fi
 
if [ ! -f "$public_key_file" ]; then
    echo "Error: Public key file '$public_key_file' not found."
    usage
fi
 
supported_principals="webserver,analytics,support,security"
IFS=',' read -ra principal <<< "$principal_str"
for word in "${principal[@]}"; do
    if ! echo "$supported_principals" | grep -qw "$word"; then
        echo "Error: '$word' is not a supported principal."
        echo "Choose from:"
        echo "    webserver - external web servers - webadmin user"
        echo "    analytics - analytics team databases - analytics user"
        echo "    support - IT support server - support user"
        echo "    security - SOC servers - support user"
        echo
        usage
    fi
done
 
if ! [[ $serial =~ ^[0-9]+$ ]]; then
    echo "Error: '$serial' is not a number."
    usage
fi
 
ssh-keygen -s "$ca_file" -z "$serial" -I "$username" -V -1w:forever -n "$principals" "$public_key_name"

The sign_key.sh script appears very similar to the sign_key_api.sh script, seen in the Docker host. The provided Bash script signs an SSH public key using a specified CA (Certificate Authority) file, ensuring several validations before proceeding. Here’s a summary of its functionality:

  1. Usage and Argument Validation:
    • Ensures exactly five arguments are provided: CA file, public key file, username, principal, and serial number.
    • If incorrect arguments are provided, it displays usage instructions and exits.
  2. File Existence Checks:
    • Confirms the CA file and public key file exist. If not, it prints an error and exits.
  3. CA Validation:
    • Prevents the use of a specific internal CA (/etc/ssh/ca-it) by comparing its contents with the provided CA file. If matched, it advises using an API for signing and exits.
  4. Principal Validation:
    • Validates that the provided principal(s) are among the supported list: webserver, analytics, support, and security.
    • If an unsupported principal is found, it prints an error, lists the supported principals, and exits.
  5. Serial Number Validation:
    • Checks if the provided serial number is a valid number. If not, it prints an error and exits.
  6. SSH Key Signing:
    • Uses ssh-keygen to sign the public key with the provided CA file, serial number, username, and principals if all validations pass.

Vulnerability


The script also has potential vulnerabilities related to Bash wildcard expansion (also known as globbing) due to how it handles user inputs, particularly in the final ssh-keygen command and possibly elsewhere.

  1. Command Injection via User Inputs:
    • The inputs provided by the user ($ca_file, $public_key_file, $username, $principal, and $serial) are not properly sanitized. If any of these inputs contain special characters or patterns, they could be exploited.
  2. Special Characters in Filenames:
    • If the ca_file or public_key_file contains special characters like *, ?, or [ that are interpreted by the shell, it could lead to unintended behavior.
  3. Injection through Principal Names:
    • The principal string is split into an array and used directly in a command without sanitization. A crafted input could manipulate the command execution.