CONTENT SECURITY POLICY
Muhammad Ridwan Na'im 07 April 2022 - 19:15:06 WIBA. PENGENALAN CONTENT SECURITY POLICY
Content Security Policy (CSP) atau dalam Bahasa Indonesia dikenal dengan Kebijakan Keamanan Konten, adalah lapisan keamanan tambahan yang membantu mendeteksi dan mengurangi jenis serangan tertentu, seperti Cross Site Scripting (XSS), serangan injeksi data, pencurian data, perusakan situs, hingga distribusi malware.
Untuk mengaktifkan Content Security Policy (CSP), kita bisa melakukan konfigurasi pada webserver seperti Apache, Nginx, dan semisalnya. Selain webserver, kita juga bisa menentukan CSP melalui tag HTML dan pada bahasa pemrograman backend yang digunakan, seperti PHP dan sejenisnya (akan dibahas kemudian).
Adapun ilustrasi dari penerapan CSP dan pengaruhnya terhadap client dapat dilihat pada gambar berikut (Gambar 1). Pada gambar tersebut disimulasikan client mengakses website http://example.com yang memiliki aset berupa javascript ‘file.js’ dan css‘file.css’. Lalu peretas menyisipkan script jahat berupa javascript dari website http://malicious.com bernama xss.js. Sementara webserver menerapkan CSP default-src http://www.example.com.
Maka yang akan ditampilkan pada client dan dieksekusi oleh browser hanyalah file.js dan file.css karena kedua file tersebut berasal dari server yang sama. Sedangkan file xss.js yang disisipkan oleh peretas, akan diblokir oleh browser yang membaca respon dari HTTP Header Content Security Policy karena bersumber dari website yang berbeda.
Gambar 1 – Bagaimana CSP Bekerja
Gambar 2 – Contoh Penerapan CSP
Sebelum menerapkan Content Security Policy pada server, ada beberapa istilah yang harus kita kenali dan beberapa kondisi pada website/aplikasi yang harus kita pahami. Teknologi yang digunakan pada website atau aplikasi akan mempengaruhi konfigurasi dari CSP itu sendiri. Demikian juga sebaliknya. Adapun istilah-istilah yang harus kita pahami kegunaannya pada konfigurasi CSP bisa dilihat pada tabel berikut.
Istilah | Penjelasan | Turunan dari Istilah |
---|---|---|
Direvtives |
Istilah dalam CSP yang berfungsi untuk menentukan kebijakan konten yang akan dieksekusi |
base-uri | block-all-mixed content | child-src | connect-src | default-src | disown-opener | font-src | form-action | frame ancestors | frame-src | img-src | manifest-src | media-src | navigate-to | object-src | plugin-types | prefetch-src | referrer | reflected-xss | report- uri | report-to | require-sri-for | sandbox | script-src | script-src- attr | script-src-elem | style-src | style-src-attr | style-src-elem | upgrade-insecure-requests | worker-src |
Source List |
Sumber konten yang akan digunakan |
Hosts | Keywords | Data | Hashes | Nonces |
Directives pada CSP berfungsi sebagai penentu kebijakan yang akan diterapkan. Contoh, kita ingin menerapkan directive script-src, maka artinya kita akan menentukan script yang bersumber dari mana saja yang akan diizinkan untuk dieksekusi. Perlu diperhatikan bahwa directive default-src wajib ada dalam konfigurasi CSP untuk menyesuaikan dengan kompatibilitas browser karena masih ada beberapa browser yang mungkin belum mendukung directive tersebut. Misal, jika browser tidak mendukung directive object src, maka kebijakan sumber konten akan ditentukan oleh directive default-src. Atau jika object-src tidak dideklarasikan pada CSP, maka konten yang terkait dengan object seperti tag HTML sejenisnya, kebijakannya akan dikembalikan pada default-src. Namun perlu digarisbawahi bahwa tidak semua directive akan dikembalikan kepada default-src. Selanjutnya, directive pada CSP harus diikuti dengan source list karena di sinilah ditentukan sumber-sumber konten yang akan diizinkan.
a. Macam-macam Directive pada CSP dan Penjelasannya
Directive | Penjelasan | Level CSP | Browser Support |
base-uri |
Mendefinisikan satu set URL yang diizinkan yang dapat digunakan dalam atribut src dari tag dasar HTML. |
Level 2 |
Chrome 40+ | Edge 15+ |
default-src |
Mendefinisikan kebijakan default untuk mengambil assets atau resource seperti javascript, gambar, CSS, font, AJAX request, frame, dan Media HTML5. |
Level 1 |
Chr ome 25+ | Mozilla 23+ | Safari 7+ | Edge 12+ |
script-src |
Mendefinisikan sumber yang valid untuk javascript. |
Level 1 |
Chrome 25+ | Mozilla 23+ | Safari 7+ | Edge 12+ |
style-src |
Mendefinisikan sumber yang valid untuk stylesheet atau CSS. |
Level 1 |
Chrome 25+ | Mozilla 23+ | Safari 7+ | Edge 12+ |
img-src |
Mendefinisikan sumber yang valid untuk gambar. |
Level 1 |
Chrome 25+ | Mozilla 23+ | Safari 7+ | Edge 12+ |
connect-src |
Digunakan untuk manajemen request seperti XMLHttpRequest (AJAX), websocket, fetch(), atau EventSource. |
Level 1 |
Chrome 25+ | Mozilla 23+ | Safari 7+ | Edge 12+ |
font-src |
Mendefinisikan sumber font style (gaya huruf) yang akan dimuat. |
Level 1 |
Chrome 25+ | Mozilla 23+ | Safari 7+ | Edge 12+ |
object-src |
Mendefinisikan sumber yang valid untuk plugin seperti atau
|
Level 1 |
Chrome 25+ | Mozilla 23+ | Safari 7+ | Edge 12+ |
media-src |
Mendefinisikan sumber yang valid untuk audio dan video. |
Level 1 |
Chrome 25+ | Mozilla 23+ | Safari 7+ | Edge 12+ |
frame-src |
Mendefinisikan sumber yang valid untuk memuat frame. Directive ini tidak digunakan lagi pada CSP versi 2. Gunakan child-src sebagai gantinya. Namun pada CSP 3 bisa digunakan kembali. |
Level 1 |
- |
child-src |
Mendefinisikan sumber yang valid untuk workers dan nested browsing context yang dimuat menggunakan frame dan iframe |
Level 2 |
Chrome 40+ | Mozilla 45+ | Safari 15+ |
worker-src |
Mendefinisikan sumber yang valid untuk mengeksekusi Worker, Sharedworker atau ServiceWorker. |
Level 3 |
Chrome 59+ | Mozilla 58+ |
prefetch-src |
Menentukan sumber yang valid untuk permitaan prefetch dan prerendering, misalnya melalui tag tautan dengan rel="prefetch" atau rel="prerender": |
Level 3 |
|
sandbox |
Mengaktifkan sandbox untuk resource yang diminta. Semua akan dibatasi jika sandbox tidak diikuti dengan value. Value yang berlaku untuk sandbox: allow-forms allow-same-origin allow-scripts allow-popups, allow-modals, allow-orientation-lock, allow-pointer-lock, allow-presentation, allow-popups-to-escape-sandbox, and allow-top-navigation. |
Level 1 |
Chrome 25+ | Mozilla 50+ | Safari 7+ | Edge 12+ |
report-uri |
Directive ini harus diikuti dengan value berupa URL lokasi untuk melaporkan pelanggaran kebijakan. Directive ini akan menginstruksikan browser untuk mengirim laporan pelanggaran kebijakan ke URI yang telah ditentukan. Anda juga dapat menggunakan Content-Security-Policy-Report-Only sebagai Header Name untuk menginstruksikan browser agar hanya mengirim laporan (tidak memblokir apa pun). Directive ini tidak digunakan lagi di CSP Level 3 dan digantikan dengan direktif report-to. |
Level 1 |
Chrome 25+ | Mozilla 23+ | Safari 7+ | Edge 12+ |
frame-ancestors |
Mendefinisikan sumber yang valid untuk menyematkan resource menggunakan iframe Jika value 'none' sama dengan penerapan HTTP Header dengan X-Frame-Options: DENY. Artinya, website tidak diizinkan menggunakan tag-tag yang disebutkan di atas. Directive ini dinilai lebih aman dari pada menggunakan HTTP Header X-Frame-Options |
Level 2 |
Chrome 39+ | Mozilla 33+ | Edge 15+ |
form-action |
Mendefinisikan sumber valid yang dapat digunakan sebagai action dari tag form HTML. |
Level 2 |
Chrome 40+ | Mozilla 36+ | Edge 15+ |
plugin-types |
Mendefinisikan tipe MIME yang valid untuk plugin yang dipanggil melalui kita harus menentukan application/x-java-applet. |
Level 2 |
Chrome 40+ | Edge 15+ |
navigate-to |
Membatasi URL yang dapat dinavigasi oleh dokumen dengan cara apa pun. Misalnya ketika tautan diklik, formulir dikirimkan, atau window.location dipanggil. Jika form-action ada, maka directive ini diabaikan untuk pengiriman formulir. |
Level 3 |
|
block-all-mixed-content |
Mencegah browser memuat aset apa pun menggunakan protokol http saat halaman dimuat menggunakan protokol https. Directive ini sebaiknya tidak digunakan lagi. |
Level 1 |
Chrome | Edge 79+ | Mozilla 48+ |
disown-opener |
Mencegah navigasi ke website lain saat jendela baru pada browser dibuka. |
Level 3 |
|
referrer |
Mengontrol informasi yang disajikan di header referrer. Directive ini sebaiknya tidak digunakan lagi. |
Level 1 |
|
reflected-xss |
Directive ini sebaiknya tidak digunakan lagi. |
Level 1 |
|
report-to |
Token yang mendefinisikan report group tempat laporan dikirim jika ada pelanggaran kebijakan. |
Level 3 |
Chrome 70+ | Edge 79+ |
require-sri-for |
Directive ini sebaiknya tidak digunakan lagi. |
Level 1 |
Chrome 54+ | Edge 79+ |
script-src-attr |
Mendefinisikan sumber yang valid untuk event handler inline javascript. |
Level 3 |
Chrome 75 | Edge 79 |
script-src-attr |
Mendefinisikan sumber yang valid untuk event handler inline javascript. |
Level 3 |
Chrome 75 | Edge 79 |
script-src-elem |
Mendefinisikan sumber yang valid untuk elemen script javascript. |
Level 3 |
Chrome 75 | Edge 79 |
style-src-attr |
Mendefinisikan sumber yang valid untuk inline stylesheet (CSS). |
Level 3 | Chrome 75 | Edge 79 |
style-src-elem |
Mendefinisikan sumber yang valid untuk elemen style dan link dengan atribut rel=”stylesheet” |
Level 3 | Chrome 75 | Edge 79 |
upgrade-insecure-requests; |
Memaksa broser untuk meningkatkan permintaan http apa pun ke https saat halaman dimuat melalui https. |
Level 1 |
Chrome 43 | Edge 17 | Mozilla 42 | Safari 10.1 |
Directive | Penjelasan | Level CSP | Browser Support |
b. Referensi Source List
Semua arahan yang diakhiri dengan -src mendukung nilai serupa yang dikenal sebagai source list. Beberapa nilai source list dapat dipisahkan spasi dengan pengecualian 'none' yang seharusnya menjadi satu-satunya value.
Source Value | Example | Description |
* |
img-src * |
Mengizinkan URL apa pun kecuali skema data: blob: filesystem:. |
'none' |
object-src 'none' |
Mencegah memuat resource berupa objek yang dimuat oleh object, frame, dan applet dari sumber apa pun. |
'self' |
script-src 'self' |
Memungkinkan memuat resource dari asal yang sama (skema, host, dan port yang sama). |
data: |
img-src 'self' data: |
Memungkinkan memuat resource melalui skema data: (misalnya gambar yang di-encode ke dalam Base64). |
domain.example.com |
img-src domain.example.com |
Memungkinkan memuat resource dari nama domain yang ditentukan. |
*.example.com |
img-src *.example.com |
Mengizinkan memuat resource dari subdomain mana pun di bawah example.com. |
https://cdn.com |
img-src https://cdn.com |
Mengizinkan memuat sumber daya hanya melalui HTTPS yang cocok dengan domain yang diberikan. |
https: |
img-src https: |
Mengizinkan memuat sumber daya hanya melalui HTTPS di domain apa pun. |
'unsafe-inline' |
script-src 'unsafe-inline' |
Mengizinkan penggunaan elemen inline source seperti style attribute, onclick, atau script tag bodies (bergantung pada konteks sumber yang menerapkannya) dan javascript: URI |
'unsafe-eval' |
script-src 'unsafe-eval' |
Mengizinkan evaluasi kode dinamis yang tidak aman seperti javascript eval() |
'sha256-' |
script-src 'sha256-xyz...' |
Mengizinkan inline script atau CSS untuk dieksekusi jika hash-nya cocok dengan hash yang ditentukan di header. Saat ini mendukung SHA256, SHA384 atau SHA512. Akan dibahas selanjutnya. CSP Level 2 |
'nonce-' |
script-src 'nonce-r@nd0m' |
Mengizinkan inline script atau CSS untuk dijalankan jika skrip (misalnya: <script nonce="r@nd0m">) tag berisi atribut nonce yang cocok dengan nonce yang ditentukan di header CSP. Nonce harus berupa string acak yang aman, dan tidak boleh digunakan kembali. CSP Level 2 |
'strict-dynamic' |
script-src 'strict-dynamic' |
Mengaktifkan skrip yang diizinkan untuk memuat skrip tambahan melalui elemen skrip non-"parser-inserted" (misalnya document.createElement('script'); diperbolehkan). CSP Level 3 |
'unsafe-hashes' |
script-src 'unsafe-hashes' 'sha256-abc...' |
Memungkinkan kita untuk mengaktifkan skrip pada event handler (misalnya onclick). Tidak berlaku untuk javascript: atau script . sebaris CSP Level 3 |
B. IMPLEMENTASI CONTENT SECURITY POLICY
1. Contoh Konfigurasi Dasar dan Sederhana
Contoh konfigurasi CSP pada Nginx.
add_header Content-Security-Policy "default-src 'self' https://cdn.bootstrap.com;\
script-src 'self' https://cdn.bootstrap.com; style-src 'self' \
https://cdn.bootstrap.com; img-src 'self';";
Contoh konfigurasi CSP pada Apache.
Header set Content-Security-Policy "default-src 'self' https://cdn.bootstrap.com;\
script-src 'self' https://cdn.bootstrap.com; style-src 'self'\
https://cdn.bootstrap.com; img-src 'self';";
Contoh konfigurasi CSP dengan <meta> tag HTML.
meta http-equiv="Content-Security-Policy" content="default-src 'self' https://cdn.bootstrap.com;; script-src 'self' https://cdn.bootstrap.com; style-src 'self' https://cdn.bootstrap.com; img-src 'self';"
Contoh konfigurasi CSP pada pemrograman PHP.
<?php
header("Content-Security-Policy: default-src 'self' https://cdn.bootstrap.com;; script-src 'self' https://cdn.bootstrap.com; style-src 'self' https://cdn.bootstrap.com; img-src 'self';");
?>
Konfigurasi di atas akan menghasilkan kebijakan konten sebagai berikut:
- default-src ‘self’ https://cdn.bootstrap.com artinya konten dan resource yang ditampilkan berupa gambar, font style, css, koneksi, media, objek hanya yang berasal dari website kita sendiri dan https://cdn.bootstrap.com.
- script-src ‘self’ https://cdn.bootstrap.com; artinya konten dan resource yang ditampilkan berupa javascript hanya yang berasal dari website kita sendiri dan https://cdn.bootstrap.com. Jika directive ini tidak dideklarasikan, maka kebijakan akan dikembalikan pada directive default-src.
- style-src ‘self’ https://cdn.bootstrap.com; artinya konten dan resource yang ditampilkan berupa CSS hanya yang berasal dari website kita sendiri dan https://cdn.bootstrap.com. Jika directive ini tidak dideklarasikan, maka kebijakan akan dikembalikan pada directive default-src.
- img-src ‘self’ artinya konten dan resource yang ditampilkan berupa gambar hanya yang berasal dari website kita sendiri. Jika directive ini tidak dideklarasikan, maka kebijakan akan dikembalikan pada directive default-src.
2. Penerapan Source dengan Skema (Scheme)
add_header Content-Security-Policy "default-src 'self' \
https://cdn.bootstrap.com; script-src 'self' https://cdn.bootstrap.com; \
style-src 'self' https://cdn.bootstrap.com; img-src 'self' data:; \
object-src 'self' blob:;";
Konfigurasi di atas akan menghasilkan kebijakan konten sebagai berikut:
- default-src ‘self’ https://cdn.bootstrap.com; artinya konten dan resource yang ditampilkan berupa gambar, font style, css, koneksi, media, objek hanya yang berasal dari website kita sendiri dan https://cdn.bootstrap.com.
- script-src ‘self’ https://cdn.bootstrap.com; artinya konten dan resource yang ditampilkan berupa javascript hanya yang berasal dari website kita sendiri dan https://cdn.bootstrap.com. Jika directive ini tidak dideklarasikan, maka kebijakan akan dikembalikan pada directive default-src.
- style-src ‘self’ https://cdn.bootstrap.com; artinya konten dan resource yang ditampilkan berupa CSS hanya yang berasal dari website kita sendiri dan https://cdn.bootstrap.com. Jika directive ini tidak dideklarasikan, maka kebijakan akan dikembalikan pada directive default-src.
- img-src ‘self’ data: artinya konten dan resource yang ditampilkan berupa gambar hanya yang berasal dari website kita sendir dan mengizinkan memuat gambar yang di-encoding dengan base64() seperti format data:image/webp;base64,/b4s364ImAgeEnc0dinG==. Jika directive ini tidak dideklarasikan, maka kebijakan akan dikembalikan pada directive default-src.
- object-src ‘self’ blob: artinya konten dan resource yang ditampilkan berupa object baik itu yang dimuat dengan frame, object, atau applet harus bersumber dari website kita sendiri dan mengizinkan tipe data object dengan bentuk blob. Seperti blob:https://website.com/123-45jhjfg-123btnbg1-345345.
3. Penerapan Hash dan Nonce
Jika ada penerapan inline script atau inline style pada website kita, kita harus menyertakan ‘unsafe-inline’ pada directive script-src atau style-src. Namun cara demikian menyebabkan kemanan website kita akan lebih rentan terhadap serangan. Sebagai alternatifnya, CSP menyediakan fitur nonce atau hash. Nonce adalah karakter acak sekali pakai berbentuk base64 yang digunakan pada tag script atau style dan nonce tersebut nantinya didaftarkan pada Rule CSP. Sedangkan hash adalah hasil hashing dari inline script tanpa menyertakan tag script atau style.
Gambar 3 – Penerapan Inline Script yang ditolak oleh browser karena Konfigurasi CSP
Ketika ‘unsafe-inline’ tidak diterapkan pada CSP sedangkan website anda menggunakan inline style atau inline script, maka pada console browser akan tampil error seperti di atas. Pada console akan ditampilan nilai hash dari script yang diblokir atau saran menggunakan nonce.
Misal, website kita menerapkan inline script sebagai berikut.
// Without nonce
<\script\>
alert(‘Hello World’);
<\/script\>
Solusinya menambahkan atribut nonce pada tag script.
<\script nonce=”s0m3sTrin9rAndomEx4mplE”\>
alert(‘Hello World’);
<\/script\>
Kemudian menambahkan nonce value tersebut pada rule CSP kita.
Content-Security-Policy: "default-src 'self'; script-src 'self' \
‘nonce-s0m3sTrin9rAndomEx4mplE’;
Atau cara kedua adalah membuat hash dari script di atas. Dalam modul ini saya menggunakan fitur script and style hasher pada website https://report-uri.com/. Salin script (tanpa menyertakan tag script) lalu paste pada form yang telah disediakan kemudian klik tombol hash.
Gambar 4 – Script and Style Hasher
Nilai hash akan muncul dan sertakan nilai hash tersebut pada rule CSP yang akan kita buat.
Content-Security-Policy: "default-src 'self'; script-src 'self' \
'sha256-DUTqIDSUj1HagrQbSjhJtiykfXxVQ74BanobipgodCo=';
Untuk menjalankan script pada event hanlders seperti script pada atribut onclick, selain menambahkan nilai hash-nya, kita harus menambahkan ‘unsafe-hashes’ pada rule CSP. Contohnya sebagai berikut.
<\button type=”button” onclick=”jsFunction()”\>
CSP rule-nya adalah sebagai berikut.
Content-Security-Policy: "default-src 'self'; script-src 'self' 'unsafe-hashes' \
'sha256-DUTqIDSUj1HagrQbSjhJtiykfXxVQ74BanobipgodCo=';
Yang perlu diperhatikan ketika kita memilih untuk menggunakan nonce, nonce yang diterapkan haruslah bersifat dinamis, bukan statis. Nonce harus berubah setiap halaman dimuat ulang karena, jika nonce tidak berubah-ubah, peretas dapat melakukan bypass terhadap rule CSP yang kita buat. Adapun syarat-syarat lainnya sebagai berikut:
- Nonce harus unik untuk setiap HTTP Response
- Nonce harus dibuat menggunakan generator acak yang aman secara kriptografis
- Nonce harus memiliki panjang yang cukup, bertujuan untuk setidaknya 128 bit entropi (32 karakter hex, atau sekitar 24 karakter base64).
- Tag skrip yang memiliki atribut nonce tidak boleh memiliki variabel tidak tepercaya/tidak lolos di dalamnya. Artinya harus terdaftar di CSP rule.
Untuk lebih lengkapnya tentang penerapan dynamic noce bisa dilihat pada link berikut.
- Generate a nonce with Apache 2.4 (for a Content Security Policy header) - Stack Overflow
- CSP Nonce support in Nginx
4. Penerapan Directive report-uri dan Konfigurasi URI Reporting pada Website report-uri.com
Pada CSP terdapat fitur reprot-uri dan report-to yang berfungsi untuk melaporkan pelanggaran terhadap CSP. Directive report-uri akan diikuti oleh URL di maka laporan akan dikirim oleh server jika terjadi pelanggaran. Sedangkan report-to diikuti nama grup URL pelaporan yang telah didefinisikan sebelumnya pada HTTP Header Report-To.
Penggunaan report-uri pada CSP.
Content-Security-Policy: "default-src 'self'; script-src 'self' 'unsafe-hashes' \
'sha256-DUTqIDSUj1HagrQbSjhJtiykfXxVQ74BanobipgodCo='; \
report-uri https://report.location.tld;
Penggunaan report-to pada CSP.
Report-To: {"group":"default","max_age":10886400,"endpoints":[{"url":"https://report.location.tld"}],"include_subdomains":true}
Content-Security-Policy: "default-src 'self'; script-src 'self' 'unsafe-hashes' 'sha256-DUTqIDSUj1HagrQbSjhJtiykfXxVQ74BanobipgodCo='; report-uri https://report.location.tld; report-to delfault;
Untuk mendapatkan URI Reporting, kita bisa mendaftar secara gratis pada website Report URI: Register (report-uri.com). Setelah itu, kita akan mendapatkan link verifikasi pada email kita. Klik link yang dikirimkan untuk menyelesaikan proses registrasi.
Gambar 6 – Halaman Registrasi Report URI
Setelah proses registrasi selesai, silakan login pada halaman berikut: Report URI: Login (report-uri.com).
Gambar 7 – Tampilan Halaman Login Report URI
Gambar 8 - Tampilan Dashboard Report URI
Klik icon CUSTOMISE pada Dashboard kemudian website akan mengarahkan kita pada halaman setup. Pada halaman ini kita bisa melakukan kustomisasi URI Reporting dan mendapatkan Reporting API.
Gambar 9 – Halaman Setup Report URI
5. Analisa Security Header dan CSP Scanner
Kita bisa menganalisa hasil dari konfigurasi HTTP Header dan CSP kita melalui website https://securityheaders.com atau dengan extension CSP Scanner pada browser Chrome dan Edge.
Gambar 10 – Hasil Analisa HTTP Header terhadap Website https://govcsirt.tangerangkota.go.id
Gambar 11 – Hasil Analisa CSP Header terhadap Website https://govcsirt.tangerangkota.go.id
Gambar 12 – Peringatan Kelemahan Konfigurasi yang Mungkin Bisa diperbaiki pada Website https://govcsirt.tangerangkota.go.id
Gambar 13 – Hasil Analisa CSP Header terhadap Website https://govcsirt.tangerangkota.go.id Menggunakan Extension CSPScanner pada Browser Ms. Edge.
Gambar 14 – Warning pada Konfigurasi CSP dari Website https://govcsirt.tangerangkota.go.id yang mungkin bisa diperbaiki.
Post Terkait
Trending
Bug Zero Day Terbaru pada Browser Chrome. Update Browsermu Segera!
Muhammad Ridwan Na'im 07 April 2022 - 21:31:47 WIB
Lima Ancaman Keamanan Jaringan Dan Cara Mengamankannya
Muhammad Ridwan Na'im 27 September 2022 - 12:07:37 WIB