Problema

Problema

Problema

algunos viejosServidor WS_FTPDejó de arrancar en el trabajo después de una actualización de Windows. El administrador correspondiente ya no está. La única información que tengo es:

  • estructura de archivos
  • nombres de usuario
  • hash SHA256 sin sal para cada usuario

Uno de esos hashes es:

5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

que corresponde a "password". Podría consultar con: echo -n password | sha256sum.

Ni siquiera sé dónde están los clientes FTP. Algunos de ellos son sensores remotos a los que no puedo acceder. Seguían enviando datos hasta que el servidor se detuvo. Los datos no son confidenciales, pero aun así son importantes para nosotros.

Intentos

  • Intenté correrjuan el destripadoren los hashes. Encontró 4 contraseñas de 30.

  • Intenté encontrar un servidor FTP de Linux que utilice hashes SHA256 sin sal. Creo que es demasiado inseguro, por lo que ningún servidor lo propuso, al menos no de forma predeterminada.

  • Algunos servidores (por ejemplovsftpd) delegar en htpasswd. Sin embargo, no pude encontrar una manera de guardar un hash SHA256 sin sal.

Pregunta

¿Es posible crear un htpasswdhash con SHA256, sin sal y de una sola ronda? El mínimo parece ser un salt de 8 bytes y 1000 rondas con mkpasswd.

¿Existe otro servidor FTP de Linux que pueda configurarse para funcionar con esos hashes?

No me importa mucho la seguridad, sólo me gustaría configurar un servidor FTP que acepte conexiones entrantes de los sensores.

Respuesta1

@Broco sugirió usarpyftpdlib, ¡que funcionó perfectamente para mis necesidades!

Aquí están los pasos:

  • Instalar un servidor Linux
  • InstalarAnaconda
  • Instalarpyftpdlib
  • Cree un archivo json con un dictado de nombre de usuario, hash y carpeta
  • Cree un script pyftpdlib para un servidor FTP que compare los hashes SHA256
  • Redirigirpuerto 21 al puerto 8021
  • ejecutarlo como ununidad del sistemacomo usuario sin privilegios
  • Reinicie elservidor ftp automáticamentesi se modifica el archivo json.

Aquí hay una plantilla para el archivo json:

{
    "user1": {
        "folder": "users/user1",
        "sha256": "DFB0CE07EDF923F1F40BA56CC9BA9C396B53E3399E3164D60E35050BAA2BE9C9"
    },
    "user2": {
        "folder": "users/user2",
        "sha256": "5E884898DA28047151D0E56F8DC6292773603D0D6AABBDD62A11EF721D1542D8"
    }
}

Aquí está el guión:

#!/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()

El script registra las contraseñas en texto plano, lo cual es aceptable porque los datos no son confidenciales. Después de unos meses, cambiaré a vsftpd.

información relacionada