Saya perhatikan beberapa waktu lalu bahwa nama pengguna dan kata sandi yang diberikan curl
sebagai argumen baris perintah tidak muncul dalam ps
output (meskipun tentu saja mereka mungkin muncul dalam riwayat bash Anda).
Mereka juga tidak muncul di /proc/PID/cmdline
.
(Namun, panjang argumen gabungan nama pengguna / kata sandi dapat diturunkan.)
Demonstrasi di bawah ini:
[root@localhost ~]# nc -l 80 &
[1] 3342
[root@localhost ~]# curl -u iamsam:samiam localhost &
[2] 3343
[root@localhost ~]# GET / HTTP/1.1
Authorization: Basic aWFtc2FtOnNhbWlhbQ==
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.15.3 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Host: localhost
Accept: */*
[1]+ Stopped nc -l 80
[root@localhost ~]# jobs
[1]+ Stopped nc -l 80
[2]- Running curl -u iamsam:samiam localhost &
[root@localhost ~]# ps -ef | grep curl
root 3343 3258 0 22:37 pts/1 00:00:00 curl -u localhost
root 3347 3258 0 22:38 pts/1 00:00:00 grep curl
[root@localhost ~]# od -xa /proc/3343/cmdline
0000000 7563 6c72 2d00 0075 2020 2020 2020 2020
c u r l nul - u nul sp sp sp sp sp sp sp sp
0000020 2020 2020 0020 6f6c 6163 686c 736f 0074
sp sp sp sp sp nul l o c a l h o s t nul
0000040
[root@localhost ~]#
Bagaimana efek ini dicapai? Apakah ada di suatu tempat dalam kode sumber curl
? (Saya menganggap itu adalah curl
fitur, bukan ps
fitur? Atau apakah ini semacam fitur kernel?)
Juga: dapatkah ini dicapai dari luar kode sumber biner yang dapat dieksekusi? Misalnya dengan menggunakan perintah shell, mungkin dikombinasikan dengan izin root?
Dengan kata lain, bisakah saya menutupi argumen agar tidak muncul di /proc
atau di ps
output (hal yang sama, saya pikir) yang saya sampaikan ke beberapa perintah shell sewenang-wenang ? (Saya kira jawaban untuk ini adalah "tidak" tapi sepertinya layak untuk memasukkan setengah pertanyaan tambahan ini.)
environ
langsung untuk mengakses variabel lingkungan? - intinya: daftar argumen, seperti daftar variabel lingkungan, ada dalam memori proses baca / tulis pengguna, dan dapat dimodifikasi oleh proses pengguna.grep
pola Anda menjadi kelas karakter. Misalnyaps -ef | grep '[c]url'
curl
cocokcurl
tetapi[c]url
tidak cocok[c]url
. Jika Anda perlu lebih detail, ajukan pertanyaan baru dan saya akan dengan senang hati menjawab.Jawaban:
Ketika kernel mengeksekusi suatu proses, itu menyalin argumen baris perintah untuk membaca-tulis memori milik proses (pada stack, setidaknya di Linux). Proses dapat menulis ke memori itu seperti memori lainnya. Saat
ps
menampilkan argumen, itu membaca kembali apa pun yang disimpan di alamat tertentu dalam memori proses. Sebagian besar program menyimpan argumen asli, tetapi dimungkinkan untuk mengubahnya. The POSIX deskripsips
menyatakan bahwaAlasan mengapa hal ini disebutkan adalah bahwa sebagian besar varian unix mencerminkan perubahan, tetapi implementasi POSIX pada jenis sistem operasi lain mungkin tidak.
Fitur ini terbatas penggunaannya karena proses tidak dapat membuat perubahan sewenang-wenang. Paling tidak, panjang total argumen tidak dapat ditingkatkan, karena program tidak dapat mengubah lokasi di mana
ps
akan mengambil argumen dan tidak dapat memperluas area di luar ukuran aslinya. Panjangnya dapat dikurangi secara efektif dengan meletakkan byte nol di akhir, karena argumen adalah string C-style null-terminated (ini tidak bisa dibedakan dari memiliki banyak argumen kosong di akhir).Jika Anda benar-benar ingin menggali, Anda dapat melihat sumber dari implementasi open-source. Di Linux, sumbernya
ps
tidak menarik, yang Anda akan lihat hanyalah bahwa ia membaca argumen baris perintah dari sistem file proc , di . Kode yang menghasilkan konten file ini ada di dalam kernel, di dalam . Bagian dari memori proses (diakses dengan ) pergi dari alamat ke ; alamat-alamat ini dicatat dalam kernel ketika proses dimulai dan tidak dapat diubah setelahnya./proc/PID/cmdline
proc_pid_cmdline_read
fs/proc/base.c
access_remote_vm
mm->arg_start
mm->arg_end
Beberapa daemon menggunakan kemampuan ini untuk mencerminkan status mereka, misalnya mereka mengubahnya
argv[1]
menjadi string sepertistarting
atauavailable
atauexiting
. Banyak varian unix memilikisetproctitle
fungsi untuk melakukan ini. Beberapa program menggunakan kemampuan ini untuk menyembunyikan data rahasia. Perhatikan bahwa ini penggunaan terbatas karena argumen baris perintah terlihat saat proses dimulai.Sebagian besar bahasa tingkat tinggi menyalin argumen ke objek string dan tidak memberikan cara untuk memodifikasi penyimpanan asli. Berikut adalah program C yang menunjukkan kemampuan ini dengan mengubah
argv
elemen secara langsung.Output sampel:
Anda dapat melihat
argv
modifikasi dalam kode sumber ikal. Curl mendefinisikan fungsicleanarg
dalamsrc/tool_paramhlp.c
yang digunakan untuk mengubah argumen untuk semua ruang menggunakanmemset
. Dalamsrc/tool_getparam.c
fungsi ini digunakan beberapa kali, misalnya dengan mereduksi kata sandi pengguna . Karena fungsi dipanggil dari parameter parsing, itu terjadi di awal doa curl, tetapi membuang baris perintah sebelum ini terjadi masih akan menampilkan kata sandi.Karena argumen disimpan dalam memori proses sendiri, mereka tidak dapat diubah dari luar kecuali dengan menggunakan debugger.
sumber
ps
argumen laporan dari sepotong memori kernel, mengabaikan perubahan yang dibuat dalam memori baca-tulis proses? Tetapi (jika saya benar?) Sebagian besar variasi UNIX bahkan tidak melakukan yang pertama, jadi Anda tidak dapat membuatps
implementasi melakukan yang terakhir tanpa modifikasi kernel, karena data asli tidak disimpan di mana pun?argv
entri diubah (Anda tidak dapat mengaturargv[i]
, tetapi Anda dapat menulisargv[i][0]
sampaiargv[i][strlen(argv[i])]
), sehingga harus ada salinan dalam memori proses.ps
output, banyak argumen kosong sepertinya tidak ada di sana, tapi ya, itu membuat perbedaan jika Anda memeriksa berapa banyak ruang yang ada, dan Anda dapat mengamati lebih langsung dari/proc/PID/cmdline
.Jawaban yang lain menjawab pertanyaan dengan baik secara umum. Untuk secara spesifik menjawab " Bagaimana efek ini dicapai? Apakah ada di suatu tempat dalam kode sumber curl? ":
Di bagian parsing argumen dari kode sumber ikal ,
-u
opsi ditangani sebagai berikut:Dan
cleanarg()
fungsinya didefinisikan sebagai berikut:Jadi kita dapat secara eksplisit melihat bahwa argumen username: password di
argv
ditimpa dengan spasi, seperti yang dijelaskan oleh jawaban lain.sumber
cleanarg
negara secara eksplisit bahwa ia melakukan apa yang ditanyakan pertanyaan!Suatu proses tidak hanya dapat membaca parameternya tetapi juga menuliskannya.
Saya bukan pengembang jadi saya tidak terbiasa dengan hal ini tetapi mungkin dari luar dengan pendekatan yang mirip dengan perubahan parameter lingkungan:
https://stackoverflow.com/questions/205064/is-there-a-way-to-change-another-processs-environment-variables
sumber
bash -c 'awk 1 /proc/$$/cmdline; set -- something; awk 1 /proc/$$/cmdline'
Menunjukkan bahwa setidaknya dalam shell, pengaturan parameter berbeda dari memodifikasi apa yang dilihat kernel sebagai parameter proses.