Skip to content

Command injection in bundled netntlm.pl via shell metacharacters in the capture file name #6011

Description

@nuartvision

Command injection in run/netntlm.pl

Advisory fields

  • Title: netntlm.pl executes shell commands from untrusted capture file name
  • Vulnerability class: Command injection
  • Affected version/commit: b544069b3 (bleeding-jumbo)
  • Affected code path:
    • run/netntlm.pl:68
    • run/netntlm.pl:79
    • run/netntlm.pl:111
    • run/netntlm.pl:146
    • run/netntlm.pl:181
  • Trust boundary crossed: An attacker-controlled hash/capture file is passed to a helper script that the user is expected to run on security data. The script then interpolates the file name directly into a shell pipeline (open ... "|" and system(...)), so untrusted file-system metadata becomes shell code.

Description

run/netntlm.pl is a bundled helper that takes an LM/NTLM challenge/response capture file (--file) and orchestrates John runs. The file name is interpolated unescaped into multiple shell command strings:

open (HAND, "$JOHN -format:netlm -show $opt{'file'} |") || die(...);
...
open (HAND, "$JOHN -format:netntlm -config:$tmpconf -wordlist:$tmpdict -rules -user:\"$account\" -session:$tmpsession $opt{'file'} |") || die(...);
...
system("$JOHN -format:netlm -config:$tmpconf -external:HalfLM -incremental:LM -session:$tmpsession $tmppasswd");

Because Perl open with a trailing | invokes a shell, and system with a single string also invokes a shell, shell metacharacters in $opt{'file'} are executed before john is even started. The account name parsed from previously cracked output is similarly double-quoted and susceptible to backtick/$() injection, but the file-name vector is the simplest to reproduce.

Preconditions

  • The attacker can provide or influence the name of the capture file passed to netntlm.pl.
  • The victim runs netntlm.pl --file <attacker-influenced name>.
  • The injected command must avoid / characters in the file name itself because Linux file names cannot contain /. Commands that use relative paths or shell builtins work directly; arbitrary absolute-path commands can be staged with a first-stage download/relative payload.

Step-by-step reproduction

  1. Create a capture file whose name contains an embedded shell command. The following uses backticks to run id > pwn.txt (relative to the current working directory):
# create a file literally named: /tmp/evil`id>pwn.txt`.lc
python3 - <<'PY'
open('/tmp/evil`id>pwn.txt`.lc', 'w').close()
PY
  1. Run the helper:
cd /home/john/run
perl netntlm.pl --file '/tmp/evil`id>pwn.txt`.lc'
  1. Observe that the injected command executes before the script reports "No seed supplied for testing." and that pwn.txt is created in the current directory:
uid=1000(test) gid=1000(test) groups=1000(test),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),117(netdev),1001(docker)

The uid=... line comes from the shell pipeline spawned by netntlm.pl, not from John output.

Impact

An attacker who can get a user to run netntlm.pl on a maliciously named file achieves arbitrary command execution as the user running the script. In a security-research or SOC workflow where analysts run helper scripts on untrusted capture files, this can lead to local privilege escalation if the script is invoked from a privileged wrapper, or to data exfiltration / malware installation otherwise.

Why this is not just an unsafe configuration

The vulnerability is in the script's handling of a normal product input (the capture file path). No optional or knowingly dangerous configuration is required; the script is intended to be run on third-party capture files.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions