المحتويات
المقدمة
يشغّل Linux معظم الخوادم المكشوفة على الإنترنت والحاويات وأحمال العمل السحابية التي يستهدفها المهاجمون، وتختلف حوادثه عن حوادث Windows. فلا يوجد سجل نظام ولا prefetch، ويعتمد التسجيل كثيرًا على إعداد الجهاز، وتنتهي اختراقات كثيرة بمعدّن عملات أو web shell أو مفتاح SSH هادئ بدل برنامج فدية. يغطي هذا الدليل فرز جهاز Linux مشبوه من أول تواصل إلى الاحتواء: ما يجب جمعه، وبأي ترتيب، وبأي أوامر وأدوات، وما تعنيه الأدلة.
القواعد الأساسية لفرز Linux
- لا تثق بالبرامج الموجودة على الجهاز. تستبدل برامج rootkit في مساحة المستخدم ps وls وnetstat وss، وتعترض برامج rootkit عبر LD_PRELOAD استدعاءات المكتبات التي تستخدمها تلك الأدوات. أحضر أدوات مربوطة ثابتًا على وسيط للقراءة فقط، وقارن نتائجها مع /proc.
- اجمع حسب درجة التطاير: الذاكرة، ثم اتصالات الشبكة والعمليات، ثم المستخدمون المسجلون وأنظمة الملفات المؤقتة مثل /tmp و/dev/shm و/run، ثم القرص والسجلات.
- قلل أثرك. فكل أمر يغيّر أوقات الوصول، ويكتب في سجل الصدفة، وقد يستبدل بيانات محذوفة. اكتب المخرجات إلى وسيط خارجي أو أرسلها عبر الشبكة، ولا تكتب أبدًا إلى نظام الملفات المشبوه.
- لا تعد التشغيل. فالذاكرة والبرمجيات الخبيثة العاملة ومحتوى /dev/shm وحالة الشبكة تختفي كلها، وقد تؤدي إعادة التشغيل إلى تنظيف من المهاجم أو حمولة مدمرة في نص بدء التشغيل.
- اعمل بتوقيت UTC وسجل كل أمر مع وقته. تقوم الأداة script بذلك نيابة عنك.
- إذا كان الجهاز سحابيًا، فخذ لقطة للأقراص عبر API المزود قبل أي إجراء تدخلي. فهذه اللقطة هي نسخة الأدلة إذا دُمر الجهاز.
sudo mkdir -p /mnt/ir && sudo mount -o ro /dev/sdb1 /mnt/ir # read-only toolkit
export PATH=/mnt/ir/bin:$PATH # trusted static binaries first
export LC_ALL=C TZ=UTC
unset HISTFILE # do not overwrite user history
OUT=/mnt/evidence/$(hostname)-$(date -u +%Y%m%dT%H%M%SZ) # separate writable evidence disk
mkdir -p "$OUT"
script -q -a "$OUT/session.log"
# No spare disk? Stream each output to your analysis host instead:
ps auxwwf | ssh analyst@10.0.0.50 "cat > /cases/host01/ps.txt"cat /etc/ld.so.preload 2>/dev/null # normally missing or empty
echo "LD_PRELOAD=$LD_PRELOAD"
grep -r LD_PRELOAD /etc/environment /etc/profile /etc/profile.d /etc/bash.bashrc 2>/dev/null
ldd /bin/ps /bin/ls /usr/bin/ss # unexpected libraries are a warning signإذا كان /etc/ld.so.preload موجودًا ويذكر مكتبة لا تستطيع تفسيرها، فافترض أن rootkit في مساحة المستخدم نشط وأن الأدوات العادية تكذب. انتقل بالكامل إلى البرامج الثابتة والقراءة المباشرة من /proc، وخطط لتحليل الذاكرة.
حقيبة أدوات فرز Linux
| الأداة | الغرض | ملاحظات |
|---|---|---|
| UAC (Unix-like Artifacts Collector) | استجابة مباشرة مؤتمتة وجمع الآثار | مجانية، وتعمل على Linux وBSD وmacOS وSolaris وAIX، دون تثبيت |
| Velociraptor | استجابة مباشرة عن بُعد وصيد على مستوى الأجهزة كلها | مجانية، والخادم نفسه لـ Windows وLinux وmacOS |
| AVML | التقاط الذاكرة دون وحدة نواة | مجانية من Microsoft، وتعمل على معظم النوى الحديثة |
| LiME | التقاط الذاكرة عبر وحدة نواة قابلة للتحميل | يجب تجميعها للنواة العاملة تحديدًا |
| Volatility 3 | تحليل الذاكرة | تحتاج إلى جدول رموز (ISF) مبني للنواة تحديدًا |
| busybox وcoreutils ثابتان | بدائل موثوقة لـ ps وls وnetstat وغيرها | ابنها أو نزلها مسبقًا واحسب بصماتها |
| unhide وchkrootkit وrkhunter | فحص العمليات والمنافذ المخفية وrootkit | توقع إنذارات خاطئة وقارن بخط أساس سليم |
| YARA وTHOR Lite وLoki | فحص الملفات وذاكرة العمليات بالبصمات | قواعد مجتمعية للمعدّنين وweb shells وبرمجيات Linux الخبيثة |
| bpftool | عرض برامج eBPF وخرائطها المحملة | تكشف rootkit القائم على eBPF والتتبع غير المتوقع |
| The Sleuth Kit وPlaso | تحليل صور الأقراص والجداول الزمنية | fls وmactime وistat، وlog2timeline للجداول الزمنية الشاملة |
| osquery | استعلامات SQL على حالة النظام المباشرة | مفيدة لطرح الأسئلة نفسها على أجهزة كثيرة |
الدقائق الأولى: السياق
{
date -u; hostname -f; cat /etc/os-release; uname -a
uptime; cat /proc/uptime; timedatectl 2>/dev/null
ip -br addr; ip route
cat /etc/resolv.conf
df -hT; findmnt -D
who -a; w
} > "$OUT/context.txt" 2>&1سجل كل ما يبدو خاطئًا: مدة تشغيل تطابق بداية النشاط المشبوه، أو ربط غير معتاد مثل tmpfs في غير مكانه، أو محلل DNS غير معروف، أو جلسة مسؤول من عنوان غير مألوف. وإذا كان الجهاز جزءًا من مجموعة أو خلف موازن حمل، فسجل الأجهزة التي يتصل بها، فعلى الأرجح ستحتاج إلى فرزها أيضًا.
التقاط الذاكرة وتحليلها
تعيش في الذاكرة البرمجيات الخبيثة دون ملفات، والكود المحقون، والبرامج المحذوفة التي ما زالت تعمل، والإعدادات المفكوكة التشفير. وتعد AVML أبسط أداة في الأنظمة الحديثة لأنها لا تحتاج إلى وحدة نواة، أما LiME فهي البديل عندما تعجز AVML عن قراءة الذاكرة، لكن يجب بناؤها لإصدار النواة تحديدًا، ويفضل على جهاز سليم مطابق لا على الجهاز المشبوه.
# AVML: a single static binary
sudo /mnt/ir/bin/avml "$OUT/memory.lime"
sha256sum "$OUT/memory.lime" | tee -a "$OUT/hashes.txt"
# LiME: module compiled for $(uname -r) on a clean build host
sudo insmod /mnt/ir/lime/lime-$(uname -r).ko "path=$OUT/memory.lime format=lime"
sudo rmmod limeتحتاج Volatility 3 إلى جدول رموز لإصدار النواة تحديدًا. أنشئه باستخدام dwarf2json من رموز التصحيح، التي تنشرها التوزيعات باسم linux-image-*-dbgsym في Ubuntu وlinux-image-*-dbg في Debian وkernel-debuginfo في RHEL. افعل ذلك على جهاز التحليل لا على الجهاز المشبوه.
dwarf2json linux --elf /usr/lib/debug/boot/vmlinux-6.8.0-45-generic > volatility3/symbols/linux/6.8.0-45-generic.json
vol -f memory.lime linux.pslist
vol -f memory.lime linux.pstree
vol -f memory.lime linux.psaux # full command lines
vol -f memory.lime linux.bash # bash history recovered from memory
vol -f memory.lime linux.sockstat # sockets per process
vol -f memory.lime linux.lsof --pid 4127
vol -f memory.lime linux.malfind # injected executable memory
vol -f memory.lime linux.lsmod
vol -f memory.lime linux.check_modules # modules hidden from the module list
vol -f memory.lime linux.check_syscall # hooked system call table entries
vol -f memory.lime linux.envars --pid 4127غالبًا ما يكون ملحق linux.bash أكثر المخرجات فائدة: فهو يستعيد سجل الأوامر من ذاكرة عمليات bash العاملة، بما في ذلك أوامر الجلسات التي عطل فيها المهاجم ملف السجل أو حذفه.
العمليات
ps -eo pid,ppid,user,lstart,etime,stat,%cpu,%mem,cmd --forest > "$OUT/ps.txt"
ps auxwwf >> "$OUT/ps.txt"
# Raw view from /proc, which a userland rootkit cannot easily filter
for p in /proc/[0-9]*; do
pid=$(basename "$p")
printf '%s\t%s\t%s\t%s\n' "$pid" "$(awk '/^PPid/{print $2}' "$p/status" 2>/dev/null)" \
"$(readlink "$p/exe" 2>/dev/null)" "$(tr '\0' ' ' < "$p/cmdline" 2>/dev/null)"
done > "$OUT/proc-list.tsv"P=4127
ls -l /proc/$P/exe /proc/$P/cwd # "(deleted)" means the binary was removed
tr '\0' ' ' < /proc/$P/cmdline; echo
tr '\0' '\n' < /proc/$P/environ # SSH_CLIENT, PWD, unusual variables
cat /proc/$P/status | grep -E 'Name|PPid|Uid|Gid'
ls -l /proc/$P/fd # open files, sockets, pipes
cat /proc/$P/maps | grep -v '\.so' # anonymous and odd mappings
cat /proc/$P/net/tcp /proc/$P/net/tcp6
# Recover the binary even if it was deleted from disk
cp /proc/$P/exe "$OUT/pid-$P.bin" && sha256sum "$OUT/pid-$P.bin" | tee -a "$OUT/hashes.txt"# Processes whose binary has been deleted
ls -l /proc/[0-9]*/exe 2>/dev/null | grep deleted
# Processes running from temporary or hidden locations
ls -l /proc/[0-9]*/exe 2>/dev/null | grep -E '/tmp/|/var/tmp/|/dev/shm/|/run/user/|/\.'
# User processes pretending to be kernel threads: real kernel threads have PPID 2 and no exe
ps -eo pid,ppid,args | awk '$2 != 2 && $2 != 0 && $3 ~ /^\[/'
# Hash every running executable through /proc, including deleted ones
sha256sum /proc/[0-9]*/exe 2>/dev/null | sort -u -k1,1 > "$OUT/exe-hashes.txt"
# Processes hidden from ps
unhide proc; unhide sys- مفسرات لها مقابس شبكة: عندما يحتفظ bash أو sh أو python أو perl أو php باتصال TCP، فهذا يعني عادةً صدفة عكسية. ابحث عن /dev/tcp في الأوامر.
- عمليات فرعية لخادم الويب: تشغيل nginx أو apache2 أو httpd أو php-fpm أو java لـ sh أو bash أو curl أو wget أو nc يشير إلى تنفيذ كود عبر تطبيق الويب.
- الاستهلاك المرتفع والمستمر للمعالج من عملية باسم غير مألوف علامة تقليدية على معدّن عملات، وغالبًا ما يُسمى ليشبه خدمة نظام (kworkerds وkthreaddi وsystemd-udevd في مسار خاطئ).
- العمليات التي يكون مجلد عملها /tmp أو /dev/shm أو مجلدًا مخفيًا، والعمليات التابعة لحسابات خدمة مثل www-data أو postgres التي يجب ألا تشغل أدوات تفاعلية أبدًا.
حالة الشبكة
{
ss -tunap; ss -xp
ip addr; ip route; ip neigh
ip link | grep -i promisc # sniffers put interfaces in promiscuous mode
iptables-save 2>/dev/null; nft list ruleset 2>/dev/null
cat /etc/hosts
conntrack -L 2>/dev/null | head -500
} > "$OUT/network.txt" 2>&1
# Compare against the kernel tables directly
cat /proc/net/tcp /proc/net/tcp6 /proc/net/udp > "$OUT/proc-net.txt"
unhide-tcp # ports in use but hidden from ssانتبه إلى الاتصالات بمنافذ غير معتادة (3333 و4444 و5555 و7777 و14444 منافذ شائعة لمجمعات التعدين والصدفات العكسية)، والاتصالات الخارجة الطويلة من عمليات الخادم، والمستمعين على منافذ عالية مربوطة بكل الواجهات، وقواعد جدار الحماية التي لم ينشئها نظام إدارة الإعدادات. ويمكن لالتقاط قصير للحزم تأكيد ما ينقله اتصال مشبوه، مع استثناء جلستك منه.
timeout 300 tcpdump -i any -nn -s 0 -w "$OUT/capture.pcap" 'not (host 10.0.0.50 and port 22)'المستخدمون والمفاتيح والمصادقة
يحتفظ المهاجمون على Linux بالوصول غالبًا عبر الحسابات ومفاتيح SSH لا البرمجيات الخبيثة. فالمفتاح المصرح به الجديد يبقى بعد كل تحديث وكل تنظيف وكل تغيير لكلمة المرور، لذلك تعد مراجعة المفاتيح والحسابات من أهم أجزاء الفرز.
awk -F: '$3 == 0 {print "UID 0:", $1}' /etc/passwd # only root expected
awk -F: '$3 >= 1000 || $7 !~ /(nologin|false)$/ {print $1, $3, $6, $7}' /etc/passwd
awk -F: '$2 !~ /^[!*]/ {print "has password:", $1}' /etc/shadow
grep -E '^(sudo|wheel|adm|docker|lxd|disk):' /etc/group
cat /etc/sudoers /etc/sudoers.d/* 2>/dev/null | grep -Ev '^\s*(#|$)'
ls -la --time-style=full-iso /etc/passwd /etc/shadow /etc/group /etc/sudoers /etc/sudoers.d/العضوية في docker أو lxd أو disk تعادل root عمليًا، ويضيف المهاجمون أنفسهم إليها لأن قليلين يفحصونها. وقاعدة NOPASSWD لكل الأوامر، أو لمحرر أو مفسر أو find، تعادل root أيضًا. قارن أوقات تعديل ملفات الهوية بنافذة الحادثة.
sshd -T 2>/dev/null | grep -Ei 'authorizedkeysfile|authorizedkeyscommand|permitrootlogin|passwordauthentication'
awk -F: '{print $1, $6}' /etc/passwd | while read -r user home; do
for f in "$home/.ssh/authorized_keys" "$home/.ssh/authorized_keys2"; do
[ -f "$f" ] || continue
echo "===== $user $f"
ls -la --time-style=full-iso "$f"
cat "$f"
done
done > "$OUT/authorized-keys.txt" 2>&1
lsattr /root/.ssh/authorized_keys /home/*/.ssh/authorized_keys 2>/dev/null # immutable flag set?ابحث عن المفاتيح التي لا تستطيع ربطها بشخص أو نظام، والتعليقات التي لا تناسب تسمياتكم (أو غيابها)، وخيارات forced command أو from التي لم تضبطها، والمفاتيح على حسابات خدمة مثل www-data أو postgres، وملفات authorized_keys التي جُعلت غير قابلة للتعديل عبر chattr لإفشال التنظيف. وتأكد أيضًا من أن sshd لا يقرأ إلا ملفات المفاتيح المتوقعة، فقد يضيف المهاجم مسار AuthorizedKeysFile في sshd_config.
last -Faiwx > "$OUT/last.txt" # wtmp: logins, reboots, shutdowns
lastb -Faiw > "$OUT/lastb.txt" 2>/dev/null # btmp: failed logins
lastlog 2>/dev/null > "$OUT/lastlog.txt"
# Newer distributions record logins in wtmpdb and lastlog2 instead
wtmpdb last 2>/dev/null >> "$OUT/last.txt"; lastlog2 2>/dev/null >> "$OUT/lastlog.txt"
# Debian and Ubuntu: /var/log/auth.log RHEL: /var/log/secure
zgrep -h 'Accepted' /var/log/auth.log* /var/log/secure* 2>/dev/null | sort > "$OUT/ssh-accepted.txt"
zgrep -h 'Failed password' /var/log/auth.log* /var/log/secure* 2>/dev/null |
grep -oE 'from [0-9a-f.:]+' | sort | uniq -c | sort -rn | head -30
journalctl _COMM=sshd --since "2026-10-20" -o short-iso-precise --utc | grep -E 'Accepted|session opened'
journalctl _COMM=sudo --since "2026-10-20" -o short-iso-precise --utcمع LogLevel VERBOSE، يُسجل كل دخول مقبول بالمفتاح مع بصمته، ويمكنك مطابقتها مع authorized_keys عبر ssh-keygen -lf. والدخول الناجح من عنوان يظهر أيضًا في قائمة كلمات المرور الفاشلة علامة على تخمين نجح. افحص العبث في wtmp باستخدام utmpdump: سجلات مصفّرة، أو فجوات في إدخالات إعادة التشغيل، أو ملف أصغر بكثير مما توحي به دورة السجلات.
السجلات والسجل التاريخي
| المصدر | Debian وUbuntu | عائلة RHEL | ما يعرضه |
|---|---|---|---|
| المصادقة | /var/log/auth.log | /var/log/secure | SSH وsudo وsu وPAM وتغييرات المستخدمين |
| النظام | /var/log/syslog | /var/log/messages | الخدمات وcron والنواة ومعظم الخدمات الخلفية |
| سجل systemd | /var/log/journal/ (إذا كان دائمًا) | /var/log/journal/ (إذا كان دائمًا) | كل ما سبق بصيغة منظمة مع بيانات العمليات |
| التدقيق | /var/log/audit/audit.log | /var/log/audit/audit.log | استدعاءات النظام والتنفيذ ومراقبة الملفات وتسجيلات الدخول إذا ضُبطت |
| تغييرات الحزم | /var/log/dpkg.log و/var/log/apt/history.log | /var/log/dnf.log وdnf history | البرمجيات التي ثبتها المهاجم أو أزالها |
| Cron | syslog وjournal | /var/log/cron | تشغيل المهام المجدولة |
| خوادم الويب | /var/log/nginx/ و/var/log/apache2/ | /var/log/nginx/ و/var/log/httpd/ | محاولات الاستغلال واستخدام web shells |
| تسجيلات الدخول | /var/log/wtmp وbtmp وlastlog | /var/log/wtmp وbtmp وlastlog | الجلسات والفشل وآخر دخول لكل مستخدم |
| سجل الصدفة | ~/.bash_history و~/.zsh_history | ~/.bash_history و~/.zsh_history | الأوامر المكتوبة إذا لم يُعطَّل |
| الحاويات | /var/lib/docker/containers/*/*-json.log | /var/lib/docker/containers/*/*-json.log | stdout وstderr للحاويات |
| الوكلاء السحابيون | /var/log/cloud-init.log ووكلاء المزود | /var/log/cloud-init.log ووكلاء المزود | نصوص user data وتغييرات البيانات الوصفية |
journalctl --list-boots
journalctl --since "2026-10-20 00:00" --until "2026-10-28 00:00" -o short-iso-precise --utc > "$OUT/journal.txt"
journalctl -k --since "2026-10-20" --utc | grep -Ei 'module|taint|segfault|denied'
journalctl --verify 2>&1 | tail # detects corrupted or altered journal files
ausearch -i -m USER_LOGIN,USER_AUTH,USER_CMD --start 10/20/2026 00:00:00 > "$OUT/audit-auth.txt"
ausearch -i -m EXECVE --start recent | head -200
aureport -x --summary # most executed programs
aureport --login --failed --summary
# ausearch dates follow the system locale; use "recent", "today" or "this-week" to avoid surprisesfor h in /root /home/*; do
for f in "$h"/.*history; do
[ -f "$f" ] || continue
echo "===== $f"
ls -la --time-style=full-iso "$f"
cat "$f"
done
done > "$OUT/histories.txt" 2>&1
ls -la /root/.bash_history /home/*/.bash_history 2>/dev/null | grep -E ' -> |^l| 0 ' # symlinked to /dev/null or emptyلا يكتب Bash السجل إلا عند إغلاق الصدفة بشكل سليم، ولا يتضمن أوقاتًا ما لم يُضبط HISTTIMEFORMAT، ويسهل تعطيله جدًا. تعامل معه كإضافة لا كسجل موثوق. ومن علامات العبث ملف سجل مربوط بـ /dev/null، وتغيير HISTFILE أو HISTSIZE في نص الملف الشخصي، وسجل يتوقف فجأة، وأوامر مثل history -c أو unset HISTFILE أو shred فيما تبقى.
L=/var/log/nginx/access.log*
zcat -f $L | awk '{print $1}' | sort | uniq -c | sort -rn | head -20
zcat -f $L | grep -E '"POST [^"]+\.(php|jsp|aspx?|cgi)' | awk '{print $7}' | sort | uniq -c | sort -rn | head -30
zcat -f $L | grep -Ei 'union.+select|\.\./\.\.|/etc/passwd|cmd=|exec=|base64_decode|wget%20|curl%20|\$\{jndi:' | head -50
zcat -f $L | awk '$9 == 200 && $7 ~ /\.(php|jsp)/' | grep -Ev 'index\.php|wp-cron' | awk '{print $7}' | sort | uniq -c | sort -n | headيظهر web shell عادةً كنص نادر الطلب، غالبًا في مجلد رفع أو تخزين مؤقت، يتلقى طلبات POST من عناوين قليلة ويرد بالرمز 200. وبمجرد العثور على طلب واحد، انطلق من عنوان العميل وuser agent لمعرفة كل ما فعله، ثم من اسم الملف لمعرفة وقت إنشائه.
البحث عن وسائل الاستمرار
آليات الاستمرار في Linux ملفات عادية في أماكن معروفة، ولذلك يسهل البحث عنها بعد معرفة القائمة. يلخص الجدول المواقع الشائعة، وتجمعها الأوامر أدناه. ابدأ بأوقات التعديل داخل نافذة الحادثة، وبكل ما ينزل أو يفك الترميز أو يشغّل من مجلد مؤقت.
| الآلية | أين تبحث | علامات الخطر |
|---|---|---|
| Cron وat | /etc/crontab و/etc/cron.* و/var/spool/cron/ و/etc/anacrontab وatq | curl أو wget موجهان إلى sh، وBase64، ومهام كل دقيقة، ومهام لحسابات الخدمة |
| وحدات systemd ومؤقتاته | /etc/systemd/system/ و/usr/lib/systemd/system/ و~/.config/systemd/user/ والمولدات | وحدات جديدة بأسماء عامة، وExecStart في /tmp أو مجلد منزلي، وRestart=always لبرامج غير معروفة |
| SSH | authorized_keys وsshd_config و~/.ssh/rc و/etc/ssh/sshrc | مفاتيح غير معروفة، ومسارات AuthorizedKeysFile إضافية، ونصوص rc |
| ملفات بدء الصدفة | /etc/profile و/etc/profile.d/ و/etc/bash.bashrc و~/.bashrc و~/.profile و~/.bash_logout | أوامر في الخلفية، وأسماء مستعارة تستبدل sudo أو ssh، وتصدير LD_PRELOAD |
| الرابط الديناميكي | /etc/ld.so.preload و/etc/ld.so.conf.d/ | أي إدخال preload، ومكتبات في مسارات غير معتادة |
| PAM | /etc/pam.d/ و/lib/x86_64-linux-gnu/security/ و/usr/lib64/security/ | pam_unix.so معدل، ووحدات غير معروفة، وأسطر pam_exec |
| وحدات النواة | /etc/modules و/etc/modules-load.d/ وlsmod و/sys/module | وحدات غير موقعة أو خارج الشجرة، ونواة tainted، ووحدات غير موجودة في lsmod |
| نصوص init وrc.local | /etc/rc.local و/etc/init.d/ | نصوص أضيفت حديثًا على أجهزة systemd |
| MOTD وخطافات الدخول | /etc/update-motd.d/ | نصوص تعمل بحساب root عند كل دخول SSH |
| قواعد udev | /etc/udev/rules.d/ | إدخالات RUN+= تشغل نصوصًا |
| خطافات مدير الحزم | /etc/apt/apt.conf.d/ و/etc/yum/pluginconf.d/ و/etc/dnf/plugins/ | أوامر Pre-Invoke أو Post-Invoke |
| Web shells | جذور المستندات ومجلدات الرفع والإضافات والتخزين المؤقت | نصوص معدلة حديثًا فيها eval أو assert أو system أو حمولات Base64 |
| setuid والقدرات | في أي مكان على القرص | برامج setuid جديدة، وcap_setuid على المفسرات |
{
ls -la --time-style=full-iso /etc/cron* /var/spool/cron /var/spool/cron/crontabs 2>/dev/null
cat /etc/crontab /etc/cron.d/* /etc/anacrontab 2>/dev/null
for u in $(cut -d: -f1 /etc/passwd); do crontab -l -u "$u" 2>/dev/null | sed "s/^/[$u] /"; done
atq 2>/dev/null; ls -la /var/spool/cron/atjobs /var/spool/at 2>/dev/null
} > "$OUT/cron.txt" 2>&1
{
systemctl list-unit-files --state=enabled --no-pager
systemctl list-timers --all --no-pager
find /etc/systemd /usr/lib/systemd /lib/systemd /run/systemd /home/*/.config/systemd /root/.config/systemd \
-type f -newermt "2026-10-01" -printf '%TY-%Tm-%Td %TT %p\n' 2>/dev/null | sort
ls -la /etc/systemd/system-generators /usr/lib/systemd/system-generators 2>/dev/null
} > "$OUT/systemd.txt" 2>&1
systemctl cat suspicious.servicels -la --time-style=full-iso /etc/profile /etc/profile.d/ /etc/bash.bashrc /etc/environment \
/root/.bashrc /root/.profile /home/*/.bashrc /home/*/.profile /home/*/.bash_logout 2>/dev/null
grep -HnE 'curl|wget|nc |ncat|/dev/tcp|base64|python.*-c|nohup|setsid|LD_PRELOAD|alias (sudo|ssh)' \
/etc/profile /etc/profile.d/* /etc/bash.bashrc /root/.bashrc /home/*/.bashrc /home/*/.profile 2>/dev/null
cat /etc/ld.so.preload 2>/dev/null; ls -la /etc/ld.so.conf.d/
grep -rn 'pam_exec\|pam_script' /etc/pam.d/ 2>/dev/null
ls -la --time-style=full-iso /lib/x86_64-linux-gnu/security/ /usr/lib64/security/ 2>/dev/null | sort -k6,7
ls -la --time-style=full-iso /etc/update-motd.d/ /etc/rc.local /etc/init.d/ 2>/dev/null
grep -rn 'RUN+=' /etc/udev/rules.d/ 2>/dev/null
grep -rn 'Invoke' /etc/apt/apt.conf.d/ 2>/dev/nullالتحقق من الحزم أسرع طريقة لكشف ملفات النظام المعدلة، مثل pam_unix.so أو sshd أو ps ملغوم. فهو يقارن الملفات المثبتة بالبصمات التي سجلها مدير الحزم عند التثبيت. ويستطيع مهاجم يملك root العبث بقاعدة بيانات الحزم أيضًا، لذا اعتبر النتيجة السليمة مؤشرًا داعمًا لا حكمًا نهائيًا، وتحقق من البرامج الحرجة على نظام سليم.
dpkg --verify 2>/dev/null | grep -v ' c /etc/' > "$OUT/dpkg-verify.txt" # Debian and Ubuntu
debsums -c 2>/dev/null >> "$OUT/dpkg-verify.txt"
rpm -Va 2>/dev/null | grep -E '^..5' > "$OUT/rpm-verify.txt" # RHEL: changed digest
# Who owns a suspicious file? Nothing means it did not come from a package
dpkg -S /usr/lib/x86_64-linux-gnu/security/pam_unix.so
rpm -qf /usr/lib64/security/pam_unix.solsmod > "$OUT/lsmod.txt"
cat /proc/sys/kernel/tainted # 0 is clean; non-zero needs explaining
diff <(lsmod | awk 'NR>1 {print $1}' | sort) <(ls /sys/module | sort) | grep '^>' # names in /sys only
for m in $(lsmod | awk 'NR>1 {print $1}'); do modinfo -F filename "$m"; done | grep -v '^/lib/modules'
dmesg -T | grep -Ei 'taint|module verification|loading out-of-tree'
bpftool prog list 2>/dev/null > "$OUT/bpf-progs.txt" # eBPF programs; compare with expected agents
bpftool link list 2>/dev/null >> "$OUT/bpf-progs.txt"
find / -xdev \( -perm -4000 -o -perm -2000 \) -type f -newermt "2026-10-01" -ls 2>/dev/null
getcap -r / 2>/dev/nullكثير من إدخالات /sys/module مكونات مدمجة في النواة وليست وحدات قابلة للتحميل، لذلك تحتاج المقارنة أعلاه إلى تقدير، لكن الوحدة المحملة (التي لها ملف initstate) وغير الموجودة في lsmod أُخفيت عمدًا. وتزيل برامج rootkit الحذرة نفسها من العرضين، ولهذا يهم تحليل الذاكرة عبر linux.check_modules. برامج eBPF متوقعة من وكلاء EDR وCilium وsystemd وأدوات المراقبة، أما برنامج eBPF لا يمكنك نسبته إلى برنامج ثبتّه فيستحق التصعيد، لأن rootkit القائم على eBPF يستطيع إخفاء العمليات والملفات وحركة الشبكة.
find /var/www /srv /usr/share/nginx /opt -type f \( -name '*.php' -o -name '*.phtml' -o -name '*.jsp' -o -name '*.jspx' \) \
-newermt "2026-10-01" -printf '%TY-%Tm-%Td %TT %u %p\n' 2>/dev/null | sort
grep -rlE 'eval\s*\(\s*(base64_decode|gzinflate|str_rot13|\$_(POST|GET|REQUEST|COOKIE))|assert\s*\(\s*\$_|system\s*\(\s*\$_|passthru|shell_exec|Runtime\.getRuntime\(\)\.exec' \
/var/www 2>/dev/null
# PHP files in upload folders should not exist at all
find /var/www -path '*upload*' -name '*.php*' 2>/dev/nullفرز نظام الملفات
تحتفظ أنظمة ملفات Linux بما يصل إلى أربعة أوقات لكل ملف: التعديل (mtime)، والوصول (atime، وغالبًا غير موثوق بسبب relatime)، وتغيير inode (ctime)، والإنشاء (birth time) على ext4 وXFS وBtrfs. يعيد المهاجمون ضبط mtime عبر touch كثيرًا، لكن لا يمكن ضبط ctime من مساحة المستخدم دون تغيير ساعة النظام، لذلك فإن الملف الذي يكون ctime فيه أحدث بكثير من mtime قد تم العبث به مؤخرًا.
# Content modified in the window
find / -xdev -type f -newermt "2026-10-20" ! -newermt "2026-10-28" \
-printf '%TY-%Tm-%Td %TT %u:%g %m %s %p\n' 2>/dev/null | sort > "$OUT/mtime-window.txt"
# Inode changed in the window, which catches timestomped files
find / -xdev -type f -newerct "2026-10-20" ! -newerct "2026-10-28" \
-printf '%CY-%Cm-%Cd %CT %p\n' 2>/dev/null | sort > "$OUT/ctime-window.txt"
# All four timestamps for one file, including birth time on current coreutils
stat --format='%n birth=%w modify=%y change=%z access=%x' /usr/local/bin/kswapd1ls -laR --time-style=full-iso /tmp /var/tmp /dev/shm /run/user 2>/dev/null > "$OUT/tmp-listing.txt"
# ELF binaries where software should not live
find /tmp /var/tmp /dev/shm /run /var/www /home -type f -size -20M -exec file {} + 2>/dev/null | grep -i 'ELF'
# Hidden names designed to be overlooked: "...", ". ", names starting with a dot in system folders
find / -xdev \( -name '...' -o -name '.. ' -o -name '. ' -o -name ' ' \) 2>/dev/null
find /usr /etc /var/lib /lib -xdev -name '.*' -type f 2>/dev/null | grep -v -E '\.(placeholder|keep|gitignore|build-id)'
# Immutable or append-only flags used to block cleanup
lsattr -R /etc /root /home /var/spool/cron 2>/dev/null | grep -E '^[^ ]*[ia][^ ]* 'sha256sum /tmp/.x /dev/shm/kworker /usr/local/bin/kswapd1 | tee -a "$OUT/hashes.txt"
file /tmp/.x; strings -n 8 /tmp/.x | head -100 # mining pool URLs, C2 addresses, wallet strings
yara -r -s -w /mnt/ir/rules/linux.yar /tmp /var/tmp /dev/shm /home /var/www /usr/local/bin 2>/dev/null
yara -s /mnt/ir/rules/linux.yar 4127 # scan a running process by PID
/mnt/ir/thor-lite/thor-lite-linux-64 -p /tmpانسخ البرامج المشبوهة إلى مجلد الأدلة قبل أي شيء آخر، وأرسل البصمات لا الملفات إلى الخدمات العامة: فرفع عينة إلى VirusTotal يتيحها لكل المشتركين، ومنهم المهاجم، فيعرف أنك وجدت أداته.
الجمع عبر UAC وVelociraptor وصور الأقراص
تحوّل UAC كل ما سبق إلى أمر واحد قابل للتكرار. فهي تعمل من مجلد على قرص الأدوات، وتستخدم الأدوات الموجودة على الهدف، وتجمع مخرجات الاستجابة المباشرة والسجلات والإعدادات وسجلات الأوامر وملف body للجدول الزمني، وتنتج أرشيفًا واحدًا مع بصمة وسجل جمع.
cd /mnt/ir/uac
sudo ./uac -p ir_triage /mnt/evidence # standard triage profile
sudo ./uac -a ./artifacts/memory_dump/avml.yaml -p ir_triage /mnt/evidence # plus memory
sudo ./uac -p full /mnt/evidence # broader, slower
# Stream the output when there is no local disk to write to
sudo ./uac -p ir_triage --sftp analyst@10.0.0.50:/cases/host01 /tmpعلى مستوى الأجهزة الكثيرة، تمنح Velociraptor القدرة نفسها عن بُعد، مع عمليات صيد تشغل أثرًا واحدًا على كل خوادم Linux دفعة واحدة. ومن الآثار المفيدة Linux.Sys.Pslist وLinux.Ssh.AuthorizedKeys وLinux.Sys.Crontab وLinux.Sys.Users وLinux.Search.FileFinder للبحث عن المؤشرات، إضافة إلى آثار فحص YARA للملفات وذاكرة العمليات.
sudo tar -czf - --ignore-failed-read \
/etc /var/log /var/spool/cron /root/.ssh /root/.bash_history \
/home/*/.ssh /home/*/.bash_history /tmp /var/tmp /dev/shm 2>/dev/null |
ssh analyst@10.0.0.50 "tee /cases/host01/host01-triage.tgz | sha256sum > /cases/host01/host01-triage.tgz.sha256"خذ صورة كاملة للقرص عندما تحتاج إلى استعادة الملفات المحذوفة أو المساحة المتبقية أو أدلة صالحة للقضاء. على الأجهزة الفعلية، أنشئ الصورة عبر dc3dd أو ewfacquire إلى تخزين خارجي. وعلى الأجهزة السحابية، خذ لقطة للقرص عبر المزود، وأنشئ قرصًا جديدًا منها، واربطه بجهاز جنائي مخصص في شبكة معزولة. واربطه للقراءة فقط مع noload على ext4، مما يمنع النواة من إعادة تشغيل السجل وتغيير الدليل.
# Physical or local virtual disk
sudo dc3dd if=/dev/sda hof=/mnt/evidence/host01-sda.dd hash=sha256 log=/mnt/evidence/host01-sda.log
# AWS
aws ec2 create-snapshot --volume-id vol-0abc123 --description "IR-2026-031 host01 root" \
--tag-specifications 'ResourceType=snapshot,Tags=[{Key=case,Value=IR-2026-031}]'
# On the forensic instance, with the copied volume attached as /dev/nvme1n1
sudo mount -o ro,noload,noexec,nodev /dev/nvme1n1p1 /mnt/case
sudo fls -r -m / /dev/nvme1n1p1 > host01.body
sudo mactime -b host01.body -d -z UTC 2026-10-20..2026-10-28 > host01-timeline.csvالحاويات وKubernetes
في بيئات الحاويات، قد يختفي الحمل المخترق خلال دقائق عندما يستبدل المنسق الوحدات غير السليمة. التقط أولًا ثم احتوِ: أوقف الحاوية مؤقتًا بدل إنهائها، وصدّر نظام ملفاتها، وسجل إعدادها، لأن الأدلة تختفي معها.
docker ps -a --no-trunc
docker inspect web-1 > "$OUT/web-1-inspect.json" # privileged? host mounts? capabilities?
docker top web-1
docker diff web-1 > "$OUT/web-1-diff.txt" # files added (A), changed (C), deleted (D)
docker logs --timestamps web-1 > "$OUT/web-1.log" 2>&1
docker pause web-1 # freeze processes, keep memory and state
docker export web-1 -o "$OUT/web-1-fs.tar"
# Kubernetes
kubectl get pods -A -o wide
kubectl get events -A --sort-by=.lastTimestamp | tail -50
kubectl describe pod web-7d9f -n prod
kubectl logs web-7d9f -n prod --all-containers --timestamps --previous
kubectl get clusterrolebindings -o wide | grep -v system: # unexpected cluster-admin grantsيعد docker diff من أسرع أوامر الفرز: فصورة الحاوية يجب أن تكون غير قابلة للتعديل، لذا فإن كل ملف مضاف أو متغير في حاوية عاملة إما حالة متوقعة للتطبيق أو نشاط للمهاجم. افحص عبر docker inspect الوضع الامتيازي، ومساحات أسماء PID أو الشبكة الخاصة بالخادم، وربط / أو /var/run/docker.sock أو /etc، إذ يحول كل منها اختراق الحاوية إلى اختراق للخادم. وفي السحابة، راجع أيضًا سجلات تدقيق المزود (CloudTrail وAzure Activity Log وGoogle Cloud Audit Logs) لكشف استخدام بيانات اعتماد دور الجهاز من خارجه.
فحص Rootkit
تأتي برامج rootkit في Linux بثلاثة أشكال: في مساحة المستخدم عبر استبدال البرامج أو تحميل المكتبات مسبقًا، ووحدات نواة مثل Diamorphine وReptile، والأحدث القائمة على eBPF. ويخفي كل منها العمليات والملفات والاتصالات عن الأدوات العادية، لذلك يعتمد الكشف على مقارنة عرضين للشيء نفسه وملاحظة اختلافهما.
- العمليات: مخرجات ps مقابل المرور المباشر على /proc مقابل عروض الذاكرة في Volatility مثل linux.pslist وlinux.psscan.
- المنافذ: مخرجات ss مقابل /proc/net/tcp مقابل unhide-tcp، الذي يختبر كل منفذ بمحاولة الارتباط به.
- الوحدات: lsmod مقابل /sys/module مقابل linux.check_modules في الذاكرة، إضافة إلى علامة taint في النواة.
- استدعاءات النظام: يكشف linux.check_syscall وlinux.check_idt في الذاكرة نقاط دخول النواة المعترضة.
- الملفات: قائمة مجلد على الجهاز العامل مقابل المجلد نفسه على لقطة قرص مربوطة، لا تتحكم بها النواة العاملة.
/mnt/ir/bin/chkrootkit -q
rkhunter --check --sk --rwo --nocolors
unhide proc; unhide sys; unhide brute
unhide-tcpأنماط اختراق Linux الشائعة
معدّن عملات على خدمة مكشوفة
أكثر اختراقات Linux شيوعًا. يكون الدخول عادةً عبر كلمة مرور SSH ضعيفة، أو Redis أو Docker API أو لوحة Kubernetes مكشوفة، أو تطبيق ويب غير محدث. توقع برنامجًا مثل XMRig بعد إعادة تسميته ليشبه خيط نواة في /tmp أو /dev/shm أو /var/tmp، ومهمة cron أو وحدة systemd تعيد تنزيله كل بضع دقائق، ومفتاحًا مصرحًا به جديدًا، ومعدّنين منافسين أوقفهم نص، واتصالات بمنافذ المجمعات. اجمع نص الإسقاط، فهو يوثق كل ما غيّره المهاجم. وأزل كل وسائل الاستمرار قبل إيقاف العملية، وإلا فستعود.
Web shell عبر تطبيق ضعيف
ابحث عن نص في جذر المستندات أو مجلد الرفع، وطلبات POST إليه في سجل الوصول، وعمليات فرعية لمستخدم خادم الويب. ومن هناك يقرأ المهاجم عادةً ملفات الإعداد للحصول على بيانات اعتماد قاعدة البيانات والسحابة، لذا افترض أن كل سر يمكن لمستخدم خادم الويب قراءته مخترق وبدّله. وتحقق هل وصل إلى root عبر ثغرة محلية في النواة أو sudo، بالبحث عن ملفات يملكها root أُنشئت بعد ظهور web shell بقليل.
بيانات اعتماد أو مفاتيح SSH مسروقة
الدخول المقبول من عنوان غير مألوف في وقت غير معتاد، باسم مستخدم معروف وبصمة تطابق مفتاح موظف حقيقي، يشير إلى سرقة مفتاح من جهاز أو نظام CI لا إلى تخمين. افرز مصدر المفتاح كما تفرز الخادم. وتحقق هل استخدم المهاجم تمرير وكيل SSH أو وجد مفاتيح خاصة على هذا الخادم للتحرك أبعد، وابحث عن عنوان المصدر نفسه في سجلات الصدفة والمصادقة على الأجهزة المجاورة.
سرقة بيانات الاعتماد السحابية
على الأجهزة السحابية، غالبًا ما يكون دور الجهاز أثمن هدف. ابحث عن طلبات خدمة البيانات الوصفية على 169.254.169.254 في سجلات الويب (تزوير الطلبات من جهة الخادم)، وملفات بيانات الاعتماد في ~/.aws و~/.azure و~/.config/gcloud، ومتغيرات بيئة عمليات التطبيق، ثم افحص سجل تدقيق المزود لكشف استخدام هذه البيانات من عناوين خارج بيئتك.
الاحتواء والتعافي
- اعزل أولًا على مستوى الشبكة: استبدل قواعد مجموعة الأمان أو جدار حماية المزود بقاعدة تسمح لجهاز التحليل فقط. وهذا ينجح حتى لو كان المهاجم يملك root على الجهاز ويستطيع تغيير جدار حمايته.
- جمّد بدل الإنهاء. يوقف kill -STOP العملية الخبيثة مع الاحتفاظ بذاكرتها للجمع، وإيقاف الحاوية مؤقتًا يفعل الشيء نفسه. ولا تنهِ إلا بعد جمع الذاكرة والبرامج.
- خذ لقطة للأقراص قبل الإزالة، لتبقى الأدلة بعد إعادة البناء.
- بدّل كل ما يمكن للجهاز الوصول إليه: مفاتيح SSH للخادم والمستخدمين، ورموز API، وكلمات مرور قواعد البيانات، ومفاتيح الوصول السحابية وجلسات دور الجهاز، ومفاتيح TLS الخاصة، والأسرار في متغيرات البيئة أو ملفات الإعداد.
- أعد البناء من صورة سليمة أو عبر إدارة الإعدادات بدل التنظيف في المكان. فلا يمكن تنظيف اختراق root لجهاز Linux بشكل موثوق.
- أصلح نقطة الدخول قبل تشغيل الجهاز المعاد بناؤه: حدّث التطبيق، وأغلق الخدمة المكشوفة، وافرض SSH بالمفاتيح فقط وMFA على اللوحة السحابية.
- افحص البيئة بالمؤشرات التي وجدتها (البصمات وأسماء الملفات والمفاتيح والعناوين وإدخالات cron) وراقب عن كثب لمدة 30 يومًا على الأقل.
قائمة تحقق سريعة
- خذ لقطة للأقراص السحابية، واربط حقيبة أدوات موثوقة للقراءة فقط، وابدأ صدفة مسجلة بتوقيت UTC مع تعطيل السجل.
- افحص /etc/ld.so.preload وLD_PRELOAD قبل الوثوق بأي برنامج ديناميكي.
- سجل هوية الجهاز ومدة التشغيل والربط والواجهات والمسارات والمستخدمين المسجلين.
- التقط الذاكرة عبر AVML أو LiME واحسب بصمتها.
- سجل العمليات من ps ومن /proc، واستعد البرامج المحذوفة من /proc/PID/exe.
- سجل المقابس وقواعد جدار الحماية وARP، وقارن ss مع /proc/net وunhide-tcp.
- راجع الحسابات وsudoers والمجموعات الامتيازية وكل ملف authorized_keys.
- اجمع سجلات المصادقة وwtmp وbtmp وjournal وسجل التدقيق وسجلات الصدفة.
- ابحث عن وسائل الاستمرار: cron وsystemd وملفات الصدفة والرابط وPAM ووحدات النواة وeBPF وMOTD وudev وخطافات الحزم وweb shells وsetuid.
- تحقق من الحزم، وابحث عن الملفات المتغيرة في النافذة عبر mtime وctime، وافحص باستخدام YARA.
- شغّل UAC أو Velociraptor لجمع كامل مع البصمات.
- للحاويات: inspect وdiff وlogs وpause وexport قبل أن يستبدلها المنسق.
- اعزل على مستوى المزود، وجمّد العمليات، وبدّل كل سر يمكن الوصول إليه، وأعد البناء، وافحص البيئة، وراقب.
الخاتمة
على جهاز Linux مخترق، ابدأ بالتحقق هل يمكنك الوثوق بأدوات النظام. ثم التقط الذاكرة والحالة المباشرة، وراجع الحسابات والسجلات ووسائل الاستمرار، واجمع الأدلة قبل الاحتواء أو إعادة البناء. حافظ على الترتيب نفسه في الخوادم والحاويات، وتدرب عليه على نظام اختبار لتكون الأوامر مألوفة عند وقوع الحادثة.
- Linux
- DFIR
- الاستجابة للحوادث
- الفرز
- التحليل الجنائي
- UAC
- Volatility
- Rootkits
- الحاويات
- صيد التهديدات