Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - DtxdF

#561
Quizás esto te ilumine:

*- You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login
*- You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login
*- You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

Por cierto, como te mencionaron antes, no solo es aplicado a los estudiantes de programación, sino en general  :). Y también no necesariamente pueden ser consecuentes de lo que mencionan los artículos que comenté, puede deberse a otro o una comorbilidad, o simplemente tienen el ego hasta la corona.

~ DtxdF
#562
Uf, muchísimas gracias @You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login, explica muchas cosas, muestra los algoritmos y lo mejor, está en español ^-^

~ DtxdF
#563
Dudas y pedidos generales / Re:Duda - Python
Julio 12, 2020, 06:02:25 AM
Creo que lo que desea hacer es eliminar la Barra de Herramientas. El siguiente código hace eso, pero no es muy portable que digamos y solo ha sido probado en debian y arch, aunque espero le sirva como un inicio:

Código: python
import tkinter as tk

root = tk.Tk()
root.attributes('-type', 'dock')
root.eval('tk::PlaceWindow %s center' % root.winfo_pathname(root.winfo_id()))
root.geometry('200x200')
root.focus_force()
root.mainloop()


Referencias:

*- You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login
*- You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

~ DtxdF
#564
Seguro tiene problemas con la partición de la UEFI, puede leer lo siguiente de la wiki de Arch: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

Quizá no esté usando Arch Linux, pero no es tan diferente hacerlo en otra distribución. Suerte  ;)

~ DtxdF
#565
Muchísimas gracias @You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login, será un placer seguir aportando estos temas ^-^

~ DtxdF
#566
@You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

CitarEres sumamente increíble gracias amigo! tu siempre resolviendo

Un placer ayudar ;-)

CitarPor cierto no conocía a WeTransfer, excelente!

Se ha logrado posicionar como un buen candidato a la transferencia de archivos, aunque hay diversas alternativas: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

~ DtxdF
#567
No, solo es trabajo duro.

Una persona podría tener una inteligencia superior a la media, pero hay un factor muy grande a tener en cuenta para lograr un objetivo y tener éxito, la autodisciplina.

Una persona disciplinada es aquella persona que es ordenada con sus hábitos y que trata de involucrarse y tener un compromiso con lo que decide y va a hacer. Mucho más allá de la perseverancia, hace falta un orden muy estricto en las cosas, a tal grado que su rutina diaria pasa a ser una pasión sin lucros y para nada efímera.

Tener un porqué es muy grato para uno mismo, porque es lo que te mantiene vivo, lo que motiva a despertar cada mañana y sentir esa presión en el pecho de que aún no puedes irte de esta tierra sin terminar eso que te hace tanta falta. Una persona que sea muy bien organizada siempre tendrá un porqué, en el caso de un informático tendrá muchos, porque constantemente tiene que aprender algo, incluso si tiene propuesto convertirse en un hacker o no.

Hay muchos hackers y programadores que han existido alrededor de la historia (Steve Wozniak, Linus Torvalds, Dennis Ritchie, Grace Hopper y muchísimos más) que han tenido ese porqué, que se han dedicado toda su vida a una y sola una cosa a lo largo de su vida, han ido mejorando, aprendiendo y poco a poco crearon lo que se imaginaban desde que decidieron iniciar sin importarles cuán inteligentes eran.


Te lo resumo: Inteligencia == Éxito: false

~ DtxdF
#568
@You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

Lo subí a Wetransfer, por lo que el periodo donde estará el PDF será de una semana (suficiente, creo): You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

~ DtxdF
#569
Gracias compañero @You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login, es un placer :'D

~ DtxdF
#570
Muchísimas gracias a los dos (@You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login y @You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login) y a todos los lectores, será un placer seguir continuando con esta temática ^-^

~ DtxdF
#571
Un ataque por diccionario es considerado un tipo de ataque contra una contraseña (o una palabra que cause validez) usando una lista de posibles contraseñas, mayormente dado en un fichero de texto o una base de datos gigante. El ataque por diccionario (muchas veces confundido con fuerza bruta) usa una gran lista de contraseñas que pueden ser generadas por un generador automatizado, preferencias de la víctima, o incluso combinarse con la mismísima fuerza bruta para lograr el cometido.


Para saber más sobre Ultra Tesla pueden leer el You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login que hace algunos momentos lo he actualizado para que coincida con el You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login del repositorio. Sin embargo es recomendable que se haga una lectura del repositorio oficial ya que puede haber un cambio reciente que no esté en algún artículo de Internet.

Erica es un script para realizar un ataque por diccionario contra numerosas funciones Hash creado por nuestro compañero @You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login. Para esta ocasión nosotros adaptaremos Erica para usarlo como un simple servicio en UTesla. Si quieres leer un tutorial sobre el script puedes leer un You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

Cabe aclarar que UTesla no está diseñado para soportar grandes cantidades de datos, pese a que se esté trabajando para mejorarlo cada día, uno de los muchos objetivos que se tienen en mente, es realizar de una forma diferente, APIs Webs siguiendo un formato no convencional. Para esta demostración usaremos un diccionario pequeño y unas pequeñas configuraciones para que funcione eficientemente


Esquema de la red:

Para este escenario se usarán tres máquinas, pero para que se tenga más rendimiento el plugin 'Erica' contiene un pequeño algoritmo que disminuye la carga "partiendo" el diccionario en mitades de longitud similar para cada parte (las partes son los servidores), incluso el límite de las líneas es un factor a tener en cuenta. Claro que todo esto estará automatizado por un plugin de UTeslaCLI

Comencemos:

Antes que nada, es importante que tengan actualizado (si es que lo tienen instalado, si no, pueden descargarlo) UTesla porque se han hecho varias actualizaciones arreglando errores y mejorandolo. Por lo que si han usado git, simplemente ejecuten:

Código: bash
git pull origin master
git submodule update --remote


O pueden descargarlo nuevamente, no tendrán que reinstalar las dependencias, así que será menos pesado  ;)

También es importante que usen la versión You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login de python, porque el plugin estará usando algunas nuevas sintaxis de ésta.

Si los repositorios de su distribución no tiene incluido la versión 3.8 de python, pueden You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login.

Es muy recomendable configurar las claves 'connect_timeout' y 'request_timeout' en la sección 'Client' del fichero 'config/UTesla.ini' según lo que se puede tardar, lo cual es relativo a la velocidad de conexión, la velocidad de procesamiento, la memoria, las líneas del archivos, entre otros.


Instalación del plugin 'Erica':

Debemos comenzar con un pequeño fichero para empezar a crear la estructura, el cual estará ubicado en 'complements/erica.py' con el siguiente contenido:

complements/erica.py:

Código: python
class Handler:
    pass


Ahora la estructura puede verse como '<Esquema>://<Dirección IP/Host>:<Puerto>/erica'

Por consiguiente necesitamos crear sub-servicios para organizar mejor el esquema, éso se hace creando la siguiente carpeta:


Código: bash
mkdir complements/erica-folder


Ahí podemos crear nuevos servicios que se verán reflejados como lo siguiente '<Esquema>://<Dirección IP/Host>:<Puerto>/erica/<Sub-servicio>'. Por ejemplo:

complements/erica-folder/get_job.py:

Código: python
import os
import tempfile
import secrets

class Handler:
    async def get(self):
        id = secrets.token_hex(16)
        workspace = '%s/erica_%s' % (
            tempfile.gettempdir(), id

        )

        os.makedirs(workspace, exist_ok=True)
       
        await self.write(id)


complements/erica-folder/write.py:
Código: python
import tempfile
import os

class Handler:
    async def post(self):
        wordlist = self.get_argument('wordlist')
        hash = self.get_argument('hash')
        hash_type = self.get_argument('hash_type')
        shake_length = str(self.get_argument('shake_length'))
        id = self.get_query_argument('id')
       
        workspace = '%s/erica_%s' % (
            tempfile.gettempdir(), id
       
        )
        hash_filename = '%s/hash.txt' % (workspace)
        hash_type_filename = '%s/hash_type.txt' % (workspace)
        wordlist_filename = '%s/wordlist.lst' % (workspace)
        shake_length_filename = '%s/shake_length.txt' % (workspace)
       
        response = {
            'error'   : False,
            'message' : None
               
        }

        if (os.path.isdir(workspace)):
            if not (os.path.isfile(hash_filename)):
                with open(hash_filename, 'w') as fd:
                    fd.write(hash)
                    fd.flush()
                    os.fsync(fd)

            if not (os.path.isfile(hash_type)):
                with open(hash_type_filename, 'w') as fd:
                    fd.write(hash_type)
                    fd.flush()
                    os.fsync(fd)

            if not (os.path.isfile(shake_length_filename)):
                with open(shake_length_filename, 'w') as fd:
                    fd.write(shake_length)
                    fd.flush()
                    os.fsync(fd)

            with open(wordlist_filename, 'a', buffering=1) as fd:
                fd.writelines(wordlist)
                os.fsync(fd)

        else:
            response['error'] = True
            response['message'] = 'El identificador de trabajo "%s" no existe' % (id)

        await self.write(response)


complements/erica-folder/crack.py:
Código: python
import tempfile
import os
import hashlib

def set_status(status, workspace):
    with open('%s/status.txt' % (workspace), 'w') as fd:
        fd.write(status)

def crack(hash, hash_type, wordlist, workspace, shake_length):
    result = False

    if not (hash_type in hashlib.algorithms_guaranteed):
        set_status('No se encuentra la función "%s"' % (hash_type), workspace)
        return

    set_status('running', workspace)

    with open(wordlist, 'r') as fd:
        for word in fd:
            word = word.strip()
            hashfunc = getattr(hashlib, hash_type)(word.encode())

            if (hash_type[:5] == 'shake'):
                hash2cmp = hashfunc.hexdigest(shake_length)

            else:
                hash2cmp = hashfunc.hexdigest()

            if (hash == hash2cmp):
                result = True
                break

    if (result):
        set_status('success:%s' % (word), workspace)

    else:
        set_status('fail', workspace)

class Handler:
    async def get(self):
        id = self.get_query_argument('id')
       
        workspace = '%s/erica_%s' % (
            tempfile.gettempdir(), id

        )
        hash_filename = '%s/hash.txt' % (workspace)
        hash_type_filename = '%s/hash_type.txt' % (workspace)
        wordlist_filename = '%s/wordlist.lst' % (workspace)
        shake_length_filename = '%s/shake_length.txt' % (workspace)

        response = {
            'error'   : False,
            'message' : None
               
        }

        if (os.path.isfile(hash_filename) and os.path.isfile(hash_type_filename) and os.path.isfile(wordlist_filename) and os.path.isfile(shake_length_filename)):
            with open(hash_filename, 'r') as fd:
                hash = fd.read().strip()

            with open(hash_type_filename, 'r') as fd:
                hash_type = fd.read().strip()

            with open(shake_length_filename, 'r') as fd:
                shake_length = int(fd.read())

            self.procs.create(crack, args=(hash, hash_type, wordlist_filename, workspace, shake_length))

        else:
            response['error'] = True
            response['message'] = 'Hay una incongruencia con los archivos del espacio de trabajo'

        await self.write(response)


complements/erica-folder/status.py:
Código: python
import os
import tempfile

class Handler:
    async def get(self):
        id = self.get_query_argument('id')

        workspace = '%s/erica_%s' % (
            tempfile.gettempdir(), id
           
        )
        response = {
            'error'   : False,
            'message' : None
               
        }

        status_file = '%s/status.txt' % (workspace)

        if (os.path.isfile(status_file)):
            with open(status_file, 'r') as fd:
                response['message'] = fd.read().strip()

        else:
            response['error'] = True
            response['message'] = 'No se puede leer el estado de la operación'

        await self.write(response)


Todos los servicios anteriormente mostrados irían en cada servidor que se desee usar para realizar el ataque por diccionario, quedando de la siguiente forma:

* - <Esquema>://<Dirección IP/Host>:<Puerto>/erica/get_job
* - <Esquema>://<Dirección IP/Host>:<Puerto>/erica/write
* - <Esquema>://<Dirección IP/Host>:<Puerto>/erica/crack
* - <Esquema>://<Dirección IP/Host>:<Puerto>/erica/status

Si parece tedioso repartir cada servicio para cada servidor, hay distintas modalidades. Se puede usar el comando You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login para transportar los archivos facilmente, usar un USB al modo tradicional o usar el módulo de python 'http.server' el cual crearía un pequeño servidor web local según donde lo hayamos ejecutado.

Como último archivo que tendría que estar ubicado sólo en nuestra máquina local, sería el cliente para comunicarse con los servicios mostrados anteriormente.

modules/Cmd/erica.py:

Código: python
import os
import sys
import asyncio
import logging
import hashlib
import tempfile
import sqlite3
import multiprocessing

from modules.Infrastructure import client
from utils.General import parse_config
from utils.extra import create_pool

conf = parse_config.parse()
client_conf = conf['Client']
server_conf = conf['Server']
username = server_conf['user_server']
public_key = server_conf['pub_key']
private_key = server_conf['priv_key']
client.config = client_conf
db_name = '%s/erica.db' % (tempfile.gettempdir())
tmp_wordlist = '%s/erica-wordlist.lst' % (tempfile.gettempdir())

information = {
    'description' : 'Realizar un ataque por diccionario',
    'commands'    : [
        {
            'argumentos principales' : [
                {
                    'args'     : ('-o', '--option'),
                    'help'     : 'El comando a ejecutar en el servidor',
                    'choices'  : ('get_job', 'write', 'crack', 'crack_local', 'status', 'reset'),
                    'default'  : 'get_job'

                }


            ]

        },
       
        {
            'argumentos requeridos por el comando \'write\'' : [
                {
                    'args' : ('-w', '--wordlist'),
                    'help' : 'La lista de palabras a usar'

                }

            ]

        },

        {
            'argumentos requeridos por el comando \'write\' y \'crack_local\'' : [
                {
                    'args'     : ('-H', '--hash'),
                    'help'     : 'La suma de verificación a atacar'

                },

                {
                    'args'     : ('-t', '--hash-type'),
                    'help'     : 'La función hash a usar'

                }

            ]

            },

        {
            'optionals'       : [
                {
                    'args'    : ('-l', '--lines'),
                    'help'    : 'Dividir el archivo en N líneas para cada servidor',
                    'default' : 1000000,
                    'type'    : int

                },

                {
                    'args'    : ('-i', '--interval'),
                    'help'    : 'El intervalo en segundos para comprobar si el trabajo a concluido',
                    'type'    : int,
                    'default' : 15

                },

                {
                    'args'    : ('-m', '--max-workers'),
                    'help'    : 'El máximo de procesos trabajando en la operación localmente',
                    'default' : multiprocessing.cpu_count(),
                    'type'    : int

                },

                {
                    'args'    : ('-L', '--shake-length'),
                    'help'    : 'La longitud del resultado en la función shake y derivados',
                    'default' : 32,
                    'type'    : int

                }

            ]

        }

    ],
    'version'     : '1.0.0'

}

def get_lines(filename):
    count = 0

    with open(filename, 'r') as fd:
        while (line := fd.readline()):
            count += 1

    return count

def crack(args):
    (wordlist, hash, hash_type) = args
    func = getattr(hashlib, hash_type)

    with open(wordlist, 'r') as fd:
        for i in fd:
            i = i.strip()
            hash2cmp = func(i.encode()).hexdigest()

            if (hash2cmp == hash):
                logging.info('Operación concluida localmente: %s (%s(%s))',
                             hash, hash_type.upper(), i)
                return True

        logging.warning('No se pudo satisfacer la operación localmente')

        return False

def chunk(fd, lines, parts):
    chunks = []

    index = 0
    count = 0

    for i in range(parts):
        chunks.append([])

    while (line := fd.readline()):
        if not (line.strip()):
            continue

        if (index == parts):
            index = 0

            yield chunks

            for i in range(parts):
                chunks[i] = []

        chunks[index].append(line)
           
        if (count == lines):
            index += 1
            count = 0

            continue
           
        count += 1

    if (chunks != []):
        yield chunks

def execute_sql_command(cmd, args=(), write=False):
    with sqlite3.connect(db_name) as sqlite_db:
        cursor = sqlite_db.cursor()
        cursor.execute('CREATE TABLE IF NOT EXISTS jobs(job VARCHAR(32) NOT NULL, network TEXT NOT NULL)')
        sqlite_db.commit()

        cursor.execute(cmd, args)

        if (write):
            sqlite_db.commit()

        else:
            return cursor.fetchall()

def getJob(net):
    result = execute_sql_command(
        'SELECT job FROM jobs WHERE network = ? LIMIT 1', (net,)

    )

    if (result != []):
        return result[0][0]

def writeControl(net, response):
    error = response['error']
    message = response['message']

    if (error):
        logging.warning('Ocurrió un error interno en el servidor "%s": %s', net, message)

    else:
        logging.info('Se ha escrito una parte del diccionario en el servidor %s', net)

def jobsControl(net, response):
    execute_sql_command('INSERT INTO jobs(job, network) VALUES (?, ?)', (response, net), True)

    logging.info('El trabajo "%s" se creó en el servidor "%s"', response, net)

def crackControl(net, response):
    error = response['error']
    message = response['message']

    if (error):
        logging.warning('Ocurrió un error interno en el servidor "%s": %s', net, message)

    else:
        logging.info('Se ha iniciado el ataque en el servidor "%s" 3:-)', net)

def statusControl(net, response):
    error = response['error']
    message = response['message']

    if (error):
        logging.warning('Ocurrió un error interno en el servidor "%s": %s', net, message)

    else:
        if (message == 'running'):
            logging.warning('La operación todavía se sigue efectuando')

        elif (message[:7] == 'success'):
            logging.info('Operación realizada con éxito, se ha obtenido la palabra correcta en la lista de palabras almacenada en el servidor "%s": %s', net, message[8:])

        elif (message == 'fail'):
            logging.warning('No se pudo obtener la palabra con éxito usando la lista de palabras almacenada en el servidor "%s" :-(', net)

        else:
            logging.warning('Estado desconocido en el servidor "%s": %s', net, message)

async def execute_command(net, cmd, data, callback, *args, method='POST', **kwargs):
    url = '%s/erica/%s' % (net, cmd)
    url_hash = hashlib.sha3_224(net.encode()).hexdigest()
    pub_key_file = '%s/servkeys/%s' % (
        server_conf['init_path'], url_hash
   
    )

    UClient = client.UTeslaClient(username)

    await UClient.set_user_keys(public_key, private_key)
    await UClient.set_server_key(pub_key_file)
   
    try:
        result = await UClient.fetch(
            url, data, method=method

        )

    except Exception as err:
        logging.warning('Ocurrió en la petición hacia el servidor "%s": %s', url, err)

        response = None

    else:
        response = UClient.get_message(result.body)

    if (response):
        return callback(net, response, *args, **kwargs)

    else:
        logging.warning('No se obtuvo ningún dato por parte del servidor %s...', net)

async def MainParser(args):
    hash = args.hash
    hash_type = args.hash_type
    wordlist = args.wordlist
    lines = args.lines
    interval = args.interval
    max_workers = args.max_workers
    option = args.option
    shake_length = args.shake_length

    db = await create_pool.create(server_conf['mysql_db'])
    networks = await db.get_networks(show_all=True)
    jobs = []
   
    if (option == 'get_job') and (os.path.isfile(db_name)):
        logging.warning('No se puede obtener nuevos trabajas hasta que se haga un reinicio para evitar alteraciones. Use el comando \'reset\' para permitir esta operación')
        return

    if (wordlist is None) and (option == 'write'):
        logging.warning('¡No se definió la ruta del diccionario a usar!')
        return

    if (hash is None or hash_type is None) and (option == 'write' or option == 'crack_local'):
        logging.warning('Falta definir el \'hash\' y/o la función a usar')
        return

    if (option == 'get_job' or option == 'status' or option == 'crack'):
        callbacks = {
            'get_job' : jobsControl,
            'crack'   : crackControl,
            'status'  : statusControl

        }

        for _, net, token in networks:
            data = {
                'token' : token

            }

            job = getJob(net)

            params = {
                'crack'   : '?id=%s' % (job),
                'status'  : '?id=%s' % (job)

            }

            jobs.append(
                execute_command(net, option + params.get(option, ''), data, callbacks[option], method='GET')

            )

    elif (option == 'write'):
        local_machine = '<Local Machine>'
        networks = networks + ((None, local_machine, None),)
        parts = len(networks)

        with open(wordlist, 'r') as fd:
            with open(tmp_wordlist, 'w', buffering=1) as tmp_fd:
                for words in chunk(fd, lines, parts):
                    for (_, net, token), chunk_val in zip(networks, words):
                        if (net == local_machine):
                            tmp_fd.writelines(chunk_val)

                        else:
                            data = {
                                'token'     : token,
                                'body'      : {
                                    'wordlist'  : chunk_val,
                                    'hash'      : hash,
                                    'hash_type' : hash_type,
                                    'shake_length'    : shake_length

                                }

                            }

                            cmd = 'write?id=%s' % (
                                getJob(net)

                            )

                            logging.warning('Escribiendo %d líneas en %s...', len(chunk_val)-1, net)
                            await execute_command(net, cmd, data, writeControl)

    elif (option == 'crack_local'):
        processes = multiprocessing.Pool(max_workers)
        processes.map(crack, [(tmp_wordlist, hash, hash_type)])
        processes.close()
        processes.join()

    elif (option == 'reset'):
        files2del = [
            tmp_wordlist,
            db_name

        ]

        for file in files2del:
            if (os.path.isfile(file)):
                os.remove(file)
                logging.warning('¡%s se ha eliminado!', file)

    await asyncio.gather(*jobs)


Preparando el escenario:

Para comenzar, necesitamos registrarnos en los diversos servidores que deseemos usar, pero la peculiaridad de todo esto es que usaremos el nombre de usuario de nuestro servidor local mas las claves de éste. Como se viene viendo en el You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login de UTesla, para generar el par de claves del servidor se usaría el siguiente comando:

Código: bash
./UTesla
# Si se desea usar la versión 3.8 de python explícitamente
# python3.8 ./UTesla



Mi par de claves RSA O:)

Aquí lo importante es la clave pública que tendrá que ser transportada en los múltiples servidores que nos registraremos. En las anteriores secciones se explicó cómo transportar dichos archivos.

Una vez estamos en los otros servidores necesitamos ejecutar el siguiente comando para registrarnos:


Código: bash
./UTeslaCLI add -u utesla -p uteslapasswd123@ -i /tmp/key.pub



Creando el usuario 'utesla' en Debian Buster


Creando el usuario 'utesla' en AntiX

Una vez se ha registrado el usuario correspondiente sin problemas en los distintos servidores de nuestra red, pasaremos a generar el token de acceso para agregar los servidores a posteriori.


Agregando 'You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login' (Debian Buster) a la red


Agregando 'You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login' (AntiX) a la red

Iniciando el ataque:

Una vez agregada las redes empecemos con el ataque, para ello simplemente ejecutemos:

Código: bash
./UTeslaCLI erica
./UTeslaCLI erica -w /tmp/wordlist.lst -t md5 -H 9d2b9e517b4c13d92a91472d1d1d4acb -o write -l 30000



Escribiendo un diccionario de 14MB en los servidores


El resultado de haber obtenido la palabra 'dtxdf' a partir de '9d2b9e517b4c13d92a91472d1d1d4acb'

Como ya hizo saber, el diccionario será dividido según las partes y el número de líneas proporcionado, en este se dividirá en tres partes; dos son de los servidores y la tercera es local, almacenada como '/tmp/erica-wordlist.lst'. Si los servidores no pudieron satisfacer la operación, se puede probar el ataque de manera local:


Intento por realizar el ataque de manera local

Como se puede observar se intentó realizar el ataque de manera local con el diccionario dividido, pero fue un intento fallido, aunque lo bueno es que el primer servidor (Debian Buster) si logró satisfacer la operación.

Notas:

* El contenido está hecho con fines demostrativos, en entornos reales y mejor preparados se usaría un cluster con buena maquinaria (en un futuro quizá haga un tutorial 3:-D)
* Tengo que aclarar nuevamente que UTesla aún no está diseñado para transportar grandes cantidades de datos eficientemente, se realizó un pequeño protocolo entre plugin/servicios para enviar por partes el archivo. Ya se está preparando la mejora para enviar cargas grandes con un buen rendimiento
* Espero hayan disfrutado y aprendido tanto como yo lo hice :D


~ DtxdF
#572
Hola @You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

También deberías considerar que no te estén restringiendo el acceso por el agente de usuario (User Agent, en inglés) dependiendo de la ruta que estés accediendo y el que estés usando, puedes cambiarlo a uno muy conocido (como el de Mozilla Firefox o Google Chrome). En el manual (You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login) te indica cómo puedes cambiarlo.

~ DtxdF
#573
Está muy bueno @You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login, cuando saque un tiempo la pruebo. Muchas gracias por tus aportes  ;D

~ DtxdF
#574
Python / Re:Sencillo cliente FTP
Julio 02, 2020, 06:45:49 AM
Hola @You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login  ;D, muchas gracias por publicar tu código y será un gusto analizarlo.

Comencemos con el método inicial "__init__":

Código: python
def __init__(self):
        while True: 
            try:
                self.host = str(input("Host address: "))
                self.ftp = FTP(self.host)
                print(self.ftp.getwelcome())
                break
            except:
                print("Couldn't connect to host")
                pass

        self.user = input("Username: ")
        self.passwd = getpass()
        self.ftp.login(self.user, self.passwd)


Mayormente no se debe interactuar con el usuario en el constructor de clase, además que como está usando POO lo que podría hacer es separar algunas cosas y que trabajen de forma independiente, o básicamente lo que trato de decir es que en vez de hacer lo anterior, usted podría hacer lo siguiente:

Código: python
while True:
    # Pedimos los datos correspondientes

    try:
        host = input("Host address: ")
        user = input("Username: ")
        passwd = getpass.getpass()

    except (EOFError, KeyboardInterrupt):
        # Para no caer en un bucle infinito, es mejor que el usuario
        # rompa el bucle de una manera más limpia, ya sea pulsando
        # CTRL-C o CTRL-D (en Windows creo que sería CTRL-Z).

        print('Operation cancelled by user :-(')
        break

    # Como se puede apreciar se instancia la clase 'ftpClient' por lo
    # cual estaremos separando funcionalidades, por ende mejora el
    # mantenimiento y usabilidad. Ahora tu clase se podría usar en otro
    # código para un uso diferente o podría usarse directamente en el
    # código como lo estamos haciendo.

    try:
        ftpclient = ftpClient(
            host, user, passwd

        )

    except Exception as err:
        # Es recomendable mostrar la excepción al momento de su ejecución
        # porque puede que el error no sea debido a un error de conexión,
        # puede que sea por un error de código o por cualquier cosa que
        # no podremos saber, lo cual generaría conflictos a la hora de
        # arreglarlo o depurarlo.

        print('Couldn\'t connect to host:', str(err))


El snippet está comentado para que vayas leyendo las recomendaciones y el porqué de su modificación. Ahora vayamos con lo siguiente:

Código: python
str(input("Host address: "))


Si estás usando la versión '2' de python podría funcionar "casi" igual que 'raw_input', no obstante debes abstener todo uso de esa función (le dejaré enlaces que expliquen mi preocupación). Sin embargo python 2 está en desuso por lo que la función 'input' es el nuevo nombre de 'raw_input' (en la versión 3) o básicamente la función encargada de requerir datos por la entrada de usuario.

Prosigamos con la siguiente declaración:

Código: python
os.system("cls")


Parece inofensivo, pero 'cls' es un comando más usado en Windows, MS-DOS, etc; para el caso de Gnu/Linux (por ejemplo), es 'clear', lo cual crearía menos portabilidad, si no es importante para usted, no me haga caso, pero si desea que sea más portable su programa/script/librería/etcétera podría o no usarlo o crear una especie de función que use el comando correspondiente según el Sistema Operativo presente, como por ejemplo:

Código: python
import os

def clear():
    if (os.name == 'nt'):
        # Si la máquina es 'Windows' o similar:

        os.system('cls')

    else:
        os.system('clear')

        # Personalmente me gusta más este "hack" que se explicará
        # mejor con enlaces que dejaré dentro de un rato.
        #
        # El siguiente código sería más eficiente que ejecutar
        # 'os.system("clear")' porque usa códigos 'ANSI' en vez
        # de generar muchísimas llamadas y una bifurcación para
        # ejecutar 'clear', aunque usar estos códigos depende de
        # la plataforma y puede generar uno que otro comportamiento
        # inesperado dependiendo de la situación, aun así es
        # conveniente si no le importa lo que dije xD.
        #
        # print('\033[1J\033[1H', end='')


Si nota, estaremos creando una función llamada "clear" la cual puede ser invocada a conveniencia y también estamos tratando de hacer "portable" el despejar lo escrito en la shell del usuario.

Código: python
        print("""
           
             ___    _____  ___       ___    _                     _   
            (  _`\ (_   _)(  _`\    (  _`\ (_ )  _               ( )_
            | (_(_)  | |  | |_) )   | ( (_) | | (_)   __    ___  | ,_)
            |  _)    | |  | ,__/'   | |  _  | | | | /'__`\/' _ `\| | 
            | |      | |  | |       | (_( ) | | | |(  ___/| ( ) || |_
            (_)      (_)  (_)       (____/'(___)(_)`\____)(_) (_)`\__)

            1. Download Files for FTP server
            2. Upload Files for FTP server
        """)


El uso de triple comillas no es recomendable así nos ahorre tiempo, las triple comillas son usadas para los docstrings.

Código: python
def menu(self):
    ...


y

Código: python
def main(self):
    ...


Esto puede generar confusión a la persona que vaya a hacer mantenimiento o esté programando un programa usando tu librería ya que su cerebro "racional" va a traducir los nombres y los va a asimilar, por lo que va a creer que son iguales o tienen la misma funcionalidad. Lo que se podría hacer es cambiar 'menu' por 'logo' o algo igual de coherente como 'banner'.


Código: python
self.option


No es la única propiedad que defines y usas localmente (por lo que me he dado cuenta), no lo hagas y no es necesario mientras todo sea local. Aunque funcione, imagina que haya que usar 'self.option' (por ejemplo) en alguna parte del código y sea definida al momento de instanciar la clase, el valor sería '1' (o cualquiera, es un ejemplo), entonces tú tranquilamente llamas a un método llamado '.metodo_cualquiera(...)' y por segunda vez llamas a '.otro_metodo(...)', pero de repente ¡pum! ocurre algo inesperado, algo truculento, algo maquiavélico, sientes que el karma, el destino, dios o como lo quieras llamar está en tu contra, pero no, resulta que el primer método al cual llamas modifica la propiedad 'self.option' por un valor que el segundo método no se esperaba. No es necesario que coloques 'self.', al menos que quieras o crear o modificar una propiedad ya existente.


Por cierto, todo lo que te he comentado son recomendaciones y espero te haya ayudado. Te deseo lo mejor y espero sigas aprendiendo, la verdad ya paré de analizar tu código porque los ojos se me están cerrando del cansancio que tengo por trasnocharme xD

Ah, se me olvidaban los enlaces:

Uno: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login
Dos: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login
Tres: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login
Cuatro: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

~ DtxdF
#575
@You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login.caedus

Acabo de modificar el código porque cuando lo probé descargué el código HTML usando el mismo navegador e hice el scraping de forma local, por lo que el código que escribí no mostraría nada, además que el código lo volví a escribir aquí en la misma entrada para comentar tu post, por lo que podría generar el típico "TabError". Mil disculpas, ya está solucionado  ;D

~ DtxdF
#576
Esto podría funcionar:

Código: python
import requests
import bs4
import re

request = requests.get('http://www.python.org.ar/trabajo/')
BeautifulSoup = bs4.BeautifulSoup(request.text, 'html.parser')
body = BeautifulSoup.body

for h4 in body.findAll('h4'):
    url = h4.a

    if (re.match(r'/trabajo/', url.get('href'))):
        print('URL:', url.get('href'))


El resultado podría ser algo como:

Código: text
URL: /trabajo/devops-engineer-6/
URL: /trabajo/automation-engineer/
URL: /trabajo/senior-javascript-developer-2/
URL: /trabajo/lider-tecnico-desarrollador-backend-django-sql-aws/
URL: /trabajo/senior-python-backend/
URL: /trabajo/back-end-software-engineer/
URL: /trabajo/desarrollador-python-32/
URL: /trabajo/sr-python-dev-con-django/
URL: /trabajo/python-developer-team-leader/
URL: /trabajo/sr-dev-pythonreact-pref-arquitectura-y-nuevos-desa/
URL: /trabajo/python-dev-senior-remoto/
URL: /trabajo/100-remote-python-developer-us-client/
URL: /trabajo/ingeniero-de-requerimientos-sr/
URL: /trabajo/python-developer-53/
URL: /trabajo/ssr-qa-automation-engineer-python-80-remoto/
URL: /trabajo/desarrollador-python-31/
URL: /trabajo/senior-python-developer-100-remoto/
URL: /trabajo/data-engineer-3/
URL: /trabajo/data-analyst-con-tableau-power-bi-qlik-o-google-an/
URL: /trabajo/devops-bash-python-ruby/
URL: /trabajo/senior-python-developer-9/
URL: /trabajo/full-stack-dev-o-front-end-dev/
URL: /trabajo/buscamos-freelance-developer-para-finalizacion-y-m/


~ DtxdF
#577
@You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

No hay problema, cualquier cosa nos avisas. Por cierto, recuerdo haberlo instalado hace mucho en una tablet con root, así que supongo será un pequeño impedimento

~ DtxdF
#578
Es porque no tienes Netcat instalado, hay una aplicación llamada 'busybox' para instalar una variedad de herramienta de unix y derivados (incluye netcat). Además te recomiendo 'Terminal emulator' porque en el caso de termux emula ser otro sistema y la anterior es directamente como la shell de Android.

~ DtxdF
#579
Como te especificó el compañero @You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login es necesario que uses la contraparte de '.encode(...)', o sea, '.decode(...)', ya que la función '.Popen(...)' acepta una cadena unicode (o simplemente llamada cadena) o un array (recomendable), por lo que te dará ese error hasta que lo corrijas.

También me estoy dando cuenta que sigues enviando datos que no son de tipo 'bytes'.

Línea 19 en el servidor:
Código: python
conn.send('terminate')


Te recomiendo los siguientes artículos si quieres aprender un poco de python mientras aprendes cómo crear una shell:

Uno: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login
Dos: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

Además de esta pequeña shell que creo, te puede ser de utilidad igualmente:

Shell: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

Incluso te recomiendo leer la documentación misma de 'subprocess' y 'shlex':

subprocess: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login
shlex: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login

~ DtxdF
#580
Cada vez que use el método '.send(...)' necesita enviarlo como tipo 'bytes' el cual se haría con el método '.encode(...)'. Por ejemplo:

Línea 23 del código del servidor:
Código: python
conn.send(command.encode())


Le recomiendo lea una transición de Python 2 a la versión 3, ya que hubo muchas incompatibilidades en el código

~ DtxdF