![问题](https://linux22.com/image/719452/%E9%97%AE%E9%A2%98.png)
问题
有些老WS_FTP 服务器Windows 更新后,在工作时停止启动。相应的管理员早已消失。我唯一掌握的信息是:
- 文件结构
- 用户名
- 每个用户的无盐 SHA256 哈希
其中一个哈希值为:
5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
对应于"password"
。我可以用以下方法检查:echo -n password | sha256sum
。
我甚至不知道 FTP 客户端在哪里。其中一些是远程传感器,我无法访问。它们仍在发送数据,直到服务器停止。这些数据不是机密的,但对我们来说仍然很重要。
尝试
我尝试跑步开膛手约翰在哈希上。它在 30 个密码中找到了 4 个。
我尝试寻找一个使用无盐 SHA256 哈希的 Linux FTP 服务器。我认为它太不安全了,所以没有服务器推荐它,至少不是默认的
某些服务器(例如vsftpd) 委托给 htpasswd。不过,我找不到保存无盐 SHA256 哈希的方法。
问题
是否可以htpasswd
使用 SHA256 创建哈希,不加盐且仅进行一轮?最低要求似乎是 8 字节盐和 1000 轮mkpasswd
。
是否有另一个 Linux FTP 服务器可以配置为使用这些哈希值?
我不太关心安全性,我只想建立一个接受来自传感器的传入连接的 FTP 服务器。
答案1
@Broco 建议使用pyftpdlib,完全满足我的需要!
步骤如下:
- 安装 Linux 服务器
- 安装蟒蛇
- 安装pyftpdlib
- 创建一个包含用户名、哈希值和文件夹的 json 文件
- 为 FTP 服务器创建一个 pyftpdlib 脚本,用于比较 SHA256 哈希值
- 重定向端口 21 到端口 8021
- 将其作为系统单元作为非特权用户
- 重新启动自动 ftp 服务器如果json文件被修改了。
以下是 json 文件的模板:
{
"user1": {
"folder": "users/user1",
"sha256": "DFB0CE07EDF923F1F40BA56CC9BA9C396B53E3399E3164D60E35050BAA2BE9C9"
},
"user2": {
"folder": "users/user2",
"sha256": "5E884898DA28047151D0E56F8DC6292773603D0D6AABBDD62A11EF721D1542D8"
}
}
脚本如下:
#!/opt/anaconda3/bin/python -u
#encoding: UTF-8
import re
import os
import hashlib
import json
from pathlib import Path
from pyftpdlib.authorizers import DummyAuthorizer, AuthenticationFailed
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
from pyftpdlib.filesystems import AbstractedFS
FTP_FOLDER = Path("/media/ftp_data")
with open('input/ftp_users.json') as users_json:
USERS = json.loads(users_json.read())
current_folder = Path.cwd().resolve()
def login_dump(username, password, success):
if success:
subfolder = 'logins'
attr = 'w'
else:
subfolder = 'logins/failed'
attr = 'a'
logins_folder = current_folder.joinpath(subfolder)
logins_folder.mkdir(parents=True, exist_ok=True)
with open(str(logins_folder.joinpath(username)), attr) as user_file:
# NOTE: Could write better hash directly, e.g. with `mkpasswd -m sha-512`
user_file.write(password + "\n")
class SHA256Authorizer(DummyAuthorizer):
def validate_authentication(self, username, password, handler):
sha256_hash = hashlib.sha256(password.encode('ascii')).hexdigest().upper()
try:
# NOTE: Case sensitive!
if self.user_table[username]['pwd'] != sha256_hash:
login_dump(username, password, False)
raise AuthenticationFailed
except KeyError:
login_dump(username, password, False)
raise AuthenticationFailed
login_dump(username, password, True)
authorizer = SHA256Authorizer()
for user, params in USERS.items():
print("Adding user %r" % user)
folder = FTP_FOLDER.joinpath(params['folder'])
folder.mkdir(parents=True, exist_ok=True)
authorizer.add_user(user,
params['sha256'].upper(),
str(folder),
perm="elradfmw",
msg_login="Welcome, %s!" % user)
handler = FTPHandler
handler.authorizer = authorizer
handler.banner = "FTP server"
class WindowsOrUnixPathFS(AbstractedFS):
def ftpnorm(self, ftppath):
# NOTE: Some old clients still think they talk to a Windows Server
return super().ftpnorm(ftppath.replace("\\", "/"))
handler.abstracted_fs = WindowsOrUnixPathFS
handler.passive_ports = range(40000, 40500)
# NOTE: Port forwarding is needed because this script shouldn't be run as root.
# See https://serverfault.com/a/238565/442344
server = FTPServer((IP_ADDRESS, 8021), handler)
server.serve_forever()
该脚本以纯文本形式记录密码,这是可以接受的,因为数据不是机密的。几个月后,我将切换到 vsftpd。