Sanitasi Masukan
Jangan pernah mempercayai masukan pengguna. Selalu validasi dan sanitasi semua data masukan sebelum menggunakannya. XOOPS menyediakan kelas MyTextSanitizer untuk membersihkan input teks dan berbagai fungsi pembantu untuk validasi.
Dokumentasi Terkait
Section titled “Dokumentasi Terkait”- Keamanan-Praktik Terbaik - Panduan keamanan komprehensif
- CSRF-Protection - Sistem token dan kelas XoopsSecurity
- SQL-Pencegahan Injeksi - Praktik keamanan basis data
Aturan Emas
Section titled “Aturan Emas”Jangan pernah mempercayai masukan pengguna. Semua data dari sumber eksternal harus:
- Divalidasi: Periksa apakah cocok dengan format dan jenis yang diharapkan
- Disanitasi: Hapus atau hindari karakter yang berpotensi berbahaya
- Escaped: Saat mengeluarkan, escape untuk konteks tertentu (HTML, JavaScript, SQL)
Kelas MyTextSanitizer
Section titled “Kelas MyTextSanitizer”XOOPS menyediakan kelas MyTextSanitizer (biasanya disebut sebagai $myts) untuk sanitasi teks.
Mendapatkan Instance
Section titled “Mendapatkan Instance”// Get the singleton instance$myts = MyTextSanitizer::getInstance();Sanitasi Teks Dasar
Section titled “Sanitasi Teks Dasar”$myts = MyTextSanitizer::getInstance();
// For plain text fields (no HTML allowed)$title = $myts->htmlSpecialChars($_POST['title']);
// This converts:// < to <// > to >// & to &// " to "// ' to 'Pemrosesan Konten Textarea
Section titled “Pemrosesan Konten Textarea”Metode displayTarea() menyediakan pemrosesan textarea yang komprehensif:
$myts = MyTextSanitizer::getInstance();
$content = $myts->displayTarea( $_POST['content'], $allowhtml = 0, // 0 = No HTML allowed, 1 = HTML allowed $allowsmiley = 1, // 1 = Smilies enabled $allowxcode = 1, // 1 = XOOPS codes enabled (BBCode) $allowimages = 1, // 1 = Images allowed $allowlinebreak = 1 // 1 = Line breaks converted to <br>);Metode Sanitasi Umum
Section titled “Metode Sanitasi Umum”$myts = MyTextSanitizer::getInstance();
// HTML special characters escaping$safe_text = $myts->htmlSpecialChars($text);
// Strip slashes if magic quotes are on$text = $myts->stripSlashesGPC($text);
// Convert XOOPS codes (BBCode) to HTML$html = $myts->xoopsCodeDecode($text);
// Convert smileys to images$html = $myts->smiley($text);
// Make clickable links$html = $myts->makeClickable($text);
// Complete text processing for preview$preview = $myts->previewTarea($text, $allowhtml, $allowsmiley, $allowxcode);Validasi Masukan
Section titled “Validasi Masukan”Memvalidasi Nilai Integer
Section titled “Memvalidasi Nilai Integer”// Validate integer ID$id = isset($_REQUEST['id']) ? (int)$_REQUEST['id'] : 0;
if ($id <= 0) { redirect_header('index.php', 3, 'Invalid ID'); exit();}
// Alternative with filter_var$id = filter_var($_REQUEST['id'] ?? 0, FILTER_VALIDATE_INT);if ($id === false || $id <= 0) { redirect_header('index.php', 3, 'Invalid ID'); exit();}Memvalidasi Alamat Email
Section titled “Memvalidasi Alamat Email”$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
if (!$email) { redirect_header('form.php', 3, 'Invalid email address'); exit();}Memvalidasi URL
Section titled “Memvalidasi URL”$url = filter_var($_POST['url'], FILTER_VALIDATE_URL);
if (!$url) { redirect_header('form.php', 3, 'Invalid URL'); exit();}
// Additional check for allowed protocols$parsed = parse_url($url);$allowed_schemes = ['http', 'https'];if (!in_array($parsed['scheme'], $allowed_schemes)) { redirect_header('form.php', 3, 'Only HTTP and HTTPS URLs are allowed'); exit();}Memvalidasi Tanggal
Section titled “Memvalidasi Tanggal”$date = $_POST['date'] ?? '';
// Validate date format (YYYY-MM-DD)if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) { redirect_header('form.php', 3, 'Invalid date format'); exit();}
// Validate actual date validity$parts = explode('-', $date);if (!checkdate($parts[1], $parts[2], $parts[0])) { redirect_header('form.php', 3, 'Invalid date'); exit();}Memvalidasi Nama File
Section titled “Memvalidasi Nama File”// Remove all characters except alphanumeric, underscore, and hyphen$filename = preg_replace('/[^a-zA-Z0-9_-]/', '', $_POST['filename']);
// Or use a whitelist approach$allowed_chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';$filename = '';foreach (str_split($_POST['filename']) as $char) { if (strpos($allowed_chars, $char) !== false) { $filename .= $char; }}Menangani Berbagai Jenis Input
Section titled “Menangani Berbagai Jenis Input”Masukan String
Section titled “Masukan String”$myts = MyTextSanitizer::getInstance();
// Short text (titles, names)$title = $myts->htmlSpecialChars(trim($_POST['title']));
// Limit lengthif (strlen($title) > 255) { $title = substr($title, 0, 255);}
// Check for empty required fieldsif (empty($title)) { redirect_header('form.php', 3, 'Title is required'); exit();}Masukan Numerik
Section titled “Masukan Numerik”// Integer$count = (int)$_POST['count'];$count = max(0, min($count, 1000)); // Ensure range 0-1000
// Float$price = (float)$_POST['price'];$price = round($price, 2); // Round to 2 decimal places
// Validate rangeif ($price < 0 || $price > 99999.99) { redirect_header('form.php', 3, 'Invalid price'); exit();}Masukan Boolean
Section titled “Masukan Boolean”// Checkbox values$is_active = isset($_POST['is_active']) ? 1 : 0;
// Or with explicit value check$is_active = ($_POST['is_active'] ?? '') === '1' ? 1 : 0;Masukan Array
Section titled “Masukan Array”// Validate array input (e.g., multiple checkboxes)$selected_ids = [];if (isset($_POST['ids']) && is_array($_POST['ids'])) { foreach ($_POST['ids'] as $id) { $clean_id = (int)$id; if ($clean_id > 0) { $selected_ids[] = $clean_id; } }}Masukan Select/Option
Section titled “Masukan Select/Option”// Validate against allowed values$allowed_statuses = ['draft', 'published', 'archived'];$status = $_POST['status'] ?? '';
if (!in_array($status, $allowed_statuses)) { redirect_header('form.php', 3, 'Invalid status'); exit();}Objek Permintaan (XMF)
Section titled “Objek Permintaan (XMF)”Saat menggunakan XMF, kelas Permintaan menyediakan penanganan input yang lebih bersih:
use Xmf\Request;
// Get integer$id = Request::getInt('id', 0);
// Get string$title = Request::getString('title', '');
// Get array$ids = Request::getArray('ids', []);
// Get with method specification$id = Request::getInt('id', 0, 'POST');$search = Request::getString('q', '', 'GET');
// Check request methodif (Request::getMethod() !== 'POST') { redirect_header('form.php', 3, 'Invalid request method'); exit();}Membuat Kelas Validasi
Section titled “Membuat Kelas Validasi”Untuk formulir yang kompleks, buat kelas validasi khusus:
<?phpnamespace XoopsModules\MyModule;
class Validator{ private $errors = [];
public function validateItem(array $data): bool { $this->errors = [];
// Title validation if (empty($data['title'])) { $this->errors['title'] = 'Title is required'; } elseif (strlen($data['title']) > 255) { $this->errors['title'] = 'Title must be 255 characters or less'; }
// Email validation if (!empty($data['email'])) { if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) { $this->errors['email'] = 'Invalid email format'; } }
// Status validation $allowed = ['draft', 'published']; if (!in_array($data['status'], $allowed)) { $this->errors['status'] = 'Invalid status'; }
return empty($this->errors); }
public function getErrors(): array { return $this->errors; }
public function getError(string $field): ?string { return $this->errors[$field] ?? null; }}Penggunaan:
$validator = new Validator();$data = [ 'title' => $_POST['title'], 'email' => $_POST['email'], 'status' => $_POST['status'],];
if (!$validator->validateItem($data)) { $errors = $validator->getErrors(); // Display errors to user}Sanitasi untuk Penyimpanan Basis Data
Section titled “Sanitasi untuk Penyimpanan Basis Data”Saat menyimpan data dalam database:
$myts = MyTextSanitizer::getInstance();
// For storage (will be processed again on display)$title = $myts->addSlashes($_POST['title']);
// Better: Use prepared statements (see SQL Injection Prevention)$sql = "INSERT INTO " . $xoopsDB->prefix('mytable') . " (title) VALUES (?)";$result = $xoopsDB->query($sql, [$_POST['title']]);Sanitasi untuk Tampilan
Section titled “Sanitasi untuk Tampilan”Konteks yang berbeda memerlukan pelolosan yang berbeda:
$myts = MyTextSanitizer::getInstance();
// HTML contextecho $myts->htmlSpecialChars($title);
// Within HTML attributesecho htmlspecialchars($title, ENT_QUOTES, 'UTF-8');
// JavaScript contextecho json_encode($title);
// URL parameterecho urlencode($title);
// Full URLecho htmlspecialchars($url, ENT_QUOTES, 'UTF-8');Kesalahan Umum
Section titled “Kesalahan Umum”Pengkodean Ganda
Section titled “Pengkodean Ganda”Masalah: Data dikodekan beberapa kali
// Wrong - double encoding$title = $myts->htmlSpecialChars($myts->htmlSpecialChars($_POST['title']));
// Right - encode once, at the appropriate time$title = $_POST['title']; // Store rawecho $myts->htmlSpecialChars($title); // Encode on outputPengkodean Tidak Konsisten
Section titled “Pengkodean Tidak Konsisten”Masalah: Beberapa output dikodekan, beberapa tidak
Solusi: Selalu gunakan pendekatan yang konsisten, sebaiknya pengkodean pada keluaran:
// Template assignment$GLOBALS['xoopsTpl']->assign('title', htmlspecialchars($title, ENT_QUOTES, 'UTF-8'));Validasi Hilang
Section titled “Validasi Hilang”Masalah: Hanya melakukan sanitasi tanpa memvalidasi
Solusi: Selalu validasi terlebih dahulu, lalu sanitasi:
// First validateif (!preg_match('/^[a-z0-9_]+$/', $_POST['username'])) { redirect_header('form.php', 3, 'Username contains invalid characters'); exit();}
// Then sanitize for storage/display$username = $myts->htmlSpecialChars($_POST['username']);Ringkasan Praktik Terbaik
Section titled “Ringkasan Praktik Terbaik”- Gunakan MyTextSanitizer untuk pemrosesan konten teks
- Gunakan filter_var() untuk validasi format tertentu
- Gunakan casting tipe untuk nilai numerik
- Masukkan nilai yang diizinkan untuk input tertentu
- Validasi sebelum melakukan sanitasi
- Escape pada keluaran, bukan pada masukan
- Gunakan pernyataan yang telah disiapkan untuk kueri database
- Buat kelas validasi untuk formulir kompleks
- Jangan pernah mempercayai validasi sisi klien - selalu validasi sisi server
#keamanan #sanitasi #validasi #xoops #MyTextSanitizer #penanganan input