Perubahan sudo-rs di Ubuntu 26.04 dan aturan sudoers
Ubuntu 26.04 menjadikan sudo-rs sebagai default. Wildcard argumen seperti * tidak lagi cocok di sudoers; gunakan aturan perintah eksplisit sebagai gantinya.
Perubahan sudo-rs pada Ubuntu
Ubuntu 26.04 LTS menyertakan sudo-rs sebagai sudo default. Karena itu, perintah sudo pada server baru menjalankan implementasi ulang dalam Rust, bukan program C asli. Sebagian besar file sudoers tetap berfungsi seperti sebelumnya. Aturan yang bermasalah adalah aturan yang menggunakan wildcard di dalam argumen perintah, karena sudo-rs tidak mencocokkan pola glob dengan teks argumen.
Ubuntu 25.10 menjadi versi pertama yang beralih, dan Ubuntu 26.04 LTS mempertahankan perubahan tersebut. Ubuntu 24.04 LTS tidak terdampak karena masih menggunakan sudo asli, kecuali Anda menginstal sudo-rs secara manual. Perubahan ini mulai relevan ketika Anda melakukan upgrade dari Ubuntu 24.04 ke 26.04, atau ketika Anda menyiapkan server baru dengan rilis yang lebih baru. Jika Anda juga menggunakan rilis interim, perbedaan rilis Ubuntu LTS dan interim pada server menjelaskan mesin mana yang lebih dahulu mengalami perubahan seperti ini.
Periksa sudo yang benar-benar dijalankan server Anda
Jangan menentukan hal ini dari nomor rilis. Tanyakan langsung kepada mesin.
sudo --version
update-alternatives --config sudo
dpkg -l 'sudo*'Percayai sudo --version pada mesin Anda sendiri, bukan tabel versi mana pun di Internet, termasuk halaman ini. update-alternatives --config sudo adalah bagian lain dari jawabannya: perintah ini mencantumkan setiap penyedia /usr/bin/sudo yang terinstal dan menandai penyedia yang dipilih. Paket yang terinstal tidak berarti paket tersebut dipilih, jadi baca pilihan yang aktif, bukan daftar paket.
Kedua implementasi tersebut dikemas selama masa transisi. Implementasi Rust adalah sudo-rs, dengan versi 0.2.13 pada 26.04 per Agustus 2026. Implementasi asli, yang dikelola oleh Todd C. Miller, dikemas sebagai sudo.ws, dan programnya memiliki akhiran .ws: sudo.ws dan visudo.ws.
Mengapa Ubuntu beralih ke sudo-rs
sudo menggunakan setuid root. Setiap pengguna pada server dapat menjalankannya, dan proses tersebut dimulai dengan hak akses penuh. Karena itu, bug memori di dalamnya dapat menjadi eksploitasi root lokal. CVE-2021-3156 adalah contoh kasus tersebut: heap buffer overflow yang dapat dijangkau oleh pengguna lokal mana pun. Bug ini berada dalam kode yang telah dirilis selama sekitar sepuluh tahun. Rust mendeteksi kelas bug tersebut saat kompilasi. Inilah alasan utama penulisan ulang tersebut.
Alasan kedua adalah cakupan fitur. Alasan ini yang berdampak langsung pada konfigurasi Anda. sudo asli telah mengumpulkan banyak fitur selama tiga dekade. Setiap fitur menambah kode yang berjalan sebagai root. sudo-rs sengaja hanya mengimplementasikan sebagian fitur. Fitur yang dianggap tidak umum atau berpotensi membahayakan oleh pengembangnya tidak disertakan. Karena itu, konstruksi sudoers yang telah berfungsi selama bertahun-tahun dapat saja tidak tersedia. Aturan wildcard Anda adalah salah satunya.
Keamanan memori menghilangkan satu kelas bug. Namun, hal itu tidak membuat program bebas bug. sudo-rs sendiri telah menerima perbaikan keamanan sejak menjadi default. Terapkan patch pada sudo-rs seperti pada perangkat lunak lainnya.
Aturan sudoers yang masih berfungsi
File tersebut tetap sama. sudo-rs membaca /etc/sudoers dan file drop-in di /etc/sudoers.d/, serta mendukung konfigurasi umum yang biasanya ditulis oleh operator server:
deploy ALL=(ALL:ALL) ALL, serta bentuk grup seperti%sudo ALL=(ALL:ALL) ALL- tag
NOPASSWD:danPASSWD: User_Alias,Runas_Alias,Host_Alias, danCmnd_Alias- perintah dengan daftar argumen yang persis, misalnya
/usr/bin/systemctl restart app-api - perintah yang diikuti
"", yang mengizinkan perintah hanya tanpa argumen apa pun - perintah yang diikuti
*sebagai argumen terakhirnya, yang mengizinkan argumen tambahan apa pun - path direktori yang diakhiri
/, yang mengizinkan perintah apa pun di direktori tersebut !untuk menghapus sebuah perintah dari daftar- subset
Defaultsyang berguna, termasuksecure_path,env_keep,env_check,timestamp_timeout,passwd_tries,editor,umask,targetpw,rootpw, danuse_pty
Dua default berperilaku berbeda dan sering menimbulkan kesalahan. env_reset tidak dapat dinonaktifkan di sudo-rs: opsi ini selalu aktif. use_pty aktif secara default, sehingga perintah dijalankan dalam pseudo-terminalnya sendiri.
Mengapa wildcard pada aturan sudoers Anda berhenti cocok
Wildcard masih diizinkan di satu tempat: nama file perintah. Aturan %ops ALL = /sbin/fsck* masih mengizinkan sudo fsck dan sudo fsck_exfat, karena * merupakan bagian dari path yang dicocokkan dengan filesystem.
Di dalam daftar argumen, sudo-rs hanya menerima dua bentuk khusus, dan keduanya bukan pola. "" berarti tidak ada argumen. * di posisi terakhir berarti argumen tambahan apa pun. Setiap argumen lainnya dibandingkan sebagai teks literal. Karena itu, %ops ALL = /sbin/service ntp * valid: ntp bersifat literal dan * berada di posisi terakhir. Namun, aturan berikut tidak memberikan izin yang Anda maksud:
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app-*app-* merupakan pola di tengah argumen. sudo-rs tidak mengembangkannya, sehingga aturan tersebut tidak mencakup systemctl restart app-api dan sudo menolak perintah itu. Dua perintah berikut menunjukkan kondisi sebenarnya dari aturan apa pun di server Anda: sudo -l -U deploy, yang dijalankan sebagai root, menampilkan perintah yang benar-benar dapat dijalankan oleh akun tersebut, sedangkan sudo visudo -c memberi tahu apakah file tersebut dapat diurai. Jalankan keduanya sebelum mulai mengubah file secara acak.
Aturan wildcard selalu menjadi celah
Pada sudo asli, argumen yang Anda ketik digabungkan menjadi satu string, lalu dicocokkan dengan string argumen pada aturan menggunakan glob. Glob mencocokkan spasi. Inilah bagian yang hampir selalu terlewatkan.
Dokumentasi sudo-rs memberikan demonstrasi yang paling jelas. Aturan /bin/rm *.txt juga mengizinkan sudo rm -rf /home .txt, karena satu * mencakup -rf /home dan string yang digabungkan tetap diakhiri dengan .txt. Aturan tersebut dibaca sebagai "hanya file teks". Maknanya adalah "argumen apa pun, selama baris tersebut diakhiri dengan .txt".
Hal yang sama berlaku untuk contoh systemctl. Karena argumen dibandingkan sebagai satu string yang digabungkan, pola di bagian akhir juga mencocokkan apa pun yang ditambahkan setelahnya. Dengan demikian, restart app-* mencakup restart app-api serta argumen tambahan apa pun yang diberikan pemanggil. Pola di dalam sebuah argumen membocorkan argumen di sekitarnya, padahal argumen menentukan kemampuan sebuah perintah. sudo-rs menolak konstruksi tersebut alih-alih mencoba membuatnya aman, karena tidak ada bentuk umum yang aman untuk konstruksi itu.
Ganti wildcard dengan daftar perintah eksplisit
Sebagian besar aturan wildcard ada karena seseorang tidak ingin mengetik empat baris. Ketik keempat baris tersebut.
Cmnd_Alias APP_RESTART = /usr/bin/systemctl restart app-api, /usr/bin/systemctl restart app-worker
Cmnd_Alias APP_STATUS = /usr/bin/systemctl status app-api, /usr/bin/systemctl status app-worker
deploy ALL=(root) NOPASSWD: APP_RESTART, APP_STATUSPastikan path-nya benar. Aturan yang mencantumkan /bin/systemctl pada sistem yang binarinya berada di /usr/bin/systemctl tidak pernah cocok, dan kegagalannya terlihat sama seperti masalah izin. Konfirmasikan dengan command -v systemctl, lalu tempelkan hasil yang ditampilkannya.
Letakkan aturan tersebut dalam file drop-in tersendiri, bukan di /etc/sudoers, agar pemutakhiran paket tidak pernah bertentangan dengan perubahan Anda:
sudo visudo -f /etc/sudoers.d/90-deploy
sudo visudo -c
sudo -l -U deployBeri nama file tanpa titik dan tanpa tilde di bagian akhir. sudo asli mengabaikan file di sudoers.d yang namanya mengandung titik, sehingga 90-deploy.conf adalah no-op klasik yang tidak menghasilkan pesan apa pun. Mengikuti konvensi ini tidak membutuhkan biaya apa pun.
Gunakan wrapper milik root jika daftarnya panjang
Jika daftar yang diizinkan terlalu besar untuk ditulis, pindahkan keputusan tersebut dari sudoers ke program kecil yang dimiliki oleh root.
sudo tee /usr/local/sbin/app-restart >/dev/null <<'EOF'
#!/bin/sh
set -eu
case "${1:-}" in
app-api|app-worker) ;;
*) echo "app-restart: not allowed: ${1:-}" >&2; exit 1 ;;
esac
exec /usr/bin/systemctl restart "$1"
EOF
sudo chown root:root /usr/local/sbin/app-restart
sudo chmod 0755 /usr/local/sbin/app-restart
ls -l /usr/local/sbin/app-restartDi sisi sudoers, cukup cantumkan satu perintah:
deploy ALL=(root) NOPASSWD: /usr/local/sbin/app-restart ** di bagian akhir dapat diterima di sini karena skrip, bukan sudo, yang menentukan hal-hal yang diizinkan. Ini hanya berlaku selama skrip dimiliki oleh root dan tidak dapat ditulis oleh akun lain. Jika deploy dapat menulis ke file tersebut, deploy dapat mengganti isinya dan menjalankan apa pun sebagai root. Ini lebih berbahaya daripada aturan wildcard yang Anda hapus. Periksa mode file dengan ls -l. Jika outputnya tidak langsung jelas, mempelajari string izin drwxr-xr-x hanya memerlukan waktu lima menit. Aturan yang sama berlaku untuk direktorinya: /usr/local/sbin juga tidak boleh dapat ditulis oleh akun tersebut, karena direktori yang dapat ditulis memungkinkan file diganti seluruhnya.
Berikan tugas tersebut akun khusus, bukan aturan sudo
Pertanyaan yang lebih tepat sering kali adalah mengapa perintah tersebut memerlukan root. Service yang berjalan sebagai user khusus dapat dikelola oleh user tersebut, sehingga tidak ada baris sudoers yang diperlukan. Untuk unit sistem, systemd sudah mendelegasikan keputusan tersebut kepada polkit. Karena itu, aturan dapat menyebutkan satu unit dan satu operator:
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.systemd1.manage-units" &&
action.lookup("unit") == "app-api.service" &&
subject.user == "deploy") {
return polkit.Result.YES;
}
});Simpan aturan tersebut sebagai /etc/polkit-1/rules.d/50-app-api.rules agar deploy dapat menjalankan systemctl restart app-api tanpa sudo sama sekali. Uji aturan tersebut dari konteks persis yang akan menggunakannya, karena aturan yang berfungsi dalam sesi SSH perlu dikonfirmasi dari cron sebelum Anda mengandalkannya. Bagaimanapun, account yang menjalankan tugas tersebut sebaiknya dibuat khusus untuk tugas itu. Ini merupakan alasan yang sama di balik account user dengan hak minimum pada VPS.
Hal lain yang tidak disertakan sudo-rs
sudo -E belum diimplementasikan. Beri nama variabel yang diperlukan menggunakan Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" sebagai gantinya, dan ingat bahwa env_reset selalu aktif, sehingga apa pun yang tidak dipertahankan akan dihapus.
Penyimpanan sudoers terpusat di LDAP sudah tidak tersedia. sudoers.ldap dan cvtsudoers belum diimplementasikan, dan paket sudo-ldap dihapus pada 26.04. Autentikasi LDAP melalui PAM atau SSSD tetap berfungsi. Bagian yang tidak termasuk dalam cakupan adalah kebijakan yang disimpan dalam direktori.
INTERCEPT, yang berupaya mencegah shell escape dari perintah yang diizinkan, belum diimplementasikan. Fitur tersebut juga tidak akan efektif terhadap pengguna yang benar-benar berniat menghindarinya. Jika sebuah aturan mengizinkan seseorang menjalankan editor atau interpreter sebagai root, orang tersebut sudah memiliki akses root, dan tidak ada opsi sudo yang dapat mengubahnya.
Perekaman sesi belum diimplementasikan, sehingga tidak ada log I/O dan tidak ada sudoreplay. Logging hanya dikirim ke syslog. Tidak ada opsi logfile untuk mengalihkannya ke lokasi lain, sehingga pesan sudo masuk ke lokasi yang sudah digunakan sistem Anda untuk mengirim syslog.
Beralih kembali ke sudo.ws?
Anda dapat melakukannya. Selama siklus 26.04, paket asli tetap disediakan tepat untuk alasan ini.
sudo apt install sudo.ws
update-alternatives --config sudo
sudo update-alternatives --set sudo /usr/bin/sudo.wsSalin path yang persis dari output --config, bukan dari halaman ini, karena daftar tersebut adalah daftar yang dapat diterima oleh sistem Anda sendiri. Untuk kembali ke sudo-rs nanti, atur alternative ke path biner sudo-rs dari daftar yang sama.
Biarkan sesi SSH kedua tetap terbuka, dalam keadaan login dan idle, sebelum mengubah apa pun yang memengaruhi sudo. File sudoers yang gagal diparse, atau alternative yang menunjuk ke biner yang tidak terpasang, dapat membuat Anda tidak memiliki cara untuk menjadi root pada server remote. Kebiasaan ini sama pentingnya dengan semua hal lain yang Anda lakukan dalam sepuluh menit pertama pada VPS baru.
Perlakukan perpindahan kembali ini sebagai batas waktu, bukan sebagai perbaikan. Langkah ini memberi Anda waktu satu minggu untuk menulis ulang aturan dengan benar. Penulisan ulang tersebut layak dilakukan karena setiap aturan wildcard yang Anda hapus sebelumnya memberikan izin yang lebih luas daripada yang dimaksudkan oleh pembuatnya.
FAQ
Mengapa aturan wildcard sudoers saya berhenti berfungsi di Ubuntu 26.04?
Karena Ubuntu 26.04 LTS memilih sudo-rs sebagai sudo default, dan sudo-rs tidak mencocokkan pola wildcard di dalam argumen perintah. sudo-rs mengizinkan wildcard pada nama file perintah, "" untuk menunjukkan bahwa tidak ada argumen, dan satu * sebagai argumen terakhir. Aturan seperti /usr/bin/systemctl restart app-* menempatkan pola di tengah argumen, sehingga tidak memberikan hak apa pun dan perintah ditolak. Jalankan sudo -l -U deploy sebagai root untuk melihat hak yang benar-benar dimiliki akun tersebut, lalu ganti aturan itu dengan perintah yang ditulis secara persis atau dengan skrip wrapper yang dimiliki root.
Bagaimana cara kembali ke sudo asli di Ubuntu 26.04?
Sudo asli dikemas sebagai sudo.ws. Instal dengan sudo apt install sudo.ws, lalu arahkan alternative ke sana dengan sudo update-alternatives --set sudo /usr/bin/sudo.ws. Jalankan update-alternatives --config sudo terlebih dahulu untuk melihat path persis yang tersedia pada sistem Anda, dan biarkan sesi SSH kedua tetap terbuka saat Anda mengubahnya. Langkah ini tidak mengembalikan sudo-ldap, yang telah dihapus dari 26.04, terlepas dari implementasi yang Anda pilih.
Apakah sudo-rs membaca file /etc/sudoers yang sama?
Ya. sudo-rs membaca /etc/sudoers dan file drop-in di bawah /etc/sudoers.d/, dengan sintaks yang sama untuk pengguna, grup, alias, spesifikasi run-as, dan tag NOPASSWD. sudo-rs mengimplementasikan subset bahasa sudoers, sehingga perbedaannya muncul sebagai konstruksi yang tidak tersedia, bukan konstruksi yang berperilaku berbeda. Edit dengan sudo visudo, lalu verifikasi dengan sudo visudo -c sebelum menutup sesi Anda.
Apa pengganti sudo -E di sudo-rs?
sudo -E tidak diimplementasikan. Fitur tersebut juga sudah tidak dianjurkan pada sudo asli karena memberikan proses root environment yang dikendalikan oleh pemanggil merupakan cara yang umum untuk mengubah perilaku proses tersebut. Cantumkan hanya variabel yang benar-benar diperlukan di sudoers, dengan baris seperti Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY". env_reset selalu aktif di sudo-rs dan tidak dapat dinonaktifkan, sehingga setiap variabel yang tidak Anda pertahankan akan dihapus.