How-to Ruby : Simple SSH Bruteforcer

Oct 23, 2015 02:32 PM
Oct 23, 2015 02:35 PM
635811825538428494.jpg

Hello fellow training hackers.

I do not know if many of you are familiar with ruby, but since it is a useful scripting language, that hasn't been covered too much here on Null Byte, I thought why not do some How-tos about it now and then.

The idea is to write simple scripts and then explain them step by step, each time learning new ruby fonctionnalities . I will NOT go into the basics of programming in this guide nor will I explain in detail some of the obvious code.

Intro

First of all, here is the pastebin for the full code before we break it down in detail : http://pastebin.com/X78hBMgi

Sorry for the formatting that was messed up when copy pasting on the SSH connection part.

Disclaimer : The script is so slow at trying passwords you DO NOT want to use this as a means to bruteforce SSH, this was made purely to show some ruby code for those wishing to learn, Ruby is not the language of performance, and this script will never be as fast as many of the bruteforcers that are already out there.

Now that we passed the formalities, let's head right into it.

prerequisites : install both the net-ssh and net-ping gem (the second one is not necessary for the script to work)

to install gems you might use a command such as this :

gem install net-ssh

You may encounter some dependencies problem with the gem install command, but ruby is quite clear with its error messages and you should be able to figure out by yourselves how to install them (i believe in you :D)

Step 1: Now onto the Code (Warm Up Part) :

635811786047022206.jpg

These 2 lines are pretty simple, we import the libraries (called gems in ruby) we just installed, because we are going to need some functions in them.

635811787608740950.jpg

Here we can see a classic if statement. In this case, it checks if the number of arguments entered is 3, and if not, gives a nice, friendly message to the user and terminates the program.

As you can probably guess from this check, the command line arguments in ruby are stored into an array named ARGV, of which we check the length.

Here we want precisely 3 arguments that are the following :

635811789770462604.jpg

target, user, and wordlist. This is all we need. We have to give the arguments in this precise order because the array comes in the order the arguments are given in command line. example run :

ruby ssh-bruteforce.rb 10.55.33.22 admin rockyou.txt

There are other ways to treat argument and options in Ruby, but these are reserved for later ;)

Step 2: Connectivity Testing

635811792394834291.jpg

This one requires explaining. It's a very ruby-ish structure that you won't see anywhere else (I think).

The first line uses the function Net::Ping::ICMP.new() to create a new ICMP object tied to the IP of the target. We will later use the .ping method on this object to ping the IP the ICMP object is associated with.

What the loop does is 5.times do {block}. as its written it executes the block 5 times like a for loop would. The .count method does put into the variable network the number of times the pass on the block has returned true.

We are basically telling ruby to count how many times the block will return true when executing 5 times.

After this if the connectivity was poor we terminate the programm like so :

635811796978740838.jpg

Two interesting things here.

Firt the unless condition, that is the counterpart of the IF, and executes the block unless the condition is false.

Second, the abort keyword that is a combination of print and exit.

The abort word prints the message then exits the program.

Now that the boring work is done, we can go to the main part, the actual bruteforce! :D

Step 3: Main Code

635811800774678330.jpg

First the structure :

random-array do |element-of-array|

{block}

end

is a classic ruby structure that loops until the end of the array, element-of-array being a local variable for the block.

File.foreach(file) makes an array whose elements are the lines of the file. Adding the index clause associates to each line the place it occupies in the array. So in this case the loop we explained above is going to last for as many lines as there are in the wordlist file or until we tell it to stop inside the block.

Second the .chomp method : this method returns the string it is applied on without any newline or carriage return (\n and \r)

Third print statement : we saw puts earlier, puts always appends a newline at the end of the string when print does not. We use the #{variable} syntax to print the variable value and a carriage return "\r" at the beginning of the line, so each subsequent line does erase the one before it. This is meant to keep track of how many passwords were tested withtout flooding the screen.

Fourth the begin rescue structure :

begin

rescue error

{block1}

else

{block2}

end

In our case this structure allow us to continue the program even if an error occurs (which we know is going to happen if we try to connect to ssh with a wrong password) rescue basically allows us to control the error handling for a certain error.

the begin and end statements allow us to tell ruby in which part of the program to rescue the error in such a structure.

Here we continue as normal if the error is present, and if it's not, then we have found the password and can stop the program with a good 'ol abort statement (printing the password of course).

Net::SSH::AuthenticationFailed is the error we know we are going to get everytime we try a wrong password.

The main part of the "work" itself is done by NET::SSH.start() that tries to establish an SSH connection with the parameters we give to it.

target and user are the only two mandatory parameters this requires, the rest are given as options with the structure :option => value.

important thing to note is the method authentication password Of course we dont want to use keys to establish the ssh session. Also, the number of password prompts is important so when the password fails, ruby does not ask you to manually retry the password via a prompt.

If the connection is established, no error rescued, we enter the else block and we abort the programm printing the password. Voila !

Conclusion

I think that is all, let me know what you think about this kind of article. I might do more if some of you guys like it and i feel like it.

Also, please excuse me for the poor formatting of the post, I'm not used to writing things on Null Byte really.

If any Questions/Suggestions, let me know. Cheers :D

Comments

No Comments Exist

Be the first, drop a comment!