Find What Recreates the File — Linux Audit, PID Tracking & Launcher Removal

翻译

YOU DELETED THE FILE. YOU LEFT ITS CREATOR RUNNING.

HACKER MINDSET. FORENSIC PRECISION.

Find what recreates the file

Linux Audit · PID tracking · Launcher removal

Ελληνικά

Αυτή είναι διαδικασία διερεύνησης για πραγματικό Linux server. Οι εντολές δεν εκτελέστηκαν στο προηγούμενο πείραμα της εικόνας. Εκεί ο δημιουργός του αρχείου ήταν γνωστός. Εδώ η καταγραφή χρησιμοποιείται για να εντοπιστεί το πρόγραμμα που κάνει τη νέα αλλαγή.

Απαιτούνται δικαιώματα διαχειριστή (sudo), ενεργό Linux Audit και πρόσβαση στο Linux που εκτελεί το πρόγραμμα. Σε φιλοξενία χωρίς αυτά τα δικαιώματα, την καταγραφή πρέπει να αναλάβει ο πάροχος. Οι κανόνες παρακάτω αφορούν 64-bit προγράμματα. Πρόσθετος κανόνας arch=b32 χρειάζεται αν εμπλέκονται 32-bit προγράμματα σε σύστημα που τα υποστηρίζει.

Πού γράφεις τις εντολές: στο Terminal (παράθυρο εντολών) του Linux server. Αν εργάζεσαι από Mac ή άλλον υπολογιστή, συνδέσου πρώτα με ssh username@server, αντικαθιστώντας τα στοιχεία. Μετά τη σύνδεση οι εντολές εκτελούνται στον server. Το sudo εκτελεί μια εντολή με δικαιώματα διαχειριστή. Τα παραδείγματα εκτελούνται ένα βήμα τη φορά, με έλεγχο του αποτελέσματος.

Τα τρία εργαλεία: το auditctl ορίζει τι θα καταγράφει το Linux Audit, το ausearch αναζητά τις καταγραφές του και το ps δείχνει στοιχεία προγραμμάτων που εκτελούνται τώρα. Το PID είναι ο αριθμός που ξεχωρίζει μία συγκεκριμένη εκτέλεση προγράμματος από τις υπόλοιπες.

1. Ενεργοποίηση καταγραφής

Αν λείπει το auditd (υπηρεσία που αποθηκεύει τις καταγραφές ενεργειών του Linux), σε Ubuntu/Debian:

sudo apt-get update
sudo apt-get install auditd
sudo service auditd start

Έλεγξε την κατάσταση και τους υπάρχοντες κανόνες:

sudo auditctl -s
sudo auditctl -l

Χρειάζεται ενεργή καταγραφή και υπηρεσία auditd σε λειτουργία. Αν η ρύθμιση είναι κλειδωμένη ή οι κανόνες αποκλείουν την καταγραφή, χρειάζεται ο διαχειριστής του server. Δεν διαγράφουμε όλους τους υπάρχοντες κανόνες για να προσθέσουμε τον δικό μας.

2. Παρακολούθηση του φακέλου

Αντικατάστησε τη διαδρομή του παραδείγματος με τον πραγματικό φάκελο όπου επιστρέφει το αρχείο. Ο φάκελος πρέπει να υπάρχει. Παρακολουθούμε τον φάκελο ώστε να καλύπτουμε και τη νέα δημιουργία του αρχείου.

sudo auditctl -a always,exit -F arch=b64 \
  -F dir=/var/www/example/wp-content/uploads/ \
  -F perm=wa -F key=wp_recreate

Το auditctl ορίζει τον κανόνα. Το dir είναι ο φάκελος, το perm=wa αφορά ενέργειες εγγραφής και αλλαγής χαρακτηριστικών, και το key=wp_recreate είναι η ετικέτα των σχετικών καταγραφών. Πρόκειται για καταγραφή μελλοντικών ενεργειών, μετά την προσθήκη του κανόνα.

3. Ανάγνωση του γεγονότος που αφορά το αρχείο

Κράτησε αντίγραφο του ύποπτου αρχείου και των σχετικών καταγραφών εκτός του φακέλου που εξυπηρετεί το site πριν από την αφαίρεσή του. Μόλις καταγραφεί νέα δημιουργία/εγγραφή, αντικατάστησε και το όνομα αρχείου στο παρακάτω παράδειγμα:

sudo ausearch -k wp_recreate \
  -f /var/www/example/wp-content/uploads/suspicious.php \
  -ts recent -i

Το ausearch διαβάζει τα γεγονότα που ταιριάζουν. Το recent καλύπτει τα τελευταία δέκα λεπτά και το -i εμφανίζει ερμηνευμένες τιμές. Για παλαιότερη επανεμφάνιση προσαρμόζεις το χρονικό φίλτρο.

Αν το φίλτρο ονόματος δεν βρίσκει το γεγονός, αναζήτησε όλη την καταγραφή του κανόνα με sudo ausearch -k wp_recreate -ts recent -i. Έλεγξε τα PATH και CWD (φάκελος εργασίας): το όνομα μπορεί να έχει καταγραφεί ως σχετική διαδρομή. Η απουσία αποτελεσμάτων δεν αποδεικνύει ότι δεν έγινε εγγραφή.

Εξέτασε το γεγονός επιτυχημένης δημιουργίας/ανοίγματος για εγγραφή ή μετονομασίας προς το συγκεκριμένο αρχείο. Θα υπάρχουν και γεγονότα της δικής σου διαγραφής, τα οποία δεν προσδιορίζουν τον δημιουργό.

Πεδίο Τι διαβάζεις
PATH Ποιο αρχείο αφορά το γεγονός.
pid Αριθμός αναγνώρισης του προγράμματος που έκανε την ενέργεια.
ppid PID της γονικής διεργασίας εκείνη τη στιγμή. Βοηθά να ακολουθήσεις την προέλευση, αλλά δεν αποτελεί πλήρες ιστορικό εκκίνησης.
exe Ποιο εκτελέσιμο πρόγραμμα χρησιμοποιήθηκε, π.χ. Python ή PHP.
PROCTITLE Η γραμμή εντολής που καταγράφηκε για τη διεργασία, όπου είναι διαθέσιμη.

4. Έλεγχος του προγράμματος και της εκκίνησής του

Το 1234 είναι αποκλειστικά παράδειγμα: το αντικαθιστάς με το πραγματικό pid της καταγραφής.

sudo ps -ww -p 1234 -o pid,ppid,user,lstart,args
sudo systemctl status 1234 --no-pager --full

Το ps δείχνει στοιχεία του προγράμματος που εκτελείται τώρα, μαζί με ώρα εκκίνησης και εντολή. Το -ww αποτρέπει την περικοπή λόγω πλάτους οθόνης. Για να εξετάσεις τη γονική διεργασία, επανάλαβε την ίδια εντολή ps με τον αριθμό της στήλης PPID στη θέση του 1234. Το systemctl, σε server με systemd (σύστημα διαχείρισης υπηρεσιών), μπορεί να δείξει σε ποια υπηρεσία ανήκει. Αυτό δεν αποδεικνύει ότι η ίδια η υπηρεσία είναι κακόβουλη.

Έλεγξε ότι πρόκειται ακόμη για το ίδιο πρόγραμμα: οι αριθμοί PID μπορούν να επαναχρησιμοποιηθούν. Αν έχει ήδη τερματιστεί, αξιοποίησε την ιστορική καταγραφή του Audit. Η γραμμή εντολής είναι στοιχείο της έρευνας, όχι από μόνη της απόδειξη για όλο τον κώδικα που εκτελέστηκε.

5. Αφαίρεση του συγκεκριμένου μηχανισμού

Η ενέργεια εξαρτάται από το εύρημα, αφού επιβεβαιωθεί ότι πρόκειται για τον κακόβουλο δημιουργό. Εφάρμοσε την περίπτωση που αντιστοιχεί στο εύρημά σου. Πριν από αλλαγές κράτησε αντίγραφο των αρχείων και της ρύθμισης εκκίνησης. Αν υπάρχει μηχανισμός αυτόματης επανεκκίνησης, απενεργοποίησέ τον ώστε να μη δημιουργήσει νέο αντίγραφο του προγράμματος.

  • Αυτόνομο κακόβουλο πρόγραμμα: ζήτησε να σταματήσει με sudo kill -TERM 1234, αφού ελέγξεις ξανά την ταυτότητά του. Το TERM είναι αίτημα τερματισμού. Έλεγξε ξανά με την παραπάνω εντολή ps ότι η συγκεκριμένη διεργασία έχει τερματιστεί. Αν συνεχίζει να εκτελείται, ο τερματισμός δεν έχει επιβεβαιωθεί. Έπειτα απομάκρυνε το αρχείο του δημιουργού όπως δείχνει το παράδειγμα παρακάτω.
  • Cron (προγραμματισμένη εργασία του Linux): έλεγξε το πρόγραμμα εργασιών του λογαριασμού που βρέθηκε με sudo crontab -u ACCOUNT -l και επεξεργάσου το με sudo crontab -u ACCOUNT -e. Το ACCOUNT αντικαθίσταται με τον πραγματικό λογαριασμό. Αφαίρεσε μόνο την επιβεβαιωμένη κακόβουλη εργασία. Έλεγξε επίσης /etc/crontab και /etc/cron.d/. Η αφαίρεση της εργασίας δεν σταματά από μόνη της ένα ήδη εκτελούμενο πρόγραμμα.
  • Υπηρεσία ή timer του systemd (υπηρεσία ή χρονοδιακόπτης εκκίνησης): εξέτασε τη ρύθμιση με sudo systemctl cat ACTUAL.service και, αν υπάρχει σχετικός timer, με sudo systemctl cat ACTUAL.timer. Σταμάτησε και απενεργοποίησε τα συγκεκριμένα επιβεβαιωμένα κακόβουλα στοιχεία με sudo systemctl disable --now ACTUAL.timer ACTUAL.service. Χρησιμοποίησε τα πραγματικά ονόματα των στοιχείων που υπάρχουν. Αφαίρεσε επίσης τον κακόβουλο κώδικα και άλλες εντολές/εξαρτήσεις που μπορούν να τον εκκινήσουν: το disable μόνο του δεν αποκλείει κάθε άλλο τρόπο εκκίνησης.
  • PHP-FPM (προγράμματα PHP που εξυπηρετούν το site): το εύρημα προσδιορίζει το πρόγραμμα PHP, όχι αυτομάτως το μολυσμένο plugin. Συνδύασε ώρα και PID με την καταγραφή αιτημάτων της PHP και ερεύνησε τον κώδικα του αντίστοιχου αιτήματος. Αποκατάστησε το παραβιασμένο plugin/theme ή άλλο αρχείο από έμπιστη πηγή και αφαίρεσε επιβεβαιωμένες κακόβουλες προγραμματισμένες εργασίες. Ο τερματισμός ενός προγράμματος PHP δεν διορθώνει τον κακόβουλο κώδικα που το site μπορεί να εκτελέσει ξανά.

Πώς απομακρύνεις ένα επιβεβαιωμένο πρόσθετο κακόβουλο αρχείο: αφού έχει σταματήσει η εκτέλεσή του και έχει αφαιρεθεί η εκκίνησή του, μετακίνησέ το εκτός του site, σε φάκελο προσβάσιμο μόνο στον διαχειριστή:

sudo install -d -o root -g root -m 0700 /root/wp-incident
sudo mv -i -- /path/to/confirmed-writer.php /root/wp-incident/

Αντικατάστησε τη διαδρομή με το αρχείο του κακόβουλου δημιουργού που επιβεβαίωσες. Το install -d δημιουργεί/ρυθμίζει τον φάκελο και το mv μετακινεί το αρχείο. Το -i ζητά επιβεβαίωση αν υπάρχει ήδη αρχείο με το ίδιο όνομα. Ο φάκελος /root/wp-incident πρέπει να παραμένει εκτός των διαδρομών που εξυπηρετεί το site. Έτσι κρατάς το δείγμα για την έρευνα και το αφαιρείς από την ενεργή θέση του. Αν έχει αλλοιωθεί νόμιμο αρχείο plugin/theme, αποκατάστησε καθαρό αντίγραφο του στοιχείου από έμπιστη πηγή· μην αφήσεις την εγκατάσταση με απαραίτητα αρχεία που λείπουν.

Για PHP-FPM, ο διαχειριστής μπορεί να προσθέσει στην αντίστοιχη ρύθμιση pool (ομάδα προγραμμάτων PHP του συγκεκριμένου site) καταγραφή με PID και αρχικό script:

access.log = /var/log/client-site-fpm-access.log
access.format = "%t pid=%p script=%f request=%m %r status=%s duration_us=%{microseconds}d"

Αυτή είναι ρύθμιση αρχείου PHP-FPM, όχι εντολή Terminal. Απαιτεί έλεγχο της ρύθμισης με το πραγματικό εκτελέσιμο PHP-FPM και επαναφόρτωση της σωστής υπηρεσίας. Το %f δείχνει το αρχικό script του αιτήματος: αν είναι index.php, δεν αποκαλύπτει μόνο του ποιο plugin έκανε την εγγραφή.

Μια αρχική αναζήτηση για άμεσες αναφορές στο όνομα του αρχείου, σε ελεγμένο αντίγραφο του κώδικα, είναι:

rg -n --fixed-strings -- 'suspicious.php' /path/to/reviewed-copy/wp-content/

Το rg αναζητά κείμενο στα αρχεία. Η αναζήτηση βοηθά την έρευνα, αλλά δυναμικά κατασκευασμένα ονόματα μπορεί να μην εμφανίζονται αυτούσια. Αν η διαδρομή του κώδικα παραμένει άγνωστη, χρειάζεται περαιτέρω ανάλυση του συγκεκριμένου αιτήματος σε ελεγχόμενο περιβάλλον.

6. Επανέλεγχος

Μετά την αφαίρεση του μηχανισμού, αφαίρεσε το κακόβουλο αρχείο και επανάλαβε τις συνθήκες που το επανέφεραν: αντίστοιχο αίτημα στο site, εκτέλεση της σχετικής προγραμματισμένης εργασίας ή κύκλο επανεκκίνησης. Παρακολούθησε επαρκώς για τον πραγματικό μηχανισμό, κλείσε την αρχική είσοδο της παραβίασης και αντικατάστησε διαπιστευτήρια που εκτέθηκαν. Τα 4,2 δευτερόλεπτα του προηγούμενου πειράματος δεν αποτελούν καθολικό κριτήριο καθαρισμού.

Όταν ολοκληρωθεί η καταγραφή, αφαίρεσε μόνο τον προσωρινό κανόνα που πρόσθεσες, με ακριβώς την ίδια διαδρομή και πεδία:

sudo auditctl -d always,exit -F arch=b64 \
  -F dir=/var/www/example/wp-content/uploads/ \
  -F perm=wa -F key=wp_recreate

English

LinkedIn post — controlled lab

YOU DELETED THE FILE. YOU LEFT ITS CREATOR RUNNING.

HACKER MINDSET. FORENSIC PRECISION.

What if everything looks clean? Antivirus. Checksums. Logs.

Yet the file keeps returning.

Delete it once. Delete it five times.

While the program writing it keeps running, it can keep bringing it back.

Same name. Same content.

One second later.

Stop deleting blindly.

Start watching.

In a controlled Linux lab, we reproduce this behavior using a harmless test file.

We started a program written in Python. Its instruction:

“Every second, check whether the file exists. If it is missing, recreate it.”

We recorded its PID (the ID of the running program). Its identity was known from the start.

inotifywait (a file-monitoring tool) watches the uploads folder and records:

  • CREATE — file creation.
  • DELETE — file deletion.
  • CLOSE_WRITE — closing a file opened for writing.

We delete the file.

The program keeps running.

It detects the missing file.

It recreates it.

The capture records the changes. File events alone do not identify the program responsible.

Here, however, the known program’s source code exposes the mechanism:

CHECK EVERY SECOND → FILE IS MISSING → THE PROGRAM WRITES IT AGAIN.

We stop the program.

The lab’s helper program uses proc.terminate() (a Python call requesting that the program we launched stop).

Once it stopped, we deleted the file again.

Monitored the folder for 4.2 seconds.

The file remained absent during that window.

DELETING THE FILE IS NOT REMOVING THE CAUSE.

The image shows the source code, captured file events, recorded program PID and verification result.

The commands run in the Linux Terminal.

For access from a Mac to a remote Linux computer, SSH lets you execute commands on that computer.

No client data. No production system. Controlled lab.

Real terminal evidence.

Stop chasing the file.

Find what brings it back.

What’s the most persistent reinfection you’ve investigated — and what was bringing it back?

#WordPress #CyberSecurity #MalwareAnalysis #IncidentResponse #Linux #Forensics


Technical comment — quick reference

FIND THE WRITER. REMOVE THE CAUSE. VERIFY THE FIX.

Run these commands in the Linux server’s Terminal, directly or over SSH. You need administrator access and Linux Audit enabled.

Example for 64-bit programs. Replace the directory and example PID 1234 with your actual values.

1. auditctl — sets a rule to record future changes in the directory:

sudo auditctl -a always,exit -F arch=b64 \
  -F dir=/path/to/uploads/ \
  -F perm=wa -F key=wp_recreate

2. ausearch — reads recorded activity after the file returns:

sudo ausearch -k wp_recreate -ts recent -i

Find the file’s successful creation/write event and its PID (the ID of the program that performed the operation).

3. ps — shows that program’s details, parent ID and command:

sudo ps -ww -p 1234 -o pid,ppid,user,lstart,args

Disable the confirmed malicious launcher.

For a confirmed standalone malicious program, request termination with sudo kill -TERM 1234. Verify it stopped, then move its script outside the site. Restore modified legitimate plugin files from a trusted source.

Repeat the conditions that caused the file to return and check for recurrence.

Full investigation procedure (auditd, PID tracking, launcher removal) follows below.


Full investigation procedure

This is an investigation procedure for a real Linux server. It was not executed in the earlier image's demonstration, where the writer was already known.

You need administrator privileges, working Linux Audit and access to the Linux host running the writer. On managed hosting without those privileges, the provider must arrange the capture. The following rule covers 64-bit programs; supported 32-bit programs need a corresponding arch=b32 rule.

Where to run the commands: in the Linux server's Terminal (command window). From a Mac or another computer, connect using ssh username@server, replacing the example details. Commands entered after connection run on the server. sudo runs a command with administrator privileges. Work through the examples one step at a time and check each result.

The three tools: auditctl sets Linux Audit recording rules; ausearch searches its recorded events; ps inspects programs running now. A PID is the number identifying a particular running instance of a program.

1. Prepare the capture

On Ubuntu/Debian, if auditd (the service storing Linux Audit events) is missing:

sudo apt-get update
sudo apt-get install auditd
sudo service auditd start
sudo auditctl -s
sudo auditctl -l

Confirm that auditing and its logging service are working. Locked configurations or rules suppressing events require the server administrator. Do not clear all existing rules to add this one.

2. Watch the existing parent directory

Replace the example path with the actual directory where the file returns:

sudo auditctl -a always,exit -F arch=b64 \
  -F dir=/var/www/example/wp-content/uploads/ \
  -F perm=wa -F key=wp_recreate

dir selects the directory; perm=wa selects write-related and attribute-change operations; key labels the matching events. The rule captures future activity, not earlier events.

3. Inspect the event for the returning file

Preserve a copy of the suspicious file and relevant logs outside the web-served directory before removal. Immediately after a new creation/write is captured, replace the example filename and run:

sudo ausearch -k wp_recreate \
  -f /var/www/example/wp-content/uploads/suspicious.php \
  -ts recent -i

ausearch searches matching Audit events. recent means the last ten minutes; -i interprets encoded values. Adjust the time filter for older events.

If the filename filter misses an event, search the whole rule with sudo ausearch -k wp_recreate -ts recent -i. Inspect PATH and CWD (working directory): filenames may be recorded as relative paths. No search results does not prove that no write occurred.

Select the successful creation/write-open or rename event for the returning file, rather than your own deletion. Read PATH (affected file), pid (program ID), ppid (parent process ID at the time), exe (executable) and PROCTITLE (recorded process command line, where available). The parent ID is a lead, not a complete launch history.

4. Inspect the program and its launcher

Replace the illustrative PID 1234 with the actual recorded PID:

sudo ps -ww -p 1234 -o pid,ppid,user,lstart,args
sudo systemctl status 1234 --no-pager --full

ps displays the current program's start time, account and command. -ww prevents display-width truncation. To inspect the parent, repeat the same ps command with the number from the PPID column in place of 1234. On a systemd host, systemctl can identify the containing service; that does not by itself make the service malicious.

Confirm that it is still the same program: PIDs can be reused. If it has exited, use the historical Audit event. A command line is an investigative lead, not proof of every piece of code that ran.

5. Remove the confirmed mechanism

Use the case matching your finding. Preserve the relevant files and launch configuration before changes. Disable any confirmed automatic launcher so it cannot start a replacement process.

  • Standalone malicious program: after verifying its identity, request termination with sudo kill -TERM 1234. Recheck with the earlier ps command that this process has terminated. If it keeps running, termination has not been verified. Then remove the writer's file from its active location as shown below.
  • Cron job (scheduled Linux task): inspect the relevant account using sudo crontab -u ACCOUNT -l; edit it using sudo crontab -u ACCOUNT -e, replacing ACCOUNT with the actual account. Remove the confirmed malicious entry. Also inspect /etc/crontab and /etc/cron.d/. Removing a job does not terminate a program already running.
  • Systemd service/timer: inspect the actual configuration with sudo systemctl cat ACTUAL.service and, where applicable, sudo systemctl cat ACTUAL.timer. Stop and disable the confirmed malicious units with sudo systemctl disable --now ACTUAL.timer ACTUAL.service, using only the actual existing names. Remove the malicious code and other launch paths as well; disabling a unit does not prohibit every other activation path.
  • PHP-FPM (PHP programs serving the site): an Audit event identifies the PHP program, not automatically the compromised plugin. Correlate its PID and time with PHP request logs and investigate the code handling the corresponding request. Restore compromised components from a trusted source and remove confirmed malicious scheduled tasks. Terminating a PHP program does not repair code that the site can execute again.

How to remove a confirmed added malicious file: after stopping its execution and removing its launcher, move it outside the site into an administrator-only directory:

sudo install -d -o root -g root -m 0700 /root/wp-incident
sudo mv -i -- /path/to/confirmed-writer.php /root/wp-incident/

Replace the example path with the confirmed malicious writer's file. install -d creates/configures the directory; mv moves the file. -i asks before overwriting an existing file of the same name. Keep /root/wp-incident outside all web-served paths. This preserves the sample for investigation and removes it from its active location. For modified legitimate plugin/theme files, restore a clean component from a trusted source rather than leaving required files missing.

The administrator can configure the relevant PHP-FPM pool to record request PID and entry script:

access.log = /var/log/client-site-fpm-access.log
access.format = "%t pid=%p script=%f request=%m %r status=%s duration_us=%{microseconds}d"

This belongs in PHP-FPM configuration, not the Terminal. Validate the configuration with the actual PHP-FPM binary and reload the correct service. %f is the request's entry script; index.php alone does not identify a plugin writer.

An initial search for direct references in a reviewed copy is:

rg -n --fixed-strings -- 'suspicious.php' /path/to/reviewed-copy/wp-content/

rg searches file text. Dynamically constructed filenames may not appear literally. If the responsible code remains unknown, continue analyzing the particular request in a controlled environment.

6. Verify and remove the temporary rule

After removing the mechanism, remove the malicious file and reproduce its actual trigger: the relevant request, scheduled execution or restart cycle. Observe long enough for that mechanism. Close the original entry point and replace exposed credentials. The previous lab's 4.2-second window is not a universal cleanup criterion.

Remove only your temporary rule using exactly its original path and fields:

sudo auditctl -d always,exit -F arch=b64 \
  -F dir=/var/www/example/wp-content/uploads/ \
  -F perm=wa -F key=wp_recreate

Primary documentation

添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论