diff --git a/app/classes/ratelimiter.php b/app/classes/ratelimiter.php index 9c63204..a9c56e5 100644 --- a/app/classes/ratelimiter.php +++ b/app/classes/ratelimiter.php @@ -1,15 +1,15 @@ db = $database->getConnection(); diff --git a/app/pages/security.php b/app/pages/security.php new file mode 100644 index 0000000..be6a603 --- /dev/null +++ b/app/pages/security.php @@ -0,0 +1,63 @@ +hasRight($user_id, 'superuser') || + $userObject->hasRight($user_id, 'edit whitelist') || + $userObject->hasRight($user_id, 'edit blacklist') || + $userObject->hasRight($user_id, 'edit ratelimiting'))) { + include '../app/templates/error-unauthorized.php'; + exit; +} + +$action = $_GET['action'] ?? 'view'; +$section = $_GET['section'] ?? 'whitelist'; + +// Handle form submissions +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + switch ($_POST['action']) { + case 'add_whitelist': + if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit whitelist')) { + $ip = $_POST['ip_address']; + $description = $_POST['description']; + $is_network = isset($_POST['is_network']) ? 1 : 0; + $rateLimiter->addToWhitelist($ip, $is_network, $description, $currentUser); + } + break; + + case 'remove_whitelist': + if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit whitelist')) { + $ip = $_POST['ip_address']; + $rateLimiter->removeFromWhitelist($ip, $user_id, $currentUser); + } + break; + + case 'add_blacklist': + if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit blacklist')) { + $ip = $_POST['ip_address']; + $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); + } + break; + + case 'remove_blacklist': + if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit blacklist')) { + $ip = $_POST['ip_address']; + $rateLimiter->removeFromBlacklist($ip, $user_id, $currentUser); + } + break; + } + + // Redirect to prevent form resubmission + header("Location: {$app_root}?page=security§ion={$section}"); + exit; +} + +// Get the lists +$whitelisted = $rateLimiter->getWhitelistedIps(); +$blacklisted = $rateLimiter->getBlacklistedIps(); + +// Include the template +include '../app/templates/security.php'; +?> diff --git a/app/templates/page-sidebar.php b/app/templates/page-sidebar.php index 794fc4f..36d7fdb 100644 --- a/app/templates/page-sidebar.php +++ b/app/templates/page-sidebar.php @@ -92,12 +92,23 @@ $timeNow = new DateTime('now', new DateTimeZone($userTimezone)); config file + +hasRight($user_id, 'superuser') || + $userObject->hasRight($user_id, 'edit whitelist') || + $userObject->hasRight($user_id, 'edit blacklist') || + $userObject->hasRight($user_id, 'edit ratelimiting')) { ?> + +
  • + security +
  • +
  • status
  • + hasRight($user_id, 'view app logs')) {?>
  • diff --git a/app/templates/security.php b/app/templates/security.php new file mode 100644 index 0000000..631795e --- /dev/null +++ b/app/templates/security.php @@ -0,0 +1,223 @@ + +
    +
    +
    +

    Security Settings

    +
    +
    +
    + + hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit whitelist'))) { ?> + +
    +
    +
    +
    +

    IP Whitelist

    + IP addresses and networks that will always bypass the ratelimiting login checks. +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    + + +
    +
    +
    + +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    IP AddressNetworkDescriptionAdded ByAdded OnActions
    +
    + + + +
    +
    +
    +
    +
    +
    + + + hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit blacklist'))) { ?> + +
    +
    +
    +
    +

    IP Blacklist

    + IP addresses and networks that will always get blocked at login. +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    + + +
    +
    +
    + +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    IP AddressNetworkReasonAdded ByAdded OnExpiresActions
    +
    + + + +
    +
    +
    +
    +
    +
    + + + hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit ratelimiting'))) { ?> + +
    +
    +
    +
    +

    Rate Limiting Settings

    + Restricts brute force or flooding attempts at login page. +
    +
    +
    +

    Current Settings

    +
      +
    • Maximum login attempts: maxAttempts ?>
    • +
    • Time window: decayMinutes ?> minutes
    • +
    • Auto-blacklist threshold: autoBlacklistThreshold ?> attempts
    • +
    • Auto-blacklist duration: autoBlacklistDuration ?> hours
    • +
    +

    + Note: These settings can be modified in the RateLimiter class configuration. +

    +
    + +

    Recent Failed Login Attempts

    + + + + + + + + + + db->prepare(" + SELECT ip_address, username, attempted_at + FROM {$rateLimiter->ratelimitTable} + ORDER BY attempted_at DESC + LIMIT 10 + "); + $stmt->execute(); + $attempts = $stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($attempts as $attempt) { + ?> + + + + + + + +
    IP AddressUsernameAttempted At
    +
    +
    +
    +
    + +
    + diff --git a/doc/jilo-web.rights.schema b/doc/jilo-web.rights.schema index 44dfc99..8bc853d 100644 --- a/doc/jilo-web.rights.schema +++ b/doc/jilo-web.rights.schema @@ -1,13 +1,16 @@ -INSERT OR IGNORE INTO rights VALUES(1,'superuser'); -INSERT OR IGNORE INTO rights VALUES(2,'edit users'); -INSERT OR IGNORE INTO rights VALUES(3,'view config file'); -INSERT OR IGNORE INTO rights VALUES(4,'edit config file'); -INSERT OR IGNORE INTO rights VALUES(5,'view own profile'); -INSERT OR IGNORE INTO rights VALUES(6,'edit own profile'); -INSERT OR IGNORE INTO rights VALUES(7,'view all profiles'); -INSERT OR IGNORE INTO rights VALUES(8,'edit all profiles'); -INSERT OR IGNORE INTO rights VALUES(9,'view app logs'); -INSERT OR IGNORE INTO rights VALUES(10,'view all platforms'); -INSERT OR IGNORE INTO rights VALUES(11,'edit all platforms'); -INSERT OR IGNORE INTO rights VALUES(12,'view all agents'); -INSERT OR IGNORE INTO rights VALUES(13,'edit all agents'); +INSERT OR IGNORE INTO rights (`id`, `name`) VALUES(1,'superuser'); +INSERT OR IGNORE INTO rights (`name`) VALUES('edit users'); +INSERT OR IGNORE INTO rights (`name`) VALUES('view config file'); +INSERT OR IGNORE INTO rights (`name`) VALUES('edit config file'); +INSERT OR IGNORE INTO rights (`name`) VALUES('view own profile'); +INSERT OR IGNORE INTO rights (`name`) VALUES('edit own profile'); +INSERT OR IGNORE INTO rights (`name`) VALUES('view all profiles'); +INSERT OR IGNORE INTO rights (`name`) VALUES('edit all profiles'); +INSERT OR IGNORE INTO rights (`name`) VALUES('view app logs'); +INSERT OR IGNORE INTO rights (`name`) VALUES('view all platforms'); +INSERT OR IGNORE INTO rights (`name`) VALUES('edit all platforms'); +INSERT OR IGNORE INTO rights (`name`) VALUES('view all agents'); +INSERT OR IGNORE INTO rights (`name`) VALUES('edit all agents'); +INSERT OR IGNORE INTO rights (`name`) VALUES('edit whitelist'); +INSERT OR IGNORE INTO rights (`name`) VALUES('edit blacklist'); +INSERT OR IGNORE INTO rights (`name`) VALUES('edit ratelimiting'); diff --git a/public_html/index.php b/public_html/index.php index 40fedd2..90c47a7 100644 --- a/public_html/index.php +++ b/public_html/index.php @@ -44,6 +44,7 @@ $allowed_urls = [ 'config', 'status', 'logs', + 'security', 'help', 'login', @@ -148,6 +149,29 @@ if ($page == 'logout') { include '../app/templates/block-message.php'; include '../app/pages/login.php'; +} elseif ($page === 'security') { + // Security settings require login + if (!isset($currentUser)) { + include '../app/templates/error-unauthorized.php'; + exit; + } + + // Get user details and rights + $user_id = $userObject->getUserId($currentUser)[0]['id']; + $userDetails = $userObject->getUserDetails($user_id); + $userRights = $userObject->getUserRights($user_id); + $userTimezone = isset($userDetails[0]['timezone']) ? $userDetails[0]['timezone'] : 'UTC'; + + // Initialize RateLimiter + require_once '../app/classes/ratelimiter.php'; + $rateLimiter = new RateLimiter($dbWeb); + + include '../app/templates/page-header.php'; + include '../app/templates/page-menu.php'; + include '../app/templates/page-sidebar.php'; + include '../app/pages/security.php'; + include '../app/templates/page-footer.php'; + } else { // if user is logged in, we need user details and rights