Saya mengelola kotak Gentoo Hardened yang menggunakan kemampuan file untuk menghilangkan sebagian besar kebutuhan untuk binari setuid-root (mis. /bin/ping
Memiliki CAP_NET_RAW, dll.).
Infact, satu-satunya biner yang tersisa adalah ini:
abraxas ~ # find / -xdev -type f -perm -u=s
/usr/lib64/misc/glibc/pt_chown
abraxas ~ #
Jika saya menghapus bit setuid, atau remount filesystem root saya nosuid
, sshd dan GNU Screen berhenti bekerja, karena mereka memanggil grantpt(3)
master pesudoterminals dan glibc rupanya mengeksekusi program ini untuk chown dan chmod slave pseudoterminal di bawah /dev/pts/
, dan GNU Screen peduli ketika fungsi ini gagal
Masalahnya adalah, manual untuk grantpt(3)
menyatakan secara eksplisit bahwa di Linux, dengan sistem devpts
file yang terpasang, tidak ada biner pembantu seperti itu diperlukan; kernel akan secara otomatis mengatur UID & GID dari slave ke UID & GID yang sebenarnya dari proses yang dibuka /dev/ptmx
(dengan memanggil getpt(3)
).
Saya telah menulis contoh program kecil untuk menunjukkan ini:
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int master;
char slave[16];
struct stat slavestat;
if ((master = getpt()) < 0) {
fprintf(stderr, "getpt: %m\n");
return 1;
}
printf("Opened a UNIX98 master terminal, fd = %d\n", master);
/* I am not going to call grantpt() because I am trying to
* demonstrate that it is not necessary with devpts mounted,
* the owners and mode will be set automatically by the kernel.
*/
if (unlockpt(master) < 0) {
fprintf(stderr, "unlockpt: %m\n");
return 2;
}
memset(slave, 0, sizeof(slave));
if (ptsname_r(master, slave, sizeof(slave)) < 0) {
fprintf(stderr, "ptsname: %m\n");
return 2;
}
printf("Device name of slave pseudoterminal: %s\n", slave);
if (stat(slave, &slavestat) < 0) {
fprintf(stderr, "stat: %m\n");
return 3;
}
printf("Information for device %s:\n", slave);
printf(" Owner UID: %d\n", slavestat.st_uid);
printf(" Owner GID: %d\n", slavestat.st_gid);
printf(" Octal mode: %04o\n", slavestat.st_mode & 00007777);
return 0;
}
Amati dalam tindakan dengan bit setuid pada program yang disebutkan di atas dihapus:
aaron@abraxas ~ $ id
uid=1000(aaron) gid=100(users) groups=100(users)
aaron@abraxas ~ $ ./ptytest
Opened a UNIX98 master terminal, fd = 3
Device name of slave pseudoterminal: /dev/pts/17
Information for device /dev/pts/17:
Owner UID: 1000
Owner GID: 100
Octal mode: 0620
Saya hanya punya beberapa ide tentang cara mengatasi masalah ini:
1) Ganti program dengan kerangka yang hanya mengembalikan 0.
2) Patch grantpt () di libc saya untuk tidak melakukan apa pun.
Saya dapat mengotomatiskan keduanya, tetapi apakah ada yang punya rekomendasi untuk yang satu di atas yang lain, atau rekomendasi untuk cara lain untuk menyelesaikan ini?
Setelah ini diselesaikan, saya akhirnya bisa mount -o remount,nosuid /
.
sumber
pty
(sebagaimana mestinya) tetapi untuk program ini?Jawaban:
Jika glibc Anda cukup mutakhir, dan devpts sudah diatur dengan benar, seharusnya tidak perlu memanggil
pt_chown
helper sama sekali.Anda mungkin mengalami masalah yang diketahui / potensial menghapus setuid-root dari
pt_chown
.grantpt()
didukungdevfs
dari glibc-2.7 , perubahan dilakukan di glibc-2.11 sehingga daripada memeriksa secara eksplisitDEVFS_SUPER_MAGIC
, ia memeriksa sebagai gantinya untuk melihat apakah perlu melakukan pekerjaan apa pun sebelum mencobachown()
atau mundur untuk memohonpt_chown
.Dari
glibc-2.17/sysdeps/unix/grantpt.c
Sebuah bait serupa digunakan untuk memeriksa gid dan izin. Tangkapannya adalah bahwa uid, gid dan mode harus sesuai dengan harapan (Anda, tty, dan tepat 620; konfirmasi dengan
/usr/libexec/pt_chown --help
). Jika tidak,chown()
(yang akan membutuhkan kapabilitas CAP_CHOWN, CAP_FOWNER dari pemanggilan biner / proses) dicoba, dan jika itu gagal,pt_chown
penolong eksternal (yang harus di-setuid-root) dicoba. Agarpt_chown
dapat menggunakan kemampuan itu (dan karenanya glibc Anda) harus dikompilasi denganHAVE_LIBCAP
. Namun , tampaknya itupt_chown
(pada glibc-2.17 , dan seperti yang Anda catat meskipun Anda belum menyatakan versinya) sulit dikodekan untuk menginginkangeteuid()==0
terlepas dariHAVE_LIBCAP
, kode yang relevan dariglibc-2.17/login/programs/pt_chown.c
:(Berharap
geteuid()==0
sebelum mencoba menggunakan kapabilitas tampaknya tidak benar-benar sesuai semangat kapabilitas, saya akan menggunakan logging bug yang satu ini.)Solusi potensial mungkin untuk memberikan CAP_CHOWN, CAP_FOWNER ke program yang terpengaruh, tapi saya benar-benar tidak merekomendasikan itu karena Anda tidak dapat membatasi itu untuk ptys tentu saja.
Jika itu tidak membantu Anda menyelesaikannya, menambal
sshd
danscreen
sedikit kurang menyenangkan dibandingkan menambal glibc. Karena masalahnya terletak pada glibc, pendekatan yang lebih bersih adalah penggunaan selektif injeksi DLL untuk mengimplementasikan dummygrantpt()
.sumber