Praktik Terbaik Keamanan
2.5.x ✅ 4.0.x ✅
Dokumen ini memberikan praktik terbaik keamanan komprehensif untuk pengembang module XOOPS. Mengikuti panduan ini akan membantu memastikan bahwa module Anda aman dan tidak menimbulkan kerentanan pada instalasi XOOPS.
Prinsip Keamanan
Section titled “Prinsip Keamanan”Setiap pengembang XOOPS harus mengikuti prinsip keamanan dasar berikut:
- Pertahanan Mendalam: Menerapkan kontrol keamanan berlapis
- Hak Istimewa Terkecil: Hanya memberikan hak akses minimum yang diperlukan
- Validasi Input: Jangan pernah mempercayai input pengguna
- Aman secara Default: Keamanan harus menjadi konfigurasi default
- Tetap Sederhana: Sistem yang kompleks lebih sulit diamankan
Dokumentasi Terkait
Section titled “Dokumentasi Terkait”- CSRF-Protection - Sistem token dan kelas XoopsSecurity
- Sanitasi Masukan - MyTextSanitizer dan validasi
- SQL-Pencegahan Injeksi - Praktik keamanan basis data
Daftar Periksa Referensi Cepat
Section titled “Daftar Periksa Referensi Cepat”Sebelum merilis module Anda, verifikasi:
- Semua formulir termasuk token XOOPS
- Semua masukan pengguna divalidasi dan dibersihkan
- Semua output di-escape dengan benar
- Semua kueri basis data menggunakan pernyataan berparameter
- Unggahan file divalidasi dengan benar
- Pemeriksaan autentikasi dan otorisasi telah dilakukan
- Penanganan kesalahan tidak mengungkapkan informasi sensitif
- Konfigurasi sensitif dilindungi
- Perpustakaan pihak ketiga sudah diperbarui
- Pengujian keamanan telah dilakukan
Otentikasi dan Otorisasi
Section titled “Otentikasi dan Otorisasi”Memeriksa Otentikasi Pengguna
Section titled “Memeriksa Otentikasi Pengguna”// Check if user is logged inif (!is_object($GLOBALS['xoopsUser'])) { redirect_header(XOOPS_URL, 3, _NOPERM); exit();}Memeriksa Izin Pengguna
Section titled “Memeriksa Izin Pengguna”// Check if user has permission to access this moduleif (!$GLOBALS['xoopsUser']->isAdmin($xoopsModule->mid())) { redirect_header(XOOPS_URL, 3, _NOPERM); exit();}
// Check specific permission$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();}Menyiapkan Izin module
Section titled “Menyiapkan Izin module”// Create permission in install/update function$gpermHandler = xoops_getHandler('groupperm');$gpermHandler->deleteByModule($module->getVar('mid'), 'mymodule_view');
// Add permission for all groups$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'));}Keamanan Sesi
Section titled “Keamanan Sesi”Praktik Terbaik Penanganan Sesi
Section titled “Praktik Terbaik Penanganan Sesi”- Jangan menyimpan informasi sensitif dalam sesi tersebut
- Buat ulang ID sesi setelah login/privilege berubah
- Validasi data sesi sebelum menggunakannya
// Regenerate session ID after loginsession_regenerate_id(true);
// Validate session dataif (isset($_SESSION['mymodule_user_id'])) { $user_id = (int)$_SESSION['mymodule_user_id']; // Verify user exists in database}Mencegah Fiksasi Sesi
Section titled “Mencegah Fiksasi Sesi”// After successful loginsession_regenerate_id(true);$_SESSION['mymodule_user_ip'] = $_SERVER['REMOTE_ADDR'];
// On subsequent requestsif ($_SESSION['mymodule_user_ip'] !== $_SERVER['REMOTE_ADDR']) { // Possible session hijacking attempt session_destroy(); redirect_header('index.php', 3, 'Session error'); exit();}Keamanan Pengunggahan File
Section titled “Keamanan Pengunggahan File”Memvalidasi Unggahan File
Section titled “Memvalidasi Unggahan File”// Check if file was uploaded properlyif (!isset($_FILES['userfile']) || $_FILES['userfile']['error'] != UPLOAD_ERR_OK) { redirect_header('index.php', 3, 'File upload error'); exit();}
// Check file sizeif ($_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();}Menggunakan Pengunggah XOOPS
Section titled “Menggunakan Pengunggah XOOPS”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();}Menyimpan File yang Diunggah dengan Aman
Section titled “Menyimpan File yang Diunggah dengan Aman”// Define upload directory outside web root$upload_dir = XOOPS_VAR_PATH . '/uploads/mymodule';
// Create directory if it doesn't existif (!is_dir($upload_dir)) { mkdir($upload_dir, 0755, true);}
// Move uploaded filemove_uploaded_file($_FILES['userfile']['tmp_name'], $upload_dir . '/' . $safe_filename);Penanganan Kesalahan dan Pencatatan
Section titled “Penanganan Kesalahan dan Pencatatan”Penanganan Kesalahan Aman
Section titled “Penanganan Kesalahan Aman”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();}Mencatat Peristiwa Keamanan
Section titled “Mencatat Peristiwa Keamanan”// Log security eventsxoops_loadLanguage('logger', 'mymodule');$GLOBALS['xoopsLogger']->addExtra('Security', 'Failed login attempt for user: ' . $username);Keamanan Konfigurasi
Section titled “Keamanan Konfigurasi”Menyimpan Konfigurasi Sensitif
Section titled “Menyimpan Konfigurasi Sensitif”// Define configuration path outside web root$config_path = XOOPS_VAR_PATH . '/configs/mymodule/config.php';
// Load configurationif (file_exists($config_path)) { include $config_path;} else { // Handle missing configuration}Melindungi File Konfigurasi
Section titled “Melindungi File Konfigurasi”Gunakan .htaccess untuk melindungi file konfigurasi:
# In .htaccess<Files "config.php"> Order Allow,Deny Deny from all</Files>Perpustakaan Pihak Ketiga
Section titled “Perpustakaan Pihak Ketiga”Memilih Perpustakaan
Section titled “Memilih Perpustakaan”- Pilih perpustakaan yang dipelihara secara aktif
- Periksa kerentanan keamanan
- Verifikasikan lisensi perpustakaan kompatibel dengan XOOPS
Memperbarui Perpustakaan
Section titled “Memperbarui Perpustakaan”// Check library versionif (version_compare(LIBRARY_VERSION, '1.2.3', '<')) { xoops_error('Please update the library to version 1.2.3 or higher');}Mengisolasi Perpustakaan
Section titled “Mengisolasi Perpustakaan”// Load library in a controlled wayfunction 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;}Pengujian Keamanan
Section titled “Pengujian Keamanan”Daftar Periksa Pengujian Manual
Section titled “Daftar Periksa Pengujian Manual”- Uji semua formulir dengan input yang tidak valid
- Mencoba melewati otentikasi dan otorisasi
- Uji fungsionalitas unggah file dengan file berbahaya
- Periksa kerentanan XSS di semua output
- Uji injeksi SQL di semua kueri database
Pengujian Otomatis
Section titled “Pengujian Otomatis”Gunakan alat otomatis untuk memindai kerentanan:
- Alat analisis kode statis
- Pemindai aplikasi web
- Pemeriksa ketergantungan untuk perpustakaan pihak ketiga
Keluaran Keluar
Section titled “Keluaran Keluar”Konteks HTML
Section titled “Konteks HTML”// For regular HTML contentecho htmlspecialchars($variable, ENT_QUOTES, 'UTF-8');
// Using MyTextSanitizer$myts = MyTextSanitizer::getInstance();echo $myts->htmlSpecialChars($variable);JavaScript Konteks
Section titled “JavaScript Konteks”// For data used in JavaScriptecho json_encode($variable);
// For inline JavaScriptecho 'var data = ' . json_encode($variable) . ';';URL Konteks
Section titled “URL Konteks”// For data used in URLsecho htmlspecialchars(urlencode($variable), ENT_QUOTES, 'UTF-8');Variabel template
Section titled “Variabel template”// 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));Sumber Daya
Section titled “Sumber Daya”#keamanan #praktik terbaik #xoops #pengembangan module #autentikasi #otorisasi