How to Add Custom Wordlists for Brute Force Attacks in LazyOwn

You can add custom wordlists in LazyOwn by editing the payload.json configuration file, using the interactive assign command in the shell, or passing the --wordlist flag directly to individual modules.

LazyOwn is an open-source penetration testing framework that centralizes runtime configuration through a parameter dictionary system. Understanding how to add custom wordlists for brute force attacks in LazyOwn allows security professionals to tailor dictionary attacks to specific environments without modifying module source code directly.

Understanding LazyOwn's Centralized Wordlist Architecture

LazyOwn manages all runtime options through a parameter dictionary (self.params) that is populated from payload.json when the interactive shell initializes. According to the source code in lazyown.py, the configuration loading occurs at startup:


# lazyown.py – loading the payload

with open('payload.json', 'r') as file:
    config = json.load(file)
self.params = {
    "wordlist": config.get("wordlist"),
    "usrwordlist": config.get("usrwordlist"),
    ...
}

The wordlist key serves as the default dictionary for all brute-force and fuzzing modules, including lazybrutesshuserenum.sh, lazylfi2rce.py, and lazyown_bprfuzzer.py. Because this value is centralized, updating it once propagates to every tool that references self.params["wordlist"].

Method 1: Edit payload.json for Persistent Configuration

To permanently change the default wordlist for every LazyOwn session, modify the payload.json file in the project root. This approach is ideal when you want to replace the default /usr/share/wordlists/rockyou.txt with a custom dictionary.

Locate the wordlist entry and update the path:

{
  "wordlist": "/home/user/custom_wordlist.txt",
  "usrwordlist": "/home/user/custom_userlist.txt",
  ...
}

After saving the file, restart LazyOwn. The new configuration loads into self.params during initialization (lines 28-31 in lazyown.py), and all subsequent brute-force operations will use your custom list.

Method 2: Use the assign Command for Temporary Changes

For temporary changes that do not persist across sessions, use the built-in assign command within the LazyOwn interactive shell. This method updates self.params in-memory without modifying payload.json.

The assign logic is implemented in lazyown.py (lines 1093-1114) and validates parameter names before updating the dictionary:

$ lazyown
> assign wordlist /opt/wordlists/mylist.txt
[wordlist] assign to /opt/wordlists/mylist.txt
> lazybrutesshuserenum

This approach is particularly useful when switching between wordlists during a single engagement, as the change takes effect immediately for the current session only.

Method 3: Pass Wordlists via CLI Arguments

Individual modules can accept wordlist paths directly through command-line arguments, overriding the global self.params configuration. This method is optimal for running single modules from the terminal without entering the interactive shell.

For example, lazylfi2rce.py defines a required --wordlist flag (line 50) that accepts a custom dictionary path:

$ python3 modules/lazylfi2rce.py \
    --rhost 10.10.10.10 \
    --rport 80 \
    --lhost 10.10.10.11 \
    --lport 4444 \
    --field file \
    --wordlist /tmp/custom_passlist.txt

Similarly, the fuzzer module lazyown_bprfuzzer.py supports the -w or --wordlist argument (lines 226-230), falling back to self.params["wordlist"] only when the argument is omitted.

How Wordlist Parameters Propagate Through the Codebase

Understanding the propagation pipeline helps clarify why these three methods work interchangeably. The flow follows three stages:

  1. Parameter Loading: When LazyOwnShell starts, it calls Config(load_payload()), which reads payload.json into self.params (lines 28-31 in lazyown.py).

  2. Command Construction: Modules build system commands by interpolating the wordlist path directly from self.params. For example, the SSH user enumeration functionality constructs commands as shown in lines 2074-2075:

    wordlist = self.params["wordlist"]
    self.cmd(f"{path}/modules/lazybrutesshuserenum.sh {wordlist} {rhost}")
  3. Shell Execution: The constructed command executes via os.system or subprocess, passing the wordlist path to external scripts like lazybrutesshuserenum.sh, which reads the file from $1 (lines 12-14 and 23).

Because the path is centralized in self.params, any update—whether through JSON editing, the assign command, or CLI arguments—immediately affects all dependent brute-force operations.

Practical Implementation Examples

SSH Brute-Force with Custom Userlists

When performing SSH user enumeration, combine the global wordlist with the usrwordlist parameter to test both custom usernames and passwords:

> assign usrwordlist /opt/wordlists/usernames.txt
> assign wordlist /opt/wordlists/passwords.txt
> lazybrutesshuserenum 192.168.1.100

The lazybrutesshuserenum.sh script receives these paths as positional arguments and iterates through them line-by-line.

Web Fuzzing with lazyown_bprfuzzer.py

The built-in fuzzer allows runtime wordlist specification through the -w flag, or it defaults to self.params["wordlist"] (lines 165-170):

> assign wordlist /usr/share/wordlists/dirbuster/common.txt
> lazyfuzz -u http://target.com/FUZZ -m GET

Or override for a single run:

> lazyfuzz -u http://target.com/login -m POST -w /tmp/custom_paths.txt

Summary

  • Centralized Configuration: LazyOwn stores the default wordlist path in self.params["wordlist"], loaded from payload.json at startup.
  • Three Update Methods: Edit payload.json for permanent changes, use assign wordlist <path> for temporary session changes, or pass --wordlist to individual modules for single executions.
  • Immediate Propagation: Changes to self.params instantly affect all modules including lazybrutesshuserenum.sh, lazylfi2rce.py, and lazyown_bprfuzzer.py.
  • Source Code References: Key implementation details reside in lazyown.py (lines 28-31, 1093-1114, 2074-2075) and various modules in the modules/ directory.

Frequently Asked Questions

Where does LazyOwn store the default wordlist configuration?

LazyOwn stores the default configuration in payload.json at the project root. The wordlist key within this JSON file defaults to /usr/share/wordlists/rockyou.txt and is loaded into self.params when the shell initializes (lines 28-31 in lazyown.py).

Can I use multiple wordlists simultaneously in LazyOwn?

Yes, LazyOwn supports separate wordlists for different purposes through distinct parameter keys. Use wordlist for password lists and usrwordlist for username lists. Both can be configured via payload.json or the assign command, allowing simultaneous brute-force attacks against multiple vectors.

Do I need to restart LazyOwn after using the assign command?

No, the assign command updates self.params in-memory immediately (lines 1093-1114 in lazyown.py). Changes take effect instantly for subsequent commands in the current session, though they do not persist after exiting the shell unless you also update payload.json.

Which modules support the --wordlist CLI argument?

Not all modules accept CLI arguments, but several key ones do, including lazylfi2rce.py (line 50) and lazyown_bprfuzzer.py (lines 226-230). Modules written as bash scripts, such as lazybrutesshuserenum.sh, receive the wordlist path as a positional argument constructed from self.params["wordlist"] rather than through direct CLI parsing.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →