Code Monkey home page Code Monkey logo

legba's Introduction

Join the project community on our server!


Release Crate Docker Hub Rust Report Software License

Legba is a multiprotocol credentials bruteforcer / password sprayer and enumerator built with Rust and the Tokio asynchronous runtime in order to achieve better performances and stability while consuming less resources than similar tools (see the benchmark below).

For the building instructions, usage and the complete list of options check the project Wiki. For a list of recipes you can check the legba cookbook repository.

Supported Protocols/Features:

AMQP (ActiveMQ, RabbitMQ, Qpid, JORAM and Solace), Cassandra/ScyllaDB, DNS subdomain enumeration, FTP, HTTP (basic authentication, NTLMv1, NTLMv2, multipart form, custom requests with CSRF support, files/folders enumeration, virtual host enumeration), IMAP, Kerberos pre-authentication and user enumeration, LDAP, MongoDB, MQTT, Microsoft SQL, MySQL, Oracle, PostgreSQL, POP3, RDP, Redis, Samba, SSH / SFTP, SMTP, Socks5, STOMP (ActiveMQ, RabbitMQ, HornetQ and OpenMQ), TCP port scanning, Telnet, VNC.

Benchmark

Here's a benchmark of legba versus thc-hydra running some common plugins, both targeting the same test servers on localhost. The benchmark has been executed on a macOS laptop with an M1 Max CPU, using a wordlist of 1000 passwords with the correct one being on the last line. Legba was compiled in release mode, Hydra compiled and installed via brew formula.

Far from being an exhaustive benchmark (some legba features are simply not supported by hydra, such as CSRF token grabbing), this table still gives a clear idea of how using an asynchronous runtime can drastically improve performances.

Test Name Hydra Tasks Hydra Time Legba Tasks Legba Time
HTTP basic auth 16 7.100s 10 1.560s (🚀 4.5x faster)
HTTP POST login (wordpress) 16 14.854s 10 5.045s (🚀 2.9x faster)
SSH 16 7m29.85s * 10 8.150s (🚀 55.1x faster)
MySQL 4 ** 9.819s 4 ** 2.542s (🚀 3.8x faster)
Microsoft SQL 16 7.609s 10 4.789s (🚀 1.5x faster)

* While this result would suggest a default delay between connection attempts used by Hydra. I've tried to study the source code to find such delay but to my knowledge there's none. For some reason it's simply very slow.
** For MySQL hydra automatically reduces the amount of tasks to 4, therefore legba's concurrency level has been adjusted to 4 as well.

License

Legba is released under the GPL 3 license. To see the licenses of the project dependencies, install cargo license with cargo install cargo-license and then run cargo license.

legba's People

Contributors

angelopoerio avatar cyberroute avatar dimtgsn avatar evilsocket avatar jeffmcjunkin avatar kpcyrd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

legba's Issues

GPGPU implementation by OpenCL, CUDA and similar

One of main purposes of legba is to act as a bruteforcer, so the user sets a protocol and the target is tested by the provided credentials.

Let's guess two scenarios:

Scenario 1

I manage an IT infrastructure on my company and I wish to test the authentication credentials on 100 endpoints by using several legba plugins (protocols). We could have single endpoints exposing different services by different protocols.

Let's assume also this multi-target mode request has been implemented #3

Scenario 2

I need to use a huge user/password wordlist for a single target.

Proposal

Let's consider the current benchmark vs Hydra, in order to improve more the speed of this process in both of the scenarios

Could there be a sense to implement the choice to execute computational processing by GPU instead of CPU by OpenCL libraries (or similar) when legba must manage multitarget or when it must parallelize the sent authentication requests?

The only limit I see is on the target side, how many auth requests at time unit is able to manage.

Hashcat has a similar functionality even if for a different purpose.

My 2 cents: https://stackoverflow.com/questions/9205915/opencl-cpu-device-vs-gpu-device

HTTP Plugin Path Normalization

Hi @evilsocket

First, thanks for the amazing tool! :)
I'm trying to use http.enum with a payload that contains "foo/bar/../" and playing against my own server, I noticed the path was normalized to "foo/". This is unintended if a user wants to check against some path traversal.
I tried to apply a patch right here: https://github.com/evilsocket/legba/blob/main/src/plugins/http/mod.rs#L118, but it didn't work. Sorry, I'm totally a noob in Rust.
It seems the Crate url (https://docs.rs/url/latest/url/) does not completely disable path normalization with unwrap(), as you can see here: https://stackoverflow.com/questions/62335488/how-to-obtain-raw-url-path-in-rust. If that's true, a refactor would be required to implement a flag to totally disable path normalization.
Not sure if you have any intention to add such a flag to legba.

Thanks!
Ricardo Iramar

Library not loaded

Hi, i installed legba with cargo install legba on M2 and i got the following error when i ran legba command. Can you help me to fix this? Thanks.

⋊> ~ legba
dyld[44264]: Library not loaded: /opt/homebrew/opt/samba/lib/libsmbclient.inst.dylib
  Referenced from: <CAF528BC-A7BE-3BEF-8426-A9789F8CA33F> /Users/eejay/.cargo/bin/legba
  Reason: tried: '/opt/homebrew/opt/samba/lib/libsmbclient.inst.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/opt/samba/lib/libsmbclient.inst.dylib' (no such file), '/opt/homebrew/opt/samba/lib/libsmbclient.inst.dylib' (no such file), '/opt/homebrew/Cellar/samba/4.20.0/lib/libsmbclient.inst.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/Cellar/samba/4.20.0/lib/libsmbclient.inst.dylib' (no such file), '/opt/homebrew/Cellar/samba/4.20.0/lib/libsmbclient.inst.dylib' (no such file)
fish: Job 1, 'legba' terminated by signal SIGABRT (Abort)

legba won't die with a crtl-c when running inside docker

Hello! While trying on performing some DNS enum I noticed that legba won't die with Ctrl-C -> SIGINT - until completion

alessandro@xps:~/Development/legba$ docker run -v $(pwd):/data legba dns --payloads data/subdomains-top1million-5000.txt --target example.com --dns-resolvers "8.8.8.8"
legba v0.9.0

[INFO ] target: example.com
[INFO ] using resolvers: [8.8.8.8]
[INFO ] using -> wordlist data/subdomains-top1million-5000.txt
    
[INFO ] [2024-07-16 10:12:44] (dns) <www.example.com> addresses=93.184.215.14
[INFO ] tasks=12 mem=33.4 MiB targets=1 attempts=4989 done=45 (0.90%) speed=45 reqs/s
^C[INFO ] tasks=12 mem=34.2 MiB targets=1 attempts=4989 done=193 (3.87%) speed=45 reqs/s
^C[INFO ] tasks=12 mem=34.2 MiB targets=1 attempts=4989 done=417 (8.36%) speed=29 reqs/s
[INFO ] tasks=12 mem=34.7 MiB targets=1 attempts=4989 done=3661 (73.38%) speed=50 reqs/s
[INFO ] tasks=12 mem=34.7 MiB targets=1 attempts=4989 done=3661 (73.38%) speed=20 reqs/s
^C^C^C^C^C^C[INFO ] tasks=12 mem=34.7 MiB targets=1 attempts=4989 done=3661 (73.38%) speed=0 reqs/s
^C[INFO ] tasks=12 mem=34.7 MiB targets=1 attempts=4989 done=3661 (73.38%) speed=0 reqs/s
[INFO ] tasks=12 mem=34.8 MiB targets=1 attempts=4989 done=4920 (98.62%) speed=0 reqs/s
[INFO ] tasks=12 mem=34.8 MiB targets=1 attempts=4989 done=4977 (99.76%) speed=56 reqs/s
[INFO ] runtime 209.960554362s

Running latest version:

alessandro@xps:~/Development/legba$ docker run -v $(pwd):/data legba version
legba v0.9.0

On:

alessandro@xps:~/Development/legba$ uname -a
Linux xps 5.15.0-113-generic #123~20.04.1-Ubuntu SMP Wed Jun 12 17:33:13 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

yeah perhaps I should upgrade it but I don't have issues with other code, will investigate this one btw!!! Thanks

Legba does not provide formatted output in pgsql plugin

I started legba with such example:
legba pgsql -T 10.3.2.61:5432 -U user -P passpass --output-format csv -O report.csv
But it gives only this to stdout:

legba v0.7.1

[INFO ] target: 10.3.2.61:5432
[INFO ] username -> string 'user'
[INFO ] password -> string 'passpass'
    
[INFO ] runtime 1.000179919s

And there is no report.csv.
The same behavior for other formats.
ssh plugin is work properly, but not this one.

UPD:
Checked mysql plugin, works like a charm:
legba mysql -T 10.3.2.61:3306 -U user -P passpass --output-format csv -O report.csv

legba v0.7.1

[INFO ] target: 10.3.2.61:3306
[INFO ] username -> string 'user'
[INFO ] password -> string 'passpass'
    
[INFO ] [2024-01-21 23:20:17] (mysql) <10.3.2.61:3306> username=user password=passpass
[INFO ] runtime 1.000235692s

I'v used this compose for testing purposes:

version: '3.9'

services:
  postgres:
    image: postgres:15
    environment:
        POSTGRES_USER: user
        POSTGRES_PASSWORD: passpass
        POSTGRES_DB: db
        PGPASSWORD: passpass
    ports:
      - "5432:5432"

  mysql:
    image: mysql:8
    command: --default-authentication-plugin=mysql_native_password
    environment:
      MYSQL_ROOT_PASSWORD: passpass
      MYSQL_USER: user
      MYSQL_PASSWORD: passpass
      MYSQL_DATABASE: db
    ports:
      - "3306:3306" 

error install

Kali


  Compiling encoding-index-singlebyte v1.20141219.5
   Compiling encoding-index-korean v1.20141219.5
   Compiling rand_os v0.1.3
   Compiling rand_jitter v0.1.4
   Compiling enum-as-inner v0.6.0
   Compiling chacha20 v0.9.1
   Compiling heck v0.3.3
   Compiling idna v0.4.0
   Compiling serde_bytes v0.11.14
   Compiling scylla-macros v0.2.3
   Compiling ascii v1.1.0
   Compiling mime v0.3.17
   Compiling kerberos_constants v0.0.9
   Compiling hashbrown v0.12.3
   Compiling base64 v0.11.0
   Compiling convert_case v0.4.0
   Compiling rlimit v0.10.1
   Compiling hex-literal v0.4.1
   Compiling russh v0.40.2
   Compiling derive_more v0.99.17
   Compiling x509-parser v0.6.5
   Compiling red_asn1 v0.3.5
   Compiling scylla-cql v0.0.9
   Compiling bson v2.10.0
   Compiling trust-dns-proto v0.23.2
   Compiling strum_macros v0.23.1
   Compiling encoding v0.2.33
   Compiling red_asn1_derive v0.2.1
   Compiling cookie_store v0.16.2
   Compiling async-channel v2.3.1
   Compiling sqlx-macros v0.7.4
   Compiling num v0.2.1
   Compiling num_enum v0.4.3
   Compiling serde_with v1.14.0
   Compiling tokio-rustls v0.24.1
   Compiling trust-dns-resolver v0.21.2
   Compiling russh-sftp v2.0.1
   Compiling hmac v0.7.1
   Compiling hyper-tls v0.5.0
   Compiling clap v4.5.4
error: failed to run custom build command for `pavao v0.2.6`

Caused by:
  process didn't exit successfully: `/tmp/cargo-installkIC3bG/release/build/pavao-39ffcae57f3f3bcd/build-script-build` (exit status: 101)
  --- stdout
  cargo:rustc-check-cfg=cfg(arm)
  cargo:rustc-check-cfg=cfg(aarch64)
  cargo:rustc-check-cfg=cfg(riscv64)
  cargo:rustc-check-cfg=cfg(x86_64)
  cargo:rustc-cfg=x86_64
  cargo:rustc-check-cfg=cfg(macos)
  cargo:rustc-check-cfg=cfg(linux)
  cargo:rustc-cfg=linux
  cargo:rustc-check-cfg=cfg(unix)
  cargo:rustc-cfg=unix
  cargo:rustc-check-cfg=cfg(linux_aarch64)
  cargo:rustc-check-cfg=cfg(linux_riscv64)
  cargo:rustc-check-cfg=cfg(linux_x86_64)
  cargo:rustc-cfg=linux_x86_64
  cargo:rustc-check-cfg=cfg(linux_arm)
  cargo:rerun-if-env-changed=SMBCLIENT_NO_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG
  cargo:rerun-if-env-changed=SMBCLIENT_STATIC
  cargo:rerun-if-env-changed=SMBCLIENT_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
  error: SMB Client library not found! Probably libsmbclient is not installed.

  --- stderr
  thread 'main' panicked at /home/kali/.cargo/registry/src/index.crates.io-6f17d22bba15001f/pavao-0.2.6/build.rs:32:13:

  pkg-config exited with status code 1
  > PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 pkg-config --libs --cflags smbclient

  The system library `smbclient` required by crate `pavao` was not found.
  The file `smbclient.pc` needs to be installed and the PKG_CONFIG_PATH environment variable must contain its parent directory.
  The PKG_CONFIG_PATH environment variable is not set.

  HINT: if you have installed the library, try setting PKG_CONFIG_PATH to the directory containing `smbclient.pc`.

  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error: failed to compile `legba v0.9.0`, intermediate artifacts can be found at `/tmp/cargo-installkIC3bG`.
To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path.
                                                    

Recipes engine.

It'd be nice to have a "recipe" engine for complex plugin use cases.

For instance, in order to target a Wordpress blog, right now we can either target its xmlrpc.php (faster) or wp-login.php pages via the legba http plugin. As per wiki:

HTTP Post Request (Wordpress wp-login.php page):

legba http \
    --username admin \
    --password wordlists/passwords.txt \
    --target http://localhost:8888/wp-login.php \
    --http-method POST \
    --http-success-codes 302 \ # wordpress redirects on successful login
    --http-payload 'log={USERNAME}&pwd={PASSWORD}'

HTTP Post Request (Wordpress xmlrpc.php)

legba http \
    --username admin \
    --password wordlists/passwords.txt \
    --target http://localhost:8888/xmlrpc.php \
    --http-method POST \
    --http-payload '<?xml version="1.0" encoding="iso-8859-1"?><methodCall><methodName>wp.getUsersBlogs</methodName><params><param><value><string>{USERNAME}</string></value></param><param><value><string>{PASSWORD}</string></value></param></params></methodCall>' \
    --http-success-string 'isAdmin' # what string successful response will contain

This recipe engine would simplify these cases with YAML files and a simple custom-variable syntax. The previous examples would become two recipes:

wordpress/xmlrpc.yml

plugin: http
args:
    - target: {$schema or https}://{$host}:{$port or 443}{$path or /}xmlrpc.php
    - http-method: POST
    - http-success-string: isAdmin
    - http-payload: 
        <?xml version="1.0" encoding="iso-8859-1"?>
        <methodCall>
            <methodName>wp.getUsersBlogs</methodName>
            <params>
                <param>
                    <value><string>{USERNAME}</string></value>
                </param>
                <param>
                    <value><string>{PASSWORD}</string></value>
                </param>
            </params>
        </methodCall>

wordpress/wp-login.yml

plugin: http
args:
    - target: {$schema or https}://{$host}:{$port or 443}{$path or /}wp-login.php
    - http-method: POST
    - http-success-codes: 302
    - http-payload: log={USERNAME}&pwd={PASSWORD}

These recipe files could then be used to shorten the required command line:

legba \
    --recipe wordpress/xmlrpc.yml \
    --host www.something.com \
    --username admin \
    --password wordlists/passwords.txt

or

legba \
    --recipe wordpress/wp-login.yml \
    --host www.something.com \
    --username admin \
    --password wordlists/passwords.txt

This way plugins and specific combinations/uses of their arguments could be "aliased".

Can't build on Windows 10

Compiling rust-crypto v0.2.36 error: failed to run custom build command forrust-crypto v0.2.36 note: To improve backtraces for build dependencies, set the CARGO_PROFILE_DEV_BUILD_OVERRIDE_DEBUG=true environment variable to enable debug information generation.

Add blank username in http authentication

I ran into a website which only wanted a code, so the username is not required.

legba v0.6.1
error: a value is required for '--username ' but none was supplied
For more information, try '--help'.
From this message I think that you can't use the http auth without a username like hydra did with (-l '').
And also if you don't put the username at all it will randomly generate one:
username -> permutations (min:4 max:8 charset:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_ !"#$%&'()*+,-./:;<=>?@[]^`{|}~)
Which is really cool, just whished for something like hydra did.
Thanks

Evaluate using LTO, Profile-Guided Optimization (PGO) and Post-Link Optimization (PLO) like LLVM BOLT

Hi!

Recently I checked Profile-Guided Optimization (PGO) improvements on multiple projects. The results are here. According to my tests, PGO helps with achieving better performance in many application domains, including the network-oriented software (e.g. see the results for Envoy, HAProxy, httpd). Since this, I decided to test PGO on Legba. And here are my results.

Test environment

  • Fedora 38
  • Linux kernel 6.5.6
  • AMD Ryzen 9 5900x
  • 48 Gib RAM
  • SSD Samsung 980 Pro 2 Tib
  • Compiler - Rustc 1.73
  • Legba version: the latest for now from the main branch on commit 5f0739a974f4ad92c254ddfe37aca033b40600e6
  • Disabled Turbo boost

Benchmark

For benchmark purposes, I use "HTTP basic auth" scenario from the test_server directory with the legba http.basic -t 127.0.0.1:8888 --username admin666 --password ./passwords_1m.txt --concurrency 1 command line. concurrency 1 is used just for reducing multithreading jitter influence on the results. As password_1m.txt file I use this where test12345 password is moved to the end of the file.

For the training PGO phase, I use completely the same command but with a smaller password file (1050 passwords + test12345 at the end) (just to boost the PGO training phase).

I tested the following Legba configurations:

  • Release build: cargo build --release
  • Release + lto = true + codegen-units = 1 (enable LTO): Apply LTO changes to Cargo.toml and then cargo build --release
  • Release + lto = true + codegen-units = 1 + PGO: cargo pgo build + cargo pgo optimize build. It's done with cargo-pgo.
  • Release + lto = true + codegen-units = 1 + PGO + BOLT: Also via cargo-pgo

All benchmarks are done multiple times, on the same machine (with the same hardware/software configuration), with the same background noise (as much as I can guarantee ofc).

Results

I got the following results:

  • Release: 276s
  • Release + lto = true + codegen-units = 1: 262s
  • Release + lto = true + codegen-units = 1 + PGO optimized: 247s
  • Release + lto = true + codegen-units = 1 + PGO optimized + BOLT optimized: 247s

At least in the benchmark above, LTO and PGO help with achieving better performance in Legba. However, seems like LLVM BOLT has no measurable results in this benchmark.

For reference, here are results for the smaller file with 1051 password, so you can estimate how slower PGO instrumented Legba is compared to other configurations:

  • Release: 273ms
  • Release + LTO: 261ms
  • Release + LTO + PGO instrumented: 311ms
  • Release + LTO + PGO optimized + BOLT instrumented: 300ms

Here are binary sizes after the strip command:

  • Release: 21 Mib
  • Release + LTO: 17 Mib
  • Release + LTO + PGO instrumented: 53 Mib
  • Release + LTO + PGO optimized: 15 Mib
  • Release + LTO + PGO optimized + BOLT instrumented: 68 Mib
  • Release + LTO + PGO optimized + BOLT optimized: 20 Mib

Also, I measured build time changes between configurations:

  • Release: 3m 10s
  • Release + lto = true + codegen-units = 1: 6m 57s
  • Release + lto = true + codegen-units = 1 + PGO instrumented: 11m 14s
  • Release + lto = true + codegen-units = 1 + PGO optimized: 6m 40s

Further steps

I can suggest the following action points:

  • Perform more PGO benchmarks on Legba in various scenarios. If it shows improvements - add a note to the documentation about possible improvements in legba's performance with PGO.
  • Providing an easier way (e.g. a build option) to build scripts with PGO can be helpful for the end-users and maintainers since they will be able to optimize legba according to their own workloads.

Here are some examples of how PGO optimization is integrated in other projects:

The Content-Type: header is not set correctly

Hello. I discovered a small issue that seems to be related to the fact that when the request body is assembled, the Content-Type header is set to application/x-www-form-urlencoded, which may overwrite any preset Content-Type headers passed via the command line.

To solve this problem, we can modify the setup_request_body method so that it checks if the Content-Type header has already been set before setting the default value. If Content-Type is already set, we won't override it.

Here is the proposed updated setup_request_body method:

fn setup_request_body(
    &self,
    creds: &Credentials,
    csrf: Option<csrf::Token>,
    mut request: RequestBuilder,
) -> RequestBuilder {
    let mut do_body = true;
    if self.strategy == Strategy::BasicAuth {
        // set basic authentication data
        request = request.basic_auth(&creds.username, Some(&creds.password));
    } else if self.strategy == Strategy::Form {
        // set form data
        let fields = payload::parse_fields(self.payload.as_ref(), creds).unwrap();
        let mut form = multipart::Form::new();
        for (key, value) in fields {
            form = form.text(key, value);
        }

        // handle csrf
        if let Some(token) = csrf.as_ref() {
            form = form.text(token.name.clone(), token.value.clone());
        }

        request = request.multipart(form);

        // we already added the --http-body value as fields
        do_body = false;
    }

    // do we have any fields left to add?
    if do_body && self.payload.is_some() {
        if method_requires_payload(&self.method) {
            // add as body
            let mut body = payload::parse_body(self.payload.as_ref(), creds).unwrap();

            // handle csrf
            if let Some(token) = csrf.as_ref() {
                body.push_str(&format!("&{}={}", token.name, token.value));
            }

            request = request.body(body);
            // Check if Content-Type is set already, if not set default
            if !self.headers.contains_key("Content-Type") {
                request = request.header("Content-Type", "application/x-www-form-urlencoded");
            }
        } else {
            // add as query string
            let mut query = payload::parse_fields(self.payload.as_ref(), creds).unwrap();

            // handle csrf
            if let Some(token) = csrf.as_ref() {
                query.push((token.name.clone(), token.value.clone()));
            }

            request = request.query(&query);
        }
    }

    request
}

Notice the section of code that sets the Content-Type header. It now checks if self.headers already contains a Content-Type header. If it does not contain it, it sets the default value. Have a good day.

NSInvalidArgumentException with Cargo package on macOS Sonoma

Installed on an M2 with cargo, every command fails with the same error:

legba --version
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString stringByStandardizingPath]: unrecognized selector sent to instance 0x600002068140'
...

Enhancement request: --http-failure-string

When I try to bruteforce a HTTP login form, I often dont know any valid login data, so I only now the failure status code and message.
I can try to guess the success status code, but that is not always correct, also the success and failure status code can be the same in some cases.

A --http-failure-string flag would be very helpful. I always know the failure string and can be sure that it does not trigger on success. Hydra also supports this.

It would be great if you implement it, I think it should not be much work to do.

Kali error pavao

Just run :
apt install -y libsmbclient-dev libsmbclient
and after :
cargo install legba

RDP Plugin with Xrdp Does Not Report Successful Login

Using legba v0.9.0 with the RDP plugin against xrdp server does not report successful login.

My Linux xrdp server works OK with an RDP client, but Legba fails to report successful authentication:

~ ﹪docker run --rm evilsocket/legba -U admin -P Password123 -T 192.168.1.245 rdp
legba v0.9.0

[INFO ] target: 192.168.1.245
[INFO ] username -> string 'admin'
[INFO ] password -> string 'Password123'

[INFO ] runtime 1.004151917s

Dockerfile with xrdp server and admin:Password123 credentials attached.

On macOS I'm using kkRemote as my RDP client and I can authenticate and get an RDP session against this xrdp Docker target successfully. The container logs the output of the successful login with kkRemote as follows:

xrdp[10]: [INFO ] Socket 11: AF_INET6 connection received from ::ffff:192.168.65.1 port 44607
xrdp[12]: [INFO ] Using default X.509 certificate: /etc/xrdp/cert.pem
xrdp[12]: [INFO ] Using default X.509 key file: /etc/xrdp/key.pem
xrdp[12]: [INFO ] Security protocol: configured [SSL|RDP], requested [SSL|HYBRID|RDP], selected [SSL]
xrdp[12]: [INFO ] Connected client computer name: Joshuas-MBP
xrdp[12]: [WARN ] Received [MS-RDPBCGR] TS_UD_HEADER type 0xc006 is unknown (ignored)
xrdp[12]: [WARN ] Received [MS-RDPBCGR] TS_UD_HEADER type 0xc00a is unknown (ignored)
xrdp[12]: [INFO ] xrdp_load_keyboard_layout: Keyboard information sent by the RDP client, keyboard_type:[0x04], keyboard_subtype:[0x00], keylayout:[0x00000000]
xrdp[12]: [INFO ] xrdp_load_keyboard_layout: model [] variant [] layout [us] options []
xrdp[12]: [INFO ] TLS connection established from ::ffff:192.168.65.1 port 44607: TLSv1.3 with cipher TLS_AES_256_GCM_SHA384
xrdp[12]: [INFO ] xrdp_caps_process_pointer: client supports new(color) cursor
xrdp[12]: [INFO ] xrdp_caps_process_codecs: RemoteFX, codec id 3, properties len 49
xrdp[12]: [WARN ] Cannot find keymap file /etc/xrdp/km-00000000.ini
xrdp[12]: [WARN ] Cannot find keymap file /etc/xrdp/km-00000000.ini
xrdp[12]: [INFO ] Loading keymap file /etc/xrdp/km-00000409.ini
xrdp[12]: [WARN ] local keymap file for 0x00000000 found and doesn't match built in keymap, using local keymap file
xrdp[12]: [ERROR] dynamic_monitor_open_response: error
xrdp[12]: [ERROR] xrdp_rdp_recv: xrdp_channel_process failed
xrdp[12]: [INFO ] connecting to sesman on 127.0.0.1:3350
xrdp-sesman[9]: [INFO ] Socket 11: AF_INET6 connection received from ::1 port 41300
xrdp[12]: [INFO ] xrdp_wm_log_msg: sesman connect ok
xrdp[12]: [INFO ] sesman connect ok
xrdp[12]: [INFO ] sending login info to session manager. Please wait...
xrdp-sesman[9]: [INFO ] Terminal Server Users group is disabled, allowing authentication
xrdp-sesman[9]: [INFO ] ++ created session (access granted): username admin, ip ::ffff:192.168.65.1:44607 - socket: 11
xrdp-sesman[9]: [INFO ] starting Xorg session...
xrdp-sesman[9]: [INFO ] Starting session: session_pid 13, display :10.0, width 1024, height 768, bpp 24, client ip ::ffff:192.168.65.1:44607 - socket: 11, user name admin
xrdp-sesman[13]: [INFO ] [session start] (display 10): calling auth_start_session from pid 13
xrdp-sesman[9]: [ERROR] sesman_data_in: scp_process_msg failed
xrdp[12]: [INFO ] xrdp_wm_log_msg: login successful for user admin on display 10
xrdp-sesman[13]: pam_env(xrdp-sesman:setcred): Unable to open env file: /etc/default/locale: No such file or directory
xrdp-sesman[13]: pam_unix(xrdp-sesman:session): session opened for user admin(uid=1000) by (uid=0)
xrdp[12]: [INFO ] login successful for user admin on display 10
xrdp-sesman[13]: pam_systemd(xrdp-sesman:session): Failed to connect to system bus: No such file or directory
xrdp-sesman[9]: [ERROR] sesman_main_loop: trans_check_wait_objs failed, removing trans
xrdp[12]: [INFO ] loaded module 'libxup.so' ok, interface size 10296, version 4
xrdp[12]: [INFO ] started connecting
xrdp[12]: [INFO ] lib_mod_connect: connecting via UNIX socket
xrdp[12]: [INFO ] lib_mod_log_peer: xrdp_pid=12 connected to X11rdp_pid=15 X11rdp_uid=1000 X11rdp_gid=1000 client_ip=::ffff:192.168.65.1 client_port=44607
xrdp[12]: [INFO ] connected ok
xrdp-sesman[13]: [INFO ] Found X server running at /tmp/.X11-unix/X10
xrdp-sesman[14]: [INFO ] Found X server running at /tmp/.X11-unix/X10
xrdp-sesman[13]: [INFO ] Session started successfully for user admin on display 10
xrdp-sesman[23]: [INFO ] Starting the xrdp channel server for display 10
xrdp-sesman[13]: [INFO ] Session in progress on display 10, waiting until the window manager (pid 14) exits to end the session

When I use legba against the same target, I get the following output from xrdp:

xrdp[10]: [INFO ] Socket 11: AF_INET6 connection received from ::ffff:192.168.65.1 port 26124
xrdp[11]: [INFO ] Using default X.509 certificate: /etc/xrdp/cert.pem
xrdp[11]: [INFO ] Using default X.509 key file: /etc/xrdp/key.pem
xrdp[11]: [INFO ] Security protocol: configured [SSL|RDP], requested [SSL|HYBRID|RDP], selected [SSL]
xrdp[11]: [INFO ] Connected client computer name: rdp-rs
xrdp[11]: [INFO ] xrdp_load_keyboard_layout: Keyboard information sent by the RDP client, keyboard_type:[0x04], keyboard_subtype:[0x00], keylayout:[0x00000409]
xrdp[11]: [INFO ] xrdp_load_keyboard_layout: model [] variant [] layout [us] options []
xrdp[11]: [INFO ] TLS connection established from ::ffff:192.168.65.1 port 26124: TLSv1.3 with cipher TLS_AES_256_GCM_SHA384
xrdp[11]: [ERROR] received wrong flags, likely decrypt not working
xrdp[11]: [ERROR] xrdp_sec_recv: xrdp_sec_process_logon_info failed
xrdp[11]: [ERROR] xrdp_rdp_recv: xrdp_sec_recv failed
xrdp[11]: [ERROR] libxrdp_process_data: xrdp_rdp_recv failed
xrdp[11]: [ERROR] xrdp_process_data_in: xrdp_process_loop failed

Possibly related to TLS negotiation difference between kkRemote RDP client and Legba? received wrong flags, likely decrypt not working

xrdptarget.zip

Suggestion: SSH Key Based Authentication

It would be exceptionally pleasant to have support for SSH key based auth - provide a directory of SSH private keys, and have the tool test them against target.

Problems when running the ssh plugin

Helloo,
I am a github noob, so forgive me if I am doing this wrong.

So I was testing your tool to brute force SSH credentials on 2 machines in my network. I have installed all the dependencies and the tool runs without any error.
My machine:-
Linux Bruteforcer 5.4.0-166-generic #183-Ubuntu SMP Mon Oct 2 11:28:33 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

It is the same for the other 2 machines as well.

So the command I used was:
./legba ssh --username ubuntu --password wordlists/passwords.txt --target @target.txt -O result --output-format jsonl -Q
and go the expected result
image

Also note that the only password stored in the passwords.txt is Lab4man1.
image

When I run the same command but this time remove the -Q flag, I get this error
image

This keeps running forever, until I stop it.

If there are multiple passwords in the password list the same error as the over one is noticed. But in case of -Q flag , it doesn't run forever.

Multiple passwords file:
image

./legba ssh --username ubuntu --password wordlists/password-new.txt --target @target.txt -O result --output-format jsonl

image

./legba ssh --username ubuntu --password wordlists/password-new.txt --target @target.txt -O result --output-format jsonl -Q

image

Once again , sorry If this isn't the way to ask a question.
Thank you.

Telnet brute seems not work(Mac)

I test legba on Mac(M1) by docker, my command is

docker run -it evilsocket/legba telnet --username admin --password ~/wordlist.txt--target ip:23 --telnet-user-prompt "login: "   --telnet-pass-prompt "Password: "  --telnet-prompt ":~$ " --single-match

and then , the output on my shell is like bellow:

iShot_2024-04-17_00 01 55

really wonder what happend, thx

certain ssh hosts increase memory usage considerably

[INFO ] tasks=700 mem=2.9 GiB targets=24338819 attempts=73016457 done=195051 (0.27%) errors=117237 speed=196 reqs/s
[INFO ] tasks=700 mem=3.9 GiB targets=24338819 attempts=73016457 done=195051 (0.27%) errors=117237 speed=196 reqs/s
[INFO ] tasks=700 mem=4.1 GiB targets=24338819 attempts=73016457 done=195051 (0.27%) errors=117237 speed=196 reqs/s

Adding docker-compose.yml

Is there the chance (and a sense) to create a docker-compose.yml file to deploy the solution by docker-compose?

I hope so. Thanks.

invalid socket address syntax

Hey!

Tryin to run a simple rdp brute and even if I have only 1 ip in my ip file, it always returning syntax error!

root@debian:~# legba -t @/root/rdp_targets.txt --username @/root/admin_userlist.txt --password @/root/passwords.txt --rdp-auto-logon --output /root/LEGBA_GOOD.txt --output-format text --timeout 30000 --retries 5 --retry-time 1000 --concurrency 5 --jitter-min 500 --jitter-max 500 rdp

[INFO ] targeting @/root/rdp_targets.txt
Error: "invalid socket address syntax"

Content of rdp_targets.txt is:
ip
ip
ip
ip

What is the problem causing this ? Is there any other format for the ip-s in the file ? File contains IPv4 addresses, not 6.

Thanks!

Enhancement request: multiple target mode

As far as I can tell, only single target --target mode is supported, meaning I have to spawn new processes for new targets, which seems at odds with the async nature of the authentication checker. Multi protocol mode would be nice too, being able to for instance specify protocol:ip:port would be ideal.

Thank you!

Mutation engine

It'd be useful to have an engine that given the input users and/or passwords list could mutate each one in order to generate new ones. These mutation could have names such as upper (mutate letters to uppercase), lower (to lowercase), l337 (mutate via leet code), etc and can be configured by user argument.

For instance:

... -U "aa" --user-mutations "upper"

Would generate the following permutations from "aa": aa (seed), Aa, aA, AA.

mutations can be combined via comma:

... -U "aa" --user-mutations "upper, lower, l337"

and of course used for both usernames and passwords, being them generated using the permutation engine, from wordlist file, combinations file or constant value.

Wordlist vs. Single Password Error

This is probably PEBCAK, but I'm not getting the results I expect with Legba against a test SSH server after reading the directions in the wiki SSH and SFTP page.

First, verifying the SSH username and password with Hydra:

$ hydra -l josh -p admin -t 4 ssh://10.10.75.1
Hydra v8.6 (c) 2017 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (http://www.thc.org/thc-hydra) starting at 2023-11-03 15:27:05
[DATA] max 1 task per 1 server, overall 1 task, 1 login try (l:1/p:1), ~1 try per task
[DATA] attacking ssh://10.10.75.1:22/
[22][ssh] host: 10.10.75.1   login: josh   password: admin
1 of 1 target successfully completed, 1 valid password found
Hydra (http://www.thc.org/thc-hydra) finished at 2023-11-03 15:27:05

This works OK, and I'm able to recover the same single username and password with Legba:

$ alias legba
alias legba='docker run -it evilsocket/legba:latest'
$ legba ssh --username josh --password admin --target 10.10.75.1:22
legba v0.3.0

[INFO ] targeting 10.10.75.1:22
[INFO ] username -> string 'josh'
[INFO ] password -> string 'admin'
    
[INFO ] [58.742147ms] result found: username=josh password=admin
[INFO ] runtime 1.001350043s

When using a wordlist though, I am unable to recover the password from the target:

$ file wordlist.txt
wordlist.txt: ASCII text
$ wc -l wordlist.txt 
7 wordlist.txt
$ grep admin wordlist.txt
admin
$ legba ssh --username josh --password ./wordlist.txt --target 10.10.75.1:22
legba v0.3.0

[INFO ] targeting 10.10.75.1:22
[INFO ] username -> string 'josh'
[INFO ] password -> string './wordlist.txt'
    
[INFO ] tasks=4 mem=20 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=4 mem=20.1 MiB done=0 (0.00%) speed=0 reqs/s
[ERROR] attempt 10/10: deadline has elapsed
[INFO ] tasks=4 mem=20.1 MiB done=1 (100.00%) errors=1 speed=0 reqs/s
[INFO ] runtime 20.009169702s

I tried different variations of the wordlist file name, using relative subdirectories for the wordlist, etc. Why doesn't Legba recognize my --password argument as a wordlist?

likely clap error

Win10

PS C:\Users\Enomothem\Desktop\legba-0.6.1> .\target\debug\legba.exe ssh --username root --password .\p.txt --target 192.168.66.132:22
legba v0.6.1

thread 'main' panicked at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\clap_builder-4.4.7\src\builder\debug_asserts.rs:275:9:
Command legba: Argument group name must be unique

        'Options' is already in use
stack backtrace:
   0:     0x7ff74ae31a7a - std::sys_common::backtrace::_print::impl$0::fmt
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\sys_common\backtrace.rs:44
   1:     0x7ff74ae50f4b - core::fmt::rt::Argument::fmt
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\core\src\fmt\rt.rs:138
   2:     0x7ff74ae50f4b - core::fmt::write
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\core\src\fmt\mod.rs:1094
   3:     0x7ff74ae2d1d1 - std::io::Write::write_fmt<std::sys::windows::stdio::Stderr>
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\io\mod.rs:1714
   4:     0x7ff74ae317fa - std::sys_common::backtrace::_print
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\sys_common\backtrace.rs:47
   5:     0x7ff74ae317fa - std::sys_common::backtrace::print
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\sys_common\backtrace.rs:34
   6:     0x7ff74ae33f9a - std::panicking::default_hook::closure$1
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:270
   7:     0x7ff74ae33c08 - std::panicking::default_hook
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:290
   8:     0x7ff74ae3464e - std::panicking::rust_panic_with_hook
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:707
   9:     0x7ff74ae3453d - std::panicking::begin_panic_handler::closure$0
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:599
  10:     0x7ff74ae32469 - std::sys_common::backtrace::__rust_end_short_backtrace<std::panicking::begin_panic_handler::closure_env$0,never$>
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\sys_common\backtrace.rs:170
  11:     0x7ff74ae34240 - std::panicking::begin_panic_handler
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:595
  12:     0x7ff74ae87b75 - core::panicking::panic_fmt
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\core\src\panicking.rs:67
  13:     0x7ff74adad5c9 - clap_builder::builder::debug_asserts::assert_app
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\clap_builder-4.4.7\src\builder\debug_asserts.rs:275
  14:     0x7ff74ad2ea9b - clap_builder::builder::command::Command::_build_self
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\clap_builder-4.4.7\src\builder\command.rs:4043
  15:     0x7ff74ad2e3a2 - clap_builder::builder::command::Command::_do_parse
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\clap_builder-4.4.7\src\builder\command.rs:3914
  16:     0x7ff7490de73b - clap_builder::builder::command::Command::try_get_matches_from_mut<std::env::ArgsOs,std::ffi::os_str::OsString>
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\clap_builder-4.4.7\src\builder\command.rs:791
  17:     0x7ff7490de2ae - clap_builder::builder::command::Command::get_matches_from<std::env::ArgsOs,std::ffi::os_str::OsString>
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\clap_builder-4.4.7\src\builder\command.rs:662
  18:     0x7ff7490ba7a9 - clap_builder::builder::command::Command::get_matches
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\clap_builder-4.4.7\src\builder\command.rs:571
  19:     0x7ff7490e4651 - clap_builder::derive::Parser::parse<legba::options::Options>
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\clap_builder-4.4.7\src\derive.rs:27
  20:     0x7ff7490341fc - legba::setup
                               at C:\Users\Enomothem\Desktop\legba-0.6.1\src\main.rs:39
  21:     0x7ff748fd7737 - legba::main::async_block$0
                               at C:\Users\Enomothem\Desktop\legba-0.6.1\src\main.rs:62
  22:     0x7ff74914024f - tokio::runtime::park::impl$4::block_on::closure$0<enum2$<legba::main::async_block_env$0> >
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\tokio-1.33.0\src\runtime\park.rs:282
  23:     0x7ff74913ffca - tokio::runtime::coop::with_budget
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\tokio-1.33.0\src\runtime\coop.rs:107
  24:     0x7ff74913ffca - tokio::runtime::coop::budget
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\tokio-1.33.0\src\runtime\coop.rs:73
  25:     0x7ff74913ffca - tokio::runtime::park::CachedParkThread::block_on<enum2$<legba::main::async_block_env$0> >
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\tokio-1.33.0\src\runtime\park.rs:282
  26:     0x7ff749190a82 - tokio::runtime::context::blocking::BlockingRegionGuard::block_on<enum2$<legba::main::async_block_env$0> >
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\tokio-1.33.0\src\runtime\context\blocking.rs:66
  27:     0x7ff748fc1a82 - tokio::runtime::scheduler::multi_thread::impl$0::block_on::closure$0<enum2$<legba::main::async_block_env$0> >
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\tokio-1.33.0\src\runtime\scheduler\multi_thread\mod.rs:87
  28:     0x7ff749131c6c - tokio::runtime::context::runtime::enter_runtime<tokio::runtime::scheduler::multi_thread::impl$0::block_on::closure_env$0<enum2$<legba::main::async_block_env$0> >,enum2$<core::result::Result<tuple$<>,alloc::string::String> > >
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\tokio-1.33.0\src\runtime\context\runtime.rs:65
  29:     0x7ff748fc1a29 - tokio::runtime::scheduler::multi_thread::MultiThread::block_on<enum2$<legba::main::async_block_env$0> >
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\tokio-1.33.0\src\runtime\scheduler\multi_thread\mod.rs:86
  30:     0x7ff7490338d0 - tokio::runtime::runtime::Runtime::block_on<enum2$<legba::main::async_block_env$0> >
                               at D:\bx+eno_tools\bx_eno_enviroment_rust\cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\tokio-1.33.0\src\runtime\runtime.rs:350
  31:     0x7ff74903518c - legba::main
                               at C:\Users\Enomothem\Desktop\legba-0.6.1\src\main.rs:91
  32:     0x7ff7491d8543 - core::ops::function::FnOnce::call_once<enum2$<core::result::Result<tuple$<>,alloc::string::String> > (*)(),tuple$<> >
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\core\src\ops\function.rs:250
  33:     0x7ff748f705ed - std::sys_common::backtrace::__rust_begin_short_backtrace<enum2$<core::result::Result<tuple$<>,alloc::string::String> > (*)(),enum2$<core::result::Result<tuple$<>,alloc::string::String> > >
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\std\src\sys_common\backtrace.rs:154
  34:     0x7ff7490dec36 - std::rt::lang_start::closure$0<enum2$<core::result::Result<tuple$<>,alloc::string::String> > >
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\std\src\rt.rs:166
  35:     0x7ff74ae25998 - std::rt::lang_start_internal::closure$2
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\rt.rs:148
  36:     0x7ff74ae25998 - std::panicking::try::do_call
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:502
  37:     0x7ff74ae25998 - std::panicking::try
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panicking.rs:466
  38:     0x7ff74ae25998 - std::panic::catch_unwind
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\panic.rs:142
  39:     0x7ff74ae25998 - std::rt::lang_start_internal
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library\std\src\rt.rs:148
  40:     0x7ff7490dec0a - std::rt::lang_start<enum2$<core::result::Result<tuple$<>,alloc::string::String> > >
                               at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33\library\std\src\rt.rs:165
  41:     0x7ff749035269 - main
  42:     0x7ff74ae8569c - invoke_main
                               at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
  43:     0x7ff74ae8569c - __scrt_common_main_seh
                               at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
  44:     0x7ffaf5cd7614 - BaseThreadInitThunk
  45:     0x7ffaf76e26f1 - RtlUserThreadStart

Get the password and stop immediately

Get the password and continue

  • rustc 1.73.0 (cc66ad468 2023-10-03)
  • cargo 1.73.0 (9c4383fb5 2023-08-26)
  • Windows10

image

.\legba.exe mysql --username root --password .\password.txt --target localhost:3306

password.txt 10000words

Combined username and password lists

I commonly use lists containing username and password combinations to enumerate both default logins and shared passwords across multiple systems. In my experience a option to pass username:password pairs as a wordlist would be great.

Most tools and public lists use : as separator and i cannot recall ever seeing a username containing : so this may be a the best approach.

BadFileDescriptor

I just tried out legba as it seemed to be a promising alternative to CrackMapExec.

However I am experiencing issues with it:

docker run -it -v '/home/pascal/Pentesting/OffSec/OSCP/Challenges/Medtech':/medtech -v '/usr/share/wordlists/seclists/Passwords/Leaked-Databases':/wordlists evilsocket/legba:latest smb --target 172.16.236.10 --username /medtech/VM1/users.txt --password /wordlists/rockyou.txt
legba v0.8.0

[INFO ] target: 172.16.236.10
[INFO ] username -> wordlist /medtech/VM1/users.txt
[INFO ] password -> wordlist /wordlists/rockyou.txt
    
[INFO ] searching private share for 172.16.236.10:445 ...
thread 'tokio-runtime-worker' panicked at src/plugins/samba/mod.rs:81:44:
called `Result::unwrap()` on an `Err` value: BadFileDescriptor
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I tried both the native version as well as the docker version. Both are causing issues.

Scripting engine (LUA).

I'm thinking to integrate a Lua interpreter to do stuff like:

function find_open_ports(host)
    legba("tcp.ports --tcp-ports 80-10000 --target " .. host .. "'")
end

function scan_web_resources(host, port)
    local schema = (tostring(port).endswith('3') and 'https' or 'http')
    legba("http.enum --payloads data/http-enum.txt --target '" .. schema .. "://" .. host .. ":" .. port .. "'")
end

if loot.plugin == 'dns'
    find_open_ports(loot.data.subdomain)

else if loot.plugin == 'tcp.ports'
    scan_web_resources(loot.data.host, loot.data.port)
end

The idea here is to start with the dns module to enumerate the subdomains of a given host. Then for each found subdomain, trigger the tcp.ports module to scan its ports and ultimately, for each open port, trigger the http.enum module to perform http pages enumeration.

This is just an example, i'm opening this issue to track ideas and (ideally) users suggestions.

Fix cross compilation in order to generate and distribute precompiled binaries.

Currently, when a new release is published, docker images for linux/amd64 and linux/arm64 are automatically built and pushed to https://hub.docker.com/r/evilsocket/legba. While this allows users to just pull the image and use it on any platform supported by Docker, it'd be ideal to also be able to generate and distribute precompiled binaries that might be better suited for certain scenarios (embedded devices for one).

While I had some success in cross compiling this project for x86_64-unknown-linux-gnu using cross with this Cross.toml project file, the build still fails for some OS/arch, mostly due to the libsmbclient and libssl native dependencies that somehow I still am trying to cross compile and/or install incorrectly.

It'd be awesome if someone with more experience than me on Rust cross compilation could help.

To start we'd need to generate binaries for:

  • aarch64-unknown-linux-gnu
  • arm-unknown-linux-gnueabi
  • armv7-unknown-linux-gnueabi
  • x86_64-pc-windows-gnu
  • aarch64-apple-darwin
  • x86_64-apple-darwin

Ideally support Android and iOS targets in the future too.

statistics are reported before session is fully initialized

the statistic reporting task is spawned here before the session is fully initialized by invoking session.combinations (which loads any wordlist if needed and calculates how many total attempts are going to be executed). This means that wrong statistics (see https://twitter.com/MikeWeinerRules/status/1721954308814463294) will be reported while, for instance, a very big wordlist's lines have been counted (or if disk I/O is particularly slow).

Invalid address was provided: failed to lookup address information: Name or service not known

root@debian:~/thc-hydra# legba ssh -t @/root/thc-hydra/ssh_targets.txt --username @/root/thc-hydra/users.txt --password @/root/thc-hydra/passwords.txt --output /root/thc-hydra/LEGBA_SSH_GOOD.txt --output-format text --timeout 30000 --retries 5 --retry-time 1000 --concurrency 5 --jitter-min 500 --jitter-max 500
legba v0.3.0

[INFO ] targeting @/root/thc-hydra/ssh_targets.txt
[INFO ] username -> string '@/root/thc-hydra/users.txt'
[INFO ] password -> string '@/root/thc-hydra/passwords.txt'

[INFO ] tasks=5 mem=19.7 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=5 mem=19.9 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=5 mem=19.9 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=5 mem=19.9 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=5 mem=19.9 MiB done=0 (0.00%) speed=0 reqs/s
[INFO ] tasks=5 mem=19.9 MiB done=0 (0.00%) speed=0 reqs/s
[ERROR] attempt 5/5: Invalid address was provided: failed to lookup address information: Name or service not known
[INFO ] tasks=5 mem=19.9 MiB done=1 (100.00%) errors=1 speed=0 reqs/s
[INFO ] runtime 7.090724367s

Content of ssh_targets.txt is:
ip
ip
ip
etc..

how to use this

after "docker-compose up", I entered "legba -L" ,but it is no use.

Continued Status Output after EOF

I'm seeing Legba behavior where Legba continues to provide status output after failing to identify a successful password. For example:

$ docker run --rm -it -v $(pwd):/data evilsocket/legba -C /data/credentials.txt -T 172.30.0.64 mysql
legba v0.9.0

[INFO ] target: 172.30.0.64
[INFO ] username -> wordlist /data/credentials.txt
[INFO ] password -> wordlist /data/credentials.txt

[INFO ] tasks=4 mem=38.7 MiB targets=1 attempts=596 done=259 (43.46%) speed=258 reqs/s
[INFO ] tasks=4 mem=39.2 MiB targets=1 attempts=596 done=447 (75.00%) speed=189 reqs/s
[INFO ] tasks=4 mem=39.5 MiB targets=1 attempts=596 done=572 (95.97%) speed=125 reqs/s
[INFO ] tasks=4 mem=39.5 MiB targets=1 attempts=596 done=593 (99.50%) speed=21 reqs/s
[INFO ] tasks=4 mem=39.5 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.5 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.5 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.5 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.5 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.5 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.6 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.6 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.6 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.6 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.6 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.6 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.6 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.6 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.6 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.6 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.6 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] tasks=4 mem=39.6 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
^C[INFO ] stopping ...
[INFO ] tasks=4 mem=39.6 MiB targets=1 attempts=596 done=593 (99.50%) speed=0 reqs/s
[INFO ] runtime 23.188148286s

The MySQL target here is a basic MariaDB container:

docker run --rm --ip 172.30.0.64 --name mariadb    -h mariadb    --env MARIADB_ROOT_PASSWORD=changeme mariadb

I've attached credentials.txt used for testing. I expect Legba to fail to identify a valid username/password combination based on the MariaDB configuration and credentials.txt file. However, I would expect Legba to get to the EOF in credentials.txt, stop the [INFO] status lines and exit, but it keeps going at 99.5% completion until I interrupt with CTRL+C.

credentials.txt

http encoding issue

Hi, thanks for the awesome project!

I'm testing legba with my hckops/hckctl tool against the owasp juice shop and it looks like something is wrong with the encoding or escaping of special chars, could you please verify?

This is how I found the issue

# starts juice-shop
hckctl box start vulnerable/owasp-juice-shop

# generates users.txt
curl -sS -H "Accept: application/json" "http://juiceshop:3000/rest/products/search?q=foo%'))+UNION+SELECT+id,username,email,password,role,deluxeToken,totpSecret,isActive,createdAt+FROM+Users;--" | \
  jq -r '.data[].description' > /hck/share/users.txt

cat /hck/share/users.txt
[email protected] # <<<<<<<<<< user with password admin123
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected] # <<<<<<<<<< user with password 0Y8rMnww$*9VFYE§59-!Fg1L6t&6lB
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
demo
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

# password not found
hckctl task legba --inline -- legba http \
  --target http://box-owasp-juice-shop-<RANDOM>:3000/rest/user/login \
  --username /hck/share/users.txt \
  --password '0Y8rMnww$*9VFYE§59-!Fg1L6t&6lB' \
  --http-method POST \
  --http-payload 'email={USERNAME}&password={PASSWORD}'

Official solution https://help.owasp-juice.shop/appendix/solutions.html, search for Dumpster dive the Internet for a leaked password and log in to the original user account it belongs to or the password

In order to exclude that it's an issue with my tool, I built the project locally and this is how I verify it

# password spray with admin123
RUST_LOG=debug ./target/release/legba http \
  --target http://localhost:3000/rest/user/login \
  --username ${HOME}/.local/state/hck/share/users.txt \
  --password 'admin123' \
  --http-method POST \
  --http-payload 'email={USERNAME}&password={PASSWORD}'
# prints
# [INFO ] [2023-11-08 09:58:03] (http) <http://localhost:3000/rest/user/login> [email protected] password=admin123

# password spray with 0Y8rMnww$*9VFYE§59-!Fg1L6t&6lB
RUST_LOG=debug ./target/release/legba http \
  --target http://localhost:3000/rest/user/login \
  --username ${HOME}/.local/state/hck/share/users.txt \
  --password '0Y8rMnww$*9VFYE§59-!Fg1L6t&6lB' \
  --http-method POST \
  --http-payload 'email={USERNAME}&password={PASSWORD}'
# not found

# I can confirm that the password is valid and solve the challenge with
http http://localhost:3000/rest/user/login email="[email protected]" password='0Y8rMnww$*9VFYE§59-!Fg1L6t&6lB'
{
    "authentication": {
        "bid": 6,
        "token": "<REDACTED>",
        "umail": "[email protected]"
    }
}

I wanted to actually debug it properly, and probably it's because I'm not familiar with rust, I can build legba disabling the mqtt plugin, but when i'm trying to run it (same error with vscode, intellij, rustrover) I keep getting

thread 'main' panicked at <REDACTED>.cargo/registry/src/index.crates.io-6f17d22bba15001f/clap_builder-4.4.7/src/builder/debug_asserts.rs:275:9:
Command legba: Argument group name must be unique

        'Options' is already in use
stack backtrace:
   0: rust_begin_unwind
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/panicking.rs:595:5

Could you please verify it? I'm more than happy to contribute to the project and open a pr if this is an actual issue.
Thanks!

SMB, Exchange (OWA/EWS), SMTP (NTLM) support

Hello!

I'm loving this project, but given how often I encounter the above protocols, is there a consideration or timeline for authentication via the following protocols?

Sorry to make an issue for a wish list, but I think the above protocols could get this project even more traction as well.

Cheers!

Account Lockout Considerations

I would suggest implementing some features to account for account lockouts. For example if I feed http.ntlm2 module a list of usernames and a list of passwords have it spray the first password against all usernames and then have a flag where I can set how long to wait before spraying the next password and all usernames.

Also, I was wondering if the output flag only outputs successful attempts? It would be useful to have a record of all of the username/password combinations tried in a file.

building from source failing v0.7.1

If anyone is facing this issue when building with cargo install legba:

error: failed to run custom build command for `pavao v0.2.3`
...
  error: could not find system library 'smbclient' required by the 'pavao' crate
...

As declared by the pavao readme page you need to install some deps:

sudo apt install -y libsmbclient-dev libsmbclient

Done this you should be good to go.

@evilsocket you can close the issue as it's not that useful to keep this open, just wrote this to link that if anyone has this problem.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.