I am following along with code from the Violent Python book. This is what I have here, testing a brute-force of an FTP:
import ftplib
def bruteLogin(hostname, passwdFile):
pF = open(passwdFile, 'r')
for line in pF.readlines():
userName = line.split(':')[0]
passWord = line.split(':')[1].strip('\r').strip('\n')
print("[+] Trying: "+userName+"/"+passWord)
try:
ftp = ftplib.FTP(hostname)
ftp.login(userName, passWord)
print('\n[*] ' + str(hostname) +\
' FTP Logon Succeeded: '+userName+"/"+passWord)
ftp.quit()
return (userName, passWord)
except Exception as e:
pass
print('\n[-] Could not brute force FTP credentials.')
return (None, None)
host = '192.168.95.179'
passwdFile = 'C:/Users/Andrew/Documents/Python Stuff/userpass.txt'
bruteLogin(host, passwdFile)
Using an example 'userpass.txt' consisting of:
administrator:password
admin:12345
root:secret
guest:guest
root:root
When running (I am using Python 3.4, by the way) it is supposed to return a result of this:
[+] Trying: administrator/password
[+] Trying: admin/12345
[+] Trying: root/secret
[+] Trying: guest/guest
[*] 192.168.95.179 FTP Logon Succeeded: guest/guest
The above is an example of a successful logon, of course. When actually running it, it returns the "Could not find the brute force FTP credentials", but seems to only try the very first line of the text file, instead of passing through the exception and trying the other lines, as described in the book. Any ideas?
You should print that "Could not find..." line only after the loop has completed. Your current code does it with every iteration, so if the first attempt doesn't succeed, it is printed already.
Also, it is easier to reason about exceptions if you keep the try block as short as possible and the exception to be caught as specific as possible. That reduces the number of cases where an exception is handled and lets all other, unrelated exceptions explode and become visible, helping you debug your code in the places that you don't expect to raise exceptions. Your code could look like this then:
def bruteLogin(hostname, passwdFile):
pF = open(passwdFile, 'r')
ftp = ftplib.FTP(hostname) # reuse the connection
for line in pF.readlines():
userName, passWord = line.split(':', 1) # split only once, the pw may contain a :
passWord = passWord.strip('\r\n') # strip any of the two characters
print("[+] Trying: {}/{}".format(userName, passWord))
try:
ftp.login(userName, passWord)
except ftplib.error_perm:
continue
else:
print('\n[*] {} FTP Logon Succeeded: {}/{}'.format(hostname, userName, passWord))
ftp.quit()
return userName, passWord
print('\n[-] Could not brute force FTP credentials.')
return None, None
Related
I have a short code that ftps a small file into a server.
session = ftplib.FTP("192.168.0.164", "admin", "admin")
file = open("path/test.txt", "rb")
try:
session.storbinary("STOR application/test.txt", file)
except:
print("failed")
else:
print("success!")
file.close()
In the above piece I changed the IP address to so it would fail (there is no 192.168.0.164 device) and it doesn't print failed like it's supposed to. In the terminal I get a
"connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond" error.
if I mistype the path, I also don't get a failed print on the terminal.
If I type in the correct IP the success part does work.
Am I using the try/except wrong?
UPDATE:
Current code looks like this:
file = open("path/test.txt", "rb")
try:
session = ftplib.FTP("192.168.0.161", "admin", "admin")
session.storbinary("STOR application/test.txt", file)
except:
print("Unable to reach host")
else:
print("success!")
session.quit()
finally:
print ("DONE!!")
file.close()
I figure the ftplib.all_errors will catch all errors (host unreachable, and file not found). It seems to catch the unable to reach host errors, but no file not found errors.
Am I using the try/except wrong?
Your syntax is correct, but Python is not actually reaching the try block at all.
When you call session = ftplib.FTP(host, ...) where host is unreachable, the code will stop in its tracks there. That's because FTP.__init__() greedily calls self.connect(). This will in turn call socket.create_connection(), which will not succeed for an unreachable host.
So, you'd need to modify to:
with open("path/test.txt", "rb") as file:
try:
session = ftplib.FTP("192.168.0.164", "admin", "admin")
session.storbinary("STOR application/test.txt", file)
except Exception as e:
print("failed")
print(e)
else:
print("success!")
finally:
session.quit()
I have a script that uses SSH via Paramiko to login to switches and initiate a TFTP copy of the startup-config. This almost works like I want except the file name does not include the .txt file type.
The specific line I'm working with is:
command.send("copy startup-config tftp://192.168.0.1/Backup-{}.txt \n".format(i))
Tried looking at examples on Google.
#!/usr/bin/env python3
###############################################
# THIS SCRIPT SAVES THE RUNNING-CONFIG TO #
# STARTUP-CONFIG AND THEN COPIES THE #
# STARTUP-CONFIG TO THE SPECIFIED IP VIA TFTP #
###############################################
#
import paramiko
import sys, time
#
username = 'user'
password = 'pass'
#
with open('Advantech_Test_IPs', 'r') as host_list:
for i in host_list:
str(i)
try:
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(i, username=username, password=password)
command = ssh_client.invoke_shell()
command.send("copy running-config startup-config \n")
time.sleep(1)
command.send("copy startup-config tftp://.../Backup-{}.txt \n".format(i))
time.sleep(1)
ssh_client.close
print(i, "BACKUP COMPLETE")
except paramiko.ssh_exception.NoValidConnectionsError as e:
pass
print(i, "No Valid Connections")
except paramiko.ssh_exception.AuthenticationException as ea:
print(i, "Authentication Failed")
except paramiko.ssh_exception.BadHostKeyException as eb:
print(i, "Bad Host Key")
except Exception as ex:
print(i, "SOMETHING WENT WRONG!")
print("All done.")
The file gets copied over, but the .txt file extension is not appended so I end up with file types that match the last part of the IP address.
The i contains a new line at the end. So effectively you are sending a two lines to the server:
copy startup-config tftp://192.168.0.1/Backup-IP
.txt
You can use str.strip (or str.rstrip) to remove the newline:
command.send("copy startup-config tftp://192.168.0.1/Backup-{}.txt \n".format(i.strip()))
Wizards of stackoverflow. I'm trying to read in commands from a .txt file to SSH using paramiko. Currently it will read in the first line from the file and execute it. When I get to the second line though, it will throw an EOFError and quit. I put a check in to see if the second command makes it to print and it does, however, it does not execute. I was hoping someone would be able to help and solve this issue with me. Here is my code:
from paramiko import client
import logging
import os
#Clear the screen before starting the script
os.system('cls')
# Prompting for the user input config file
filename = input('Input configuration filename, the file extension must be attached: ')
# Creating the LOG file for the execution of the config file
logFileName = "LOG" + filename[0:]
try:
logging.basicConfig(filename= logFileName ,format='%(asctime)s %(message)s', level= logging.DEBUG)
print ("The file was created!")
except IOError:
print ("File failed to create")
logging.info("---------------------------------------------------------------------------")
logging.info("NEW CONFIGURATION LOG ENTRY")
logging.info("---------------------------------------------------------------------------")
# Class for creating an SSH client, logging in, letting us write out commands, and close the client.
class ssh:
client = None
def __init__(self, address, username, password):
print ("Connecting to server...")
logging.info('Connecting to server...')
self.client = client.SSHClient()
self.client.set_missing_host_key_policy(client.AutoAddPolicy())
self.client.connect(address, username= username, password= password, look_for_keys= False)
logging.info("Address: " + address)
logging.info("Username: " + username)
print ("Connection successful!")
logging.info('Connection successful!')
def sendCommand(self, command):
if (self.client):
stdin, stdout, stderr = self.client.exec_command(command)
receiveData = b""
while not stdout.channel.exit_status_ready():
receiveData += stdout.channel.recv(1024)
if stdout.channel.recv_ready():
received = stdout.channel.recv(1024)
while received:
receiveData += received
received = stdout.channel.recv(1024)
if receiveData:
print (str(receiveData, "utf8"))
else:
print ("stdout is empty")
else:
print ("Connection failed, check credentials and try again..")
logging.warning('Connection failed, check credentials and try again..')
connection = ssh('0.0.0.0', 'test', 'test')
with open(filename) as f:
for line in f:
print(line)
connection.sendCommand(line)
The .txt file would read something like this:
configure terminal
Interface Gi0/9
description Test_Interface
Any help is much appreciated, thank you.
Possible bug. Current implementation of sendCommand may not receive output (or full output).
Reason
exit_status_ready is a non blocking way to find that exit status is received. It is possible that lastpart of output still not readed by script. You need to call recv after while if recv_ready is True.
Also, I don't think that checking recv_ready in while loop is good idea. It's non-blocking method. Because of it while loop will uselessly run multiple times, just wasting your CPU power.
This version work for me:
receiveData = b""
while not stdout.channel.exit_status_ready():
receiveData += stdout.channel.recv( 2048 )
if stdout.channel.recv_ready():
received = stdout.channel.recv( 2048 )
while received: #received will be empty only when all data received
receiveData += received
received = stdout.channel.recv( 2048 )
if receiveData:
print( str( receiveData, "utf8" ) )
else:
print( "stdout is empty" )
Also I should mention that there is easer way to build string from output. You can use the fact that stdin, stdout, and stderr are file like objects.
Here simpler example for stderr (it may be good idea to read it too):
data = ""
for line in stderr:
#line in string already (probably will work only if locale is utf8)
data += line
if data:
print( data )
else:
print( "stderr is empty" )
Update:
if you don't have multiple commands on one line then
filename = input('Input configuration filename, the file extension must be attached: ')
# define ssh class here (i'll skip it to make it shorter)
connection = ssh('0.0.0.0', 'test', 'test')
with open(filename) as f:
for line in f:
connection.sendCommand( line )
If you have several commands per line just split them to array of different commands.
I am trying to read the response or exception of pop3 hotmail server. its very simple question but i am beginner in python don't know how to read it? this is my code:
import poplib
import sys
host = 'pop3.live.com'
port = 995
email='123456#hotmail.com'
pwd='123456'
server = poplib.POP3_SSL(host, port)
try:
server.user(email)
server.pass_(pwd)
if('+OK'):
print 'Email: '+email+'password: '+pwd
server.quit()
sys.exit(1)
except poplib.error_proto:
if('POP+disabled'):
print 'Email: '+email+'password: '+pwd
server.quit()
sys.exit(1)
elif('authentication+failed'):
print "wronge user and pass. try again"
continue
continue
in exception "if ('POP+disabled')" used to eliminate that user login and password is correct but the account has not enabled POP3 in options.
when I run the above code then it also display email password whether i put wrong password...
Can any body help me please how to handle this problem?
You can use the server.getwelcome() method to check for the server response before proceeding into parsing messages.
The server object lets you request the list of messages after authentication and then you can call retr to retrieve each message.
welcomeresp = server.getwelcome()
if welcomeresp.find("+OK"):
numMessages = len(server.list()[1])
for i in range(numMessages):
for j in server.retr(i+1):
server_msg, body, octets = j
for line in body:
print line
Take a look at the documentation for the POP library for more information and an example:
https://docs.python.org/2/library/poplib.html
I'm downloading files from a flaky FTP server that often times out during file transfer and I was wondering if there was a way to reconnect and resume the download. I'm using Python's ftplib. Here is the code that I am using:
#! /usr/bin/python
import ftplib
import os
import socket
import sys
#--------------------------------#
# Define parameters for ftp site #
#--------------------------------#
site = 'a.really.unstable.server'
user = 'anonymous'
password = 'someperson#somewhere.edu'
root_ftp_dir = '/directory1/'
root_local_dir = '/directory2/'
#---------------------------------------------------------------
# Tuple of order numbers to download. Each web request generates
# an order numbers
#---------------------------------------------------------------
order_num = ('1','2','3','4')
#----------------------------------------------------------------#
# Loop through each order. Connect to server on each loop. There #
# might be a time out for the connection therefore reconnect for #
# every new ordernumber #
#----------------------------------------------------------------#
# First change local directory
os.chdir(root_local_dir)
# Begin loop through
for order in order_num:
print 'Begin Proccessing order number %s' %order
# Connect to FTP site
try:
ftp = ftplib.FTP( host=site, timeout=1200 )
except (socket.error, socket.gaierror), e:
print 'ERROR: Unable to reach "%s"' %site
sys.exit()
# Login
try:
ftp.login(user,password)
except ftplib.error_perm:
print 'ERROR: Unable to login'
ftp.quit()
sys.exit()
# Change remote directory to location of order
try:
ftp.cwd(root_ftp_dir+order)
except ftplib.error_perm:
print 'Unable to CD to "%s"' %(root_ftp_dir+order)
sys.exit()
# Get a list of files
try:
filelist = ftp.nlst()
except ftplib.error_perm:
print 'Unable to get file list from "%s"' %order
sys.exit()
#---------------------------------#
# Loop through files and download #
#---------------------------------#
for each_file in filelist:
file_local = open(each_file,'wb')
try:
ftp.retrbinary('RETR %s' %each_file, file_local.write)
file_local.close()
except ftplib.error_perm:
print 'ERROR: cannot read file "%s"' %each_file
os.unlink(each_file)
ftp.quit()
print 'Finished Proccessing order number %s' %order
sys.exit()
The error that I get:
socket.error: [Errno 110] Connection timed out
Any help is greatly appreciated.
Resuming a download through FTP using only standard facilities (see RFC959) requires use of the block transmission mode (section 3.4.2), which can be set using the MODE B command. Although this feature is technically required for conformance to the specification, I'm not sure all FTP server software implements it.
In the block transmission mode, as opposed to the stream transmission mode, the server sends the file in chunks, each of which has a marker. This marker may be re-submitted to the server to restart a failed transfer (section 3.5).
The specification says:
[...] a restart procedure is provided to protect users from gross system failures (including failures of a host, an FTP-process, or the underlying network).
However, AFAIK, the specification does not define a required lifetime for markers. It only says the following:
The marker information has meaning only to the sender, but must consist of printable characters in the default or negotiated language of the control connection (ASCII or EBCDIC). The marker could represent a bit-count, a record-count, or any other information by which a system may identify a data checkpoint. The receiver of data, if it implements the restart procedure, would then mark the corresponding position of this marker in the receiving system, and return this information to the user.
It should be safe to assume that servers implementing this feature will provide markers that are valid between FTP sessions, but your mileage may vary.
A simple example for implementing a resumable FTP download using Python ftplib:
def connect():
ftp = None
with open('bigfile', 'wb') as f:
while (not finished):
if ftp is None:
print("Connecting...")
FTP(host, user, passwd)
try:
rest = f.tell()
if rest == 0:
rest = None
print("Starting new transfer...")
else:
print(f"Resuming transfer from {rest}...")
ftp.retrbinary('RETR bigfile', f.write, rest=rest)
print("Done")
finished = True
except Exception as e:
ftp = None
sec = 5
print(f"Transfer failed: {e}, will retry in {sec} seconds...")
time.sleep(sec)
More fine-grained exception handling is advisable.
Similarly for uploads:
Handling disconnects in Python ftplib FTP transfers file upload
To do this, you would have to keep the interrupted download, then figure out which parts of the file you are missing, download those parts and then connect them together. I'm not sure how to do this, but there is a download manager for Firefox and Chrome called DownThemAll that does this. Although the code is not written in python (I think it's JavaScript), you could look at the code and see how it does this.
DownThemll - http://www.downthemall.net/