PHP WebShell
Текущая директория: /var/www/bitcardoApp/backyard/models/security
Просмотр файла: throttle.php
<?php
// backyard/models/security/throttle.php
// Helper functions to inspect and clear throttle / rate-limit tables safely.
if (!function_exists('h')) {
function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
}
function th_allowed_tables(): array {
// hard-allow only these tables
return ['auth_throttle','rate_limits','request_limits'];
}
function th_table_exists(mysqli $conn, string $table): bool {
$table_safe = mysqli_real_escape_string($conn, $table);
$sql = "SHOW TABLES LIKE '{$table_safe}'";
if ($res = mysqli_query($conn, $sql)) {
$ok = mysqli_num_rows($res) > 0;
mysqli_free_result($res);
return $ok;
}
return false;
}
/**
* List rows with very defensive SQL. We try to show common columns if present.
* @return array{columns: string[], rows: array<int,array>, total:int}
*/
function th_list(mysqli $conn, string $table, array $filters = [], int $page = 1, int $per_page = 50): array {
$out = ['columns'=>[], 'rows'=>[], 'total'=>0];
$allowed = th_allowed_tables();
if (!in_array($table, $allowed, true) || !th_table_exists($conn, $table)) {
return $out;
}
$page = max(1, (int)$page);
$per_page = max(1, min(200, (int)$per_page));
$offset = ($page - 1) * $per_page;
// Discover columns
$cols = [];
if ($res = mysqli_query($conn, "DESCRIBE `{$table}`")) {
while ($r = mysqli_fetch_assoc($res)) { $cols[] = $r['Field']; }
mysqli_free_result($res);
}
$out['columns'] = $cols;
// Build WHERE from a few common filters if those columns exist
$w = [];
$bind = [];
$like = function($v){ return '%'.str_replace(['%','_'],['\%','\_'],$v).'%'; };
if (!empty($filters['q'])) {
$q = $filters['q'];
// try match ip, token, key, user_id columns if they exist
$targetCols = array_intersect(['ip','token','key','api_key','identifier','user_id'], $cols);
if ($targetCols) {
$parts = [];
foreach ($targetCols as $c) {
$parts[] = "`$c` LIKE '".mysqli_real_escape_string($conn, $like($q))."'";
}
$w[] = '('.implode(' OR ', $parts).')';
}
}
if (!empty($filters['only_locked'])) {
// look for status/locked/blocked columns
foreach (['locked','blocked','is_blocked','status'] as $c) {
if (in_array($c, $cols, true)) {
if ($c === 'status') {
$w[] = "`status` IN ('locked','blocked','throttled')";
} else {
$w[] = "`{$c}` IN (1,'1',true,'true')";
}
break;
}
}
}
$where = $w ? ('WHERE '.implode(' AND ', $w)) : '';
// Total
$sqlTotal = "SELECT COUNT(*) AS c FROM `{$table}` {$where}";
if ($res = mysqli_query($conn, $sqlTotal)) {
$r = mysqli_fetch_assoc($res);
$out['total'] = (int)($r['c'] ?? 0);
mysqli_free_result($res);
}
// Order by a best-effort timestamp/created column, else id, else nothing
$orderBy = '';
foreach (['updated_at','created_at','last_seen','timestamp','ts','id'] as $c) {
if (in_array($c, $cols, true)) {
$orderBy = "ORDER BY `{$c}` DESC";
break;
}
}
$sql = "SELECT * FROM `{$table}` {$where} {$orderBy} LIMIT {$per_page} OFFSET {$offset}";
if ($res = mysqli_query($conn, $sql)) {
while ($r = mysqli_fetch_assoc($res)) { $out['rows'][] = $r; }
mysqli_free_result($res);
}
return $out;
}
/**
* Attempt to delete a single row by primary key if possible.
* We try common PK names: id, fee_id, rate_id, etc; fallback: match by provided composite key.
*/
function th_delete(mysqli $conn, string $table, array $idPayload): array {
$allowed = th_allowed_tables();
if (!in_array($table, $allowed, true) || !th_table_exists($conn, $table)) {
return ['ok'=>false, 'error'=>'Invalid table'];
}
// Identify a primary/unique column
$pk = null;
$cols = [];
if ($res = mysqli_query($conn, "DESCRIBE `{$table}`")) {
while ($r = mysqli_fetch_assoc($res)) { $cols[] = $r['Field']; }
mysqli_free_result($res);
}
foreach (['id','lock_id','limit_id','rid'] as $c) {
if (in_array($c, $cols, true) && isset($idPayload[$c])) { $pk = $c; break; }
}
if ($pk) {
$val = mysqli_real_escape_string($conn, (string)$idPayload[$pk]);
$sql = "DELETE FROM `{$table}` WHERE `{$pk}` = '{$val}' LIMIT 1";
return ['ok'=> (bool)mysqli_query($conn, $sql), 'error'=> mysqli_error($conn)];
}
// Fallback: try to match by ip / token / key
foreach (['ip','token','key','api_key','identifier'] as $c) {
if (in_array($c, $cols, true) && isset($idPayload[$c])) {
$val = mysqli_real_escape_string($conn, (string)$idPayload[$c]);
$sql = "DELETE FROM `{$table}` WHERE `{$c}` = '{$val}' LIMIT 1";
return ['ok'=> (bool)mysqli_query($conn, $sql), 'error'=> mysqli_error($conn)];
}
}
return ['ok'=>false, 'error'=>'No matching identifier'];
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!