
أداة جمع القطع الأثرية لأنظمة *nix
fennec هي أداة لجمع القطع الأثرية مكتوبة بلغة Rust تُستخدم أثناء الاستجابة للحوادث على الأنظمة المستندة إلى *nix. تتيح لك fennec كتابة ملف إعدادات يحدد كيفية جمع القطع الأثرية.
fennec 0.4.1 AbdulRhman Alfaifi [email protected] Aritfact collection tool for *nix systems
USAGE: fennec [OPTIONS]
OPTIONS: -c, --config Sets a custom config file (Embedded : true)
-o, --output <FILE>
Sets output file name [default: ABDULRHMAN-PC.zip]
-l, --log-level <LEVEL>
Sets the log level [default: info] [possible values: trace, debug, info, error]
-f, --log-file <FILE>
Sets the log file name [default: fennec.log]
-u, --upload-artifact <CONFIG>...
Upload configuration string. Supported Protocols:
* s3 : Upload artifact package to S3 bucket (ex. minio)
* Format :
s3://<ACCESS_KEY>:<SECRET_ACCESS_KEY>@(http|https)://<HOSTNAME>:<PORT>/<BUCKET_NAME>:<PATH>
* Example (minio): s3://minioadmin:minioadmin@http://192.168.100.190:9000/fennec:/
* aws3 : Upload artifact package to AWS S3 bucket
* Format : aws3://<ACCESS_KEY>:<SECRET_ACCESS_KEY>@<AWS_REGOIN>.<BUCKET_NAME>:<PATH>
* Example: aws3://AKIAXXX:[email protected]:/
* scp : Upload artifact package to a server using SCP protocol
* Format : scp://<USERNAME>:<PASSWORD>@<HOSTNAME>:<PORT>:<PATH>
* Example: scp://testusername:[email protected]:22:/dev/shm
-q, --quiet
Do not print logs to stdout
-t, --timeout <SEC>
Sets osquery queries timeout in seconds [default: 60]
-h, --help
Print help information
--non-root
Run Fennec with non root permisions. This isn't recommended, most artifacts require root
permissions
--osquery-path <PATH>
Sets osquery path, if osquery is embedded it will be writen to this path otherwise the
path will be used to spawn osquery instance (Embedded : true) [default: ./osqueryd]
--output-format <FORMAT>
Sets output format [default: jsonl] [possible values: jsonl, csv, kjson]
--show-config
Show the embedded configuration file
--show-embedded
Show the embedded files metadata
-V, --version
Print version information
* `-c`, `--config` : استخدم ملف التكوين المحدد بدلاً من التكوين المضمن
* `-f`, `--log-file` : تغيير الاسم الافتراضي لملف السجل (الافتراضي: `fennec.log`)
* `-h`, `--help` : طباعة رسالة المساعدة
* `-l`, `--log-level` : تغيير مستوى السجل الافتراضي (الافتراضي: `info`)
* `-o`, `--output` : تغيير اسم ملف الإخراج الافتراضي لملف zip (الافتراضي: `{HOSTNAME}.zip`، حيث اسم المضيف هو اسم مضيف الجهاز الذي تم تقييمه وقت التشغيل)
* `--osquery-path` : المسار إلى الملف التنفيذي لـ osquery، سيتم استخدام هذه القيمة بناءً على هذه الشروط:
* إذا كان ثنائي osquery مضمنًا في `fennec`، فسيتم استخراجه ووضعه في `--osquery-path`
* إذا لم يكن osquery مضمنًا في `fennec`، فسيتم استخدام ثنائي osquery الموجود في المسار `--osquery-path`
* `--output-format` : اختر تنسيق الإخراج، التنسيقات المدعومة:
* jsonl : كائنات JSON مفصولة بأسطر جديدة (الافتراضي)
* csv: قيم مفصولة بفاصلة
* kjson: استخدم هذا التنسيق إذا كنت تريد رفع الملف الناتج إلى منصة تحليل [Kuiper](https://github.com/DFIRKuiper/Kuiper)
* `-q`, `--quiet` : لا تطبع السجلات إلى `stdout`
* `--non-root` : تشغيل Fennec بصلاحيات غير جذرية. افتراضيًا، يتطلب Fennec صلاحيات `root` وسيخرج برسالة خطأ إذا لم يكن جذرًا.
* `--show-config` : طباعة التكوين المضمن ثم الخروج
* `--show-embedded` : عرض الملفات المضمنة
* `-t`, `--timeout` : تعيين المهلة بالثواني لكل استعلام osquery في نوع الأداة الاستعلامية
* `-u`, `--upload-artifact` : رفع حزمة الأداة إلى خادم بعيد. البروتوكولات المدعومة:
* `s3` : رفع حزمة الأداة إلى دلو S3
* `الصيغة` : s3://<ACCESS_KEY>:<SECRET_ACCESS_KEY>@(http|https)://<HOSTNAME>:<PORT>/<BUCKET_NAME>:<PATH>
* `مثال`: s3://minioadmin:minioadmin@http://192.168.100.190:9000/fennec:/
* `aws3` : رفع حزمة الأداة إلى دلو AWS S3
* `الصيغة` : aws3://<ACCESS_KEY>:<SECRET_ACCESS_KEY>@<AWS_REGOIN>.<BUCKET_NAME>:<PATH>
* `مثال`: aws3://AKIAXXXXXXXXXXXXXXXXX:[email protected]:/
* `scp` : رفع حزمة الأداة إلى خادم باستخدام بروتوكول SCP
* `الصيغة` : scp://`<USERNAME>`:`<PASSWORD>`@`<HOSTNAME>`:`<PORT>`:`<PATH>`
* `مثال`: scp://testusername:[email protected]:22:/dev/shm
* `-V`, `--version` : طباعة إصدار `fennec` ثم الخروج
## التجميع مع التبعيات 👨💻
يعتمد fennec على `osquery` لتشغيل الأدوات من نوع `query`. يحتوي الدليل المسمى `deps` على الملف الذي سيتم تضمينه في الثنائي اعتمادًا على نظام التشغيل والهندسة المستهدفة، قبل التجميع اتبع الخطوات التالية:
* قم بتعديل ملف التكوين `deps/<TARGET_OS>/fennec.yaml` حسب الحاجة
* قم ببناء الثنائي باستخدام أحد الأوامر التالية:
* مرتبط ديناميكيًا: ```bash
cargo build --release
يمكنك أيضًا استخدام الملفات الثنائية المترجمة مسبقًا في قسم الإصدارات.
فيما يلي مثال تم تشغيله على Ubuntu 20 بنفس التكوينات الموجودة في هذا المستودع:

لإخراج البيانات إلى التنسيق المدعوم من Kuiper، قم بتنفيذ Fennec باستخدام الوسيطة التالية:```bash sudo ./fennec --output-format kjson
أو أضف ما يلي إلى قسم `args` في التهيئة:```yaml
args:
- "--output-format"
- "kjson"
إعادة الترجمة ثم التنفيذ:```bash sudo ./fennec
ثم قم بتحميل ملف zip الناتج إلى Kuiper، فيما يلي مثال:

## التكوين🔨
بشكل افتراضي، سيتم تضمين التكوين الموجود في المسار `deps/<TARGET_OS>/fennec.yaml` داخل الملف القابل للتنفيذ أثناء الترجمة. التكوين بتنسيق YAML ويحتوي على قسمين:
### Args
يحتوي على قائمة من الوسائط التي سيتم تمريرها إلى الملف القابل للتنفيذ كوسائط سطر أوامر، فيما يلي مثال لقسم `args` الذي سيحدد تنسيق الإخراج إلى `jsonl` واسم ملف السجل إلى `fennec.log`:
```yaml
args:
output-format: jsonl
log-file: fennec.log
``````yaml
args:
- "--output-format"
- "jsonl"
- "--log-file"
- "fennec.log"
...
سيتم استخدام وسائط سطر الأوامر بالأولويات التالية:
يحتوي على قائمة بالقطع الأثرية المراد جمعها. تحتوي كل قطعة أثرية على الحقول التالية:
stdout في حالة القطعة الأثرية commandتنفيذ استعلامات osquery SQL. المثال التالي لقطعة أثرية لاسترداد جميع المستخدمين على النظام:```yaml artifacts:
#### أنواع القطع الأثرية: التجميع
يقوم هذا النوع من القطع الأثرية بجمع الملفات/المجلدات المحددة في الحقل **المسارات**. فيما يلي مثال على هذا النوع من القطع الأثرية الذي يقوم بجمع سجلات النظام:```yaml
artifacts:
- name: logs
type: collection
description: "Collect system logs"
paths:
- '/var/log/**/*'
...
تنفيذ أوامر النظام باستخدام مترجم أوامر الصدفة حسب الأولوية التالية:
هذا مثال عن هذا النوع من القطع الأثرية الذي يسترد تسجيلات الدخول الفاشلة:```yaml artifacts:
سيقوم هذا النوع من القطع الأثرية بتنفيذ الأوامر في القائمة `commands` وتحليل `stdout` باستخدام التعبير النمطي المحدد في الحقل `regex`. لاحظ أن التعبير النمطي سيتم معالجته فقط على دفق `stdout` وليس `stderr`. كما أن الحقل `regex` اختياري. فيما يلي مثال على النتائج عند استخدام حقل `regex` وبدونه:
##### بدون حقل `regex````json
{
"line": 0,
"stdout": "root pts/1 2023-09-12T17:13:28+03:00 - 2023-09-12T17:13:28+03:00 (00:00)"
}
{ "username": "root", "tty": "pts/1", "src_ip": null, "login_time": "2023-09-12 14:13:28", "logout_time": "2023-09-12T17:13:28+03:00", "duration": "00:00", "@timestamp": "2023-09-12 14:13:28" }
#### أنواع القطع الأثرية: Parse
هذا النوع من القطع الأثرية يوفر القدرة على تحليل ملفات النص باستخدام regex وإرجاع البيانات بتنسيق منظم. المثال أدناة يقوم بتحليل سجلات الوصول الخاصة بـ nginx وإرجاع النتائج بتنسيق منظم:```yaml
artifcats:
- name: nginx_access
type: parse
description: "Nginx access logs"
paths:
- /var/log/nginx/access.*
regex: '(?P<c_ip>[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}) - (?P<remote_user>[^ ]+) \[(?P<time>[0-9]{2}/[a-zA-Z]{3}/[0-9]{4}:[0-9]{2}:[0-9]{2}:[0-9]{2} \+[0-9]{4})\] "(?P<method>[A-Z]+)?[ ]?(?P<uri>.*?)[ ]?(HTTP/(?P<http_prot>[0-9\.]+))?" (?P<status_code>[0-9]{3}) (?P<body_bytes_sent>[0-9]+) "(?P<referer>.*?)" "(?P<user_agent>.*?)"'
هذا التكوين سيقرأ الملفات في المسار /var/log/nginx/access.* سطرًا سطرًا ويطبق التعبير النمطي لاستخراج الحقول. كما يتحقق هذا الأثر مما إذا كان الملف بتنسيق gzip الذي يُستخدم لضغط السجلات القديمة لتوفير المساحة، ويقوم بفك ضغطها وتحليلها. يجب أن يكون التعبير النمطي بتنسيق التقاطات مسماة كما هو موثق في مكتبة تعابير Rust النمطية. فيما يلي مثال لسجل وصول nginx قبل وبعد التحليل:
* سجل مُحلل ```json
{
"c_ip": "192.168.133.70",
"remote_user": "-",
"time": "23/Jan/2022:19:14:37 +0000",
"method": "GET",
"uri": "/blog/",
"http_prot": "1.1",
"status_code": "200",
"body_bytes_sent": "2497",
"referer": "https://u0041.co/",
"user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0",
"full_path": "/var/log/nginx/access.log.9.gz"
}
يمكن استخدام هذا الحقل الاختياري لتغيير أسماء حقول النتائج وتشغيل معالجة لاحقة تسمى معدِّلات على قيمة الحقل. المثال أدناه سيُظهر نتائج تحليل سجل الوصول لـ nginx بدون خرائط:
* السجل الأصلي```verilog
192.168.133.70 - - [23/Jan/2022:19:14:37 +0000] "GET /blog/ HTTP/1.1" 200 2497 "https://u0041.co/" "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0"
لتغيير اسم الحقل `time` إلى `@timestamp` نضيف تكوين الخرائط التالي إلى تكوينات الأداة:```yaml
artifcats:
- name: nginx_access
type: parse
description: "Nginx access logs"
paths:
- /var/log/nginx/access.*
regex: '(?P<c_ip>[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}) - (?P<remote_user>[^ ]+) \[(?P<time>[0-9]{2}/[a-zA-Z]{3}/[0-9]{4}:[0-9]{2}:[0-9]{2}:[0-9]{2} \+[0-9]{4})\] "(?P<method>[A-Z]+)?[ ]?(?P<uri>.*?)[ ]?(HTTP/(?P<http_prot>[0-9\.]+))?" (?P<status_code>[0-9]{3}) (?P<body_bytes_sent>[0-9]+) "(?P<referer>.*?)" "(?P<user_agent>.*?)"'
maps:
- from: time #change field name from
to: '@timestamp' # to this name
بعد تشغيل أداة التجميع مع التهيئة على نفس سجل الوصول لـ nginx، نحصل على الناتج التالي:```json { "c_ip": "192.168.133.70", "remote_user": "-", "@timestamp": "23/Jan/2022:19:14:37 +0000", "method": "GET", "uri": "/blog/", "http_prot": "1.1", "status_code": "200", "body_bytes_sent": "2497", "referer": "https://u0041.co/", "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0", "full_path": "/var/log/nginx/access.log.9.gz" }
#### المعدِّلات
modifiers توفر معالجة لاحقة لقيمة الحقل لنتائج artifact. على سبيل المثال إعادة تنسيق التاريخ والوقت. استمرارًا على المثال أعلاه يمكننا تغيير تنسيق التاريخ والوقت في الحقل `@timestamp` إلى التنسيق `%Y-%m-%d %H:%M:%S`. يمكننا إضافة ما يلي إلى تكوينات artifact لتحقيق ذلك:```yaml
artifacts:
- name: nginx_access
type: parse
description: "Nginx access logs"
paths:
- /var/log/nginx/access.*
regex: '(?P<c_ip>[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}) - (?P<remote_user>[^ ]+) \[(?P<time>[0-9]{2}/[a-zA-Z]{3}/[0-9]{4}:[0-9]{2}:[0-9]{2}:[0-9]{2} \+[0-9]{4})\] "(?P<method>[A-Z]+)?[ ]?(?P<uri>.*?)[ ]?(HTTP/(?P<http_prot>[0-9\.]+))?" (?P<status_code>[0-9]{3}) (?P<body_bytes_sent>[0-9]+) "(?P<referer>.*?)" "(?P<user_agent>.*?)"'
maps:
- from: time
to: "@timestamp"
modifier:
name: datetime_to_iso
parameters:
input_time_format: '%d/%b/%Y:%H:%M:%S %z'
output_time_format: '%Y-%m-%d %H:%M:%S'
السجل الناتج سيبدو هكذا:```json { "c_ip": "192.168.133.70", "remote_user": "-", "@timestamp": "2022-01-23 19:14:37", "method": "GET", "uri": "/blog/", "http_prot": "1.1", "status_code": "200", "body_bytes_sent": "2497", "referer": "https://u0041.co/", "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0", "full_path": "/var/log/nginx/access.log.9.gz" }
المعدلات المتاحة هي:
| الاسم | التفاصيل | input_time_format | output_time_format |
| ------------------------ | ------------------------------------------------------------ | -------------------------------------- | ------------------------------------------------------------ |
| epoch_to_iso | يحول الطابع الزمني للـ epoch إلى تنسيق تاريخ ووقت مخصص | N/A | حدد تنسيق التاريخ والوقت المخرَج، الافتراضي هو `%Y-%m-%d %H:%M:%S` |
| datetime_to_iso | إعادة تنسيق التاريخ والوقت من التنسيق `input_time_format` إلى التنسيق `output_time_format` | حدد تنسيق التاريخ والوقت المُدخَل | حدد تنسيق التاريخ والوقت المخرَج، الافتراضي هو `%Y-%m-%d %H:%M:%S` |
| time_without_year_to_iso | تنسيق التاريخ والوقت بدون بيانات السنة من التنسيق `input_time_format` إلى التنسيق `output_time_format` | حدد تنسيق التاريخ والوقت المُدخَل | حدد تنسيق التاريخ والوقت المخرَج، الافتراضي هو `%Y-%m-%d %H:%M:%S` |
| to_int | تحويل بيانات نصية (مثل أنواع القطع `command` و `parse`) إلى أعداد صحيحة (`i64` أي عدد صحيح 64 بت مع إشارة). هذا مفيد مع حقول مثل حجم الملف حتى نتمكن من إجراء تحقق مثل `size < 1024` باستخدام منصة البيانات التي نختارها | N/A | N/A |
يعمل المعدل `time_without_year_to_iso` على النحو التالي:
* أضف السنة الحالية ثم تحقق مما إذا كان وقت المحلل < الوقت الحالي، إذا كان كذلك فهذا هو الوقت الصحيح
* وإلا فهي السنة السابقة
يفترض هذا المعدل أن السجلات تعود فقط لسنة واحدة، استخدم هذا المعدل بحذر
| تفاصيل نظام التشغيل | المعمارية | نجاح؟ | التفاصيل |
|---|
| Ubuntu 20.04.3 LTS | x86_64 | ✅ | |
| Ubuntu 19.04 | x86_64 | ✅ | |
| Ubuntu 18.04.6 LTS | x86_64 | ✅ | |
| Ubuntu 17.04 | x86_64 | ✅ | |
| Ubuntu 16.04.7 LTS | x86_64 | ✅ | |
| Ubuntu 15.10 | x86_64 | ✅ | |
| Ubuntu 14.04.6 LTS | x86_64 | ✅ | |
| Ubuntu 13.04 | x86_64 | ✅ | |
| Ubuntu 12.04.5 LTS | x86_64 | ✅ | |
| CentOS 8.4.2105 | x86_64 | ✅ | |
| CentOS 7.9.2009 | x86_64 | ✅ | |
| CentOS 6.10 | x86_64 | ✅ | |
| CentOS 5.11 | x86_64 | ❌ | يتطلب osquery مكتبة libc >= 2.12 |
| Ubuntu 20.04 | aarch64 | ✅ | |
| MacOS Monterey v12.0.1 | x86_64 | ✅ | ضبط الإعدادات مطلوب. إذا كانت لديك خبرة في القطع الأثرية في MacOS، فلا تتردد في المساهمة |
| Oracle Linux Server 7.9 | x86_64 | ✅ |