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 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 ,
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?