Python实现FTP弱口令扫描器的方法示例
本文详解如何使用Python的ftplib库构建FTP扫描器。内容涵盖主动与被动FTP协议差异,实现匿名登录检测及基于字典的弱口令暴力破解功能。通过argparse处理命令行参数,支持批量主机扫描,并提供完整代码示例与测试指南,旨在帮助开发者理解FTP安全检测原理。
FTP服务器
FTP服务器是互联网上提供文件存储与访问服务的计算机节点,其核心遵循FTP协议。FTP即File Transfer Protocol(文件传输协议),顾名思义,它是专为文件传输设计的通信标准,支持该协议的服务器即被称为FTP服务器。
FTP协议仅基于TCP构建,不支持UDP,因为文件传输需要稳定可靠的连接保障。与一般服务不同,FTP使用两个端口:一个用于命令交互的控制端口,另一个用于数据传输的数据端口。通常控制端口为21(命名端口),数据端口为20。然而,由于FTP工作模式(主动或被动)的差异,数据端口并非固定为20,这也是主动FTP与被动FTP的主要区别所在。
- 主动FTP
在主动FTP模式下,服务器控制端口固定为21,数据端口为20。进行静态映射时,只需开放21端口,服务器将使用20端口主动发起与客户端的数据连接。
- 被动FTP
在被动FTP模式下,服务器控制端口仍为21,但数据端口是随机分配的。此时,客户端需要主动连接服务器指定的随机数据端口。因此,若仅开放21端口进行静态映射,无法完成被动模式下的数据传输。
FTP扫描的实现方案
扫描匿名FTP
匿名FTP扫描主要应用于批量检测场景,单独针对单一服务器扫描的成功率较低。许多网站开放FTP服务以方便用户下载资源,允许匿名登录并不罕见。更值得注意的是,部分网站管理员为方便软件更新而开放匿名FTP权限,这为安全测试提供了大量目标,且此类服务器往往存在较高的安全风险。
扫描FTP弱口令
弱口令扫描并非尝试所有可能的密码组合,而是针对常见、简单的密码组合进行探测。
步骤
FTP匿名扫描器的实现
本方案需使用Python的ftplib库中的FTP类,该类封装了连接服务器、查看文件、上传下载等核心功能,具体用法可参考官方API。首先定义anonScan(hostname)函数,用于检测支持匿名登录的FTP服务器。代码如下:
def anonScan(hostname): # 参数是主机名
try:
with FTP(hostname) as ftp: # 创建FTP对象
ftp.login() # FTP匿名登陆
print("\n[*]" + str(hostname) + " FTP Anonymous login successful!")
return True
except Exception as e: # 抛出异常表示匿名登陆失败
print("\n[-]" + str(hostname) + " FTP Anonymous login failure!")
return False
代码逻辑清晰简洁。函数思路如下:首先利用主机名实例化FTP对象(即ftp),随后调用不带参数的login()方法尝试匿名登录。若执行过程中未抛出异常,则判定匿名登录成功;反之,若捕获异常,则判定登录失败。
FTP弱口令的扫描
FTP弱口令扫描依赖于预置的用户名和密码字典。可下载相关密码字典,并将其命名为pwd.txt备用。
接下来,根据字典格式编写FTP弱口令扫描代码,创建文件ftpScanner.py,代码如下:
def vlcLogin(hostname, pwdFile): # Parameters (hostname, dictionary file)
try:
with open(pwdFile, 'r') as pf: # Open dictionary file
for line in pf.readlines():
userName = line.split(':')[0] # Fetch username
passWord = line.split(':')[1].strip('\r').strip('\n') # Fetch password
print('[+] Trying: ' + userName + ':' + passWord)
try:
with FTP(hostname) as ftp:
ftp.login(userName, passWord)
print('\n[+] ' + str(hostname) + ' FTP Login successful: '+ \
userName + ':' + passWord)
return (userName, passWord)
except Exception as e:
# Continue trying other usernames and passwords
pass
except IOError as e:
print('Error: the password file does not exist!')
print('\n[-] Cannot crack the FTP password, please change the password dictionary try again!')
return (None,None)
该代码核心逻辑为循环读取字典中的用户名和密码组合并尝试登录。一旦登录成功,即记录该有效凭证。由于函数设计允许主机名通过逗号分隔传入多个目标,程序在找到某个主机的弱口令后不会终止,而是继续扫描其余主机,直至完成所有目标的检测。
命令行解析
至此,FTP扫描器的核心功能已基本完成。为使脚本具备灵活性,需通过命令行输入控制扫描目标。此处引入Python的argparse库来处理命令行参数。
parser = argparse.ArgumentParser(description='FTP Scanner')
parser.add_argument('-H',dest='hostName',help='The host list with ","space')
parser.add_argument('-f',dest='pwdFile',help='Password dictionary file')
options = None
try:
options = parser.parse_args()
except:
print(parser.parse_args(['-h']))
exit(0)
hostNames = str(options.hostName).split(',')
pwdFile = options.pwdFile
整合全部代码
# -*- coding: utf-8 -*-
from ftplib import *
import argparse
import time
# Anonymous login scan
def anonScan(hostname): # The parameter is the host name
try:
with FTP(hostname) as ftp: # Create FTP object
ftp.login() # FTP anonymous login
print("\n[*]" + str(hostname) + " FTP Anonymous login successful!")
return True
except Exception as e: # Throwing an exception indicates that the anonymous login failed
print("\n[-]" + str(hostname) + " FTP Anonymous login failure!")
return False
# Brute force
def vlcLogin(hostname, pwdFile): # Parameters (hostname, dictionary file)
try:
with open(pwdFile, 'r') as pf: # Open dictionary file
for line in pf.readlines():
userName = line.split(':')[0] # Fetch username
passWord = line.split(':')[1].strip('\r').strip('\n') # Fetch password
print('[+] Trying: ' + userName + ':' + passWord)
try:
with FTP(hostname) as ftp:
ftp.login(userName, passWord)
print('\n[+] ' + str(hostname) + ' FTP Login successful: '+ \
userName + ':' + passWord)
return (userName, passWord)
except Exception as e:
# Continue trying other usernames and passwords
pass
except IOError as e:
print('Error: the password file does not exist!')
print('\n[-] Cannot crack the FTP password, please change the password dictionary try again!')
return (None,None)
def main():
parser = argparse.ArgumentParser(description='FTP Scanner')
parser.add_argument('-H',dest='hostName',help='The host list with ","space')
parser.add_argument('-f',dest='pwdFile',help='Password dictionary file')
options = None
try:
options = parser.parse_args()
except:
print(parser.parse_args(['-h']))
exit(0)
hostNames = str(options.hostName).split(',')
pwdFile = options.pwdFile
if hostNames == ['None']:
print(parser.parse_args(['-h']))
exit(0)
for hostName in hostNames:
username = None
password = None
if anonScan(hostName) == True:
print('Host: ' + hostName + ' Can anonymously!')
elif pwdFile != None:
(username,password) = vlcLogin(hostName,pwdFile)
if password != None:
print('\n[+] Host: ' + hostName + 'Username: ' + username + \
'Password: ' + password)
print('\n[*]-------------------Scan End!--------------------[*]')
if __name__ == '__main__':
main()
测试扫描
现在可以测试编写的FTP弱口令扫描器,在命令行中执行以下命令:
python ftpScanner.py -H 127.0.0.1 -f pwd.txt

由于本地未开启FTP服务,扫描结果将显示失败。读者可在服务器上开启FTP服务后进行实际测试。请注意,本工具仅限合法安全研究使用,严禁用于非法用途。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









