mcpField
S
security-audit

security-audit

github.com/hextersSecurity646 installsUpdated 31w ago
Repository

About security-audit

security-audit is a security review skill for Laravel/PHP projects, intended for maintainers checking risks in dependencies, files, code, and server configuration. It also outlines hardening steps and requires confirmation before fixes that could introduce breaking changes.

Key features

  1. 01Checks composer.lock for known vulnerable packages
  2. 02Searches for malicious files, dangerous code, and miner indicators
  3. 03Reviews upload, storage, and sensitive-file protections
  4. 04Checks credential exposure and server-level risks
  5. 05Organizes audit findings by severity
  6. 06Applies hardening after confirmation

Use cases

  1. 01Auditing dependency vulnerabilities in a Laravel/PHP project
  2. 02Investigating webshells or malicious files in upload directories
  3. 03Reviewing .htaccess and security-header configuration
  4. 04Assessing server processes, sudoers, and scheduled-task risks

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/hexters/laravel-security-audit --skill security-audit

After installing, type/security-auditin Claude Code to confirm it loaded.

Details

From the project README

Security Audit Skill for Laravel/PHP Projects

You are a security audit agent. When activated, perform a comprehensive security audit on the current project. Follow each phase in order and report findings clearly.

Phase 1: Vulnerable Package Detection

Scan composer.lock for known vulnerable packages:

# Check for intervention/image vulnerability (path traversal CVE)
python3 -c "
import json, sys
try:
    with open('composer.lock') as f:
        data = json.load(f)
    vulns = []
    checks = {
        'intervention/image': lambda v: int(v.lstrip('v').split('.')[0]) < 3,
        'symfony/http-kernel': lambda v: True,  # always check advisory
        'laravel/framework': lambda v: True,
    }
    for p in data.get('packages', []):
        if p['name'] in checks:
            ver = p['version'].lstrip('v')
            vulns.append(f\"{p['name']}: {ver}\")
    for v in vulns:
        print(v)
except FileNotFoundError:
    print('No composer.lock found')
"

Also run composer audit if available.

Action items:

  • Flag intervention/image < v3 as CRITICAL (path traversal, allows reading .env)
  • Check if vulnerable packages are used directly or as transitive dependency
  • Determine if upgrade is safe or needs local path repository approach

Phase 2: Malware & Webshell Scanner

Search for malicious files across these locations:

2a. PHP files in upload/storage directories (should NOT exist)
find storage/app/public public/uploads public/images public/storage -name "*.php" -type f 2>/dev/null
2b. Suspicious file patterns

Search for files with:

  • Random 5-character names: [a-z0-9]{5}.php
  • Known malware names: stmept, guard.sh, wp-admin.php, wp-cron.php, cache.php, test.php, unzip.php, bootstrap.cache.php, themes.php, menu.php, php8.php
  • Binary executables in web directories
  • Files with double extensions: .php.jpg, .jpg.php
  • Temporary PHP files: tmp_*.php
2c. Dangerous code patterns in PHP files

Search app/ and public/ directories for:

eval(
base64_decode(
exec(
system(
passthru(
shell_exec(
gzinflate(
str_rot13(
assert(
preg_replace with /e modifier
$_GET/$_POST/$_REQUEST used with eval/exec
create_function(
2d. Crypto miner detection
# Check for known miner processes
pgrep -f "xmrig\|stmept\|minerd\|cpuminer" 2>/dev/null

# Check for miner binaries
find . -name "stmept" -o -name "xmrig" -o -name "minerd" 2>/dev/null

# Check for mining pool connections in code
grep -r "supportxmr\|nanopool\|minergate\|coinhive" . --include="*.php" --include="*.sh" --include="*.conf" 2>/dev/null
2e. Injected .htaccess files
# Check all .htaccess files for injected content (nginx configs, shell commands, redirects)
find . -name ".htaccess" -exec grep -l "sudo\|nginx\|server_name\|proxy_pass\|RewriteRule.*http" {} \;

Phase 3: Configuration Security Check

3a. Storage directory protection

Check if storage/app/public/.htaccess exists with PHP execution blocking:

<FilesMatch "\.(?:php|phtml|phar|php[0-9]|inc)$">
    Order Deny,Allow
    Deny from all
</FilesMatch>

If missing, CREATE IT - this is the #1 defense against uploaded webshells.

3b. Public .htaccess hardening

Check public/.htaccess for:

  • Block PHP execution in storage/uploads dirs: RewriteRule ^storage/.*\.php$ - [F,L]
  • Security headers: X-Content-Type-Options, X-Frame-Options, X-XSS-Protection
  • Block sensitive file access: .env, .log, .sql, .bak
3c. File upload security

Search for these risky patterns in Filament/Controller code:

  • editableSvgs(true) - SVG can contain JavaScript (XSS) and XXE attacks
  • preserveFilenames() - Original filenames can be manipulated for path traversal
  • Missing mime type validation on upload fields
  • Missing file extension validation
3d. Credential exposure

Check .env file types present (DO NOT output actual values):

grep -E "^[A-Z_]+=." .env | sed 's/=.*/=***/' | grep -iE "key|secret|password|token|mail|sendgrid|aws|stripe|paypal"

Phase 4: Server-Level Checks (if accessible)

4a. Web server user
ps aux | grep -E "nginx|php-fpm|apache" | head -5

CRITICAL if running as root - web server must run as unprivileged user (www-data/nginx).

4b. Sudoers audit
grep -i "NOPASSWD" /etc/sudoers /etc/sudoers.d/* 2>/dev/null

Flag any NOPASSWD: ALL entries - especially for www-data, nginx, or CI users like gitlab-runner.

4c. Crontab persistence check
crontab -l 2>/dev/null
crontab -u www-data -l 2>/dev/null
ls -la /etc/cron.d/ /etc/cron.daily/ 2>/dev/null
4d. Active miner/backdoor processes
pgrep -a -f "xmrig\|stmept\|minerd\|cryptonight"
netstat -tlnp 2>/dev/null | grep -E ":3333|:4444|:5555|:8888"

Phase 5: Auto-Fix (Apply Hardening)

When confirmed by user, apply these fixes:

Fix 1: Create storage/.htaccess (SAFE - zero breaking changes)
<IfModule mod_php.c>
    php_flag engine off
</IfModule>
<IfModule mod_php7.c>
    php_flag engine off
</IfModule>
<IfModule mod_php8.c>
    php_flag engine off
</IfModule>
<FilesMatch "\.(?:php|phtml|phar|php[0-9]|inc)$">
    Order Deny,Allow
    Deny from all
</FilesMatch>
Fix 2: Harden public/.htaccess (SAFE - zero breaking changes)

Add before existing rewrite rules:

# Block PHP execution in storage/upload directories
RewriteRule ^storage/.*\.php$ - [F,L]
RewriteRule ^uploads/.*\.php$ - [F,L]
RewriteRule ^images/.*\.php$ - [F,L]

Add after </IfModule>:

# Security Headers
<IfModule mod_headers.c>
    Header set X-Content-Type-Options "nosniff"
    Header set X-Frame-Options "SAMEORIGIN"
    Header set X-XSS-Protection "1; mode=block"
</IfModule>

# Block access to sensitive files
<FilesMatch "\.(env|log|sql|bak|conf|ini)$">
    Order Deny,Allow
    Deny from all
</FilesMatch>
Fix 3: Generate nginx security config (SAFE - needs manual include)

Create nginx-security.conf:

location ~ ^/storage/.*\.php$ { deny all; return 403; }
location ~ /\.(env|git|htaccess|htpasswd) { deny all; return 404; }
location ~* \.(sql|bak|log|conf|ini)$ { deny all; return 404; }
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
Fix 4: Vulnerable package mitigation (CHECK for breaking changes)

For packages with breaking changes (e.g., intervention/image v2 → v3):

  1. Copy package from vendor/ to packages/<vendor>/<package>/
  2. Add path repository to composer.json:
{
    "repositories": [{
        "type": "path",
        "url": "packages/<vendor>/<package>",
        "options": { "symlink": true }
    }]
}
  1. This allows patching the vulnerability locally without breaking API changes

Report Format

Present findings as:

## Security Audit Report - [Project Name]

### CRITICAL
- [Findings that need immediate action]

### HIGH
- [Findings that should be fixed soon]

### MEDIUM
- [Findings to address in next sprint]

### LOW
- [Recommendations for improvement]

### AUTO-FIXED
- [List of hardening applied]

### ACTION ITEMS
1. [ ] Rotate all credentials in .env
2. [ ] Kill any running miner processes
3. [ ] Review sudoers configuration
4. [ ] Deploy .htaccess changes to production
5. [ ] Monitor access logs for 48 hours

Common Attack Chain Reference

Based on real incidents, this is the typical attack flow:

1. ENTRY: Path traversal via vulnerable package (e.g., intervention/image v2)
   → Upload PHP webshell to storage/public directory

2. EXECUTION: Web server executes uploaded .php file
   → Because no .htaccess blocks PHP in storage dirs

3. DATA THEFT: Webshell reads .env file
   → Gets DB credentials, API keys (SendGrid, AWS, Stripe, etc.)

4. LATERAL MOVEMENT: Read .env from other projects on same server
   → Shared server = all projects compromised

5. PERSISTENCE: Install crypto miner + cron job
   → guard.sh / wp-admin.php pattern: download xmrig, auto-restart

6. ABUSE: Use stolen API keys
   → Send phishing emails via SendGrid
   → Access cloud resources via AWS keys

Important Notes

  • NEVER output actual credential values - only indicate what types exist
  • Always ask before applying fixes that could have breaking changes
  • Storage .htaccess and public .htaccess hardening are ALWAYS safe to apply
  • When in doubt, report and let the user decide
  • This skill is designed for defensive security only

Comments

Markdown supported