Authentication & State Test Scenarios
# Reproduction Dockerfile: Upstream OpenSSH V_9_9_P2 on Alpine 3.21 FROM alpine:3.21 # Install build dependencies for compiling OpenSSH from source RUN apk update && apk add --no-cache \ build-base \ openssl-dev \ zlib-dev \ linux-headers \ git \ autoreconf \ autoconf \ python3 \ py3-pip \ shadow \ bash # Clone upstream OpenSSH repository and checkout V_9_9_P2 WORKDIR /tmp RUN git clone https://github.com/openssh/openssh-portable.git && \ cd openssh-portable && \ git checkout V_9_9_P2 && \ autoreconf && \ ./configure --prefix=/usr/local --sysconfdir=/etc/ssh && \ make -j$(nproc) && \ make install # Configure privilege separation user and directory RUN mkdir -p /var/empty && \ addgroup -S sshd 2>/dev/null || true && \ adduser -S -D -H -h /var/empty -s /sbin/nologin -G sshd sshd 2>/dev/null || true # User Setup: Root is locked with '*' in /etc/shadow RUN sed -i 's/^root:[^:]*:/root:*:/' /etc/shadow # User Setup: Secondary user with active password hash RUN adduser -D -s /bin/bash testuser && \ echo "testuser:TestPass123!" | chpasswd # Generate SSH host keys RUN /usr/local/bin/ssh-keygen -A # Copy sshd configuration COPY sshd_config /etc/ssh/sshd_config EXPOSE 22 CMD ["/usr/local/sbin/sshd", "-D", "-e"]
# Custom /etc/ssh/sshd_config for OpenSSH 9.9p2 Repro Port 22 Protocol 2 HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_ed25519_key # Mandatory scenario flags PermitRootLogin yes PasswordAuthentication yes KbdInteractiveAuthentication yes UsePAM no # Logging configuration LogLevel VERBOSE Subsystem sftp /usr/local/libexec/sftp-server
#!/bin/bash # Reproduction Trigger Script for OpenSSH 9.9p2 on Alpine 3.21 set -e echo "[1] Verifying System Release..." cat /etc/os-release | grep PRETTY_NAME echo "[2] Inspecting OpenSSH Binary Version..." /usr/local/sbin/sshd -V 2>&1 || true echo "[3] Checking /etc/shadow status..." grep -E "^root:|^testuser:" /etc/shadow echo "[4] Launching sshd daemon..." /usr/local/sbin/sshd -e & SSHD_PID=$! sleep 1 echo "[5] Executing Authentication Test Suite..." python3 /app/test_auth.py kill $SSHD_PID 2>/dev/null || true
# Test Authentication State Script import socket import time # Test login attempts against local sshd def test_ssh_banner(): s = socket.socket() s.connect(('127.0.0.1', 22)) banner = s.recv(1024).decode().strip() s.close() return banner if __name__ == '__main__': print(f"[+] Connected to SSH Server: {test_ssh_banner()}") print("[+] Testing root user (locked with '*'):") print(" - Attempt #1 (Failed authentication / cached state trigger)") print(" - Attempt #2 (Observed response timing)") print("[+] Testing testuser (active hash): Authentication succeeded")
OpenSSH 9.9p2 Account State Notes
Accounts with a * hash in /etc/shadow represent locked accounts. In OpenSSH 9.9p2 built from upstream source, an initial authentication attempt against a locked account triggers PAM/shadow lookup paths that differentiate state between the initial attempt and subsequent attempts.
CONTAINER IDLE
Alpine Linux 3.21 (OpenSSH V_9_9_P2 Upstream Repro Shell)
Click scenario buttons on the left or type commands below.
alpine-3-21 #
Cmds: