Bagaimana Anda menemukan pengguna asli melalui beberapa perintah sudo dan su?

93

Saat menjalankan skrip melalui sudo atau su saya ingin mendapatkan pengguna asli. Ini harus terjadi terlepas dari beberapa sudoatau suberjalan di dalam satu sama lain dan secara khusus sudo su -.

evan
sumber

Jawaban:

136

Hasil:

Gunakan who am i | awk '{print $1}'ATAU lognamekarena tidak ada metode lain yang dijamin.

Masuk sebagai diri:

evan> echo $USER
evan
evan> echo $SUDO_USER

evan> echo $LOGNAME
evan
evan> whoami
evan
evan> who am i | awk '{print $1}'
evan
evan> logname
evan
evan>

Sudo normal:

evan> sudo -s
root> echo $USER
root
root> echo $SUDO_USER
evan
root> echo $LOGNAME
root
root> whoami
root
root> who am i | awk '{print $1}'
evan
root> logname
evan
root>

sudo su -:

evan> sudo su -
[root ]# echo $USER
root
[root ]# echo $SUDO_USER

[root ]# echo $LOGNAME
root
[root ]# whoami
root
[root ]# who am i | awk '{print $1}'
evan
[root ]# logname
evan
[root ]#

sudo su -; su tom:

evan> sudo su -
[root ]# su tom
tom$ echo $USER
tom
tom$ echo $SUDO_USER

tom$ echo $LOGNAME
tom
tom$ whoami
tom
tom$ who am i | awk '{print $1}'
evan
tom$ logname
evan
tom$
evan
sumber
1
Dalam hal ini, Anda dapat menggunakanwho | awk '{print $1}'
SiegeX
2
... jika Anda satu-satunya yang masuk (dan itu hanya sekali).
Dijeda sampai pemberitahuan lebih lanjut.
9
yang Anda butuhkan hanyalah 2 argumen: who am isama dengan who smells bad. Selain itu, ini hanya berfungsi jika STDINdikaitkan dengan TTY. Jadi jika Anda menjalankannya echo "hello" | who am itidak akan berhasil.
tylerl
1
Anda tidak akan berjalan echo "hello" | who am inormal, kecuali skrip Anda berjalan di lingkungan di mana tidak ada terminal. Kemudian Anda mungkin melihat kesalahan yang who am itidak berfungsi karena ada semacam masalah dengan stdin yang tidak dapat dibaca, dalam hal ini Anda dapat mencoba memasukkan data ke who am idalam keadaan putus asa untuk memenuhi persyaratan stdin itu. tylerl hanya mencatat bahwa dia sudah melalui jalur itu, dan pipa tidak berfungsi karena stdin harus dapat dibaca dan dikaitkan dengan TTY.
Edwin Buck
4
@ Bahkan Benar, meskipun saya ingin itu memerlukan konfigurasi sesedikit mungkin, jadi saya menggunakan lognamesekarang, yang ternyata berhasil, di mana who am itidak.
Bart van Heukelom
18

Tidak ada jawaban yang sempurna . Saat Anda mengubah ID pengguna, ID pengguna asli biasanya tidak disimpan, sehingga informasinya hilang. Beberapa program, seperti lognamedan who -mmenerapkan peretasan di mana mereka memeriksa untuk melihat terminal mana yang terhubung stdin, dan kemudian memeriksa untuk melihat pengguna mana yang masuk di terminal itu.

Solusi ini sering kali berhasil, tetapi tidak selalu berhasil, dan tentunya tidak boleh dianggap aman. Misalnya, bayangkan jika whomenghasilkan yang berikut:

tom     pts/0        2011-07-03 19:18 (1.2.3.4)
joe     pts/1        2011-07-03 19:10 (5.6.7.8)

tomdigunakan suuntuk mendapatkan root, dan menjalankan program Anda. Jika STDINtidak diarahkan, maka program seperti lognameakan keluar tom. Jika IS diarahkan ulang (misalnya dari file) sebagai berikut:

logname < /some/file

Maka hasilnya adalah " no login name", karena inputnya bukan terminal. Lebih menarik lagi, bagaimanapun, adalah fakta bahwa pengguna dapat menyamar sebagai pengguna login yang berbeda. Karena Joe login pada poin / 1, Tom bisa berpura-pura menjadi dia dengan berlari

logname < /dev/pts1

Sekarang, dikatakan joemeskipun tom adalah orang yang menjalankan perintah. Dengan kata lain, jika Anda menggunakan mekanisme ini dalam peran keamanan apa pun, Anda gila.

tylerl
sumber
2
Jika Anda menjalankan skrip sendiri (sebagaimana dibuktikan dengan perintah yang digunakan), keamanan bukanlah masalahnya. Jika ya, Anda memiliki lebih banyak masalah karena mereka juga memiliki akses sudo. Orang tersebut dapat menyalin skrip dan memodifikasinya sesuka mereka. Ini hanyalah cara untuk mendapatkan nama login untuk digunakan dalam skrip. Atau apakah saya melewatkan sesuatu tentang apa yang Anda katakan?
evan
1
@evan: Memiliki akses sudo tidak menyiratkan kemampuan untuk menimpa file.
Flimzy
@Flimzy Dalam hal apa root tidak memiliki kemampuan untuk menimpa file?
evan
1
@evan: Setiap kali akses sudo Anda tidak memberi Anda akses ke shell, atau perintah lain yang dapat menimpa file, tentunya.
Flimzy
@evan sudo akses tidak selalu (tidak seharusnya dalam kebanyakan kasus admin) akses root total. Ini adalah sekumpulan konteks eksekusi terbatas yang dapat dikonfigurasi.
DylanYoung
8

Ini adalah kshfungsi yang saya tulis di HP-UX. Saya tidak tahu bagaimana ini akan bekerja Bashdi Linux. Idenya adalah bahwa sudoproses tersebut berjalan sebagai pengguna asli dan proses anak adalah pengguna target. Dengan bersepeda kembali melalui proses induk, kita dapat menemukan pengguna dari proses aslinya.

#
# The options of ps require UNIX_STD=2003.  I am setting it
# in a subshell to avoid having it pollute the parent's namespace.
#
function findUser
{
    thisPID=$$
    origUser=$(whoami)
    thisUser=$origUser
    while [ "$thisUser" = "$origUser" ]
    do
        ( export UNIX_STD=2003; ps -p$thisPID -ouser,ppid,pid,comm ) | grep $thisPID | read thisUser myPPid myPid myComm
        thisPID=$myPPid
    done
    if [ "$thisUser" = "root" ]
    then
        thisUser=$origUser
    fi
    if [ "$#" -gt "0" ]
    then
        echo $origUser--$thisUser--$myComm
    else
        echo $thisUser
    fi
    return 0
}

Saya tahu pertanyaan aslinya sudah lama sekali tetapi orang-orang (seperti saya) masih bertanya dan sepertinya ini adalah tempat yang bagus untuk memberikan solusi.

pengguna1683793
sumber
5

Bagaimana jika menggunakan logname (1) untuk mendapatkan nama login pengguna?

sam
sumber
logname(1)tidak berfungsi tetapi berfungsi logname- menambahkan hasil di atas
evan
awalnya saya telah mencoba $LOGNAMEtetapi tidak berhasil. Juga ditambahkan ke hasil di atas.
evan
Apakah lognamemasih membutuhkan tty? Dengan tes saya, itu selalu berlalu. (Mungkin saya melakukan sesuatu yang salah.) Saya menjalankan linux dengan coreutils 8.26.
simohe
Nama log saya (GNU coreutils) 8.28 on selalu mengembalikan "nama log: tidak ada nama login" (Ubuntu 18.04.2)
sondra.kinsey
5
THIS_USER=`pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1 | sed 's/[()]//g'`

Itulah satu-satunya hal yang berhasil bagi saya.

Grey Christoforo
sumber
1
Tidak ada penjelasan, dan hanya sedikit peningkatan dari jawaban yang ada
sondra.kinsey
2

Fungsi findUser () user1683793 diporting ke bashdan diperpanjang sehingga mengembalikan nama pengguna yang disimpan di pustaka NSS juga.

#!/bin/bash

function findUser() {
    thisPID=$$
    origUser=$(whoami)
    thisUser=$origUser

    while [ "$thisUser" = "$origUser" ]
    do
        ARR=($(ps h -p$thisPID -ouser,ppid;))
        thisUser="${ARR[0]}"
        myPPid="${ARR[1]}"
        thisPID=$myPPid
    done

    getent passwd "$thisUser" | cut -d: -f1
}

user=$(findUser)
echo "logged in: $user"
asdfghjkl.dll
sumber
FYI: fungsi ini (dan yang menjadi dasarnya) tidak akan berputar kembali melalui beberapa cangkang yang ditimbulkan oleh sudo bersarang satu sama lain.
asdfghjkl
2

bersepeda kembali dan memberikan daftar pengguna

berdasarkan jawaban pengguna1683793

Dengan mengecualikan proses non-TTY, saya melewati root sebagai inisiator login. Saya tidak yakin apakah itu mungkin terlalu berlebihan dalam beberapa kasus

#!/bin/ksh
function findUserList
{
    typeset userList prevUser thisPID thisUser myPPid myPid myTTY myComm
    thisPID=$$                 # starting with this process-ID
    while [ "$thisPID" != 1 ]  # and cycling back to the origin
    do
        (  ps -p$thisPID -ouser,ppid,pid,tty,comm ) | grep $thisPID | read thisUser myPPid myPid myTTY myComm
        thisPID=$myPPid
        [[ $myComm =~ ^su ]] && continue        # su is always run by root -> skip it
        [[ $myTTY == '?' ]] && continue         # skip what is running somewhere in the background (without a terminal)
        if [[ $prevUser != $thisUser ]]; then   # we only want the change of user
                prevUser="$thisUser"            # keep the user for comparing
                userList="${userList:+$userList }$thisUser"  # and add the new user to the list
        fi
        #print "$thisPID=$thisUser: $userList -> $thisUser -> $myComm " >&2
    done
    print "$userList"
    return 0
}

lognameatau who am itidak memberi saya jawaban yang diinginkan, terutama di daftar panjang su user1, su user2, su user3,...

Saya tahu pertanyaan aslinya sudah lama sekali tetapi orang-orang (seperti saya) masih bertanya dan sepertinya ini adalah tempat yang bagus untuk memberikan solusi.

ULick
sumber
2

Alternatif untuk memanggil ps beberapa kali: lakukan satu panggilan pstree

pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1

keluaran (saat masuk sebagai genap): (evan)

argumen pstree:

  • -l: garis panjang (bukan pemendekan)
  • -u: tampilkan ketika pengguna berubah sebagai (userName)
  • -s $$: tunjukkan orang tua dari proses ini

Dapatkan perubahan pengguna pertama (yaitu login) dengan grep -odanhead .

batasan: perintah tidak boleh mengandung kurung kurawal ()(biasanya tidak)

simohe
sumber
pstree -lu -s $$ | head -n1 | sed -e 's / [^ (] * (([^)] *)). * / \ 1 /'
Alexx Roche
0

Pada sistem yang berjalan systemd-logind, API systemd menyediakan informasi ini . Jika Anda ingin mengakses informasi ini dari skrip shell, perlu menggunakan sesuatu seperti ini:

$ loginctl session-status \
  | (read session_id ignored; loginctl show-session -p User $session_id)
User=1000

The session-statusdan show-ssessionsistem perintah dari loginctlmemiliki perilaku yang berbeda tanpa argumen: session-statusmenggunakan sesi saat ini, tetapi show-ssessionmenggunakan manajer. Namun, penggunaan show-sessionlebih disukai untuk penggunaan skrip karena keluarannya yang dapat dibaca mesin. Inilah sebabnya mengapa loginctldibutuhkan dua pemanggilan .

Florian Weimer
sumber