Wywołanie systemowe SELinux i chroot

21

TL; DR: To pytanie dotyczy ostatniego kroku, w przenośnym, zorientowanym na programistów procesie rootowania, który działa na wszystkich urządzeniach z Androidem. Nie opiera się na żadnym exploicie - jest to coś, co jesteśmy prawnie i moralnie uprawnieni, jako programiści, do naszych własnych maszyn. Jeśli otrzymam odpowiedź i uda mi się chrootować w moim Debianie, opublikuję zwięzły post na blogu, szczegółowo opisujący wszystkie etapy tego procesu dla wszystkich programistów, którzy chcą dostępu do roota na swoich tabletach - i nie chcą ufać podejrzanemu pochodzeniu „root-one-click”, które wiedzą Bóg na swoich komputerach (członkowie botnetu?) ... Jedynymi zależnościami będą źródła jądra maszyny (które producent jest prawnie zobowiązany) oraz obraz partycji rozruchowej (boot.img), co stanowi 99% przypadków w dostarczonych przez producenta aktualizacjach Over-The-Air lub osobno do pobrania jako samodzielny obraz z możliwością flashowania.

Minął tydzień, w którym spędziłem cały wolny czas na nowym tablecie z Androidem.

I prawie całkowicie odniosłem sukces - tworząc przenośny, zorientowany na programistów proces uzyskiwania uprawnień roota na moim tablecie z Androidem 5.0.2.

Ale brakuje jeszcze jednej rzeczy - nie mogę zrobić chroota (którego potrzebuję, aby uruchomić mój debootstrapdebian!)

Co zrobiłem do tej pory

  1. Najpierw zrobiłem drobną łatkę w źródłach jądra tabletu (dostarczonych przez producenta), a następnie skompilowałem własne jądro - w którym wyłączyłem sprawdzanie zmiany trybu wymuszania SELINUX . Konkretnie...

W security/selinux/selinuxfs.c:

...
if (new_value != selinux_enforcing) {
    /* Commented out by ttsiodras.
    length = task_has_security(current, SECURITY__SETENFORCE);
    if (length)
        goto out;
    */
    audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
        "enforcing=%d old_enforcing=%d auid=%u ses=%u",
        new_value, selinux_enforcing,
  1. Następnie zmieniłem obraz initrd /default.propna zawierający: ro.secure=0iro.debuggable=1

  2. Ponieważ initrd.imgbrakowało mi tego producenta , skompilowałem również su.cz https://android.googlesource.com/platform/system/extras/+/master/su/ i umieściłem wynikowy plik binarny pod /sbin/su, upewniając się, że jest ustawiony na SUID root ( chmod 04755 /sbin/su) .

Następnie spakowałem nowe jądro i nowy initrd, jak wyjaśniłem w odcinku 2 mojego poprzedniego postu - i uruchomiłem z własnego obrazu:

adb reboot boot-loader ; fastboot boot myboot.img

Więc jesteś rootem?

Tak, początkowo wydawało się sukcesem:

$ adb shell

shell@K01E_2:/ $ id

uid=2000(shell) gid=2000(shell) groups=1004(input),1007(log),1011(adb),
1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),
3003(inet),3006(net_bw_stats) 
context=u:r:shell:s0

shell@K01E_2:/ $ ls -l /sbin/su /sbin/_su
-rwxr-xr-x root     root          131 2015-10-03 10:44 su
-rwsr-xr-x root     root         9420 2015-10-03 01:31 _su

(the _su is the binary I compiled, set to SUID root, and "su" is
 a script I wrote to tell "su" to add me to all these groups...)

shell@K01E_2:/ $ cat /sbin/su

#!/system/bin/sh
export PATH=/system/bin:$PATH
exec /sbin/_su 0,0,1000,1028,2000,2001,1004,1007,1011,1015,\
   1028,3001,3002,3003,3006

I teraz osiągnąłem root:

shell@K01E_2:/ $ su

root@K01E_2:/ # id

uid=0(root) gid=0(root) 
groups=1000(system),1004(input),1007(log),1011(adb),
1015(sdcard_rw),1028(sdcard_r),1028(sdcard_r),2000(shell),2001(cache),
3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) 
context=u:r:shell:s0

Jestem w 100% pewien, że jestem rootem - nie tylko dlatego, idże tak mówi, ale także dlatego, że mogę robić rzeczy, których normalne procesy zdecydowanie nie mogą:

root@K01E_2:/ # ls -l /dev/block/platform/msm_sdcc.1/by-name/boot
lrwxrwxrwx root root 2015-10-03 10:47 boot -> /dev/block/mmcblk0p16

root@K01E_2:/ # dd if=/dev/block/mmcblk0p16 of=/dev/null bs=1M
16+0 records in
16+0 records out
16777216 bytes transferred in 0.569 secs (29485441 bytes/sec)

I oto - w końcu mogę odczytać surowe partycje z mojego tabletu!

I SELinux rzeczywiście znajduje się w trybie „w dół, pies”:

root@K01E_2:/ # getenforce                                                     
Permissive

Ale ... wciąż są rzeczy, których nie mogę zrobić:

root@K01E_2:/ # mkdir /my_mnt

root@K01E_2:/ # mount -t ext4 /dev/block/mmcblk1p2 /my_mnt
mount: Operation not permitted

Oznacza to, że nie mogę zamontować drugiej partycji sformatowanej w EXT4-fs na mojej zewnętrznej karcie SD.

Nie mogę też chrootować do mojego uroczego debootstrapDebiana:

root@K01E_2:/ # chroot /data/debian/ /bin/bash                             
chroot() fail
Operation not permitted

Czy to z powodu SELinuksa?

Nie wiem - jestem nowy (bardzo nowy - tydzień) w SELinux. Myślałem, że kiedy go uśpisz ( getenforceraport „Permissive”), nie będzie już przeszkadzał ...

Najwyraźniej się myliłem. W dół króliczej nory znów idziemy ...

Czy może to wynikać z kontekstu mojego procesu?

Pamiętaj, że idzwrócił ... "uid = 0 (root) gid = 0 (root) ... kontekst = u: r: shell: s0 "

Czy mogę zmienić ten kontekst? Będąc rootem, czy mogę odejść shell? A jeśli tak, przejdź do czego?

Odpowiedź na pierwsze pytanie brzmi runcon:

shell@K01E_2:/ $ runcon u:r:debuggerd:s0 /sbin/su

root@K01E_2:/ # id
uid=0(root) gid=0(root)... context=u:r:debuggerd:s0

Dobry. Ale w jakim kontekście pozwolę mounti chroot?

Czytając trochę więcej o SELinux, z powrotem na moim głównym komputerze, analizuję /sepolicyplik w katalogu głównym initrd.img:

linuxbox$ $ sesearch -A sepolicy | grep chroot
allow init_shell init_shell : capability { chown sys_chroot ...
allow init init : capability { chown dac_read_search sys_chroot ...
allow kernel kernel : capability { chown dac_override sys_chroot ... 
allow asus-dbug-d asus-dbug-d : capability { chown sys_chroot ...
...

OK, wiele możliwości! Zwłaszcza, że kernelwydaje się to obiecujące:

shell@K01E_2:/ $ runcon u:r:kernel:s0 /sbin/su

root@K01E_2:/ # id
uid=0(root) gid=0(root)... context=u:r:kernel:s0

root@K01E_2:/ # chroot /data/debian/ /bin/bash                             
chroot() fail
Operation not permitted

Cerować.

Kto do cholery mnie blokuje chroot?

Wszelkie porady są mile widziane ...

ttsiodras
źródło

Odpowiedzi:

12

Kto do cholery blokuje mi chrootowanie?

To nie był SELinux - to była gonitwa za gęsią skórką ( getenforcepowrót „Permissive” oznacza, że ​​SELinux tak naprawdę nie ma już na zdjęciu).

Winowajcą - po dodaniu sporej ilości printkźródeł jądra w celu śledzenia awarii obu chrooti mount- okazało się, że są to możliwości . Mówiąc dokładniej, „zestaw ograniczający możliwości” Androida - możesz przeczytać o nich wszystko za pomocą swojego man( man 7 capabilities) i przyznaję, że nigdy wcześniej nie zadałem sobie z tym trudu - moje codzienne zadania w systemie UNIX zależały od nich i nie miałem pojęcia ... spróbuj tego w Twój system Linux, aby przekonać się sam:

$ getfattr -d -m - /sbin/ping
getfattr: Removing leading '/' from absolute path names
# file: sbin/ping
security.capability=0s......

Widzieć? Ping nie jest już katalogiem głównym SUID - wykorzystuje informacje przechowywane w rozszerzonych atrybutach systemu plików, aby wiedzieć, że ma dostęp do warstwy surowych gniazd (więc może to zrobić ICMP - na poziomie IP).

W każdym razie, dygresję - punkt chirurgiczny w moim jądrze, w którym zatrzymałem „upuszczenie zestawu moich możliwości” - w sposób prawdopodobnie obrzydliwy, „niech oni wszyscy maszerują” - było to ( security/commoncap.c):

static long cap_prctl_drop(struct cred *new, unsigned long cap)
{
    if (!capable(CAP_SETPCAP))
        return -EPERM;
    if (!cap_valid(cap))
        return -EINVAL;

    // ttsiodras: come in, everyone, the water's fine!
    //cap_lower(new->cap_bset, cap);
    return 0;
}

Oznacza to, że NIGDY nie upuszcza się możliwości - bardzo bezpieczna konfiguracja :-)

$ adb shell

shell@K01E_2:/ $ su

root@K01E_2:/ # chroot /data/debian/ /bin/bash

root@localhost:/# export PATH=/bin:/sbin:/usr/bin:/usr/sbin:\
     /usr/local/bin:$PATH

root@localhost:/# cat /etc/issue
Debian GNU/Linux 8 \n \l

Cześć, mój słodki Debian :-)

Aha, i „Root checker” też działa - wyciąłem „su.c”, więc wszyscy na moim tablecie mogą zostać rootowani:

int main(int argc, char **argv)
{
  struct passwd *pw;
  uid_t uid, myuid;
  gid_t gid, gids[50];

  /* Until we have something better, only root and shell can use su. */
  myuid = getuid();
  //
  // ttsiodras - Oh no, you don't :-)
  //
  //if (myuid != AID_ROOT && myuid != AID_SHELL) {
  //    fprintf(stderr,"su: uid %d not allowed to su\n", myuid);
  //    return 1;
  //}

Teraz, że to działa, muszę zrobić to działać prawidłowo - to znaczy pozwolić tylko moje termuxi Terminal Emulatorużytkowników, aby wywołać sui chroot, i nie pozwolić każdy, a ich babcia :-)

ttsiodras
źródło
Czy ta metoda rootowania nie wymaga jednak możliwości flashowania własnego jądra? Aby to zrobić, należy odblokować bootloader. W tym momencie równie dobrze możesz po prostu sflashować niestandardowe odzyskiwanie i uzyskać w ten sposób root.
1110101001
@ 1110101001 Dla programu ładującego: oczywiście tak. Do odzyskiwania niestandardowego: nie ma czegoś takiego (jeszcze) dla mojego tabletu - jestem jednak teraz w stanie go utworzyć ;-)
ttsiodras
1
@ 1110101001: i jeszcze jedno - powiedział pan „zdolność do lampy błyskowej” - Ja nie błysnął mój obraz rozruchowy do tabletu, jestem po prostu uruchamianie z niego: fastboot boot my.img. Wierzę, że społeczność rootująca nazywa to rootowaniem na uwięzi :-) I oczywiście mógłbym to sflashować - gdybym chciał.
ttsiodras