Apakah dd jika = / dev / urandom dari = / dev / mem aman?

10

Apa sebenarnya yang dilakukan ini? Saya tidak mengerti bagaimana Anda dapat mengakses memori dasar dengan ini ... tampaknya agak aneh. Apakah ini aman?

dd if=/dev/urandom of=/dev/mem
Coder14
sumber
Apa "aman" yang Anda bicarakan ini? Aman berkenaan dengan apa?
waltinator
Apa yang ingin Anda capai dengan perintah ini?
Jochen

Jawaban:

23

Jangan coba ini di rumah! Itu dapat merusak sistem Anda, dan jika Anda benar-benar sial itu dapat merusak periferal atau membuat komputer Anda tidak dapat di-boot.

Sebenarnya, pada sebagian besar platform, itu hanya gagal dengan kesalahan, tetapi itu tergantung pada arsitektur perangkat keras. Jelas tidak ada jaminan bahwa ini tidak berbahaya kecuali jika Anda menjalankan perintah sebagai pengguna yang tidak memiliki hak. Dengan pengguna yang tidak memiliki hak istimewa, perintah ini sama sekali tidak berbahaya karena Anda tidak dapat membuka /dev/mem.

Saat Anda menjalankan perintah sebagai root, Anda seharusnya tahu apa yang Anda lakukan. Kernel kadang - kadang akan mencegah Anda dari melakukan sesuatu yang berbahaya, tetapi tidak selalu. /dev/memadalah salah satu hal yang berpotensi berbahaya di mana Anda benar-benar seharusnya tahu apa yang Anda lakukan.

Saya akan membahas bagaimana cara menulis /dev/membekerja di Linux. Prinsip umum akan sama pada Unix lain, tetapi hal-hal seperti opsi kernel sama sekali berbeda.

Apa yang terjadi ketika suatu proses membaca atau menulis ke file perangkat hingga kernel. Akses ke file perangkat menjalankan beberapa kode dalam driver yang menangani file perangkat ini. Misalnya, menulis untuk /dev/memmemanggil fungsi write_memdalamdrivers/char/mem.c . Fungsi ini mengambil 4 argumen: struktur data yang mewakili file terbuka, pointer ke data yang akan ditulis, jumlah byte yang akan ditulis, dan posisi saat ini dalam file.

Perhatikan bahwa Anda hanya mendapatkan sejauh itu jika penelepon memiliki izin untuk membuka file di tempat pertama. File perangkat mematuhi izin file secara normal. Hak akses normal /dev/memyang crw-r-----dimiliki oleh root:kmem, jadi jika Anda mencoba untuk membukanya untuk menulis tanpa root, Anda hanya akan mendapatkan “ijin ditolak” (EACCESS). Tetapi jika Anda root (atau jika root telah mengubah izin file ini), pembukaan akan melalui dan kemudian Anda dapat mencoba menulis.

Kode dalam write_memfungsi membuat beberapa pemeriksaan kewarasan, tetapi pemeriksaan ini tidak cukup untuk melindungi terhadap segala sesuatu yang buruk. Hal pertama yang dilakukannya adalah mengonversi posisi file saat ini *pposke alamat fisik. Jika itu gagal (dalam praktiknya, karena Anda berada di platform dengan alamat fisik 32-bit tetapi offset file 64-bit dan offset file lebih besar dari 2 ^ 32), penulisan gagal dengan EFBIG (file terlalu besar). Pemeriksaan berikutnya adalah apakah kisaran alamat fisik yang akan ditulis valid pada arsitektur prosesor khusus ini, dan ada hasil kegagalan pada EFAULT (alamat buruk).

Selanjutnya, pada Sparc dan m68k, bagian apa pun dari penulisan di halaman fisik pertama dilewati secara diam-diam.

Kami sekarang telah mencapai loop utama yang berulang pada data dalam blok yang dapat ditampung dalam satu halaman MMU . /dev/memmengakses memori fisik, bukan memori virtual, tetapi instruksi prosesor untuk memuat dan menyimpan data dalam memori menggunakan alamat virtual, sehingga kode perlu mengatur untuk memetakan memori fisik di beberapa alamat virtual. Di Linux, tergantung pada arsitektur prosesor dan konfigurasi kernel, pemetaan ini ada secara permanen atau harus dibuat dengan cepat; itulah tugas xlate_dev_mem_ptr(dan unxlate_dev_mem_ptrmembatalkan apa pun yang xlate_dev_mem_ptrdilakukan). Kemudian fungsi copy_from_usermembaca dari buffer yang diteruskan kewritepanggilan sistem dan hanya menulis ke alamat virtual di mana memori fisik saat ini dipetakan. Kode ini memancarkan instruksi penyimpanan memori normal, dan apa artinya ini tergantung pada perangkat keras.

Sebelum saya membahas bahwa penulisan ke alamat fisik tidak, saya akan membahas cek yang terjadi sebelum penulisan ini. Di dalam loop, fungsi ini page_is_allowedmemblokir akses ke alamat-alamat tertentu jika opsi konfigurasi kernel CONFIG_STRICT_DEVMEMdiaktifkan (yang merupakan kasus secara default): hanya alamat-alamat yang diizinkan oleh yang devmem_is_alloweddapat dijangkau /dev/mem, untuk yang lain penulisan gagal dengan EPERM (operasi tidak diizinkan). Deskripsi opsi ini menyatakan:

Jika opsi ini diaktifkan, dan IO_STRICT_DEVMEM = n, file / dev / mem hanya memungkinkan userspace mengakses ruang PCI dan kode BIOS dan wilayah data. Ini cukup untuk dosemu dan X dan semua pengguna umum / dev / mem.

Ini adalah deskripsi yang sangat x86-sentris. Bahkan, secara lebih umum, CONFIG_STRICT_DEVMEMmemblokir akses ke alamat memori fisik yang memetakan ke RAM, tetapi memungkinkan akses ke alamat yang tidak memetakan ke RAM. Rincian kisaran alamat fisik apa yang diizinkan tergantung pada arsitektur prosesor, tetapi semuanya tidak termasuk RAM tempat data kernel dan proses lahan pengguna disimpan. Opsi tambahan CONFIG_IO_STRICT_DEVMEM(dinonaktifkan pada Ubuntu 18.04) memblokir akses ke alamat fisik yang diklaim oleh driver.

Memori fisik alamat yang memetakan ke RAM . Jadi ada alamat memori fisik yang tidak dipetakan ke RAM? Iya. Itulah diskusi yang saya janjikan di atas tentang apa artinya menulis ke alamat.

Instruksi penyimpanan memori tidak harus menulis ke RAM. Prosesor menguraikan alamat dan memutuskan perangkat mana yang akan dikirimi toko. (Ketika saya mengatakan "prosesor", saya mencakup pengontrol periferal yang mungkin tidak berasal dari pabrikan yang sama.) RAM hanya salah satu dari periferal tersebut. Bagaimana pengiriman dilakukan sangat tergantung pada arsitektur prosesor, tetapi secara fundamental kurang lebih sama pada semua arsitektur. Prosesor pada dasarnya menguraikan bit-bit alamat yang lebih tinggi dan mencarinya di beberapa tabel yang diisi berdasarkan informasi kode-keras, informasi yang diperoleh dengan menyelidik beberapa bus, dan informasi yang dikonfigurasikan oleh perangkat lunak. Banyak caching dan buffering mungkin terlibat, tetapi singkatnya, setelah dekomposisi ini,bus dan kemudian terserah perangkat untuk menghadapinya. (Atau hasil dari pencarian tabel mungkin karena tidak ada perangkat di alamat ini, dalam hal ini prosesor memasuki kondisi jebakan di mana ia mengeksekusi beberapa kode di kernel yang biasanya menghasilkan SIGBUS untuk proses panggilan.)

Toko ke alamat yang dipetakan ke RAM tidak "melakukan" apa pun selain menimpa nilai yang sebelumnya disimpan di alamat ini, dengan janji bahwa pemuatan berikutnya pada alamat yang sama akan mengembalikan nilai terakhir yang disimpan. Tetapi bahkan RAM memiliki beberapa alamat yang tidak berperilaku seperti ini: ia memiliki beberapa register yang dapat mengontrol hal-hal seperti refresh rate dan voltase.

Secara umum, membaca atau menulis ke register perangkat keras melakukan apa pun yang diprogram untuk dilakukan perangkat keras. Sebagian besar akses ke perangkat keras bekerja dengan cara ini: perangkat lunak (biasanya kode kernel) mengakses alamat fisik tertentu, ini mencapai bus yang menghubungkan prosesor ke perangkat, dan perangkat melakukan hal tersebut. Beberapa prosesor (khususnya x86) juga memiliki instruksi CPU terpisah yang menyebabkan pembacaan / penulisan ke periferal yang berbeda dari pemuatan dan penyimpanan memori, tetapi bahkan pada x86, banyak periferal yang dicapai melalui pemuatan / penyimpanan.

Perintah dd if=/dev/urandom of=/dev/memmenulis data acak ke perangkat apa pun yang dipetakan pada alamat 0 (dan alamat berikutnya, selama penulisan berhasil). Dalam prakteknya, saya berharap bahwa pada banyak arsitektur, alamat fisik 0 tidak memiliki perangkat apa pun yang dipetakan, atau memiliki RAM, dan oleh karena itu upaya penulisan pertama gagal. Tetapi jika ada perangkat yang dipetakan di alamat 0, atau jika Anda mengubah perintah untuk menulis ke alamat yang berbeda, Anda akan memicu sesuatu yang tidak terduga di perangkat. Dengan data acak di alamat yang meningkat, tidak mungkin melakukan sesuatu yang menarik, tetapi pada prinsipnya itu bisa mematikan komputer (mungkin ada alamat yang melakukan ini sebenarnya), menimpa beberapa pengaturan BIOS yang membuatnya tidak mungkin untuk boot, atau bahkan menekan beberapa perangkat kereta dengan cara yang merusaknya.

alias Russian_roulette='dd if=/dev/urandom of=/dev/mem seek=$((4096*RANDOM+4096*32768*RANDOM))'
Gilles 'SANGAT berhenti menjadi jahat'
sumber
Terima kasih! Ini yang saya cari! Saya hanya bingung apakah / dev / mem memungkinkan akses memori ke hal-hal seperti periferal dan hal-hal yang berhubungan dengan perangkat keras!
Coder14
Periferal tidak dapat dipetakan pada alamat fisik 0 pada x86 pc; konfigurasi itu tidak akan pernah bisa boot.
Joshua
Ini tidak benar
Yvain
1
Tentu saja Anda dapat merusak kernel tetapi tidak pada bios
Yvain
1
@Yain Apa yang tidak benar? Dan sebenarnya Anda tidak dapat merusak kernel jika CONFIG_STRICT_DEVMEMdiaktifkan.
Gilles 'SANGAT berhenti menjadi jahat'
12

Aman, jika Anda telah mengkonfigurasi kernel dengan benar (aman karena tidak akan berfungsi)

Mem halaman manual (4) :

/ dev / mem adalah file perangkat karakter yang merupakan gambar dari memori utama komputer. Ini dapat digunakan, misalnya, untuk memeriksa (dan bahkan menambal) sistem.

Jadi secara teori, dd if=/dev/urandom of=/dev/memharus menimpa seluruh ruang alamat dari memori fisik yang telah Anda instal, dan karena kernel dan program lain berjalan dari memori, ini akan secara efektif membuat sistem crash. Dalam praktiknya, ada batasnya. Dari halaman manual yang sama:

Sejak Linux 2.6.26, dan tergantung pada arsitekturnya, opsi konfigurasi kernel CONFIG_STRICT_DEVMEM membatasi area yang dapat diakses melalui file ini.

Mencoba ini di mesin virtual Ubuntu 18.04, ia mengembalikan kesalahan dd: writing to '/dev/mem': Operation not permittedbahkan dengan sudodan meskipun izin untuk root crw-r-----. Dari Ubuntu Wiki :

/ dev / mem perlindungan

Beberapa aplikasi (Xorg) memerlukan akses langsung ke memori fisik dari ruang pengguna. Ada file / dev / mem khusus untuk menyediakan akses ini. Di masa lalu, dimungkinkan untuk melihat dan mengubah memori kernel dari file ini jika penyerang memiliki akses root. Opsi kernel CONFIG_STRICT_DEVMEM diperkenalkan untuk memblokir akses memori non-perangkat (awalnya bernama CONFIG_NONPROMISC_DEVMEM).

Jadi secara teknis, tidak itu tidak aman (karena itu akan merusak sistem) dan jika opsi kernel CONFIG_STRICT_DEVMEMdinonaktifkan itu lubang keamanan, tetapi dari apa yang saya lihat sejauh ini perintah tidak akan berjalan jika opsi itu diaktifkan. Menurut duplikat lintas-situs , reboot akan memperbaiki masalah dengan itu, tetapi tentu saja data dalam RAM pada saat itu akan hilang dan tidak memerah ke disk (jika ada harus).

Ada metode yang disarankan pada duplikat yang ditautkan sebelumnya menggunakan busybox devmemjadi jika Anda bertekad untuk main-main dengan RAM, mungkin ada cara.

Sergiy Kolodyazhnyy
sumber
6
"Itu aman" Tidak, itu pasti tidak. Bahkan dengan CONFIG_STRICT_DEVMEM, Anda dapat mengakses wilayah memori di mana perangkat dipetakan, yang merupakan inti dari memiliki /dev/mem. Jika Anda menulis hal-hal acak ke peripheral, apa pun mungkin terjadi. Anda mendapatkan "operasi tidak diizinkan" jika Anda mencoba mengakses alamat yang tidak dipetakan, dan perintah dimulai pada alamat 0. Apakah alamat 0 memetakan sesuatu yang buruk tergantung pada arsitektur perangkat keras. Yang saya tahu itu mungkin tidak pernah dipetakan ke apa pun di PC, tetapi secara umum tidak aman.
Gilles 'SANGAT berhenti menjadi jahat'
1
@Gilles Pada x86 (tidak yakin tentang x86-64), 1 KiB RAM pertama (alamat 0x0 hingga 0x3ff) memegang vektor interupsi; nilai alamat empat byte per vektor. Jika Anda berhasil menimpa mereka dengan sampah acak, semua hal menarik kemungkinan akan terjadi segera. Kemungkinan besar, Anda akan berakhir dengan kesalahan ganda atau tiga kali lipat dan sistem akan macet, tetapi tidak ada jaminan ...
CVn
@ aCVn Pasti ada sesuatu yang dipetakan ( head -c 1024 </dev/mem | od -tx1), tapi saya tidak tahu apakah ini digunakan ketika prosesor tidak dalam mode nyata (mode 8088). Saya tidak berpikir mereka dapat digunakan dalam mode 64-bit: setelah semua, vektor interupsi 8088 hanya memiliki 32 bit untuk alamat. Dan omong-omong ini dapat diakses dengan CONFIG_STRICT_DEVMEMset, jadi saya kira Linux tidak menggunakannya.
Gilles 'SANGAT berhenti menjadi jahat'
@Gilles: Halaman 0 pada x86 dicadangkan untuk v86, bootloader, dll; itulah tabel vektor interupsi mode nyata di sana. Dalam mode terproteksi, IVT ada di tempat lain (register mesin mengatakan di mana).
Joshua