Pengetahuan dasar tentang keamanan situs

Halo, Habr!

Keamanan adalah masalah serius. Dan seringkali masalah di bidang ini muncul secara tak terduga dan memiliki konsekuensi yang sangat tidak menyenangkan. Oleh karena itu, pengetahuan dalam topik ini sangat penting untuk setiap pengembang web.

Saya akan segera memesan - Saya jauh dari profesional, tetapi saya berusaha keras untuk ini. Karena itu, saya akan senang mengkritik, tetapi hanya objektif. Materi ini untuk pemula yang ingin meningkatkan profesionalisme dan nilai mereka sebagai spesialis.

Namun, saya menunjukkan implementasi kode sesederhana mungkin. Saya tahu tentang pengecualian, saya tahu tentang ORM, tentang perlindungan yang disediakan dalam kerangka kerja. Tujuan saya adalah menunjukkannya dengan jelas sehingga semua orang mengerti.

Jadi, inilah saatnya untuk menyelesaikan dengan pendahuluan dan mulai berlatih.

Jalur dari implementasi seorang pemula ke hasil yang waras


Saya tidak terbiasa bekerja dengan teori. Jiwaku merindukan latihan. Karena itu, berbicara tentang topik keamanan, kami akan mempertimbangkan hampir semua jenis serangan dari sudut pandang praktis - bagaimana menerapkan dan bagaimana mempertahankan diri. Ya, Anda dapat mengatakan bahwa mengajarkan peretasan itu tidak baik, tetapi, tidak tahu bagaimana serangan itu terjadi, kami tidak dapat membangun pertahanan yang kompeten.

Xss


Oke, tipe serangan pertama adalah XSS. Ya, XSS tua yang bagus yang semua orang pernah dengar. XSS (Cross Site Scripting) adalah jenis serangan yang menargetkan pengunjung situs. Bagaimana ini terjadi: melalui bidang input, penyerang menulis kode berbahaya yang memasuki database dan melakukan tugasnya. Biasanya dengan cara ini, cookie dicuri dari pengguna, yang memungkinkan mereka untuk masuk ke akun mereka tanpa kata sandi dan login.

Kami menerapkan contoh yang lebih tidak berbahaya.

Pengembang kami membuat formulir sederhana untuk menambahkan komentar:

File index.php
<?php $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; $pdo = new PDO("mysql:host=localhost;dbname=".$db,$user,$pass,$opt); $pdo->exec("SET CHARSET utf8"); $query = $pdo->prepare("SELECT * FROM `comments`"); $query->execute(); $comments = $query->fetchAll(); if ($_POST) { $username = trim($_POST['name']); $comment = trim($_POST['comment']); $query = $pdo->prepare("INSERT INTO `comments` (`username`,`message`) VALUES ('$username', '$comment')"); $query->execute(); if ($query) { echo ' !'; header("Location: index.php"); } else { echo ' !'; } } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>XSS</title> </head> <body> <form method="POST" class="addComment"> <input type="text" name="name" placeholder="Username"> <textarea name="comment"></textarea> <input type="submit" value=" "> </form> <div class="h2"></div> <div class="comments"> <?php if ($comments): foreach ($comments as $comment):?> <div class="comment"> <div class="comment_username"><?php echo $comment['username'];?></div> <div lass="comment_comment"><?php echo $comment['message'];?></div> </div> <?php endforeach;?> <?php else:?> <div class="no_comments"> </div> <?php endif;?> </div> </body> </html> 

Kode ini sangat sederhana dan tidak perlu penjelasan.

Ada penyusup - John. John menjadi bosan dan menemukan situs pengembang kami.
John menulis pesan berikut di formulir:

 <script>document.body.style.backgroundColor = "#000";</script> 

Dan sekarang semua pengguna situs memiliki latar belakang hitam. John puas, dan pengembang mendapatkan pengalaman dan teguran.

Apa yang terjadi?

John menambahkan komentar dengan kode JavaScript. Saat mengeluarkan data ke halaman, komentar teks dikonversi ke kode html. Kode html, melihat penggunaan tag skrip, menambahkannya ke markup, dan penerjemah sudah mengeksekusi kode JavaScript. Artinya, John baru saja menambahkan sepotong kode js ke kode situs yang ada.

Bagaimana kita memperbaikinya?

Untuk memperbaiki kesalahpahaman ini, fungsi htmlspecialcars dibuat. Inti dari karyanya adalah dia mengganti karakter seperti tanda kutip dan tanda kurung dengan karakter khusus. Misalnya, karakter "<" akan diganti dengan kode karakter yang sesuai. Dengan fungsi ini, kami memproses data dari formulir dan sekarang kode js John tidak lagi dapat membahayakan situs kami. Tentu saja, jika ini adalah satu-satunya formulir di situs.

Perubahan kode akan terlihat seperti ini:

File index.php
 <?php if ($_POST) { $username = htmlspecialchars(trim($_POST['name'])); $comment = htmlspecialchars(trim($_POST['comment'])); /// } 


Injeksi SQL


Jenis serangan lain yang paling umum, yang sudah mulai dilupakan. Mereka melupakannya karena ada pertanyaan dan kerangka kerja yang disiapkan.

Kami akan berbicara tentang permintaan yang disiapkan.

Apa inti dari serangan itu: penyerang memasuki bagian dari permintaan SQL ke dalam bidang input dan mengirimkan formulir. Selama eksekusi permintaan, data yang diterima ditambahkan ke database. Tetapi karena kode tersebut berisi kode tersebut, saat menambahkan catatan, ia memodifikasi logika skrip kami.

Oke, simulasikan sebuah situasi. Pengembang kami telah melindungi formulir dari serangan XSS. Dan John terus menggunakan pengetahuannya, menunjukkan kelemahan pengembang kesedihan.

Artinya, kami akan terus bekerja dengan formulir yang sama untuk menambahkan komentar.
Mari kita lakukan beberapa perubahan:

1) Pre-moderasi komentar.

Intinya adalah hanya komentar-komentar yang disetujui moderator akan ditampilkan pada halaman. Kami menerapkan pra-moderasi dalam bentuk yang paling sederhana agar tidak terganggu dari bagian utama artikel.

Untuk mengimplementasikan ide, tambahkan bidang "is_moderate" ke tabel dengan komentar, yang akan mengambil dua nilai - "1" (tampilkan komentar) atau "0" (jangan tampilkan). Secara default, tentu saja, "0".

2) Ubah permintaan.

Ini untuk kejelasan. Biarkan permintaan untuk menambahkan komentar terlihat seperti ini:

 "INSERT INTO `comments` SET `username`='$username', `message`='$comment'" 

Sekarang kode form adalah sebagai berikut:

File index.php
 <?php $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; $pdo = new PDO("mysql:host=localhost;dbname=".$db,$user,$pass,$opt); $pdo->exec("SET CHARSET utf8"); $query = $pdo->prepare("SELECT * FROM `comments` WHERE `is_moderate`='1'"); $query->execute(); $comments = $query->fetchAll(); if ($_POST) { $username = htmlspecialchars(trim($_POST['name'])); $comment = htmlspecialchars(trim($_POST['comment'])); $query = $pdo->prepare("INSERT INTO `comments` SET `username`='$username', `message`='$comment'"); $query->execute(); if ($query) { echo ' !'; } else { echo ' !'; } } ?> 


Oke, John masuk ke situs dan, melihat bahwa komentar mulai dimoderasi, ia memutuskan untuk mengejek pengembang. Selain itu, bentuk serangan XSS sekarang berhasil mencerminkan dan John telah kehilangan kesempatan untuk bersenang-senang. Dia meninggalkan komentar jenis ini: "LOL ', is_moderate =' 1" dan melewati moderasi.

Mengapa

Saat Anda mengganti komentar John dalam kueri kami, tanda kutip pecah. Artinya, seperti yang disebutkan di atas, John mampu mengeksekusi kode SQL sewenang-wenang.

Saat menjalankan permintaan dengan komentar John, permintaannya adalah sebagai berikut:

 "INSERT INTO `comments` SET `username`='John', `message`='LOL', `is_moderate`='1'" 

Selain itu, SQL Injection dapat diimplementasikan tidak hanya ketika mengirimkan formulir. Ini juga bisa terjadi ketika menerima catatan oleh pengidentifikasi mereka, memproses formulir pencarian, dan situasi lain yang tidak begitu jelas.

Bagaimana cara memperbaikinya?

Metode untuk memecahkan masalah telah dikenal sejak lama untuk pertanyaan yang disiapkan. Permintaan yang disiapkan adalah permintaan yang menjalani pemrosesan khusus sebelum dieksekusi. Pemrosesan terdiri dari menghindari tanda kutip tambahan. Anda pasti sudah mendengar fitur seperti itu. Dalam PHP, ini diterapkan seperti ini: "\ '".

Solusi paling populer adalah PDO. PDO adalah antarmuka untuk bekerja dengan database. Apa yang memiliki antarmuka yang cukup nyaman. Hanya gunakan dengan bijak.

PDO menyediakan kemampuan untuk menggunakan masker dan placeholder untuk mengimplementasikan permintaan yang disiapkan.

Maka permintaan kami saat menggunakan topeng akan terlihat seperti ini:

File index.php
 <?php $query = $pdo->prepare("INSERT INTO `comments` SET `username`=:username, `message`=:comment"); $params = ['username' => $username,'comment' => $comment]; $query->execute($params); 


Dan saat menggunakan placeholder seperti ini:

File index.php
 <?php $query = $pdo->prepare("INSERT INTO `comments` SET `username`=?, `message`=?"); $params = [$username,$comment]; $query->execute($params); 


Sekarang serangan John tidak lagi relevan. Setidaknya untuk formulir ini.

Omong-omong, moderasi kita, bahkan dalam bentuk ini, sudah melindungi terhadap jenis serangan lain - SPAM. Kami semua mendengar tentang dia. SPAM adalah pengiriman pesan apa pun di mana, dengan bantuan pengetahuan teknik sosial, penyerang melakukan serangan mereka. Sekarang satu-satunya yang akan diserang adalah moderator. Dan kemudian, jika dia tidak sebodoh itu, maka dia akan menghapus sampah dari basis data, atau jika dia malas, dia akan menolak publikasi dan hanya itu.

Serangan CSRF


CSRF - Pemalsuan Permintaan Lintas Situs. Ini berbahaya karena hanya sedikit orang yang tahu. Meskipun untuk melakukan ini cukup sederhana.

Bagaimana ini terjadi: seorang penyerang dari situs lain memalsukan formulir dan memaksa korban untuk mengikuti formulir ini. Yaitu, permintaan POST dikirim. Dengan demikian, permintaan HTTP dipalsukan dan tindakan jahat dilakukan di situs korban.

Misalnya, penyerang dapat mengirim surat kepada teman Anda di VK atas nama Anda, tetapi Anda tidak akan mengetahuinya.

Kedengarannya agak membingungkan. Saya mengusulkan untuk mempertimbangkan dalam praktik.

Pengembang kami membuat formulir, dia baik-baik saja. Dia sudah tahu bagaimana mempertahankan diri terhadap XSS, injeksi SQL dan menjaga tekanan Spam. Ini terlihat seperti ini:

File index.php di situs pengembang
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CSRF</title> </head> <body> <form action="action.php" method="POST"> <input type="text" name="username"> <textarea name="message"></textarea> <input type="submit" value=" "> </form> </body> </html> 


Tetapi Yohanes tidak sesederhana itu. Dia menerima kode formulir (hanya dari kode sumber situs di browser) dan menambahkan formulir ke situsnya.

File index.php John
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CSRF</title> <style> form input[type=submit]{ padding: 15px; font-size: 20px; color: #fff; background: #f00; cursor: pointer; } </style> </head> <body> <form action="localhost/note/action.php" method="POST"> <input type="hidden" name="username" value="lol"> <input type="hidden" name="message" value="  !   !"> <input type="submit" value=" !"> </form> </body> </html> 


Harap dicatat bahwa di situs web John, tempat di mana formulir diproses adalah file dari situs web pengembang kami. Jadi sekarang setiap pengguna yang mengklik tombol akan mengirimkan komentar yang tidak bagus.

Ini adalah serangan CSRF. Dalam versi yang paling sederhana, tentu saja.

Pengembang memiliki masalah lagi ...

Bagaimana cara memperbaiki kerentanan?

Pada satu titik, pengembang akan google apa csrf dan logika perlindungan akan menjadi sebagai berikut: untuk perlindungan, Anda perlu membuat token csrf (satu set huruf dan angka) dan menggantungnya di formulir. Juga perlu untuk memperbaiki token yang sama kepada pengguna (misalnya, melalui sesi). Dan kemudian, saat memproses formulir, bandingkan token ini. Jika cocok, kami dapat menambahkan komentar.

Kami menerapkan ini:

File index.php di situs pengembang
 <?php session_start(); $token = ''; if (function_exists('mcrypt_create_iv')) { $token = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); } else { $token = bin2hex(openssl_random_pseudo_bytes(32)); } $_SESSION['token'] = $token; ?> ... <form action="action.php" method="POST"> <input type="text" name="username"> <textarea name="message"></textarea> <input type="hidden" name="csrf_token" value="<?php echo $token;?>"> <input type="submit" value=" "> </form> 


File action.php
 <?php session_start(); if ($_POST) { if ($_SESSION['token'] == $_POST['csrf_token']) { echo ' !'; } else { echo '!'; } } 


Kata Sandi Brute Force dan Publick


Mungkin jenis serangan yang paling terkenal. Dia mendengar hampir setiap film pertama tentang peretas dan sejenisnya.

Apa intinya: ada formulir untuk otorisasi di panel admin situs. Kami membutuhkan nama pengguna dan kata sandi yang tidak diketahui John. Tetapi ia memiliki file dengan nama pengguna dan kata sandi populer. Dan dia dengan gembira berlari untuk mencobanya di situs kami.

Apa yang bisa ditentang pengembang? Misalnya, pembatasan jumlah upaya otorisasi dalam periode waktu tertentu.

Biarkan versi awal formulir otorisasi terlihat seperti ini:

File index.php
 <?php $opt = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]; $pdo = new PDO("mysql:host=localhost;dbname=".$db,$user,$pass,$opt); $pdo->exec("SET CHARSET utf8"); if (isset($_POST['autoriz'])) { $username = htmlspecialchars(trim($_POST['login'])); $password = htmlspecialchars(trim($_POST['password'])); $query = $pdo->prepare("SELECT * FROM `users` WHERE `username`=:username AND `password`=:password"); $query->execute(['username' => $username,'password' => $password]); $find_user = $query->fetchAll(); if ($find_user) { echo ' !'; } else { echo '  !'; } } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Brute Force  Public Passwords</title> </head> <body> <form method="POST"> <input type="text" name="login" placeholder="Login"> <input type="password" name="password" placeholder="Password"> <input type="submit" value="" name="autorize"> </form> </body> </html> 


Cara memperbaikinya: opsi paling sederhana, seperti yang telah disebutkan, adalah membatasi jumlah upaya otorisasi per periode waktu.

Untuk melakukan ini, ketika kami mencoba masuk, kami akan menambahkan nilai waktu saat ini kepada pengguna dalam cookie. Dan sekarang, ketika mencoba masuk, kita akan melihat bahwa pengguna dapat masuk tidak lebih dari 1 kali dalam 5 detik. Selain itu, jika kata sandi atau login tidak dimasukkan dengan benar, kami akan menambah batas waktu hingga upaya berikutnya 5 detik.

File index.php
 <?php $count_next_minit = $_COOKIE['count_try'] ? $_COOKIE['count_try'] : 1; $seconds_to_new_try = 5; $opt = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]; $pdo = new PDO("mysql:host=localhost;dbname=".$db,$user,$pass,$opt); $pdo->exec("SET CHARSET utf8"); if (isset($_POST['autorize'])) { if ($_COOKIE['last_try']) { if ($_COOKIE['last_try'] < time() - $seconds_to_new_try * $count_next_minit) { $username = htmlspecialchars(trim($_POST['login'])); $password = htmlspecialchars(trim($_POST['password'])); $query = $pdo->prepare("SELECT * FROM `users` WHERE `username`=:username AND `password`=:password"); $query->execute(['username'=>$username,'password'=>$password]); $find_user = $query->fetchAll(); setcookie('last_try', time(), time() + 3600); if ($_COOKIE['count_try']) { $old_value = (int)$_COOKIE['count_try']; setcookie('count_try', $old_value + 1, time() + 3600); } else { setcookie('count_try', 1, time() + 3600); } if ($find_user) { var_dump(' !'); } else { var_dump('  !'); } }else{ var_dump('   !    ' . $seconds_to_new_try * $count_next_minit . ' '); } }else{ setcookie('last_try', time(), time() + 3600); } } ?> 


Backtrace


Backtrace adalah cara menyerang melalui pesan kesalahan sistem. Ini adalah MySQL dan PHP.

Sebagai contoh, John memasukkan url yang salah dan diberi kesalahan mengatakan bahwa tidak ada catatan dalam database dengan id tersebut (jika catatan diterima melalui id dari bilah alamat - site.ru/article?id=12). Bahkan ada yang disebut "dorks" - pola spesifik dari alamat situs web, setelah memasuki mana pengguna melihat kesalahan. Dan ini membuka kemungkinan bagi John untuk menggunakan bot untuk melihat daftar alamat ini dan mencoba menemukan kerentanan ini di situs Anda.

Bagaimana cara memperbaikinya? Dalam hal ini, kita akan melakukan tanpa contoh, karena masalah diselesaikan hanya dengan menutup output kesalahan. Biasanya ini diimplementasikan oleh hosting, menyediakan Anda di panel admin untuk menulis log ke file yang terpisah, tetapi itu tidak akan berlebihan untuk membatasi output kesalahan sendiri.

Ini dapat dilakukan dengan menggunakan fungsi error_reporting ().

Di antara argumen yang dibutuhkan adalah: E_ERROR, E_WARNING, E_PARSE, E_NOTICE, E_ALL. Nama-nama berbicara sendiri.

Misalnya, jika Anda menggunakan error_reporting (E_NOTICE), maka semua kesalahan akan disembunyikan, kecuali untuk kesalahan dari jenis Pemberitahuan (peringatan, misalnya, bahwa tidak ada data dalam array $ _POST).
Untuk menonaktifkan output dari semua kesalahan (yang sebenarnya kita butuhkan), Anda perlu menggunakan fungsi ini sebagai berikut: error_reporting (0)

Kesalahan logis


Kesalahan logis adalah beberapa yang terburuk. Karena ini adalah kesalahan karena kecerobohan. Mereka muncul tiba-tiba, dan kadang-kadang kita bahkan tidak tahu di mana akar masalahnya. Ini adalah kesalahan dalam logika situs.

Sebagai contoh, Anda mungkin lupa memeriksa keberadaan data otorisasi di sesi dan cookie untuk salah satu halaman panel admin. Jadi mereka membuka akses ke halaman ini untuk setiap pengguna.

Dalam hal ini, hanya satu hal yang akan menyelamatkan Anda - saat menulis kode program, pikirkan bagaimana Anda dapat meretasnya.

DDOS


DOS adalah jenis serangan terhadap suatu teknik, khususnya komputer. Serangan itu bertujuan untuk menonaktifkan mesin karena kelebihan beban. DDOS hanya berbeda karena sejumlah besar komputer terlibat dalam serangan itu.

Artinya, John memanggil teman-temannya dan mereka bersama-sama mulai mengirim permintaan ke situs tersebut. Apa hubungan botnet dengan itu? Botnet adalah banyak komputer yang terinfeksi, kekhasannya adalah penyerang dapat mengontrol pekerjaan mereka sampai batas tertentu (memulai proses, dll.). Mereka mengirim begitu banyak permintaan sehingga server tidak dapat menahan beban dan, paling-paling, mulai bekerja sangat lambat, atau menolak untuk waktu yang tidak ditentukan.

Perlindungan dari serangan tersebut disediakan oleh tuan rumah sendiri, atau oleh layanan khusus seperti Cloudflare.

Cara kerja perlindungan: Layanan Cloudflare memberi Anda server DNS sendiri yang melaluinya lalu lintas akan berlalu. Itu disaring, melewati algoritma yang hanya diketahui oleh pemilik dan pengembang layanan. Dan setelah itu pengguna masuk ke situs Anda. Ya, tentu saja, ada operasi server, pembuatan halaman, dan yang lainnya, tetapi kita tidak membicarakannya sekarang.
Selain itu, berbicara tentang DDOS, orang tidak dapat gagal untuk menyebutkan pemblokiran alamat IP yang juga disediakan oleh Cloudflare.

Ya, semua ini tidak akan memberikan jaminan perlindungan 100%, tetapi terkadang akan meningkatkan peluang situs Anda tetap terapung pada saat serangan.

MITM


Man In The Middle adalah jenis serangan ketika seorang penyerang mencegat paket Anda dan menipu mereka. Kita semua mendengar bahwa data dikirimkan melalui jaringan dalam bentuk paket. Jadi, ketika menggunakan protokol http, data ditransmisikan dalam bentuk biasa, bukan dienkripsi.

Misalnya, Anda menulis "halo" ke teman, dan dia menerima "kirimi saya uang, ini dompetnya".

Untuk mengatasi masalah ini, protokol https dibuat. Saat menggunakannya, data akan dienkripsi dan John tidak akan dapat melakukan apa pun dengan lalu lintas yang diterima.
Dan untuk mendapatkan protokol https untuk situs tersebut, Anda perlu mendapatkan sertifikat SSL. Nah, atau TLS. Secara umum, TLS pada dasarnya adalah penerima SSL, karena didasarkan pada SSL 3.0. Tidak ada perbedaan signifikan dalam pekerjaan mereka.

Sertifikat SSL memberikan Cloudflare yang sama, dan gratis.

Pintu belakang


Sedikit lebih banyak teori. Untuk jenis serangan ini dapat diimplementasikan dalam banyak cara dan Anda hanya perlu memahami esensi. Backdoor adalah jenis serangan rahasia di mana skrip itu sendiri melakukan sesuatu di latar belakang. Paling sering, ini adalah plugin atau tema WordPress yang diunduh dari torrent. Plugin / tema itu sendiri akan bekerja dengan cukup memadai, tetapi bagian tertentu dari skrip ditambahkan ke kode plugin / tema diam-diam akan melakukan sesuatu. SPAM yang sama, misalnya. Ini adalah alasan untuk semua peringatan tentang undesirability mengunduh file dari torrent.

Kesimpulannya


Ya, tentu saja, ini bukan seluruh jajaran serangan. Tetapi pengetahuan ini sudah akan meningkatkan keamanan proyek Anda.

Source: https://habr.com/ru/post/id451420/


All Articles