Salta ai contenuti

Best practice di sicurezza

2.5.x ✅ 4.0.x ✅

Questo documento fornisce le migliori pratiche di sicurezza completa per gli sviluppatori di moduli XOOPS. Seguire queste linee guida aiuterà a garantire che i tuoi moduli siano sicuri e non introducano vulnerabilità nelle installazioni di XOOPS.

Ogni sviluppatore XOOPS dovrebbe seguire questi principi di sicurezza fondamentali:

  1. Defense in Depth: Implementa più livelli di controlli di sicurezza
  2. Least Privilege: Fornisci solo i diritti di accesso minimi necessari
  3. Input Validation: Non fidarti mai dell’input dell’utente
  4. Secure by Default: La sicurezza dovrebbe essere la configurazione predefinita
  5. Keep It Simple: I sistemi complessi sono più difficili da proteggere
  • CSRF-Protection - Sistema di token e classe XoopsSecurity
  • Input-Sanitization - MyTextSanitizer e validazione
  • SQL-Injection-Prevention - Pratiche di sicurezza del database

Prima di rilasciare il tuo modulo, verifica:

  • Tutti i moduli includono token XOOPS
  • Tutti gli input dell’utente sono validati e sanificati
  • Tutti gli output sono correttamente escapati
  • Tutte le query del database utilizzano istruzioni parametrizzate
  • I caricamenti di file sono correttamente validati
  • I controlli di autenticazione e autorizzazione sono in atto
  • La gestione degli errori non rivela informazioni sensibili
  • La configurazione sensibile è protetta
  • Le librerie di terze parti sono aggiornate
  • I test di sicurezza sono stati eseguiti
// Verifica se l'utente è loggato
if (!is_object($GLOBALS['xoopsUser'])) {
redirect_header(XOOPS_URL, 3, _NOPERM);
exit();
}
// Verifica se l'utente ha il permesso di accedere a questo modulo
if (!$GLOBALS['xoopsUser']->isAdmin($xoopsModule->mid())) {
redirect_header(XOOPS_URL, 3, _NOPERM);
exit();
}
// Verifica permesso specifico
$moduleHandler = xoops_getHandler('module');
$module = $moduleHandler->getByDirname('mymodule');
$moduleperm_handler = xoops_getHandler('groupperm');
$groups = $GLOBALS['xoopsUser']->getGroups();
if (!$moduleperm_handler->checkRight('mymodule_view', $item_id, $groups, $module->getVar('mid'))) {
redirect_header(XOOPS_URL, 3, _NOPERM);
exit();
}
// Crea permesso nella funzione di installazione/aggiornamento
$gpermHandler = xoops_getHandler('groupperm');
$gpermHandler->deleteByModule($module->getVar('mid'), 'mymodule_view');
// Aggiungi permesso per tutti i gruppi
$groups = [XOOPS_GROUP_ADMIN, XOOPS_GROUP_USERS, XOOPS_GROUP_ANONYMOUS];
foreach ($groups as $group_id) {
$gpermHandler->addRight('mymodule_view', 1, $group_id, $module->getVar('mid'));
}
  1. Non memorizzare informazioni sensibili nella sessione
  2. Rigenerare gli ID sessione dopo il login/cambiamenti di privilegi
  3. Validare i dati della sessione prima di usarli
// Regenerate session ID after login
session_regenerate_id(true);
// Validate session data
if (isset($_SESSION['mymodule_user_id'])) {
$user_id = (int)$_SESSION['mymodule_user_id'];
// Verify user exists in database
}
// After successful login
session_regenerate_id(true);
$_SESSION['mymodule_user_ip'] = $_SERVER['REMOTE_ADDR'];
// On subsequent requests
if ($_SESSION['mymodule_user_ip'] !== $_SERVER['REMOTE_ADDR']) {
// Possible session hijacking attempt
session_destroy();
redirect_header('index.php', 3, 'Session error');
exit();
}
// Check if file was uploaded properly
if (!isset($_FILES['userfile']) || $_FILES['userfile']['error'] != UPLOAD_ERR_OK) {
redirect_header('index.php', 3, 'File upload error');
exit();
}
// Check file size
if ($_FILES['userfile']['size'] > 1000000) { // 1MB limit
redirect_header('index.php', 3, 'File too large');
exit();
}
// Check file type
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($_FILES['userfile']['type'], $allowed_types)) {
redirect_header('index.php', 3, 'Invalid file type');
exit();
}
// Validate file extension
$filename = $_FILES['userfile']['name'];
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
$allowed_extensions = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array($ext, $allowed_extensions)) {
redirect_header('index.php', 3, 'Invalid file extension');
exit();
}
include_once XOOPS_ROOT_PATH . '/class/uploader.php';
$allowed_mimetypes = ['image/gif', 'image/jpeg', 'image/png'];
$maxsize = 1000000; // 1MB
$maxwidth = 1024;
$maxheight = 768;
$upload_dir = XOOPS_ROOT_PATH . '/uploads/mymodule';
$uploader = new XoopsMediaUploader(
$upload_dir,
$allowed_mimetypes,
$maxsize,
$maxwidth,
$maxheight
);
if ($uploader->fetchMedia('userfile')) {
$uploader->setPrefix('mymodule_');
if ($uploader->upload()) {
$filename = $uploader->getSavedFileName();
// Save filename to database
} else {
echo $uploader->getErrors();
}
} else {
echo $uploader->getErrors();
}
// Define upload directory outside web root
$upload_dir = XOOPS_VAR_PATH . '/uploads/mymodule';
// Create directory if it doesn't exist
if (!is_dir($upload_dir)) {
mkdir($upload_dir, 0755, true);
}
// Move uploaded file
move_uploaded_file($_FILES['userfile']['tmp_name'], $upload_dir . '/' . $safe_filename);
try {
$result = someFunction();
if (!$result) {
throw new Exception('Operation failed');
}
} catch (Exception $e) {
// Log the error
xoops_error($e->getMessage());
// Display a generic error message to the user
redirect_header('index.php', 3, 'An error occurred. Please try again later.');
exit();
}
// Log security events
xoops_loadLanguage('logger', 'mymodule');
$GLOBALS['xoopsLogger']->addExtra('Security', 'Failed login attempt for user: ' . $username);
// Define configuration path outside web root
$config_path = XOOPS_VAR_PATH . '/configs/mymodule/config.php';
// Load configuration
if (file_exists($config_path)) {
include $config_path;
} else {
// Handle missing configuration
}

Use .htaccess to protect configuration files:

# In .htaccess
<Files "config.php">
Order Allow,Deny
Deny from all
</Files>
  1. Choose actively maintained libraries
  2. Check for security vulnerabilities
  3. Verify the library’s license is compatible with XOOPS
// Check library version
if (version_compare(LIBRARY_VERSION, '1.2.3', '<')) {
xoops_error('Please update the library to version 1.2.3 or higher');
}
// Load library in a controlled way
function loadLibrary($file)
{
$allowed = ['parser.php', 'formatter.php'];
if (!in_array($file, $allowed)) {
return false;
}
include_once XOOPS_ROOT_PATH . '/modules/mymodule/libraries/' . $file;
return true;
}
  1. Test all forms with invalid input
  2. Attempt to bypass authentication and authorization
  3. Test file upload functionality with malicious files
  4. Check for XSS vulnerabilities in all output
  5. Test for SQL injection in all database queries

Use automated tools to scan for vulnerabilities:

  1. Static code analysis tools
  2. Web application scanners
  3. Dependency checkers for third-party libraries
// For regular HTML content
echo htmlspecialchars($variable, ENT_QUOTES, 'UTF-8');
// Using MyTextSanitizer
$myts = MyTextSanitizer::getInstance();
echo $myts->htmlSpecialChars($variable);
// For data used in JavaScript
echo json_encode($variable);
// For inline JavaScript
echo 'var data = ' . json_encode($variable) . ';';
// For data used in URLs
echo htmlspecialchars(urlencode($variable), ENT_QUOTES, 'UTF-8');
// Assign variables to Smarty template
$GLOBALS['xoopsTpl']->assign('title', htmlspecialchars($title, ENT_QUOTES, 'UTF-8'));
// For HTML content that should be displayed as-is
$GLOBALS['xoopsTpl']->assign('content', $myts->displayTarea($content, 1, 1, 1, 1, 1));

#security #best-practices #xoops #module-development #authentication #authorization