Thursday, December 17, 2020

AnonFTPCheck: a python script to check anonymous FTP server permissions

Alot of times we will come upon anonymous ftp servers and would have to check out the permissions of the server to see if any vulnerabilities exist. This script helps automate the process by checking some of the key vulnerabilities that can come with an anonymous ftp server.

#!/usr/bin/env python
"""
Created on Tue Nov 10 23:45:32 2020

[AnonFTPCheck.py]

@author: Sam
"""
import os
import sys
import random
import string
from ftplib import FTP
from pathlib import Path

mkdir = []
writable_dirs = []
username = 'anonymous'
password = 'anonymous@'

banner = """
            ###########################
            #       AnonFTPCheck      #
            ###########################                   
            """

def get_random_name():
    letters = string.ascii_letters
    string_s = ''.join(random.choice(letters) for i in range(8))   
    
    return string_s

def write_test_file(filename):
    try:
        file = open(filename, "w") 
        file.write("Hello, World!") 
        file.close()
        return filename
    except:
        return None

try:
    host = str(sys.argv[1])
except:
    print("*** [AnonFTPCheck] ***")
    print("Usage: " + sys.argv[0] + " [ip-address]")
    sys.exit(1)

print(banner)
    
ftp = FTP(host)

try:
    ftp.login(username, password)
    root_dir = ftp.pwd()
    print("[VERSION] " + ftp.getwelcome())
    print("[CURRENT DIRECTORY] " + root_dir)
    print("[DIRECTORY LISTING] ->")
    print(ftp.retrlines('LIST'))         
except:
    print('[' + host + '] is not an anonymous FTP server...')
    sys.exit(1)         

directories = ftp.nlst()

if not directories:
    print("*** FAILED: No directories found...")
    print("*** Skipping [WRITABLE DIRECTORY CHECK]...")
else:
    print("[WRITABLE DIRECTORY CHECK]")

    test_file = write_test_file(get_random_name() + ".txt")
    
    for dir in directories:
        ftp.cwd(root_dir)
        ftp.cwd(dir)   
        try:
            if test_file is None:
                print("*** FAILED: Could not create test file locally... Permissions Problem? Skipping [WRITABLE DIRECTORY CHECK]...")
                break
            else:
                fp = open(test_file, 'rb')
                ftp.storbinary('STOR %s' % os.path.basename(test_file), fp, 1024)
                fp.close()
                print("*** SUCCESS: Directory " + ftp.pwd() + " is writable! Test file " + ftp.pwd() + "/" + test_file + " wrote successfully!")
                writable_dirs.append(dir)
        except:
            continue


print("[RENAME ACCESS CHECK]")

for dir in writable_dirs:
    ftp.cwd(root_dir)
    ftp.cwd(dir)
    try: 
        ftp.rename(test_file, '654321.jpg')
        print("*** SUCCESS: Renamed " + ftp.pwd() + "/" + test_file + " to 654321.jpg")
    except:
        print("*** FAILED: Unable to successfully rename file " + ftp.pwd() + "/" + test_file + " to 654321.jpg")

print("[DELETE ACCESS CHECK]")       

for dir in writable_dirs:         
    ftp.cwd(root_dir)
    ftp.cwd(dir)
    try:
        ftp.delete('654321.jpg')
        print("*** SUCCESS: Delete access for " + ftp.pwd() + "/654321.jpg permitted!")
    except:
        print("*** FAILED: Delete access for " + ftp.pwd() + "/654321.jpg not permitted...")

print("[MKDIR ACCESS CHECK]")

test_dir = get_random_name()

for dir in directories:
    ftp.cwd(root_dir)
    ftp.cwd(dir)
    try:
        ftp.mkd(test_dir)
        mkdir.append(dir)
        print('*** SUCCESS: Created directory ' + ftp.pwd() + "/" + test_dir + '!' )
    except:
        continue
        
if not mkdir:
    print("*** FAILED: Could not any create directories...")
    print("*** Skipping [RMDIR ACCESS CHECK]...")
else:
    print("[RMDIR ACCESS CHECK]")

    for dir in mkdir:
        ftp.cwd(root_dir)
        ftp.cwd(dir)
        try:
            ftp.rmd(test_dir)
            print("*** SUCCESS: Directory " + ftp.pwd() + "/" + test_dir + " successfully removed!")
        except:
            print("*** FAILED: Unable to remove " + ftp.pwd() + "/" + test_dir + "...")
            
ftp.close()

for p in Path(".").glob("*.txt"):
    p.unlink()

print("[DONE]")

if we run the script we will get the following output.

C:\Users\Sam\Desktop\Code\anonftpcheck>python anonftpcheck.py 192.168.155.138

            ###########################
            #       AnonFTPCheck      #
            ###########################

[VERSION] 220 (vsFTPd 3.0.3)
[CURRENT DIRECTORY] /
[DIRECTORY LISTING] ->
drwxr-xr-x    2 65534    65534        4096 Dec 17 14:05 bin
drwxr-xr-x    2 65534    65534        4096 Dec 17 14:05 etc
drwxrwxrwx    2 65534    65534        4096 Jan 07 03:22 incoming
drwxr-xr-x    2 65534    65534        4096 Dec 17 14:06 lib
drwxrwxrwx    2 65534    65534        4096 Jan 07 03:23 pub
226 Directory send OK.
[WRITABLE DIRECTORY CHECK]
*** SUCCESS: Directory /incoming is writable! Test file /incoming/Uhcszbbx.txt wrote successfully!
*** SUCCESS: Directory /pub is writable! Test file /pub/Uhcszbbx.txt wrote successfully!
[RENAME ACCESS CHECK]
*** SUCCESS: Renamed /incoming/Uhcszbbx.txt to 654321.jpg
*** SUCCESS: Renamed /pub/Uhcszbbx.txt to 654321.jpg
[DELETE ACCESS CHECK]
*** SUCCESS: Delete access for /incoming/654321.jpg permitted!
*** SUCCESS: Delete access for /pub/654321.jpg permitted!
[MKDIR ACCESS CHECK]
*** SUCCESS: Created directory /incoming/ogHrROxg!
*** SUCCESS: Created directory /pub/ogHrROxg!
[RMDIR ACCESS CHECK]
*** SUCCESS: Directory /incoming/ogHrROxg successfully removed!
*** SUCCESS: Directory /pub/ogHrROxg successfully removed!
[DONE]

C:\Users\Sam\Desktop\Code\anonftpcheck>

This script will help in finding exploitable anonymous ftp servers and highlight the vulnerabilities that may exist.

1 comment:

  1. how can i put in more than 1 hosts in it??
    is there an option?

    ReplyDelete

Exploiting Weak WEBDAV Configurations

The server we are going to audit has the following fingerprint. 80/tcp open http Apache httpd 2.2.8 ((Ubuntu) DAV/2) Next we need t...