File Manager V1.5

[SYSTEM@ROOT]: /home/ketechno/public_html/
INJECT_FILE:
NEW_ENTRY:

FILE_CONTENT: secure_db_conn.php

<?php
/**
 * Secure Database Connection
 * Replaces the vulnerable db_conn.php with secure implementation
 */

require_once 'security/config.php';
require_once 'security/logger.php';

class SecureDatabase {
    private $connection;
    private $logger;
    private static $instance = null;
    
    // Database configuration (move to environment variables in production)
    private $config = [
        'host' => 'localhost',
        'username' => 'ketechno_ketechno',
        'password' => '&g4&bl$RVvQ7',
        'database' => 'ketechno_quickcheck',
        'charset' => 'utf8mb4',
        'options' => [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
            PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4"
        ]
    ];
    
    private function __construct() {
        $this->logger = new SecurityLogger();
        $this->connect();
    }
    
    /**
     * Get database instance (Singleton pattern)
     */
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * Establish secure database connection
     */
    private function connect() {
        try {
            $dsn = "mysql:host={$this->config['host']};dbname={$this->config['database']};charset={$this->config['charset']}";
            
            $this->connection = new PDO($dsn, $this->config['username'], $this->config['password'], $this->config['options']);
            
            // Log successful connection (without sensitive data)
            $this->logger->log('INFO', 'Database connection established', [
                'host' => $this->config['host'],
                'database' => $this->config['database']
            ]);
            
        } catch (PDOException $e) {
            $this->logger->log('CRITICAL', 'Database connection failed', [
                'error' => $e->getMessage(),
                'host' => $this->config['host']
            ]);
            
            // Don't expose database errors to users
            throw new Exception('Database connection failed. Please try again later.');
        }
    }
    
    /**
     * Execute prepared statement
     */
    public function execute($sql, $params = []) {
        try {
            $stmt = $this->connection->prepare($sql);
            $stmt->execute($params);
            
            $this->logger->log('DEBUG', 'SQL query executed', [
                'sql' => $this->sanitizeSQL($sql),
                'params_count' => count($params)
            ]);
            
            return $stmt;
            
        } catch (PDOException $e) {
            $this->logger->log('ERROR', 'SQL execution failed', [
                'sql' => $this->sanitizeSQL($sql),
                'error' => $e->getMessage()
            ]);
            
            throw new Exception('Database query failed.');
        }
    }
    
    /**
     * Fetch single row
     */
    public function fetchOne($sql, $params = []) {
        $stmt = $this->execute($sql, $params);
        return $stmt->fetch();
    }
    
    /**
     * Fetch multiple rows
     */
    public function fetchAll($sql, $params = []) {
        $stmt = $this->execute($sql, $params);
        return $stmt->fetchAll();
    }
    
    /**
     * Insert data and return last insert ID
     */
    public function insert($table, $data) {
        $columns = array_keys($data);
        $placeholders = ':' . implode(', :', $columns);
        $columnList = implode(', ', $columns);
        
        $sql = "INSERT INTO {$table} ({$columnList}) VALUES ({$placeholders})";
        
        $this->execute($sql, $data);
        return $this->connection->lastInsertId();
    }
    
    /**
     * Update data
     */
    public function update($table, $data, $where, $whereParams = []) {
        $setParts = [];
        foreach (array_keys($data) as $column) {
            $setParts[] = "{$column} = :{$column}";
        }
        $setClause = implode(', ', $setParts);
        
        $sql = "UPDATE {$table} SET {$setClause} WHERE {$where}";
        
        $params = array_merge($data, $whereParams);
        $stmt = $this->execute($sql, $params);
        
        return $stmt->rowCount();
    }
    
    /**
     * Delete data
     */
    public function delete($table, $where, $params = []) {
        $sql = "DELETE FROM {$table} WHERE {$where}";
        $stmt = $this->execute($sql, $params);
        return $stmt->rowCount();
    }
    
    /**
     * Begin transaction
     */
    public function beginTransaction() {
        return $this->connection->beginTransaction();
    }
    
    /**
     * Commit transaction
     */
    public function commit() {
        return $this->connection->commit();
    }
    
    /**
     * Rollback transaction
     */
    public function rollback() {
        return $this->connection->rollback();
    }
    
    /**
     * Sanitize SQL for logging (remove sensitive data)
     */
    private function sanitizeSQL($sql) {
        // Remove potential sensitive data from logs
        $sql = preg_replace('/password\s*=\s*[\'"][^\'"]*[\'"]/i', 'password=***', $sql);
        $sql = preg_replace('/email\s*=\s*[\'"][^\'"]*[\'"]/i', 'email=***', $sql);
        return $sql;
    }
    
    /**
     * Check if table exists
     */
    public function tableExists($tableName) {
        $sql = "SHOW TABLES LIKE :table";
        $stmt = $this->execute($sql, ['table' => $tableName]);
        return $stmt->rowCount() > 0;
    }
    
    /**
     * Create tables if they don't exist
     */
    public function createTablesIfNotExist() {
        // Contact form submissions table
        $contactTableSQL = "
            CREATE TABLE IF NOT EXISTS contact_submissions (
                id INT AUTO_INCREMENT PRIMARY KEY,
                name VARCHAR(255) NOT NULL,
                email VARCHAR(255) NOT NULL,
                phone VARCHAR(20),
                subject VARCHAR(500),
                message TEXT,
                ip_address VARCHAR(45),
                user_agent TEXT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                status ENUM('new', 'read', 'replied') DEFAULT 'new',
                INDEX idx_email (email),
                INDEX idx_created_at (created_at),
                INDEX idx_status (status)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
        ";
        
        // Security logs table
        $securityTableSQL = "
            CREATE TABLE IF NOT EXISTS security_events (
                id INT AUTO_INCREMENT PRIMARY KEY,
                event_type VARCHAR(50) NOT NULL,
                severity ENUM('INFO', 'WARNING', 'ERROR', 'CRITICAL') NOT NULL,
                message TEXT NOT NULL,
                ip_address VARCHAR(45),
                user_agent TEXT,
                request_uri VARCHAR(1000),
                context JSON,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                INDEX idx_event_type (event_type),
                INDEX idx_severity (severity),
                INDEX idx_ip_address (ip_address),
                INDEX idx_created_at (created_at)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
        ";
        
        try {
            $this->execute($contactTableSQL);
            $this->execute($securityTableSQL);
            
            $this->logger->log('INFO', 'Database tables created/verified');
            
        } catch (Exception $e) {
            $this->logger->log('ERROR', 'Failed to create tables: ' . $e->getMessage());
        }
    }
    
    /**
     * Get connection for direct PDO operations
     */
    public function getConnection() {
        return $this->connection;
    }
    
    /**
     * Close connection
     */
    public function close() {
        $this->connection = null;
    }
    
    /**
     * Prevent cloning
     */
    private function __clone() {}
    
    /**
     * Prevent unserialization
     */
    public function __wakeup() {
        throw new Exception("Cannot unserialize singleton");
    }
}

// Initialize database and create tables
try {
    $db = SecureDatabase::getInstance();
    $db->createTablesIfNotExist();
} catch (Exception $e) {
    error_log("Database initialization failed: " . $e->getMessage());
}

?>
[ KEMBALI ]