
DECeption with Evaluative Integrated Validation Engine (DECEIVE): Lascia che un LLM faccia tutto il duro lavoro dell'honeypot!
DECEIVE, il DECeption with Evaluative Integrated Validation Engine, è un sistema honeypot ad alta interazione e a basso sforzo. A differenza della maggior parte degli honeypot ad alta interazione, DECEIVE non fornisce agli aggressori l'accesso ad alcun sistema reale. È l'IA a fare tutto il lavoro di simulazione di un sistema honeypot realistico basato su un prompt di sistema configurabile che descrive il tipo di sistema che vuoi simulare. A differenza di molti altri honeypot ad alta interazione che richiedono uno sforzo notevole per essere popolati con utenti, dati e applicazioni realistici, il backend IA di DECEIVE fa tutto questo per te, automaticamente.
Questa versione di DECEIVE simula un server Linux tramite il protocollo SSH. Registra tutti gli input degli utenti, le risposte restituite dal backend LLM, oltre a un riepilogo di ogni sessione al termine. Ti dirà anche se ritiene che la sessione di un utente sia benigna, sospetta o apertamente dannosa.
⛔️⛔️ DECEIVE è un progetto proof-of-concept. Non è di qualità produttiva. Provalo, imparane, ma fai attenzione a distribuirlo in un ambiente di produzione. ⛔️⛔️
DECEIVE è sviluppato principalmente su MacOS 15 (Sequoia), ma dovrebbe funzionare su qualsiasi sistema di tipo UNIX in grado di eseguire Python3. Questo include altre versioni di MacOS, Linux e persino Windows (tramite Windows Subsystem for Linux).
Puoi ottenere l'ultima versione usando il seguente comando:
git clone https://github.com/splunk/DECEIVE
Il resto di queste istruzioni presuppone che tu abbia cambiato la directory corrente con quella del repository dopo il completamento della clonazione.
DECEIVE utilizza uv per la gestione delle dipendenze Python e dell'ambiente virtuale. Se non hai già installato uv, installalo con l'installer autonomo di Astral:
curl -LsSf https://astral.sh/uv/install.sh | sh
Quindi, sincronizza l'ambiente del progetto dalla radice del repository:
uv sync
I file pyproject.toml e uv.lock sono la fonte di verità per le dipendenze. Questo progetto non mantiene intenzionalmente un fallback requirements.txt.
Il server SSH richiede una coppia di chiavi TLS per le comunicazioni sicure. Dalla directory principale del repository, genera una coppia di chiavi SSH usando il seguente comando:
ssh-keygen -t rsa -b 4096 -f SSH/ssh_host_key
Copia il file SSH/config.ini.TEMPLATE in SSH/config.ini:
Apri il file SSH/config.ini e controlla le impostazioni. Aggiorna i valori come necessario, prestando particolare attenzione ai valori nella sezione [llm], dove configurerai il backend LLM che desideri utilizzare, e alla sezione [user_accounts], dove puoi configurare i nomi utente e le password che vuoi che l'honeypot supporti.
Modifica il file SSH/prompt.txt per includere una breve descrizione del tipo di sistema che vuoi che finga di essere. Non devi essere molto dettagliato qui, anche se più dettagli fornisci, migliore sarà la simulazione. Puoi mantenerlo ad alto livello, ad esempio:
You are a video game developer's system. Include realistic video game source and asset files.
Se vuoi, puoi aggiungere qualsiasi dettaglio aggiuntivo che ritieni utile. Per esempio:
You are the Internet-facing mail server for bigschool.edu, a state-sponsored university in Virginia. Valid user accounts are "a20093887", "a20093887-admin", and "mxadmin". Home directories are in "/home/$USERNAME". Everyone's default shell is /bin/zsh, except mxadmin's, which is bash. Mail spools for all campus users (be sure to include email accounts that are not valid for logon to this server) are in /var/spool/mail. Be sure to simulate some juicy emails there, but make them realistic. Some should be personal, but some should be just about the business of administering the school, dealing with students, applying for financial aid, etc. Make the spool permissions relaxed, simulating a misconfiguration that would allow anyone on the system to read the files.
Per avviare il server honeypot DECEIVE, assicurati prima di aver impostato tutte le variabili d'ambiente richieste dal backend LLM scelto. Ad esempio, se stai usando uno dei modelli OpenAI, dovrai impostare la variabile OPENAI_API_KEY in questo modo:
export OPENAI_API_KEY="<your secret API key>"
Quindi, esegui l'honeypot SSH dalla radice del repository:
uv run python SSH/ssh_server.py
Puoi anche spostarti nella directory SSH ed eseguire:
uv run python ssh_server.py
Il server si avvierà e resterà in ascolto delle connessioni SSH in ingresso sulla porta configurata. Non produrrà alcun output, ma rimarrà in esecuzione in primo piano.
Una volta che il server è in esecuzione (potrebbero volerci alcuni secondi), accedivi sulla porta configurata. Se sei su un sistema Linux o di tipo UNIX, prova il seguente comando (sostituisci "localhost" e "8022" come appropriato per la tua configurazione):
ssh guest@localhost -p 8022
Dopo aver eseguito uv sync, esegui tutti i test dalla radice del repository:
uv run pytest
Per eseguire solo i test di integrazione SSH:
uv run pytest tests/test_ssh_integration.py
I test di integrazione avviano il vero server SSH su una porta locale casuale, si collegano con un client SSH e utilizzano un backend LLM finto e deterministico, così le asserzioni non dipendono dall'output del modello reale.
I log verranno scritti nel file specificato nell'opzione di configurazione log_file. I percorsi log_file relativi vengono risolti dalla directory contenente il file di configurazione caricato, quindi il valore predefinito del template scrive in SSH/ssh_log.log.
I log di DECEIVE sono in formato JSON lines, con ogni riga che è un documento JSON completo.
Di seguito è riportato un esempio completo di una semplice sessione SSH, in cui l'utente ha eseguito due semplici comandi (pwd e exit):
{"timestamp": "2025-01-10T20:37:55.018+00:00", "level": "INFO", "task_name": "session-6355218b-59e5-4549-add3-49e6d1efc133", "src_ip": "::1", "src_port": 58164, "dst_ip": "::1", "dst_port": 8022, "message": "SSH connection received", "name": "__main__", "levelname": "INFO", "levelno": 20, "pathname": "/home/deceive/DECEIVE/SSH/./ssh_server.py", "filename": "ssh_server.py", "module": "ssh_server", "exc_info": null, "exc_text": null, "stack_info": null, "lineno": 59, "funcName": "connection_made", "created": 1736541475.0183098, "msecs": 18.0, "relativeCreated": 13872.790813446045, "thread": 8145041472, "threadName": "MainThread", "processName": "MainProcess", "process": 10823, "taskName": null}
{"timestamp": "2025-01-10T20:37:55.177+00:00", "level": "INFO", "task_name": "session-6355218b-59e5-4549-add3-49e6d1efc133", "src_ip": "::1", "src_port": 58164, "dst_ip": "::1", "dst_port": 8022, "message": "Authentication success", "name": "__main__", "levelname": "INFO", "levelno": 20, "pathname": "/home/deceive/DECEIVE/SSH/./ssh_server.py", "filename": "ssh_server.py", "module": "ssh_server", "exc_info": null, "exc_text": null, "stack_info": null, "lineno": 75, "funcName": "begin_auth", "created": 1736541475.1775439, "msecs": 177.0, "relativeCreated": 14032.02486038208, "thread": 8145041472, "threadName": "MainThread", "processName": "MainProcess", "process": 10823, "taskName": "session-6355218b-59e5-4549-add3-49e6d1efc133", "username": "guest", "password": ""}
{"timestamp": "2025-01-10T20:37:57.456+00:00", "level": "INFO", "task_name": "session-6355218b-59e5-4549-add3-49e6d1efc133", "src_ip": "::1", "src_port": 58164, "dst_ip": "::1", "dst_port": 8022, "message": "LLM response", "name": "__main__", "levelname": "INFO", "levelno": 20, "pathname": "/home/deceive/DECEIVE/SSH/./ssh_server.py", "filename": "ssh_server.py", "module": "ssh_server", "exc_info": null, "exc_text": null, "stack_info": null, "lineno": 174, "funcName": "handle_client", "created": 1736541477.4568708, "msecs": 456.0, "relativeCreated": 16311.351776123047, "thread": 8145041472, "threadName": "MainThread", "processName": "MainProcess", "process": 10823, "taskName": "session-6355218b-59e5-4549-add3-49e6d1efc133", "details": "V2VsY29tZSB0byBHYW1lRGV2IENvcnAncyBEZXZlbG9wbWVudCBFbnZpcm9ubWVudAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICBXZWxjb21lLCBndWVzdCEgCiAgIExhc3QgbG9naW46IFR1ZSBPY3QgMjQgMTQ6MzI6MTUgMjAyMyBmcm9tIDE5Mi4xNjguMS4xMAogICBQcm9qZWN0czoKICAgICAtIEZhbnRhc3lRdWVzdAogICAgIC0gU3BhY2VFeHBsb3JlcnMKICAgICAtIFJhY2luZ01hbmlhCiAgIFN5c3RlbSBTdGF0dXM6IEFsbCBzeXN0ZW1zIG9wZXJhdGlvbmFsCiAgIFJlbWVtYmVyIHRvIGNvbW1pdCB5b3VyIGNoYW5nZXMhCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmd1ZXN0QGRldi13b3Jrc3RhdGlvbjp+JCA="}
{"timestamp": "2025-01-10T20:37:59.333+00:00", "level": "INFO", "task_name": "session-6355218b-59e5-4549-add3-49e6d1efc133", "src_ip": "::1", "src_port": 58164, "dst_ip": "::1", "dst_port": 8022, "message": "User input", "name": "__main__", "levelname": "INFO", "levelno": 20, "pathname": "/home/deceive/DECEIVE/SSH/./ssh_server.py", "filename": "ssh_server.py", "module": "ssh_server", "exc_info": null, "exc_text": null, "stack_info": null, "lineno": 184, "funcName": "handle_client", "created": 1736541479.3334038, "msecs": 333.0, "relativeCreated": 18187.88480758667, "thread": 8145041472, "threadName": "MainThread", "processName": "MainProcess", "process": 10823, "taskName": "session-6355218b-59e5-4549-add3-49e6d1efc133", "details": "cHdk"}
{"timestamp": "2025-01-10T20:38:00.189+00:00", "level": "INFO", "task_name": "session-6355218b-59e5-4549-add3-49e6d1efc133", "src_ip": "::1", "src_port": 58164, "dst_ip": "::1", "dst_port": 8022, "message": "LLM response", "name": "__main__", "levelname": "INFO", "levelno": 20, "pathname": "/home/deceive/DECEIVE/SSH/./ssh_server.py", "filename": "ssh_server.py", "module": "ssh_server", "exc_info": null, "exc_text": null, "stack_info": null, "lineno": 200, "funcName": "handle_client", "created": 1736541480.189375, "msecs": 189.0, "relativeCreated": 19043.855905532837, "thread": 8145041472, "threadName": "MainThread", "processName": "MainProcess", "process": 10823, "taskName": "session-6355218b-59e5-4549-add3-49e6d1efc133", "details": "L2hvbWUvZ3Vlc3QKCmd1ZXN0QGRldi13b3Jrc3RhdGlvbjp+JCA="}
{"timestamp": "2025-01-10T20:38:01.944+00:00", "level": "INFO", "task_name": "session-6355218b-59e5-4549-add3-49e6d1efc133", "src_ip": "::1", "src_port": 58164, "dst_ip": "::1", "dst_port": 8022, "message": "User input", "name": "__main__", "levelname": "INFO", "levelno": 20, "pathname": "/home/deceive/DECEIVE/SSH/./ssh_server.py", "filename": "ssh_server.py", "module": "ssh_server", "exc_info": null, "exc_text": null, "stack_info": null, "lineno": 184, "funcName": "handle_client", "created": 1736541481.944072, "msecs": 944.0, "relativeCreated": 20798.552989959717, "thread": 8145041472, "threadName": "MainThread", "processName": "MainProcess", "process": 10823, "taskName": "session-6355218b-59e5-4549-add3-49e6d1efc133", "details": "ZXhpdA=="}
{"timestamp": "2025-01-10T20:38:04.132+00:00", "level": "INFO", "task_name": "session-6355218b-59e5-4549-add3-49e6d1efc133", "src_ip": "::1", "src_port": 58164, "dst_ip": "::1", "dst_port": 8022, "message": "Session summary", "name": "__main__", "levelname": "INFO", "levelno": 20, "pathname": "/home/deceive/DECEIVE/SSH/./ssh_server.py", "filename": "ssh_server.py", "module": "ssh_server", "exc_info": null, "exc_text": null, "stack_info": null, "lineno": 151, "funcName": "session_summary", "created": 1736541484.1324642, "msecs": 132.0, "relativeCreated": 22986.945152282715, "thread": 8145041472, "threadName": "MainThread", "processName": "MainProcess", "process": 10823, "taskName": "session-6355218b-59e5-4549-add3-49e6d1efc133", "details": "The user issued basic commands like `pwd` to check the current working directory and `exit` to terminate the session. This activity is typical of a benign user checking their environment upon logging in and then closing the session. There is no indication of reconnaissance, exploitation, or any post-foothold activity such as privilege escalation or data exfiltration. The actions appear to be standard and routine.\n\nJudgement: BENIGN", "judgement": "BENIGN"}
{"timestamp": "2025-01-10T20:38:04.139+00:00", "level": "INFO", "task_name": "session-6355218b-59e5-4549-add3-49e6d1efc133", "src_ip": "::1", "src_port": 58164, "dst_ip": "::1", "dst_port": 8022, "message": "SSH connection closed", "name": "__main__", "levelname": "INFO", "levelno": 20, "pathname": "/home/deceive/DECEIVE/SSH/./ssh_server.py", "filename": "ssh_server.py", "module": "ssh_server", "exc_info": null, "exc_text": null, "stack_info": null, "lineno": 65, "funcName": "connection_lost", "created": 1736541484.139776, "msecs": 139.0, "relativeCreated": 22994.2569732666, "thread": 8145041472, "threadName": "MainThread", "processName": "MainProcess", "process": 10823, "taskName": null}
Cose da notare:
task_name contiene un valore univoco assegnato quando viene ricevuta la connessione SSH e utilizzato in tutte le voci di log di quella sessione.SSH connection receivedAuthentication successUser inputLLM responseSession summarySSH connection closeddetails con informazioni aggiuntive:
User input contengono una copia codificata in base64 dell'intero input utente nel campo details, oltre a un campo interactive (true/false) che indica se si trattava di un comando interattivo o non interattivo (cioè se l'utente ha effettuato l'accesso con una sessione terminale o ha fornito un comando dalla riga di comando SSH).LLM response contengono una copia codificata in base64 dell'intera risposta simulata nel campo details.Session summary contengono non solo un riepilogo dei comandi, ma anche un'ipotesi su ciò che potrebbero essere stati destinati a realizzare. Ci sarà anche un campo judgement che contiene uno tra "BENIGN", "SUSPICIOUS" o "MALICIOUS".Authentication success, nei campi username e password.I contributi sono benvenuti! Invia pull request o apri issue per discutere eventuali modifiche o miglioramenti.
Questo progetto è concesso in licenza sotto la MIT License. Vedi il file LICENSE per i dettagli.