
DECeption with Evaluative Integrated Validation Engine (DECEIVE): Let an LLM do all the hard honeypot work!
DECEIVE، وهو اختصار لـ DECeption with Evaluative Integrated Validation Engine، أي محرك الخداع مع التحقق التقييمي المتكامل، هو نظام honeypot عالي التفاعل ومنخفض الجهد. على عكس معظم أنظمة honeypot عالية التفاعل، لا يمنح DECEIVE المهاجمين إمكانية الوصول إلى أي نظام فعلي. في الواقع، يتولى الذكاء الاصطناعي كل أعمال محاكاة نظام honeypot واقعي استنادًا إلى تعليمات نظام (system prompt) قابلة للتهيئة تصف نوع النظام الذي تريد محاكاته. وعلى عكس العديد من أنظمة honeypot عالية التفاعل الأخرى التي تتطلب جهدًا كبيرًا لتجهيزها بمستخدمين وبيانات وتطبيقات واقعية، فإن الواجهة الخلفية للذكاء الاصطناعي في DECEIVE ستقوم بكل هذا نيابةً عنك تلقائيًا.
تحاكي هذه النسخة من DECEIVE خادم Linux عبر بروتوكول SSH. ستسجل جميع مدخلات المستخدمين، والمخرجات التي تُرجعها الواجهة الخلفية LLM، بالإضافة إلى ملخص لكل جلسة بعد انتهائها. بل ستخبرك أيضًا إذا ما اعتقدت أن جلسة أحد المستخدمين كانت حميدة أو مشبوهة أو خبيثة تمامًا.
⛔️⛔️ DECEIVE هو مشروع إثبات مفهوم. إنه ليس بجودة الإنتاج. جرّبه وتعلم منه، ولكن كن حذرًا بشأن نشره في بيئة إنتاج. ⛔️⛔️
تم تطوير DECEIVE بشكل أساسي على MacOS 15 (Sequoia)، لكنه يجب أن يعمل على أي نظام يشبه UNIX يمكنه تشغيل Python3. ويشمل ذلك إصدارات أخرى من MacOS وLinux وحتى Windows (عبر نظام Windows الفرعي لنظام Linux).
يمكنك جلب أحدث إصدار باستخدام الأمر التالي:
git clone https://github.com/splunk/DECEIVE
تفترض بقية هذه التعليمات أنك غيّرت دليل العمل الحالي إلى المستودع بعد اكتمال الاستنساخ.
يستخدم DECEIVE uv لإدارة تبعيات Python والبيئات الافتراضية. إذا لم يكن uv مثبتًا لديك بالفعل، فثبّته باستخدام مثبّت Astral المستقل:
curl -LsSf https://astral.sh/uv/install.sh | sh
بعد ذلك، قم بمزامنة بيئة المشروع من جذر المستودع:
uv sync
يعد ملفا pyproject.toml وuv.lock المصدر الأساسي للتبعيات. لا يحتفظ هذا المشروع عمدًا بأي ملف requirements.txt كبديل.
يتطلب خادم SSH زوج مفاتيح TLS للاتصالات الآمنة. من الدليل الرئيسي للمستودع، أنشئ زوج مفاتيح SSH باستخدام الأمر التالي:
ssh-keygen -t rsa -b 4096 -f SSH/ssh_host_key
انسخ ملف SSH/config.ini.TEMPLATE إلى SSH/config.ini:
افتح ملف SSH/config.ini وراجع الإعدادات. حدّث القيم حسب الحاجة، مع إيلاء اهتمام خاص للقيم في قسم [llm]، حيث ستُهيئ الواجهة الخلفية LLM التي ترغب في استخدامها، وكذلك قسم [user_accounts]، حيث يمكنك تهيئة أسماء المستخدمين وكلمات المرور التي تريد أن يدعمها honeypot.
عدّل ملف SSH/prompt.txt ليتضمن وصفًا قصيرًا لنوع النظام الذي تريده أن يتظاهر بأنه. لست بحاجة إلى أن تكون مفصّلًا جدًا هنا، على الرغم من أن المحاكاة ستكون أفضل كلما زادت التفاصيل التي تقدمها. يمكنك إبقاء الوصف عالي المستوى، مثل:
You are a video game developer's system. Include realistic video game source and asset files.
إذا أردت، يمكنك إضافة أي تفاصيل إضافية تعتقد أنها مفيدة. على سبيل المثال:
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.
لبدء تشغيل خادم DECEIVE honeypot، تأكد أولاً من أنك قد عيّنت أي متغيرات بيئة تتطلبها الواجهة الخلفية LLM التي اخترتها. على سبيل المثال، إذا كنت تستخدم أيًا من نماذج OpenAI، فستحتاج إلى تعيين متغير OPENAI_API_KEY على النحو التالي:
export OPENAI_API_KEY="<your secret API key>"
بعد ذلك، شغّل honeypot SSH من جذر المستودع:
uv run python SSH/ssh_server.py
يمكنك أيضًا الانتقال إلى دليل SSH وتشغيل:
uv run python ssh_server.py
سيبدأ الخادم في الاستماع لاتصالات SSH الواردة على المنفذ المهيأ. لن يُصدر أي مخرجات، لكنه سيظل قيد التنفيذ في المقدمة.
بمجرد تشغيل الخادم (قد يستغرق ذلك بضع ثوانٍ)، قم بالوصول إليه عبر المنفذ المهيأ. إذا كنت على نظام Linux أو نظام مشابه لـ UNIX، فجرّب الأمر التالي (استبدل "localhost" و"8022" بما يناسب إعداداتك):
ssh guest@localhost -p 8022
بعد تشغيل uv sync، شغّل جميع الاختبارات من جذر المستودع:
uv run pytest
لتشغيل اختبارات تكامل SSH فقط:
uv run pytest tests/test_ssh_integration.py
تشغّل اختبارات التكامل خادم SSH الحقيقي على منفذ عشوائي محلي، وتتصل عبر عميل SSH، وتستخدم واجهة خلفية LLM مزيفة ذات مخرجات حتمية بحيث لا تعتمد التأكيدات على مخرجات النموذج الحية.
ستُكتب السجلات إلى الملف المحدد في خيار الإعدادات log_file. تُحل مسارات log_file النسبية انطلاقًا من الدليل الذي يحتوي على ملف الإعدادات المُحمَّل، لذا تكتب قيمة القالب الافتراضية إلى SSH/ssh_log.log.
سجلات DECEIVE بتنسيق أسطر JSON، حيث يمثل كل سطر مستند JSON كاملًا.
فيما يلي مثال كامل لجلسة SSH بسيطة، نفّذ فيها المستخدم أمرين بسيطين (pwd و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}
أمور جديرة بالملاحظة:
task_name على قيمة فريدة تُخصص عند استلام اتصال SSH وتُستخدم في جميع إدخالات السجل من تلك الجلسة.SSH connection receivedAuthentication successUser inputLLM responseSession summarySSH connection closeddetails يحتوي على معلومات إضافية
User input على نسخة مشفرة بـ base64 من إدخال المستخدم بالكامل في حقل details، بالإضافة إلى حقل interactive (true/false) يخبرك ما إذا كان هذا أمرًا تفاعليًا أم غير تفاعلي (أي ما إذا كانوا قد سجلوا الدخول بجلسة طرفية أم قدموا أمرًا عبر سطر أوامر SSH).LLM response على نسخة مشفرة بـ base64 من الاستجابة المحاكاة بالكامل في حقل .المساهمات مرحب بها! يرجى تقديم طلبات السحب (pull requests) أو فتح القضايا (issues) لمناقشة أي تغييرات أو تحسينات.
هذا المشروع مرخص بموجب رخصة MIT. راجع ملف LICENSE للحصول على التفاصيل.
detailsSession summary على ملخص للأوامر فحسب، بل تتضمن أيضًا تخمينًا حول ما قد تكون الأوامر تهدف إلى تحقيقه. سيكون هناك أيضًا حقل judgement يحتوي على إحدى القيم "BENIGN" أو "SUSPICIOUS" أو "MALICIOUS"Authentication success، في حقلي username وpassword.