T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/soundstudiopro.com/public_html/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/soundstudiopro.com/public_html/security_scan_sql.php
<?php
/**
 * SQL Injection Security Scanner
 * Scans all PHP files for potential SQL injection vulnerabilities
 * 
 * Usage: php security_scan_sql.php
 */

error_reporting(E_ALL);
ini_set('display_errors', 1);

class SQLInjectionScanner {
    private $vulnerabilities = [];
    private $scannedFiles = 0;
    private $basePath;
    
    public function __construct($basePath) {
        $this->basePath = rtrim($basePath, '/');
    }
    
    /**
     * Scan all PHP files in the directory
     */
    public function scan() {
        echo "šŸ” Starting SQL Injection Security Scan...\n\n";
        echo "Scanning directory: {$this->basePath}\n";
        echo str_repeat("=", 80) . "\n\n";
        
        $this->scanDirectory($this->basePath);
        
        $this->generateReport();
    }
    
    /**
     * Recursively scan directory
     */
    private function scanDirectory($dir) {
        $files = glob($dir . '/*.php');
        
        foreach ($files as $file) {
            // Skip backup files and this scanner itself
            if (strpos($file, '.backup') !== false || 
                strpos($file, 'security_scan_sql.php') !== false ||
                strpos($file, 'vendor/') !== false ||
                strpos($file, 'node_modules/') !== false) {
                continue;
            }
            
            $this->scanFile($file);
        }
        
        // Scan subdirectories
        $dirs = glob($dir . '/*', GLOB_ONLYDIR);
        foreach ($dirs as $subdir) {
            // Skip common directories that don't need scanning
            if (strpos($subdir, 'vendor') !== false || 
                strpos($subdir, 'node_modules') !== false ||
                strpos($subdir, '.git') !== false) {
                continue;
            }
            $this->scanDirectory($subdir);
        }
    }
    
    /**
     * Scan a single PHP file
     */
    private function scanFile($filePath) {
        $this->scannedFiles++;
        $relativePath = str_replace($this->basePath . '/', '', $filePath);
        $content = file_get_contents($filePath);
        $lines = explode("\n", $content);
        
        // Pattern 1: LIMIT/OFFSET with direct variable insertion
        if (preg_match('/LIMIT\s+\$|OFFSET\s+\$/', $content)) {
            $this->checkLimitOffset($filePath, $relativePath, $lines);
        }
        
        // Pattern 2: SQL queries with direct variable concatenation
        if (preg_match('/->(query|exec)\([^)]*\$/', $content)) {
            $this->checkDirectQuery($filePath, $relativePath, $lines);
        }
        
        // Pattern 3: SQL string concatenation with user input
        if (preg_match('/["\'].*\$_(GET|POST|REQUEST|COOKIE|SERVER).*["\']/', $content)) {
            $this->checkStringConcatenation($filePath, $relativePath, $lines);
        }
        
        // Pattern 4: WHERE/ORDER BY with direct variable insertion
        if (preg_match('/WHERE.*\$[a-zA-Z_]+|ORDER\s+BY.*\$[a-zA-Z_]+/', $content)) {
            $this->checkWhereOrderBy($filePath, $relativePath, $lines);
        }
        
        // Pattern 5: Missing prepared statements in common patterns
        $this->checkMissingPreparedStatements($filePath, $relativePath, $lines);
    }
    
    /**
     * Check for LIMIT/OFFSET vulnerabilities
     */
    private function checkLimitOffset($filePath, $relativePath, $lines) {
        foreach ($lines as $lineNum => $line) {
            if (preg_match('/LIMIT\s+(\$[a-zA-Z_]+)\s+OFFSET\s+(\$[a-zA-Z_]+)/', $line, $matches)) {
                // Check if it's using prepared statements
                $context = $this->getContext($lines, $lineNum, 20);
                if (!preg_match('/LIMIT\s+\?|OFFSET\s+\?/', $context)) {
                    $this->addVulnerability($relativePath, $lineNum + 1, 
                        "LIMIT/OFFSET with direct variable insertion",
                        $line,
                        "Use prepared statement parameters: LIMIT ? OFFSET ?"
                    );
                }
            } elseif (preg_match('/LIMIT\s+\$[a-zA-Z_]+|OFFSET\s+\$[a-zA-Z_]+/', $line)) {
                $context = $this->getContext($lines, $lineNum, 20);
                if (!preg_match('/LIMIT\s+\?|OFFSET\s+\?/', $context)) {
                    $this->addVulnerability($relativePath, $lineNum + 1,
                        "LIMIT/OFFSET with direct variable insertion",
                        $line,
                        "Use prepared statement parameters: LIMIT ? OFFSET ?"
                    );
                }
            }
        }
    }
    
    /**
     * Check for direct query() or exec() calls with variables
     */
    private function checkDirectQuery($filePath, $relativePath, $lines) {
        foreach ($lines as $lineNum => $line) {
            // Skip safe patterns (like SHOW TABLES, DESCRIBE, etc.)
            if (preg_match('/->(query|exec)\s*\(\s*["\'](SHOW|DESCRIBE|SELECT\s+1|SELECT\s+\*)/i', $line)) {
                continue;
            }
            
            if (preg_match('/->(query|exec)\s*\(\s*["\'].*\$/', $line)) {
                $context = $this->getContext($lines, $lineNum, 10);
                // Check if it's a safe static query
                if (!preg_match('/["\'](SHOW|DESCRIBE|SELECT\s+1|SELECT\s+\*)/i', $line)) {
                    $this->addVulnerability($relativePath, $lineNum + 1,
                        "Direct query()/exec() with variable in SQL string",
                        $line,
                        "Use prepared statements with ->prepare() and ->execute()"
                    );
                }
            }
        }
    }
    
    /**
     * Check for string concatenation with user input
     */
    private function checkStringConcatenation($filePath, $relativePath, $lines) {
        foreach ($lines as $lineNum => $line) {
            // Look for SQL string building with $_GET, $_POST, etc.
            if (preg_match('/["\'].*\$\_(GET|POST|REQUEST|COOKIE).*["\'].*\.\s*["\']|["\'].*\.\s*\$\_(GET|POST|REQUEST|COOKIE)/', $line)) {
                $context = $this->getContext($lines, $lineNum, 15);
                // Check if it's in a SQL context
                if (preg_match('/(SELECT|INSERT|UPDATE|DELETE|WHERE|FROM|ORDER\s+BY|GROUP\s+BY)/i', $context)) {
                    $this->addVulnerability($relativePath, $lineNum + 1,
                        "String concatenation with user input in SQL context",
                        $line,
                        "Use prepared statements with parameter binding"
                    );
                }
            }
        }
    }
    
    /**
     * Check for WHERE/ORDER BY with direct variables
     */
    private function checkWhereOrderBy($filePath, $relativePath, $lines) {
        foreach ($lines as $lineNum => $line) {
            // Check for WHERE with variables (but allow validated switch statements)
            if (preg_match('/WHERE.*\$[a-zA-Z_]+(?!\s*==|\s*===|\s*!=|\s*!==)/', $line) && 
                !preg_match('/switch\s*\(|case\s+/', $this->getContext($lines, $lineNum, 30))) {
                $this->addVulnerability($relativePath, $lineNum + 1,
                    "WHERE clause with direct variable (may be unsafe)",
                    $line,
                    "Verify variable is validated or use prepared statement parameters"
                );
            }
        }
    }
    
    /**
     * Check for missing prepared statements in common patterns
     */
    private function checkMissingPreparedStatements($filePath, $relativePath, $lines) {
        $inQuery = false;
        $queryStart = 0;
        $hasPrepare = false;
        
        foreach ($lines as $lineNum => $line) {
            // Detect SQL query start
            if (preg_match('/->prepare\s*\(/', $line)) {
                $hasPrepare = true;
            }
            
            // Check for execute without prepare
            if (preg_match('/->execute\s*\(/', $line) && !$hasPrepare) {
                $context = $this->getContext($lines, $lineNum, 30);
                if (preg_match('/(SELECT|INSERT|UPDATE|DELETE)/i', $context)) {
                    $this->addVulnerability($relativePath, $lineNum + 1,
                        "execute() called without prepare()",
                        $line,
                        "Always use ->prepare() before ->execute()"
                    );
                }
            }
            
            // Reset hasPrepare after execute
            if (preg_match('/->execute\s*\(/', $line)) {
                $hasPrepare = false;
            }
        }
    }
    
    /**
     * Get context around a line
     */
    private function getContext($lines, $lineNum, $contextLines = 10) {
        $start = max(0, $lineNum - $contextLines);
        $end = min(count($lines), $lineNum + $contextLines + 1);
        return implode("\n", array_slice($lines, $start, $end - $start));
    }
    
    /**
     * Add vulnerability to report
     */
    private function addVulnerability($file, $line, $type, $code, $recommendation) {
        $this->vulnerabilities[] = [
            'file' => $file,
            'line' => $line,
            'type' => $type,
            'code' => trim($code),
            'recommendation' => $recommendation
        ];
    }
    
    /**
     * Generate security report
     */
    private function generateReport() {
        echo "\n" . str_repeat("=", 80) . "\n";
        echo "šŸ“Š SCAN RESULTS\n";
        echo str_repeat("=", 80) . "\n\n";
        
        echo "Files scanned: {$this->scannedFiles}\n";
        echo "Vulnerabilities found: " . count($this->vulnerabilities) . "\n\n";
        
        if (empty($this->vulnerabilities)) {
            echo "āœ… No SQL injection vulnerabilities detected!\n";
            echo "All queries appear to be using prepared statements correctly.\n\n";
        } else {
            echo "āš ļø  VULNERABILITIES FOUND:\n\n";
            
            // Group by file
            $grouped = [];
            foreach ($this->vulnerabilities as $vuln) {
                $grouped[$vuln['file']][] = $vuln;
            }
            
            foreach ($grouped as $file => $vulns) {
                echo "šŸ“„ File: {$file}\n";
                echo str_repeat("-", 80) . "\n";
                
                foreach ($vulns as $vuln) {
                    echo "  Line {$vuln['line']}: {$vuln['type']}\n";
                    echo "  Code: {$vuln['code']}\n";
                    echo "  Fix: {$vuln['recommendation']}\n";
                    echo "\n";
                }
            }
            
            // Generate summary
            echo "\n" . str_repeat("=", 80) . "\n";
            echo "šŸ“‹ SUMMARY BY TYPE\n";
            echo str_repeat("=", 80) . "\n\n";
            
            $byType = [];
            foreach ($this->vulnerabilities as $vuln) {
                $byType[$vuln['type']] = ($byType[$vuln['type']] ?? 0) + 1;
            }
            
            foreach ($byType as $type => $count) {
                echo "  {$type}: {$count}\n";
            }
        }
        
        // Save report to file
        $reportFile = $this->basePath . '/security_scan_report_' . date('Y-m-d_His') . '.txt';
        $report = $this->generateTextReport();
        file_put_contents($reportFile, $report);
        echo "\nšŸ“ Full report saved to: {$reportFile}\n";
    }
    
    /**
     * Generate text report
     */
    private function generateTextReport() {
        $report = "SQL Injection Security Scan Report\n";
        $report .= "Generated: " . date('Y-m-d H:i:s') . "\n";
        $report .= str_repeat("=", 80) . "\n\n";
        
        $report .= "Files scanned: {$this->scannedFiles}\n";
        $report .= "Vulnerabilities found: " . count($this->vulnerabilities) . "\n\n";
        
        if (!empty($this->vulnerabilities)) {
            $grouped = [];
            foreach ($this->vulnerabilities as $vuln) {
                $grouped[$vuln['file']][] = $vuln;
            }
            
            foreach ($grouped as $file => $vulns) {
                $report .= "File: {$file}\n";
                $report .= str_repeat("-", 80) . "\n";
                
                foreach ($vulns as $vuln) {
                    $report .= "  Line {$vuln['line']}: {$vuln['type']}\n";
                    $report .= "  Code: {$vuln['code']}\n";
                    $report .= "  Fix: {$vuln['recommendation']}\n\n";
                }
            }
        }
        
        return $report;
    }
}

// Run the scanner
$basePath = __DIR__;
$scanner = new SQLInjectionScanner($basePath);
$scanner->scan();

echo "\nāœ… Scan complete!\n";


CasperSecurity Mini