Adds modal messages, fixes ratelimiter
parent
9c129fcf76
commit
eae2a8a47c
|
@ -53,11 +53,11 @@ class RateLimiter {
|
||||||
|
|
||||||
// Default IPs to whitelist (local interface and private networks IPs)
|
// Default IPs to whitelist (local interface and private networks IPs)
|
||||||
$defaultIps = [
|
$defaultIps = [
|
||||||
['127.0.0.1', false, 'localhost IPv4'],
|
['127.0.0.1', 0, 'localhost IPv4'],
|
||||||
['::1', false, 'localhost IPv6'],
|
['::1', 0, 'localhost IPv6'],
|
||||||
['10.0.0.0/8', true, 'Private network (Class A)'],
|
['10.0.0.0/8', 1, 'Private network (Class A)'],
|
||||||
['172.16.0.0/12', true, 'Private network (Class B)'],
|
['172.16.0.0/12', 1, 'Private network (Class B)'],
|
||||||
['192.168.0.0/16', true, 'Private network (Class C)']
|
['192.168.0.0/16', 1, 'Private network (Class C)']
|
||||||
];
|
];
|
||||||
|
|
||||||
// Insert default whitelisted IPs if they don't exist
|
// Insert default whitelisted IPs if they don't exist
|
||||||
|
@ -70,11 +70,11 @@ class RateLimiter {
|
||||||
|
|
||||||
// Insert known malicious networks
|
// Insert known malicious networks
|
||||||
$defaultBlacklist = [
|
$defaultBlacklist = [
|
||||||
['0.0.0.0/8', true, 'Reserved address space - RFC 1122'],
|
['0.0.0.0/8', 1, 'Reserved address space - RFC 1122'],
|
||||||
['100.64.0.0/10', true, 'Carrier-grade NAT space - RFC 6598'],
|
['100.64.0.0/10', 1, 'Carrier-grade NAT space - RFC 6598'],
|
||||||
['192.0.2.0/24', true, 'TEST-NET-1 Documentation space - RFC 5737'],
|
['192.0.2.0/24', 1, 'TEST-NET-1 Documentation space - RFC 5737'],
|
||||||
['198.51.100.0/24', true, 'TEST-NET-2 Documentation space - RFC 5737'],
|
['198.51.100.0/24', 1, 'TEST-NET-2 Documentation space - RFC 5737'],
|
||||||
['203.0.113.0/24', true, 'TEST-NET-3 Documentation space - RFC 5737']
|
['203.0.113.0/24', 1, 'TEST-NET-3 Documentation space - RFC 5737']
|
||||||
];
|
];
|
||||||
|
|
||||||
$stmt = $this->db->prepare("INSERT OR IGNORE INTO {$this->blacklistTable}
|
$stmt = $this->db->prepare("INSERT OR IGNORE INTO {$this->blacklistTable}
|
||||||
|
@ -155,13 +155,9 @@ class RateLimiter {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$stmt = $this->db->prepare("INSERT INTO {$this->whitelistTable}
|
$stmt = $this->db->prepare("INSERT OR REPLACE INTO {$this->whitelistTable}
|
||||||
(ip_address, is_network, description, created_by)
|
(ip_address, is_network, description, created_by)
|
||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)");
|
||||||
ON DUPLICATE KEY UPDATE
|
|
||||||
is_network = VALUES(is_network),
|
|
||||||
description = VALUES(description),
|
|
||||||
created_by = VALUES(created_by)");
|
|
||||||
|
|
||||||
$result = $stmt->execute([$ip, $isNetwork, $description, $createdBy]);
|
$result = $stmt->execute([$ip, $isNetwork, $description, $createdBy]);
|
||||||
|
|
||||||
|
@ -187,7 +183,7 @@ class RateLimiter {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from whitelist
|
// Remove from whitelist
|
||||||
public function removeFromWhitelist($ip, $userId = null, $removedBy = 'system') {
|
public function removeFromWhitelist($ip, $removedBy = 'system', $userId = null) {
|
||||||
try {
|
try {
|
||||||
// Get IP details before removal for logging
|
// Get IP details before removal for logging
|
||||||
$stmt = $this->db->prepare("SELECT * FROM {$this->whitelistTable} WHERE ip_address = ?");
|
$stmt = $this->db->prepare("SELECT * FROM {$this->whitelistTable} WHERE ip_address = ?");
|
||||||
|
@ -233,14 +229,9 @@ class RateLimiter {
|
||||||
|
|
||||||
$expiryTime = $expiryHours ? date('Y-m-d H:i:s', strtotime("+{$expiryHours} hours")) : null;
|
$expiryTime = $expiryHours ? date('Y-m-d H:i:s', strtotime("+{$expiryHours} hours")) : null;
|
||||||
|
|
||||||
$stmt = $this->db->prepare("INSERT INTO {$this->blacklistTable}
|
$stmt = $this->db->prepare("INSERT OR REPLACE INTO {$this->blacklistTable}
|
||||||
(ip_address, is_network, reason, expiry_time, created_by)
|
(ip_address, is_network, reason, expiry_time, created_by)
|
||||||
VALUES (?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?)");
|
||||||
ON DUPLICATE KEY UPDATE
|
|
||||||
is_network = VALUES(is_network),
|
|
||||||
reason = VALUES(reason),
|
|
||||||
expiry_time = VALUES(expiry_time),
|
|
||||||
created_by = VALUES(created_by)");
|
|
||||||
|
|
||||||
$result = $stmt->execute([$ip, $isNetwork, $reason, $expiryTime, $createdBy]);
|
$result = $stmt->execute([$ip, $isNetwork, $reason, $expiryTime, $createdBy]);
|
||||||
|
|
||||||
|
@ -265,7 +256,7 @@ class RateLimiter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function removeFromBlacklist($ip, $userId = null, $removedBy = 'system') {
|
public function removeFromBlacklist($ip, $removedBy = 'system', $userId = null) {
|
||||||
try {
|
try {
|
||||||
// Get IP details before removal for logging
|
// Get IP details before removal for logging
|
||||||
$stmt = $this->db->prepare("SELECT * FROM {$this->blacklistTable} WHERE ip_address = ?");
|
$stmt = $this->db->prepare("SELECT * FROM {$this->blacklistTable} WHERE ip_address = ?");
|
||||||
|
|
|
@ -9,55 +9,97 @@ if (!($userObject->hasRight($user_id, 'superuser') ||
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$action = $_GET['action'] ?? 'view';
|
// Initialize variables for feedback messages
|
||||||
$section = $_GET['section'] ?? 'whitelist';
|
$error_message = '';
|
||||||
|
$success_message = '';
|
||||||
|
|
||||||
// Handle form submissions
|
// Handle form submissions
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
||||||
switch ($_POST['action']) {
|
$action = $_POST['action'];
|
||||||
|
$section = isset($_POST['section']) ? $_POST['section'] : (isset($_GET['section']) ? $_GET['section'] : 'whitelist');
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch ($action) {
|
||||||
case 'add_whitelist':
|
case 'add_whitelist':
|
||||||
if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit whitelist')) {
|
if (!$userObject->hasRight($user_id, 'superuser') && !$userObject->hasRight($user_id, 'edit whitelist')) {
|
||||||
$ip = $_POST['ip_address'];
|
throw new Exception('You do not have permission to modify the whitelist.');
|
||||||
$description = $_POST['description'];
|
|
||||||
$is_network = isset($_POST['is_network']) ? 1 : 0;
|
|
||||||
$rateLimiter->addToWhitelist($ip, $is_network, $description, $currentUser);
|
|
||||||
}
|
}
|
||||||
|
if (empty($_POST['ip_address'])) {
|
||||||
|
throw new Exception('IP address is required.');
|
||||||
|
}
|
||||||
|
$is_network = isset($_POST['is_network']) ? 1 : 0;
|
||||||
|
if (!$rateLimiter->addToWhitelist($_POST['ip_address'], $is_network, $_POST['description'] ?? '', $currentUser, $user_id)) {
|
||||||
|
throw new Exception('Failed to add IP to whitelist. Please check the IP format.');
|
||||||
|
}
|
||||||
|
$success_message = 'IP address successfully added to whitelist.';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'remove_whitelist':
|
case 'remove_whitelist':
|
||||||
if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit whitelist')) {
|
if (!$userObject->hasRight($user_id, 'superuser') && !$userObject->hasRight($user_id, 'edit whitelist')) {
|
||||||
$ip = $_POST['ip_address'];
|
throw new Exception('You do not have permission to modify the whitelist.');
|
||||||
$rateLimiter->removeFromWhitelist($ip, $user_id, $currentUser);
|
|
||||||
}
|
}
|
||||||
|
if (empty($_POST['ip_address'])) {
|
||||||
|
throw new Exception('IP address is required.');
|
||||||
|
}
|
||||||
|
if (!$rateLimiter->removeFromWhitelist($_POST['ip_address'], $currentUser, $user_id)) {
|
||||||
|
throw new Exception('Failed to remove IP from whitelist.');
|
||||||
|
}
|
||||||
|
$success_message = 'IP address successfully removed from whitelist.';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'add_blacklist':
|
case 'add_blacklist':
|
||||||
if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit blacklist')) {
|
if (!$userObject->hasRight($user_id, 'superuser') && !$userObject->hasRight($user_id, 'edit blacklist')) {
|
||||||
$ip = $_POST['ip_address'];
|
throw new Exception('You do not have permission to modify the blacklist.');
|
||||||
$reason = $_POST['reason'];
|
|
||||||
$is_network = isset($_POST['is_network']) ? 1 : 0;
|
|
||||||
$expiry_hours = empty($_POST['expiry_hours']) ? null : intval($_POST['expiry_hours']);
|
|
||||||
$rateLimiter->addToBlacklist($ip, $is_network, $reason, $currentUser, null, $expiry_hours);
|
|
||||||
}
|
}
|
||||||
|
if (empty($_POST['ip_address'])) {
|
||||||
|
throw new Exception('IP address is required.');
|
||||||
|
}
|
||||||
|
$is_network = isset($_POST['is_network']) ? 1 : 0;
|
||||||
|
$expiry_hours = !empty($_POST['expiry_hours']) ? intval($_POST['expiry_hours']) : null;
|
||||||
|
if (!$rateLimiter->addToBlacklist($_POST['ip_address'], $is_network, $_POST['reason'] ?? '', $currentUser, $user_id, $expiry_hours)) {
|
||||||
|
throw new Exception('Failed to add IP to blacklist. Please check the IP format.');
|
||||||
|
}
|
||||||
|
$success_message = 'IP address successfully added to blacklist.';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'remove_blacklist':
|
case 'remove_blacklist':
|
||||||
if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit blacklist')) {
|
if (!$userObject->hasRight($user_id, 'superuser') && !$userObject->hasRight($user_id, 'edit blacklist')) {
|
||||||
$ip = $_POST['ip_address'];
|
throw new Exception('You do not have permission to modify the blacklist.');
|
||||||
$rateLimiter->removeFromBlacklist($ip, $user_id, $currentUser);
|
|
||||||
}
|
}
|
||||||
|
if (empty($_POST['ip_address'])) {
|
||||||
|
throw new Exception('IP address is required.');
|
||||||
|
}
|
||||||
|
if (!$rateLimiter->removeFromBlacklist($_POST['ip_address'], $currentUser, $user_id)) {
|
||||||
|
throw new Exception('Failed to remove IP from blacklist.');
|
||||||
|
}
|
||||||
|
$success_message = 'IP address successfully removed from blacklist.';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$error_message = $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
// Redirect to prevent form resubmission
|
if (empty($error_message)) {
|
||||||
header("Location: {$app_root}?page=security§ion={$section}");
|
// Only redirect if there was no error
|
||||||
|
header("Location: {$app_root}?page=security§ion={$section}" .
|
||||||
|
($success_message ? '&success=' . urlencode($success_message) : ''));
|
||||||
exit;
|
exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the lists
|
// Get success message from URL if redirected after successful action
|
||||||
|
if (isset($_GET['success'])) {
|
||||||
|
$success_message = $_GET['success'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get current lists
|
||||||
$whitelisted = $rateLimiter->getWhitelistedIps();
|
$whitelisted = $rateLimiter->getWhitelistedIps();
|
||||||
$blacklisted = $rateLimiter->getBlacklistedIps();
|
$blacklisted = $rateLimiter->getBlacklistedIps();
|
||||||
|
|
||||||
// Include the template
|
// Get current section
|
||||||
|
$section = isset($_GET['section']) ? $_GET['section'] : 'whitelist';
|
||||||
|
|
||||||
|
// Include template
|
||||||
include '../app/templates/security.php';
|
include '../app/templates/security.php';
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -3,6 +3,18 @@
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h2>Security Settings</h2>
|
<h2>Security Settings</h2>
|
||||||
|
<?php if (!empty($error_message)): ?>
|
||||||
|
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||||
|
<?= htmlspecialchars($error_message) ?>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (!empty($success_message)): ?>
|
||||||
|
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||||
|
<?= htmlspecialchars($success_message) ?>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
<ul class="nav nav-tabs">
|
<ul class="nav nav-tabs">
|
||||||
<?php if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit whitelist')) { ?>
|
<?php if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit whitelist')) { ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
|
@ -221,3 +233,21 @@
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</div>
|
</div>
|
||||||
<!-- /Security Settings -->
|
<!-- /Security Settings -->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Initialize Bootstrap alerts
|
||||||
|
var alerts = document.querySelectorAll('.alert');
|
||||||
|
alerts.forEach(function(alert) {
|
||||||
|
var closeButton = alert.querySelector('.btn-close');
|
||||||
|
if (closeButton) {
|
||||||
|
closeButton.addEventListener('click', function() {
|
||||||
|
alert.classList.remove('show');
|
||||||
|
setTimeout(function() {
|
||||||
|
alert.remove();
|
||||||
|
}, 150);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue