Institut Teknologi Massachusetts. Kursus Kuliah # 6.858. "Keamanan sistem komputer." Nikolai Zeldovich, James Mickens. Tahun 2014
Keamanan Sistem Komputer adalah kursus tentang pengembangan dan implementasi sistem komputer yang aman. Ceramah mencakup model ancaman, serangan yang membahayakan keamanan, dan teknik keamanan berdasarkan pada karya ilmiah baru-baru ini. Topik meliputi keamanan sistem operasi (OS), fitur, manajemen aliran informasi, keamanan bahasa, protokol jaringan, keamanan perangkat keras, dan keamanan aplikasi web.
Kuliah 1: “Pendahuluan: model ancaman” 
Bagian 1 / 
Bagian 2 / 
Bagian 3Kuliah 2: "Kontrol serangan hacker" 
Bagian 1 / 
Bagian 2 / 
Bagian 3Kuliah 3: “Buffer Overflows: Exploits and Protection” 
Bagian 1 / 
Bagian 2 / 
Bagian 3Kuliah 4: “Pemisahan Hak Istimewa” 
Bagian 1 / 
Bagian 2 / 
Bagian 3 Jadi apa lagi yang kita miliki dalam daftar ini? Proses Memori adalah sesuatu yang terjadi bersamaan dengan prosesnya. Jadi, jika Anda tidak dalam proses ini, maka Anda tidak dapat mengakses memorinya. Memori virtual dengan sempurna meningkatkan isolasi ini bagi kami. Selain itu, mekanisme debug memungkinkan Anda untuk "pop" ke dalam memori proses lain, jika Anda memiliki ID pengguna yang sama
Selanjutnya kita memiliki jaringan. Jaringan di 
Unix tidak cukup sesuai dengan model yang dijelaskan di atas, sebagian karena fakta bahwa 
sistem operasi 
Unix pertama kali dikembangkan, dan kemudian sebuah jaringan muncul, yang segera menjadi populer. Ini memiliki seperangkat aturan yang sedikit berbeda. Oleh karena itu, operasi yang benar-benar perlu kita perhatikan adalah menghubungkan seseorang ke jaringan jika Anda mengelola jaringan, atau mendengarkan beberapa port jika Anda bertindak sebagai server. Anda mungkin perlu membaca atau menulis data pada koneksi ini, atau mengirim dan menerima paket 
mentah .

Dengan demikian, jaringan di 
Unix sebagian besar tidak terkait dengan 
userid . Aturannya adalah siapa pun dapat selalu terhubung ke mesin apa pun atau alamat IP apa pun atau membuka koneksi. Jika Anda ingin mendengarkan port, maka dalam hal ini ada satu perbedaan, yaitu sebagian besar pengguna dilarang mendengarkan port dengan angka di bawah "nilai ajaib" 1024. Pada prinsipnya, Anda dapat mendengarkan port tersebut, tetapi dalam hal ini Anda harus Jadilah pengguna khusus yang disebut 
"pengguna super" dengan 
uid = 0 .
Secara umum, di Unix ada konsep administrator, atau superuser, yang diwakili oleh pengidentifikasi uid = 0, yang dapat melewati hampir semua pemeriksaan ini, jadi jika Anda bekerja dengan hak root, Anda dapat membaca dan menulis file, mengubah hak akses ke sana. Sistem operasi akan memungkinkan Anda untuk melakukan ini karena menurutnya Anda harus memiliki semua hak istimewa. Dan Anda benar-benar membutuhkan hak istimewa untuk mendengarkan pada port dengan angka <1024. Apa pendapat Anda tentang pembatasan aneh seperti itu?
Pemirsa: ini mengidentifikasi nomor port tertentu untuk koneksi tertentu, misalnya, untuk 
http pada port 80.
Profesor: ya, secara default 
protokol HTTP menggunakan port 80. Di sisi lain, layanan lain dapat menggunakan port dengan angka lebih tinggi dari 1024, mengapa pembatasan ini diperlukan? Apa gunanya di sini?
Pemirsa: karena Anda tidak ingin ada orang yang secara tidak sengaja mendengarkan 
HTTP Anda.
Profesor: ya. Saya pikir alasannya adalah Anda dulu memiliki banyak pengguna di mesin yang sama. Mereka masuk dengan login mereka, meluncurkan aplikasi mereka, jadi Anda ingin memastikan bahwa beberapa pengguna acak, setelah masuk ke komputer, tidak akan bisa mendapatkan server web yang menjalankannya. Karena pengguna yang terhubung dari luar tidak tahu siapa yang bekerja di port ini, dan mereka hanya terhubung ke port 80. Jika saya ingin memasuki mesin ini dan memulai server web saya sendiri, maka saya hanya mentransfer semua lalu lintas server web ke mobil ini. Ini mungkin bukan rencana yang sangat baik, tetapi itu adalah cara subsistem jaringan Unix mencegah pengguna acak dari mengontrol layanan yang dikenal berjalan pada nomor port rendah ini. Itulah alasan pembatasan semacam itu.

Selain itu, dari sudut pandang membaca dan menulis data koneksi, jika Anda memiliki file deskriptor untuk soket tertentu, maka 
Unix akan memungkinkan Anda untuk membaca dan menulis data apa pun dalam 
koneksi TCP atau 
uTP ini . Dalam mengirim paket 
mentah , 
Unix berperilaku seperti paranoid, sehingga tidak akan membiarkan Anda mengirim paket sewenang-wenang melalui jaringan. Ini harus berada dalam konteks koneksi khusus, kecuali Anda memiliki 
root - hak dan Anda dapat melakukan apa pun yang Anda inginkan.
Jadi, satu pertanyaan menarik yang bisa Anda tanyakan adalah dari mana semua 
userid ini berasal?
Kita berbicara tentang proses memiliki 
userid atau 
groupid . Ketika Anda meluncurkan 
PS di komputer Anda, Anda pasti akan melihat serangkaian proses dengan nilai 
uid yang berbeda. Dari mana mereka berasal?
Kami membutuhkan mekanisme untuk memuat semua nilai 
userid ini. 
Unix memiliki beberapa panggilan sistem yang dirancang untuk ini. Oleh karena itu, untuk mem-bootstrap nilai pengenal ini, ada fungsi yang disebut 
setuid (uid) , sehingga Anda dapat menetapkan nomor 
uid dari beberapa proses saat ini ke nilai ini. Ini sebenarnya operasi berbahaya, seperti semua yang lain dalam tradisi 
Unix , karena Anda hanya dapat melakukan ini jika 
uid Anda 
= 0 . Bagaimanapun, seharusnya begitu.
Jadi, jika Anda adalah pengguna dengan hak root dan memiliki 
uid = 0 , maka Anda dapat memanggil 
setuid (uid) dan mengalihkan pengguna ke proses apa pun. Ada beberapa panggilan sistem serupa lainnya untuk menginisialisasi 
gid terkait proses: ini adalah 
setgid dan 
setgroups . Oleh karena itu, panggilan sistem ini memungkinkan Anda untuk mengonfigurasi hak istimewa proses.

Fakta bahwa proses Anda mendapatkan hak akses yang benar ketika Anda masuk ke mesin 
Unix tidak terjadi karena Anda memiliki 
ID yang sama dengan proses, karena sistem belum tahu siapa Anda. Sebaliknya, di 
Unix, ada semacam prosedur masuk ketika 
protokol SSH secure shell memulai proses untuk siapa saja yang terhubung ke komputer dan mencoba untuk mengotentikasi pengguna.
Jadi, pada awalnya proses login ini dimulai dengan 
uid = 0 untuk pengguna dengan hak root, dan kemudian, ketika ia menerima nama pengguna dan kata sandi tertentu, ia memeriksanya di database akunnya sendiri. Sebagai aturan, pada 
Unix, data ini disimpan dalam dua file: 
/ etc / password (karena alasan historis, kata sandi tidak lagi disimpan dalam file ini), dan dalam file 
/ etc / shadow , di mana kata sandi disimpan. Namun, ada tabel di file 
/ etc / password yang menampilkan setiap nama pengguna dalam sistem sebagai nilai integer.
Dengan demikian, nama pengguna Anda dipetakan ke integer tertentu di 
file / etc / password ini , dan kemudian proses login memeriksa apakah kata sandi Anda benar sesuai dengan file ini. Jika ia menemukan integer 
uid Anda , maka ia mengatur fungsi 
setuid ke nilai 
uid itu dan memulai shell dengan perintah 
exec (/ bin / sh) . Sekarang Anda dapat berinteraksi dengan shell, tetapi ia bekerja di bawah 
uid Anda, sehingga Anda tidak akan dapat menyebabkan kerusakan yang tidak disengaja pada mesin ini.
 Pemirsa: apakah
Pemirsa: apakah mungkin untuk memulai proses baru dengan 
uid = 0 jika 
uid Anda tidak benar-benar 0?
Profesor: jika Anda memiliki hak akses root, Anda dapat membatasi diri untuk 
uid lain, menurunkan otoritas Anda, tetapi dalam hal apa pun, Anda dapat membuat proses dengan hanya 
uid yang sama seperti milik Anda. Tetapi hal itu terjadi karena berbagai alasan Anda ingin meningkatkan hak istimewa Anda. Misalkan Anda perlu menginstal paket, yang Anda perlukan hak akses 
root .
Ada dua cara untuk mengatur hak istimewa di 
Unix . Satu yang telah kami sebutkan adalah deskriptor file. Jadi jika Anda benar-benar ingin meningkatkan hak istimewa Anda, maka Anda dapat berbicara dengan seseorang yang bekerja di bawah hak root dan memintanya untuk membuka file ini untuk Anda. Atau Anda perlu menginstal beberapa antarmuka baru, maka asisten ini membuka file untuk Anda dan mengembalikan deskriptor file kepada Anda menggunakan transfer 
fd . Ini adalah salah satu cara untuk meningkatkan hak istimewa Anda, tetapi itu tidak nyaman karena dalam beberapa kasus ada proses yang berjalan dengan sejumlah besar hak istimewa. Untuk ini, 
Unix memiliki mekanisme bermasalah yang cerdas namun sekaligus disebut 
"setuid binaries" . Mekanisme ini adalah executable reguler pada 
sistem file 
Unix , kecuali ketika Anda menjalankan 
exec pada 
setuid binary, misalnya, 
/ bin / su pada sebagian besar mesin, atau 
sudo , saat startup.
Sistem 
Unix yang khas memiliki banyak binari 
setuid . Perbedaannya adalah bahwa ketika Anda menjalankan salah satu dari binari ini, itu benar-benar mengalihkan 
userid dari proses ke pemilik biner ini. Mekanisme ini terasa aneh ketika Anda pertama kali melihatnya. Sebagai aturan, cara untuk menggunakannya adalah bahwa "biner" ini kemungkinan besar memiliki pemilik 
dari 0, karena Anda benar-benar ingin mengembalikan banyak hak istimewa.

Anda ingin mengembalikan hak pengguna super sehingga Anda dapat menjalankan perintah 
su ini, dan kernel, ketika Anda menjalankan biner ini, akan mengalihkan proses 
uid ke 0, sehingga program ini sekarang akan melakukan beberapa hal istimewa.
Pemirsa: jika Anda memiliki 
uid = 0 dan Anda mengubah 
uid dari semua binari 
setuid ini ke sesuatu selain 0, dapatkah Anda mengembalikan hak istimewa Anda?
Profesor: tidak, banyak proses tidak akan dapat mengembalikan hak istimewa ketika menurunkan tingkat akses, sehingga Anda mungkin terjebak di tempat ini. Mekanisme ini tidak terikat dengan 
uid = 0 . Seperti halnya pengguna sistem 
Unix , Anda dapat membuat file biner apa pun, membangun program, mengompilasinya, dan mengatur bit 
setuid ini ke program itu sendiri. Itu milik Anda, pengguna, ID pengguna Anda. Dan itu berarti bahwa siapa pun yang menjalankan program Anda akan menjalankan kode ini dengan ID pengguna Anda. Apakah ada masalah dengan ini? Apa yang perlu dilakukan?
Hadirin: yaitu, jika ada kesalahan dalam aplikasi Anda, bisakah seseorang melakukan sesuatu dengan itu, bertindak dengan hak istimewa Anda?
Profesor: benar, itu terjadi jika aplikasi saya "buggy", atau jika itu memungkinkan Anda untuk menjalankan semua yang Anda inginkan. Misalkan saya bisa menyalin shell sistem dan membuatnya 
setuid untuk saya, tetapi siapa pun dapat menjalankan shell ini di bawah akun saya. Ini mungkin bukan rencana tindakan terbaik. Tetapi mekanisme seperti itu tidak menimbulkan masalah, karena satu-satunya orang yang dapat mengatur bit 
setuid pada file biner adalah pemilik file ini. Anda, sebagai pemilik file, memiliki hak istimewa 
uid , sehingga Anda dapat mentransfer akun Anda ke orang lain, tetapi orang lain ini tidak akan dapat membuat biner 
setuid dengan 
userid Anda.
Bit setuid ini disimpan di sebelah bit izin ini, yaitu, di setiap 
inode ada juga bit 
setuid yang mengatakan apakah file yang dapat dieksekusi ini harus atau jika program beralih ke pemilik 
uid selama eksekusi.

Ternyata ini adalah mekanisme yang sangat rumit ketika digunakan dengan benar, dan karenanya, kernel mengimplementasikan program dengan benar. Sebenarnya, ini cukup mudah dilakukan, karena hanya satu pemeriksaan dilakukan: jika 
setuid ini ada, maka proses beralih ke 
uid . Ini sangat sederhana.
Tetapi menggunakannya dengan aman cukup sulit, karena, seperti yang baru saja ditunjukkan, jika program ini mengandung kesalahan atau melakukan sesuatu yang tidak terduga, maka Anda mendapatkan kemampuan untuk melakukan hal-hal yang sewenang-wenang di bawah 
uid = 0 atau di bawah 
uid lainnya. Di 
Unix, ketika Anda menjalankan program, Anda mewarisi banyak hal dari proses induk Anda.
Misalnya, Anda bisa melewatkan variabel lingkungan ke 
setuid binari. Faktanya adalah bahwa di 
Unix Anda dapat menentukan pustaka bersama yang digunakan untuk proses dengan menetapkan variabel lingkungan, dan binari 
setuid tidak peduli tentang pemfilteran variabel lingkungan ini.
Misalnya, Anda dapat menjalankan 
bin / su , tetapi menggunakan pustaka bersama untuk fungsi 
printf , sehingga 
printf Anda akan mulai ketika 
bin / su mencetak sesuatu, dan Anda dapat menjalankan shell alih-alih mencetakf.
Ada banyak seluk-beluk yang harus Anda pahami dengan benar tentang ketidakpercayaan program terhadap data yang dimasukkan pengguna. Karena Anda biasanya mempercayai input pengguna, 
setuid tidak pernah menjadi bagian teraman dari keseluruhan sistem 
Unix . Ada pertanyaan tentang ini?
Audiens: apakah 
setuid juga berlaku untuk grup atau hanya untuk pengguna?
Profesor: ada bit 
setgid yang simetris dengan bit 
setuid , yang bisa Anda atur juga. Jika file tersebut memiliki 
gid tertentu dan bit 
setgid ini diatur saat program dimulai, maka Anda akan mendapatkannya.
Setgid tidak digunakan secara khusus, tetapi dapat berguna dalam kasus di mana Anda ingin memberikan hak istimewa yang sangat spesifik. Sebagai contoh, 
bin / su mungkin membutuhkan banyak hak istimewa, tetapi mungkin ada beberapa program yang memerlukan sedikit hak istimewa tambahan, misalnya, untuk menulis sesuatu ke file log khusus. Oleh karena itu, Anda mungkin ingin memberinya grup tertentu dan membuat file log untuknya yang dapat ditulis oleh grup ini. Jadi, bahkan jika program ini "kereta", maka Anda tidak akan kehilangan apa pun kecuali grup ini. Ini berguna sebagai mekanisme yang karena alasan tertentu tidak digunakan terlalu sering, karena bagaimanapun, orang harus menggunakan hak root lebih banyak.
Hadirin: Apakah ada batasan siapa yang dapat mengubah akses?
Profesor: ya. Implementasi 
Unix yang berbeda memiliki pemeriksaan yang berbeda untuk ini. Aturan umum adalah bahwa hanya root yang dapat mengubah pemilik file, karena Anda tidak ingin membuat file yang akan menjadi milik orang lain, dan tentu saja Anda tidak ingin menyesuaikan file orang lain. Jadi, jika 
uid Anda bukan 0, maka Anda mandek. Anda tidak dapat mengubah kepemilikan file apa pun. Jika 
uid = 0 , Anda memiliki hak akses root dan Anda dapat mengubah pemiliknya menjadi siapa saja. Ada beberapa komplikasi jika Anda memiliki 
setuid biner dan Anda beralih dari satu 
uid ke yang lain, ini cukup rumit, tetapi pada dasarnya Anda pada dasarnya tidak dapat mengubah pemilik file jika Anda tidak memiliki hak akses root.
Secara umum, ini adalah sistem yang agak ketinggalan jaman. Anda mungkin dapat membayangkan banyak cara untuk menyederhanakan proses yang dijelaskan di atas, tetapi pada kenyataannya, sebagian besar sistem yang canggih terlihat seperti ini karena mereka berkembang seiring waktu. Tetapi Anda dapat dengan sempurna menggunakan mekanisme ini sebagai "kotak pasir".
Ini hanya semacam prinsip dasar 
Unix , yang muncul di hampir setiap sistem operasi mirip Unix: 
Mac OS X , 
Linux , 
FreeBSD , 
Solaris , jika orang lain menggunakannya, dan seterusnya. Tetapi masing-masing sistem ini memiliki mekanisme yang lebih canggih yang dapat Anda gunakan. Misalnya, di 
Linux ada 
set "sandbox" 
COMP , 
Mac OS X menggunakan "sandbox" 
Seatbelt . Minggu depan saya akan memberi Anda contoh kotak pasir yang tersedia di setiap sistem berbasis 
Unix .
Jadi, salah satu mekanisme terakhir, yang akan kami pertimbangkan sebelum masuk ke 
OKWS , menjelaskan bagaimana Anda harus berurusan dengan binari 
setuid dan menunjukkan bagaimana Anda dapat melindungi diri dari lubang keamanan yang ada. Masalahnya adalah bahwa Anda pasti akan memiliki beberapa binari 
setuid pada sistem Anda, seperti 
/ bin / su , atau 
sudo , atau sesuatu yang lain, dan kemungkinan program Anda akan memiliki kesalahan. Karena itu, seseorang akan dapat menjalankan biner 
setuid dan prosesnya akan dapat memperoleh akses 
root , yang tidak ingin Anda izinkan.

Mekanisme 
Unix , yang sering digunakan untuk mencegah pelaksanaan proses yang berpotensi berbahaya menggunakan 
setuid binari, adalah dengan menggunakan namespace sistem file untuk mengubahnya menggunakan panggilan sistem 
chroot , operasi mengubah direktori root. 
OKWS , sebagai server web yang berspesialisasi dalam menciptakan layanan web yang cepat dan aman, menggunakan ini dengan cukup luas.

Jadi, di 
Unix, Anda dapat menjalankan 
chroot di direktori tertentu, jadi mungkin Anda juga dapat menjalankan 
chroot ("/ foo") .
Ada 2 penjelasan untuk apa 
chroot tidak. Yang pertama hanya intuitif, artinya setelah menjalankan 
chroot , direktori root atau direktori yang terletak di belakang slash pada dasarnya setara dengan apa yang 
digunakan sebelum Anda memanggil 
chroot . Sepertinya membatasi namespace di bawah 
/ foo Anda . Karena itu, jika Anda memiliki file yang dulu bernama 
/ foo / x , maka setelah memanggil 
chroot, Anda bisa mendapatkan file ini hanya dengan membuka 
/ x . Jadi batasi namespace Anda hanya untuk subdirektori. Inilah versi intuitifnya.

Tentu saja, dalam keamanan, itu bukan versi intuitif yang penting, tetapi apa sebenarnya yang dilakukan kernel dengan panggilan sistem ini? Dan itu pada dasarnya melakukan dua hal. Pertama, ia mengubah nilai slash ini, jadi kapan pun Anda mengakses atau ketika Anda memulai nama direktori dengan slash, kernel menyertakan file apa pun yang Anda sediakan dengan operasi 
chroot . Dalam contoh kita, ini adalah file 
/ foo sebelum Anda memanggil 
chroot , yaitu, kita mendapatkan 
/ = / foo .

Hal berikutnya yang akan coba dilakukan kernel adalah melindungi Anda agar tidak dapat "melarikan diri" dari 
/ jika Anda melakukannya 
/../ . Karena pada 
Unix, saya dapat meminta Anda untuk memberi saya, misalnya, 
/../etc/password . Jadi jika saya menambahkan baris ini seperti ini: 
/foo/../etc/password , itu tidak akan baik, karena saya bisa keluar 
/ foo dan melanjutkan untuk mendapatkan 
/ etc / password .
Hal kedua yang dilakukan kernel dengan pemanggilan sistem 
Unix adalah ketika Anda memanggil 
chroot untuk proses khusus ini, ia mengubah cara 
/../ dievaluasi dalam direktori ini. Oleh karena itu, ia memodifikasi 
/../ sehingga 
/ foo menunjuk ke dirinya sendiri. Dengan demikian, ini tidak memungkinkan Anda untuk "melarikan diri", dan perubahan ini hanya berlaku untuk proses ini dan tidak mempengaruhi sisanya. Gagasan apa yang Anda miliki tentang cara "melarikan diri" dari lingkungan 
chroot menggunakan cara penerapannya?
Menariknya, kernel hanya memonitor satu direktori 
chroot , jadi Anda mungkin dapat melakukan operasi 
chroot = (/ foo) , tetapi Anda akan terjebak di tempat ini. Jadi Anda ingin mendapatkan 
/ etc / password , tetapi bagaimana cara melakukannya? Anda dapat membuka direktori root sekarang dengan mengetik 
open (* / *) . Ini akan memberi Anda deskriptor file yang menggambarkan apa 
/ foo . Kemudian Anda dapat memanggil 
chroot lagi dan menjalankan 
chroot (`/ bar) .

, : 
root /foo , 
/foo/bar /../ /foo / bar/..
, 
/foo . 
fchdir (fd) (*/*) , 
chdir (..) .

 /foo
/foo , 
/../ . 
/foo , 
root , .
, , . . 
Unix root- 
chroot , 
chroot . , 
Unix uid = 0 , 
chroot . . , , 
chroot , 
userid . , 
Unix , , 
root , .
, , , . 
chroot — . .
: , 
inod , ?
: ! , , , : « 
inode 23», - 
hroot . , 
Unix inode inode , , , root-.
, , , 
OKWS . , 
OKWS .
, -, , - , . , , 
httpd , , 
Apache .
userid www /etc/password . , , 
SSL , 
PHP , . , , , 
MySQL , . 
MySQL . 
MySQL , , , .

, , , 
MySQL , , .
, , , , . , , , 
Apache , 
SSL , , , 
PHP . , , , .
52:30
:
Kursus MIT "Keamanan Sistem Komputer". 4: « », 2.
, . ? ? , 
30% entry-level , : VPS (KVM) E5-2650 v4 (6 Cores) 10GB DDR4 240GB SSD 1Gbps $20 ? ( RAID1 RAID10, 24 40GB DDR4).
Dell R730xd 2 ? 2 Intel Dodeca-Core Xeon E5-2650v4 128GB DDR4 6x480GB SSD 1Gbps 100 $249 ! . kelas menggunakan server Dell R730xd E5-2650 v4 seharga 9.000 euro untuk satu sen?