
Problem
Etwas altesWS_FTP-Servernach einem Windows-Update hat der Bootvorgang bei der Arbeit aufgehört. Der entsprechende Administrator ist schon lange weg. Die einzigen Informationen, die ich habe, sind:
- Dateistruktur
- Benutzernamen
- ungesalzener SHA256-Hash für jeden Benutzer
Einer dieser Hashes ist:
5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
was entspricht "password"
. Ich könnte es mit überprüfen: echo -n password | sha256sum
.
Ich weiß nicht einmal, wo die FTP-Clients sind. Einige davon sind Remote-Sensoren, auf die ich keinen Zugriff habe. Sie haben weiterhin Daten gesendet, bis der Server stoppte. Die Daten sind nicht vertraulich, aber dennoch wichtig für uns.
Versuche
Ich habe versucht zu rennenJohn der Ripperauf den Hashes. Es wurden 4 von 30 Passwörtern gefunden.
Ich habe versucht, einen Linux-FTP-Server zu finden, der ungesalzene SHA256-Hashes verwendet. Ich denke, das ist zu unsicher, also hat es kein Server vorgeschlagen, zumindest nicht als Standard
Einige Server (zBvsftpd) an htpasswd delegieren. Ich konnte jedoch keine Möglichkeit finden, einen ungesalzenen SHA256-Hash zu speichern.
Frage
Ist es möglich, einen htpasswd
Hash mit SHA256 zu erstellen, ohne Salt und nur einer Runde? Das Minimum scheint ein 8-Byte-Salt und 1000 Runden mit zu sein mkpasswd
.
Gibt es einen anderen Linux-FTP-Server, der für die Arbeit mit diesen Hashes konfiguriert werden kann?
Auf die Sicherheit lege ich keinen großen Wert, ich möchte lediglich einen FTP-Server einrichten, der eingehende Verbindungen von den Sensoren akzeptiert.
Antwort1
@Broco schlug vor,pyftpdlib, was für meine Bedürfnisse perfekt funktioniert hat!
Hier sind die Schritte:
- Installieren eines Linux-Servers
- InstallierenAnakonda
- Installierenpyftpdlib
- Erstellen Sie eine JSON-Datei mit einem Dict aus Benutzername, Hash und Ordner
- Erstellen Sie ein pyftpdlib-Skript für einen FTP-Server, der die SHA256-Hashes vergleicht
- UmleitenPort 21 bis Port 8021
- Führen Sie es aus alssystemd-Einheitals nicht-privilegierter Benutzer
- Starten Sie denFTP-Server automatischwenn die JSON-Datei geändert wird.
Hier ist eine Vorlage für die JSON-Datei:
{
"user1": {
"folder": "users/user1",
"sha256": "DFB0CE07EDF923F1F40BA56CC9BA9C396B53E3399E3164D60E35050BAA2BE9C9"
},
"user2": {
"folder": "users/user2",
"sha256": "5E884898DA28047151D0E56F8DC6292773603D0D6AABBDD62A11EF721D1542D8"
}
}
Hier ist das Skript:
#!/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()
Das Skript protokolliert die Passwörter im Klartext, was akzeptabel ist, da die Daten nicht vertraulich sind. Nach ein paar Monaten werde ich auf vsftpd umsteigen.