quick dirty php2shell docker audit script
| #!/usr/bin/env bash | |
| # ANSI Color Codes for output readability | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m' | |
| NC_RESET='\033[0m' | |
| echo -e "${BLUE}=== Starting Docker PHP2Shell Audit ===${NC_RESET}\n" | |
| # Get all running container IDs and Names | |
| containers=$(docker ps --format "{{.ID}}:{{.Names}}") | |
| if [ -z "$containers" ]; then | |
| echo -e "${YELLOW}No running Docker containers found.${NC_RESET}" | |
| exit 0 | |
| fi | |
| # Function to check if a version is vulnerable | |
| is_vulnerable() { | |
| local version=$1 | |
| # Split semantic versioning (e.g., 8.3.12 -> major=8, minor=3, patch=12) | |
| if [[ $version =~ ^([0-9]+)\.([0-9]+)\.([0-9]+) ]]; then | |
| local major=${BASH_REMATCH[1]} | |
| local minor=${BASH_REMATCH[2]} | |
| local patch=${BASH_REMATCH[3]} | |
| # Check against the patched versions released by PHP (CVE-2026-109618 / CVE-2026-109619) | |
| case "$major" in | |
| 8) | |
| case "$minor" in | |
| 5) [ "$patch" -lt 12 ] && return 0 ;; # Patched in 8.5.12 | |
| 4) [ "$patch" -lt 27 ] && return 0 ;; # Patched in 8.4.27 | |
| 3) [ "$patch" -lt 36 ] && return 0 ;; # Patched in 8.3.36 | |
| 2) [ "$patch" -lt 35 ] && return 0 ;; # Patched in 8.2.35 | |
| *) return 0 ;; # 8.0 and 8.1 are completely EOL and vulnerable | |
| esac | |
| ;; | |
| 7|5) | |
| return 0 # PHP 5.x and 7.x are EOL and vulnerable | |
| ;; | |
| *) | |
| if [ "$major" -lt 5 ]; then return 1; fi | |
| ;; | |
| esac | |
| fi | |
| return 1 # Safe or unparseable/newer version | |
| } | |
| # Loop through each running container | |
| for item in $containers; do | |
| id=$(echo "$item" | cut -d':' -f1) | |
| name=$(echo "$item" | cut -d':' -f2) | |
| # Execute and capture both stdout and stderr together | |
| php_info=$(docker exec "$id" php -v 2>&1 | head -n 1) | |
| # Gracefully intercept OCI/executable missing errors | |
| if [[ "$php_info" == *"executable file not found"* || "$php_info" == *"No such file or directory"* ]]; then | |
| # Optional: Uncomment the line below if you want to see which containers don't have PHP | |
| # echo -e "[INFO] Container: $name does not contain a PHP binary." | |
| continue | |
| fi | |
| if [ -n "$php_info" ]; then | |
| # Extract version number (e.g., 8.3.35) | |
| php_version=$(echo "$php_info" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n 1) | |
| if [ -z "$php_version" ]; then | |
| # Catch raw errors or edge cases that slipped through the OCI filter | |
| if [[ "$php_info" == *"OCI runtime"* || "$php_info" == *"Error"* ]]; then | |
| continue | |
| fi | |
| echo -e "${YELLOW}[!] Container: $name -> PHP detected but version string unparseable. (Output: $php_info)${NC_RESET}" | |
| continue | |
| fi | |
| # Cross-reference with PHP2Shell vulnerability thresholds | |
| if is_vulnerable "$php_version"; then | |
| echo -e "${RED}[VULNERABLE] Container: $name (PHP v$php_version) is vulnerable to PHP2Shell!${NC_RESET}" | |
| else | |
| echo -e "${GREEN}[SAFE] Container: $name is running patched PHP v$php_version.${NC_RESET}" | |
| fi | |
| fi | |
| done | |
| echo -e "\n${BLUE}=== Audit Complete ===${NC_RESET}" |
| $ ./audit.sh | |
| === Starting Docker PHP2Shell Audit === | |
| [SAFE] Container: kimai-kimai-1 is running patched PHP v8.3.36. | |
| [VULNERABLE] Container: nextcloud-nextcloud-aio-nextcloud-1 (PHP v8.3.19) is vulnerable to PHP2Shell! | |
| [VULNERABLE] Container: wildcard-web (PHP v8.3.31) is vulnerable to PHP2Shell! | |
| [VULNERABLE] Container: root-web (PHP v8.3.31) is vulnerable to PHP2Shell! | |
| [VULNERABLE] Container: home-web (PHP v8.4.16) is vulnerable to PHP2Shell! | |
| [VULNERABLE] Container: whblog-whblog-1 (PHP v8.2.25) is vulnerable to PHP2Shell! | |
| === Audit Complete === |
评论
?
参与讨论