$ k=v p &
[1] 3028
apakah ada cara untuk p
mengubah konten /proc/3028/environ
agar tidak menyebutkan k=v
saat p
masih berjalan?
linux
security
process
linux-kernel
environment-variables
Cetin Sert
sumber
sumber
Jawaban:
Di Linux, Anda dapat menimpa nilai string lingkungan pada stack.
Jadi, Anda dapat menyembunyikan entri dengan menimpanya dengan nol atau apa pun:
Jalankan sebagai:
yang
k=v
telah ditimpa dengan\0\0\0
.Perhatikan bahwa
setenv("k", "", 1)
untuk menimpa nilai tidak akan berfungsi seperti dalam kasus itu,"k="
string baru dialokasikan.Jika Anda tidak mengubah
k
variabel lingkungan dengansetenv()
/putenv()
, maka Anda juga harus dapat melakukan sesuatu seperti ini untuk mendapatkan alamatk=v
string pada stack (well, salah satunya):Namun perlu dicatat bahwa itu hanya menghapus salah satu
k=v
entri yang diterima di lingkungan. Biasanya, hanya ada satu, tetapi tidak ada yang menghentikan siapa pun melewati keduanyak=v1
dank=v2
(atauk=v
dua kali) dalam daftar env diteruskanexecve()
. Itu telah menjadi penyebab kerentanan keamanan di masa lalu seperti CVE-2016-2381 . Itu bisa benar-benar terjadi denganbash
sebelum shellshock ketika mengekspor variabel dan fungsi dengan nama yang sama.Bagaimanapun, akan selalu ada jendela kecil di mana string env var belum diganti, jadi Anda mungkin ingin mencari cara lain untuk meneruskan informasi rahasia ke perintah (seperti pipa misalnya) jika mengeksposnya melalui
/proc/pid/environ
adalah masalah.Juga catat bahwa bertentangan dengan
/proc/pid/cmdline
,/proc/pid/environment
hanya dapat diakses oleh proses dengan cairan atau akar yang sama (atau root hanya jika cairan dan bentuk proses tidak sama kelihatannya).Anda dapat menyembunyikan nilai itu dari mereka
/proc/pid/environ
, tetapi mereka mungkin masih bisa mendapatkan salinan lain yang Anda buat dari string dalam memori, misalnya dengan melampirkan debugger ke dalamnya.Lihat https://www.kernel.org/doc/Documentation/security/Yama.txt untuk mengetahui cara mencegah setidaknya pengguna yang bukan root melakukan hal itu.
sumber
Belum perlu menimpa string di atas (tidak benar-benar aktif ) tumpukan utas di Linux sejak 2010.
Keduanya
/proc/self/cmdline
dan/proc/self/environ
dapat dimodifikasi oleh proses itu sendiri pada saat runtime, dengan tidak memanggilprctl()
fungsi dengan masing-masingPR_SET_MM_ARG_START
+PR_SET_MM_ARG_END
atauPR_SET_MM_ENV_START
+PR_SET_MM_ENV_END
. Ini secara langsung mengatur pointer memori ke dalam ruang memori aplikasi proses, yang dipegang oleh kernel untuk setiap proses, yang digunakan untuk mengambil konten/proc/${PID}/cmdline
dan/proc/${PID}/environ
, dan karenanya baris perintah dan lingkungan dilaporkan olehps
perintah.Jadi kita hanya perlu membuat argumen baru atau string lingkungan (bukan vektor, pemberitahuan - memori yang ditunjuk harus berupa data string yang sebenarnya, digabung dan
␀
-ditinjau) dan beri tahu kernel di mana letaknya.Ini didokumentasikan di halaman manual Linux untuk
prctl(2)
fungsi sertaenviron(7)
halaman manual. Apa yang tidak didokumentasikan adalah bahwa kernel menolak upaya untuk mengatur alamat awal di atas alamat akhir, atau alamat akhir di bawah alamat awal; atau untuk (kembali) mengatur salah satu alamat ke nol. Juga, ini bukan mekanisme asli yang diusulkan oleh Bryan Donlan pada 2009, yang memungkinkan pengaturan mulai dan berakhir dalam satu operasi, secara atom. Selain itu, kernel tidak memberikan cara untuk mendapatkan nilai saat ini dari pointer ini.Ini membuatnya sulit untuk memodifikasi lingkungan dan area baris perintah
prctl()
. Kita harus memanggilprctl()
fungsi hingga empat kali karena upaya pertama dapat menghasilkan upaya untuk mengatur pointer awal lebih tinggi dari pointer akhir, tergantung dari tempat data lama dan baru berada dalam memori. Kita harus menyebutnya empat kali lebih jauh jika kita ingin memastikan bahwa ini tidak menghasilkan jendela peluang bagi proses lain pada sistem untuk memeriksa rentang ruang memori proses yang sewenang-wenang dalam periode ketika awal / akhir baru telah ditetapkan tetapi akhir / awal baru belum.Panggilan sistem atom tunggal yang menetapkan seluruh rentang dalam sekali jalan akan jauh lebih mudah bagi program aplikasi untuk digunakan dengan aman.
Kerutan lebih lanjut adalah bahwa, tanpa alasan yang benar-benar baik (mengingat pemeriksaan di kernel, toh kemampuan menimpa area data asli , dan fakta bahwa padanannya bukan operasi istimewa pada BSD manapun), di Linux ini membutuhkan superuser hak istimewa.
Saya menulis fungsi
setprocargv()
dansetprocenvv()
fungsi yang cukup sederhana untuk perangkat saya, yang menggunakan ini. Program pemuatan rantai dari perangkat yang dibangun, sepertisetenv
danforeground
, dengan demikian mencerminkan argumen perintah dan lingkungan berantai, di mana Linux mengizinkan.Perhatikan bahwa ini tidak menghalangi hal-hal yang melacak proses dan mengakses ingatannya secara langsung dengan cara lain (daripada melalui dua file pseudo ini), dan tentu saja meninggalkan jendela sebelum string dimodifikasi di mana informasi ini dapat dilihat, hanya saja seperti menimpa data di atas tumpukan utas utama. Dan seperti halnya dengan menimpa data, ini tidak memperhitungkan perpustakaan runtime bahasa yang membuat salinan lingkungan (pada heap) dalam berbagai keadaan. Secara umum, jangan menganggap ini sebagai mekanisme yang baik untuk meneruskan "rahasia" ke program karena (katakanlah) memiliki itu mewarisi deskriptor file terbuka ke ujung baca dari pipa yang tidak disebutkan namanya, membaca ke buffer input sepenuhnya di bawah kendali Anda yang kemudian Anda bersihkan.
Bacaan lebih lanjut
sumber
/proc/$pid/stat
(selain nilai-nilai lain yang Anda mungkin perlustruct prctl_mm_map
). Lihat juga contoh filter_env.c saya untuk demo kecil. JdeBP, dapatkah Anda menambahkan tautan kesetprocargv()
/setprocenvv()
fungsi Anda?