Bisakah suatu program mengetahui bahwa program tersebut dijalankan dengan sudo?

27

Saya memiliki program yang harus berperilaku berbeda jika sedang dijalankan di bawah "sudo". Apakah ada cara untuk mengetahui apakah itu dijalankan di bawah sudo?

Pembaruan: Seseorang bertanya mengapa saya ingin melakukan ini. Dalam hal ini, pada Mac menggunakan MacPorts ada output yang memberitahu Anda untuk memotong dan menempelkan perintah tertentu. Jika perintah MacPorts dijalankan dengan "sudo", itu harus menyertakan sudo dalam perintah sampel:

$ sudo port selfupdate 
--->  Updating MacPorts base sources using rsync
MacPorts base version 2.2.1 installed,
MacPorts base version 2.2.1 downloaded.
--->  Updating the ports tree
--->  MacPorts base is already the latest version

The ports tree has been updated. To upgrade your installed ports, you should run
  port upgrade outdated

^^^^^^^^^ it would be really sweet if it output "sudo port upgrade outdated" instead.  It would be even better if it just did it for you :-)
TomOnTime
sumber
Saya ingin tahu: dapatkah Anda menjelaskan bagaimana seharusnya berperilaku berbeda?
sciurus
1
@sciurus biasanya use-case yang umum adalah dalam skrip instalasi yang membutuhkan hak akses root; jika Anda tidak memilikinya, langsung mati saja.
Nick T
3
Ini terdengar seperti meta.stackexchange.com/questions/66377/what-is-the-xy-problem/… . Apa yang sebenarnya ingin Anda lakukan?
Jenny D mengatakan Reinstate Monica
Samar-samar saya ingat beberapa perintah sadar bahwa itu dijalankan sebagai root atau tidak ... Saya pikir jawabannya adalah "ya"
Rolf

Jawaban:

48

Ya, ada 4 variabel lingkungan yang ditetapkan ketika suatu program berjalan di bawah sudo:

$ sudo env |grep SUDO
SUDO_COMMAND=/usr/bin/env
SUDO_USER=tal
SUDO_UID=501
SUDO_GID=20

Perhatikan bahwa ini dapat dipalsukan dengan hanya mengaturnya. Jangan percayai mereka untuk hal-hal penting.

Sebagai contoh: Dalam program ini kita perlu memberi tahu pengguna untuk menjalankan beberapa program lain. Jika yang sekarang dijalankan dengan sudo, yang lain juga.

#!/bin/bash

echo 'Thank you for running me.'

if [[ $(id -u) == 0 ]]; then
  if [[ -z "$SUDO_COMMAND" ]]; then
    echo 'Please now run: next_command'
  else
    echo 'Please now run: sudo next_command'
  fi
else  echo 'Error: Sadly you need to run me as root.'
  exit 1
fi

Perhatikan bahwa ini hanya menguji variabel SUDO_ * jika pertama dapat membuktikan bahwa itu berjalan sebagai root. Bahkan kemudian hanya menggunakannya untuk mengubah beberapa teks bermanfaat.

TomOnTime
sumber
2
Apa yang akan saya gunakan untuk "sesuatu yang kritis?"
Kevin - Reinstate Monica
3
@Kevin jika seseorang mengacaukan lingkungannya untuk dipalsukan dengan hak istimewa yang tinggi, maka semoga mereka tahu apa yang mereka lakukan dan akan menerima konsekuensinya.
Nick T
Diturunkan karena jawaban apa pun yang harus dikualifikasi oleh "jangan percayai mereka untuk hal-hal yang kritis" sama sekali bukan jawaban, tetapi peretasan yang jelek.
Stephen C
Ini adalah jawaban yang bisa diterima untuk pertanyaan yang diajukan. Peringatan itu harus ada untuk orang-orang yang mungkin mencoba untuk mencegah penggunaan sudo, daripada hanya mendeteksinya . Pencegahan harus dilakukan dengan menggunakan alias perintah sudo untuk membatasi perintah apa yang dapat dijalankan pengguna.
dwurf
11

Ini tidak menjawab pertanyaan secara langsung tetapi saya tidak berpikir pertanyaan yang tepat diajukan di sini. Sepertinya saya penanya menginginkan program yang akan bertindak berbeda mungkin jika memiliki izin tertentu atau tidak, namun saya berpendapat bahwa memeriksa sudo bukanlah cara untuk melakukan itu. Pertama banyak sistem mungkin tidak mengimplementasikan "sudo", itu sama sekali tidak diperlukan di Linux atau banyak Unix.

Misalnya seorang pengguna mungkin sudah login sebagai root, membuat sudo tidak masuk akal atau mungkin sistem memiliki pengguna non root yang masih memiliki kemampuan untuk melakukan tugas administratif yang mungkin ingin dilakukan oleh program. Akhirnya mungkin sistem tidak memiliki root atau sudo sama sekali dan sebagai gantinya menggunakan sistem kontrol akses wajib dengan kemampuan yang berbeda dan tidak menangkap semua pengguna super untuk sudo ke. Atau pengguna bisa saja sudoed, tetapi ke dalam akun yang memiliki -kurang-izin daripada akun mereka sendiri karena alasan keamanan (saya sering menjalankan kode yang tidak terpercaya dengan pengguna sementara yang tidak dapat diandalkan yang hanya dapat menulis ke ramdis untuk turun, tidak menaikkan izin saya ). Secara keseluruhan adalah ide yang buruk untuk mengasumsikan model izin khusus seperti sudo atau keberadaan root atau menganggap pengguna sudo memiliki hak istimewa tertentu.

Jika Anda ingin mengetahui apakah Anda memiliki izin untuk melakukan operasi, cara terbaik biasanya adalah dengan hanya mencoba dan melakukannya kemudian periksa errno untuk masalah izin jika gagal atau jika ini adalah operasi multi-tahap yang harus gagal atau berhasil. Anda dapat memeriksa apakah suatu operasi akan berfungsi dengan fungsi-fungsi seperti akses POSIX fungsi (waspadai kemungkinan kondisi balapan di sini jika izin diubah secara aktif)

Jika selain itu Anda perlu tahu pengguna sebenarnya di balik sudo Anda dapat menggunakan getlogin fungsi yang harus bekerja untuk setiap sesi interaktif dengan terminal yang mendasarinya dan akan memungkinkan Anda misalnya untuk menemukan siapa yang 'benar-benar' menjalankan perintah untuk mengaudit atau menemukan direktori home dari pengguna nyata untuk menyimpan log.

Akhirnya jika yang Anda inginkan adalah untuk mengetahui apakah pengguna memiliki akses root (Masih ide yang buruk tetapi kurang spesifik implementasi) Anda dapat menggunakan getuid untuk memeriksa uid dari 0 dan dengan demikian root.

Vality
sumber
7

Ada dua mekanisme yang bisa digunakan.

  • Memeriksa variabel lingkungan dapat dipalsukan, namun merupakan cara termudah untuk dilakukan. growisofstidak suka dijalankan di bawah SUDO, jadi saya hapus variabel SUDO di skrip tempat saya menggunakannya. Itu bisa dipalsukan dengan cara lain. (Variabel SUDO juga dibawa ke lingkungan untuk skrip dijalankan di bawah perintah at dan batch.)
  • Cara lain untuk melihat apakah Anda menjalankan sudo adalah dengan menjalankan daftar proses dari proses induk Anda mencari sudo. Akan sulit untuk menyembunyikan bahwa Anda menjalankan sudo dengan cara ini, tetapi lebih rumit. Dimungkinkan untuk berpura-pura bahwa Anda menjalankan sudo.

Lebih umum untuk memeriksa apakah Anda menjalankan sebagai pengguna yang sesuai. The idperintah dapat digunakan untuk melakukan hal ini. Skrip TomOnTime menggunakan idperintah untuk menentukan apakah sudomungkin diperlukan untuk menjalankan perintah berikutnya.

BillThor
sumber
1
> Akan sulit untuk menyembunyikan bahwa Anda menjalankan sudo dengan cara ini. Tidak bisakah Anda mengganti nama sudobiner menjadi sesuatu yang lain? Atau sebutkan beberapa executable lain sudountuk memalsukan yang sebaliknya? Bukannya aku benar-benar berharap ada orang waras untuk melakukan itu ...
Bob
@ Bob Anda akan membutuhkan rootakses untuk mengganti nama sudoexecutable. Pengguna normal tidak akan bisa melakukan ini. Saya memang mencatat bahwa Anda dapat berpura-pura bahwa Anda berjalan di bawah sudo. Mengganti nama program yang ada akan berhasil. Kode yang diperlukan untuk sudoprogram palsu khusus sepele.
BillThor
Anda cukup mengunduh sudo biner dari suatu tempat dan memberikan izin yang tepat ...
Jens Timmerman
@JensTimmerman Anda memerlukan akses root untuk memberikan izin yang benar. Jika Anda hanya dapat mengubah nama atau menautkannya. Tidak perlu mengunduhnya. Jika Anda menginstalnya SUID ke id pengguna target (jika akan bekerja seperti itu), Anda harus sudah mengompromikan id pengguna target.
BillThor
ah, benar, ia menolak untuk bekerja tanpa setuid, salahku ...
Jens Timmerman
2

Anda dapat membandingkan id pengguna efektif vs nyata.

Ini tidak berarti bahwa program ini sedang menjalankan undo sudo (bisa juga setuid'd), tetapi menunjukkan bahwa program memiliki lebih banyak hak daripada yang diharapkan pengguna. (misalnya dalam program yang biasanya dijalankan tanpa hak tersebut, tetapi perlu dijalankan dengan mereka selama instalasi atau untuk menginstal pembaruan. Kemudian, Anda dapat menggunakan ini untuk memberikan umpan balik peringatan tentang itu).

blabla999
sumber
2
Tidak, sudosetel id efektif dan nyata. Berbeda dengan suid, yang tidak. Berikut ini adalah program C sepele yang dapat Anda gunakan untuk menguji (maaf, komentar akan menghapus baris baru, Anda harus menambahkannya kembali):#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { printf("real = %i, effective = %i\n", getuid(), geteuid()); return 0; }
derobert
... atau, sebagai alternatif,perl -E 'say $<, "\n", $>'
derobert
2

Anda dapat memeriksa variabel UID (EUID) yang efektif, sebagai berikut:

if [[ $EUID -eq 0 ]]; then
    echo "running as root"
else
    echo "not running as root"
fi
Eliran Malka
sumber
Ini tidak menjawab pertanyaan. Kode memberikan output yang sama ketika dijalankan sebagai root seperti halnya ketika dijalankan sebagai sudo.
Stephen C
@StephenC - saya pikir untuk keperluan OP, tidak ada perbedaan. IMHO tujuan mereka adalah untuk mengidentifikasi eksekusi sudo atau eksekusi dari shell root otentik tanpa perbedaan.
Eliran Malka
1
Saya pikir Anda mungkin benar. Saya datang ke sini karena saya tidak mengerti mengapa sudo echo $USERmencetak nama pengguna yang tidak terjangkau (variabel diganti SEBELUM sudo). Saya akhirnya menggunakan kode Anda dalam skrip saya. Terima kasih!
Stephen C
selamat datang :)
Eliran Malka
-1

Anda dapat menyentuh file di /rootdan kemudian if -e. Dan jika -e benar, rm(memeriksa kode kesalahan) itu jadi tes Anda bekerja lain kali.

Memeriksa kode kesalahan (atau mengembalikan kode) setelah rm mencegah seseorang dengan mudah menggunakan kekuatan sudo untuk membuat file untuk memainkan lelucon pada Anda.

Chris K
sumber
4
Jawaban ini memeriksa apakah proses tersebut memiliki izin untuk menulis /root(yang tidak harus sama dengan menjalankan sebagai UID 0), tetapi tidak memeriksa apakah proses tersebut menggunakan izin tersebut sudo.
Ladadadada
Ya, "ribuan cara menguliti kucing"; ketika saya menulis jawabannya, saya memikirkan 4 atau 5 hal lagi, jadi saya membungkusnya.
Chris K
-2

Saya menemukan bahwa ini bekerja dengan baik untuk ini

[ $(cat /proc/$PPID/loginuid) -ne 0 ] && [ "$USER" == "root" ]
keributan
sumber
Ini tidak berfungsi ketika saya mencobanya di FreeBSD, Centos7, atau MacOS X. Saya pikir maksud Anda "/ proc" bukan "/ etc". Tetapi bahkan dengan perubahan itu, itu tidak bekerja pada salah satu dari ketiganya. "$ USER" disetel ulang oleh sudo. Apakah maksud Anda $ SUDO_USER? Juga, maksud Anda "[[" bukannya "["?
TomOnTime
1
saya memperbaiki contohnya. pada dasarnya memeriksa loginuid tidak sama dengan 0, tetapi pengguna root.
ruckc