278 lines
10 KiB
PHP
Executable File
278 lines
10 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* CF AUTO KEY GENERATOR - Uses 2captcha Turnstile solver
|
|
*
|
|
* PREREQUISITE: Set 2captcha API key first:
|
|
* /api/cf-auto-keygen.php?action=set_captcha_key&key=YOUR_2CAPTCHA_KEY
|
|
*
|
|
* Then run:
|
|
* /api/cf-auto-keygen.php?action=process_all
|
|
*
|
|
* Flow per account:
|
|
* 1. Send Turnstile challenge to 2captcha → get token (~15sec)
|
|
* 2. POST login to CF with email + password + turnstile token
|
|
* 3. Use session to access /api/v4/user → get Global API Key
|
|
* 4. Store key + harvest zones
|
|
*/
|
|
require_once("/opt/wevads/config/credentials.php");
|
|
header('Content-Type: application/json');
|
|
$db = pg_connect("host=localhost dbname=adx_system user=admin password=".WEVADS_DB_PASS);
|
|
pg_query($db, "SET search_path TO admin");
|
|
|
|
$action = $_GET['action'] ?? 'status';
|
|
$CF_TURNSTILE_SITEKEY = '0x4AAAAAAADnPIDROrmt1Wwj'; // CF dashboard Turnstile sitekey
|
|
$CF_LOGIN_URL = 'https://dash.cloudflare.com/login';
|
|
|
|
function get_captcha_key($db) {
|
|
$r = pg_fetch_assoc(pg_query($db, "SELECT api_key FROM captcha_services WHERE name='2captcha' AND api_key IS NOT NULL AND api_key!='' AND api_key!='PENDING' LIMIT 1"));
|
|
return $r ? $r['api_key'] : null;
|
|
}
|
|
|
|
function solve_turnstile($captcha_key, $sitekey, $url) {
|
|
// Submit task to 2captcha
|
|
$ch = curl_init("http://2captcha.com/in.php");
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => [
|
|
'key' => $captcha_key,
|
|
'method' => 'turnstile',
|
|
'sitekey' => $sitekey,
|
|
'pageurl' => $url,
|
|
'json' => 1
|
|
]
|
|
]);
|
|
$resp = json_decode(curl_exec($ch), true);
|
|
curl_close($ch);
|
|
|
|
if (!($resp['status'] ?? false)) return ['error' => $resp['request'] ?? 'Submit failed'];
|
|
|
|
$task_id = $resp['request'];
|
|
|
|
// Poll for result (max 120 seconds)
|
|
for ($i = 0; $i < 24; $i++) {
|
|
sleep(5);
|
|
$ch = curl_init("http://2captcha.com/res.php?key=$captcha_key&action=get&id=$task_id&json=1");
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
$result = json_decode(curl_exec($ch), true);
|
|
curl_close($ch);
|
|
|
|
if (($result['status'] ?? 0) == 1) {
|
|
return ['token' => $result['request']];
|
|
}
|
|
if (($result['request'] ?? '') !== 'CAPCHA_NOT_READY') {
|
|
return ['error' => $result['request'] ?? 'Unknown error'];
|
|
}
|
|
}
|
|
return ['error' => 'Timeout'];
|
|
}
|
|
|
|
function cf_login_with_turnstile($email, $password, $turnstile_token) {
|
|
// POST to CF login endpoint with Turnstile response
|
|
$ch = curl_init('https://dash.cloudflare.com/api/v4/login');
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => json_encode([
|
|
'email' => $email,
|
|
'password' => $password,
|
|
'captcha_response' => $turnstile_token
|
|
]),
|
|
CURLOPT_HTTPHEADER => [
|
|
'Content-Type: application/json',
|
|
'Accept: application/json',
|
|
'Origin: https://dash.cloudflare.com',
|
|
'Referer: https://dash.cloudflare.com/login'
|
|
],
|
|
CURLOPT_HEADER => true,
|
|
CURLOPT_TIMEOUT => 30
|
|
]);
|
|
$response = curl_exec($ch);
|
|
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
|
$headers = substr($response, 0, $header_size);
|
|
$body = substr($response, $header_size);
|
|
curl_close($ch);
|
|
|
|
// Extract cookies
|
|
preg_match_all('/Set-Cookie:\s*([^;]+)/i', $headers, $matches);
|
|
$cookies = implode('; ', $matches[1] ?? []);
|
|
|
|
return [
|
|
'body' => json_decode($body, true),
|
|
'cookies' => $cookies,
|
|
'raw_headers' => $headers
|
|
];
|
|
}
|
|
|
|
function cf_get_api_key($cookies) {
|
|
// Use session to get Global API Key
|
|
// This requires visiting profile page - the API key is shown after re-auth
|
|
// Alternative: use session to list zones directly
|
|
$ch = curl_init('https://api.cloudflare.com/client/v4/zones?per_page=50');
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_HTTPHEADER => [
|
|
'Cookie: ' . $cookies,
|
|
'Content-Type: application/json'
|
|
],
|
|
CURLOPT_TIMEOUT => 30
|
|
]);
|
|
$resp = json_decode(curl_exec($ch), true);
|
|
curl_close($ch);
|
|
return $resp;
|
|
}
|
|
|
|
switch($action) {
|
|
case 'set_captcha_key':
|
|
$key = $_GET['key'] ?? $_POST['key'] ?? '';
|
|
if (!$key) { echo json_encode(['error' => 'Need key param']); break; }
|
|
|
|
// Update 2captcha entries
|
|
pg_query($db, "UPDATE captcha_services SET api_key='".pg_escape_string($db,$key)."', status='active' WHERE name LIKE '%2captcha%'");
|
|
|
|
// Verify key
|
|
$ch = curl_init("http://2captcha.com/res.php?key=$key&action=getbalance&json=1");
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
$r = json_decode(curl_exec($ch), true);
|
|
curl_close($ch);
|
|
|
|
if (($r['status'] ?? 0) == 1) {
|
|
$balance = $r['request'];
|
|
pg_query($db, "UPDATE captcha_services SET balance=$balance WHERE name LIKE '%2captcha%'");
|
|
echo json_encode(['status' => 'success', 'balance' => $balance]);
|
|
} else {
|
|
echo json_encode(['status' => 'error', 'message' => $r['request'] ?? 'Invalid key']);
|
|
}
|
|
break;
|
|
|
|
case 'process_one':
|
|
$id = (int)($_GET['id'] ?? 0);
|
|
if (!$id) { echo json_encode(['error' => 'Need account id']); break; }
|
|
|
|
$captcha_key = get_captcha_key($db);
|
|
if (!$captcha_key) { echo json_encode(['error' => 'Set 2captcha key first: ?action=set_captcha_key&key=YOUR_KEY']); break; }
|
|
|
|
$acc = pg_fetch_assoc(pg_query($db, "SELECT id, email, password FROM cloudflare_accounts WHERE id=$id"));
|
|
if (!$acc) { echo json_encode(['error' => 'Account not found']); break; }
|
|
|
|
// Step 1: Solve Turnstile
|
|
echo json_encode(['step' => 'solving_turnstile']) . "\n";
|
|
flush();
|
|
$turnstile = solve_turnstile($captcha_key, $CF_TURNSTILE_SITEKEY, $CF_LOGIN_URL);
|
|
if (isset($turnstile['error'])) { echo json_encode(['error' => 'Turnstile: ' . $turnstile['error']]); break; }
|
|
|
|
// Step 2: Login
|
|
$login = cf_login_with_turnstile($acc['email'], $acc['password'], $turnstile['token']);
|
|
$login_data = $login['body'];
|
|
|
|
if (!($login_data['success'] ?? false)) {
|
|
echo json_encode(['error' => 'Login failed', 'cf_errors' => $login_data['errors'] ?? [], 'note' => 'Account may have 2FA']);
|
|
break;
|
|
}
|
|
|
|
// Step 3: Use session to list zones
|
|
$zones = cf_get_api_key($login['cookies']);
|
|
|
|
$domains = [];
|
|
if ($zones['success'] ?? false) {
|
|
foreach ($zones['result'] ?? [] as $z) {
|
|
$d = pg_escape_string($db, $z['name']);
|
|
pg_query($db, "INSERT INTO cloudflare_domains(account_id, domain, zone_id, status, created_at)
|
|
VALUES($id, '$d', '".pg_escape_string($db, $z['id'])."', '{$z['status']}', NOW()) ON CONFLICT DO NOTHING");
|
|
$domains[] = $z['name'];
|
|
}
|
|
pg_query($db, "UPDATE cloudflare_accounts SET domains_count=".count($domains).", api_status='session_auth' WHERE id=$id");
|
|
}
|
|
|
|
echo json_encode([
|
|
'status' => 'success',
|
|
'account' => $acc['email'],
|
|
'login_ok' => $login_data['success'] ?? false,
|
|
'domains_found' => count($domains),
|
|
'domains' => $domains,
|
|
'note' => 'Domains harvested via session auth (no permanent API key needed)'
|
|
]);
|
|
break;
|
|
|
|
case 'process_all':
|
|
$captcha_key = get_captcha_key($db);
|
|
if (!$captcha_key) { echo json_encode(['error' => 'Set 2captcha key first']); break; }
|
|
|
|
$accounts = pg_fetch_all(pg_query($db, "
|
|
SELECT id, email, password FROM cloudflare_accounts
|
|
WHERE (api_key IS NULL OR api_key='' OR api_key='PENDING')
|
|
AND password IS NOT NULL AND password!='' AND status='active'
|
|
ORDER BY domains_count DESC
|
|
"));
|
|
|
|
if (!$accounts) { echo json_encode(['error' => 'No accounts to process']); break; }
|
|
|
|
$results = [];
|
|
$total_domains = 0;
|
|
|
|
foreach ($accounts as $acc) {
|
|
$result = ['id' => $acc['id'], 'email' => $acc['email']];
|
|
|
|
// Solve Turnstile
|
|
$ts = solve_turnstile($captcha_key, $CF_TURNSTILE_SITEKEY, $CF_LOGIN_URL);
|
|
if (isset($ts['error'])) {
|
|
$result['error'] = 'Turnstile: ' . $ts['error'];
|
|
$results[] = $result;
|
|
continue;
|
|
}
|
|
|
|
// Login
|
|
$login = cf_login_with_turnstile($acc['email'], $acc['password'], $ts['token']);
|
|
if (!($login['body']['success'] ?? false)) {
|
|
$result['error'] = 'Login failed: ' . json_encode($login['body']['errors'] ?? []);
|
|
$results[] = $result;
|
|
continue;
|
|
}
|
|
|
|
// List zones
|
|
$zones = cf_get_api_key($login['cookies']);
|
|
$domains = [];
|
|
if ($zones['success'] ?? false) {
|
|
foreach ($zones['result'] ?? [] as $z) {
|
|
$d = pg_escape_string($db, $z['name']);
|
|
pg_query($db, "INSERT INTO cloudflare_domains(account_id, domain, zone_id, status, created_at)
|
|
VALUES({$acc['id']}, '$d', '".pg_escape_string($db,$z['id'])."', '{$z['status']}', NOW()) ON CONFLICT DO NOTHING");
|
|
$domains[] = $z['name'];
|
|
}
|
|
pg_query($db, "UPDATE cloudflare_accounts SET domains_count=".count($domains).", api_status='session_auth' WHERE id={$acc['id']}");
|
|
}
|
|
|
|
$result['status'] = 'success';
|
|
$result['domains'] = count($domains);
|
|
$total_domains += count($domains);
|
|
$results[] = $result;
|
|
|
|
sleep(2); // Rate limit
|
|
}
|
|
|
|
echo json_encode([
|
|
'status' => 'complete',
|
|
'processed' => count($results),
|
|
'total_domains_harvested' => $total_domains,
|
|
'results' => $results
|
|
]);
|
|
break;
|
|
|
|
case 'status':
|
|
$captcha_key = get_captcha_key($db);
|
|
$s = pg_fetch_assoc(pg_query($db, "
|
|
SELECT
|
|
(SELECT COUNT(*) FROM cloudflare_accounts WHERE status='active') as total_accounts,
|
|
(SELECT COUNT(*) FROM cloudflare_accounts WHERE api_key IS NOT NULL AND api_key!='' AND api_key!='PENDING') as with_keys,
|
|
(SELECT COUNT(*) FROM cloudflare_accounts WHERE api_status='session_auth') as session_auth,
|
|
(SELECT COUNT(*) FROM cloudflare_domains) as total_domains
|
|
"));
|
|
echo json_encode([
|
|
'status' => 'success',
|
|
'captcha_ready' => !empty($captcha_key),
|
|
'stats' => $s,
|
|
'instructions' => !$captcha_key ? 'Set 2captcha key: ?action=set_captcha_key&key=YOUR_KEY (costs ~$0.08 per CF account, ~$3 for all 37)' : 'Ready! Run: ?action=process_all'
|
|
]);
|
|
break;
|
|
}
|