Le framework Android s'occupe de beaucoup de choses lorsqu'il s'agit de forker une application à partir de zygote
. En bref, il est presque impossible d'exécuter un processus d'application à partir de la ligne de commande pour qu'il se comporte de la manière suivante "exactement de la même manière" comme si l'application était correctement lancée. Continuez à lire pour avoir une idée de la raison pour laquelle il en est ainsi.
Afin d'exécuter bash
dans le contexte de l'application Termux afin qu'elle se comporte exactement de la même manière que si elle était lancée depuis l'application, elle doit au moins être exécutée :
- Avec l'UID/GID de l'application attribué par le gestionnaire de paquets au moment de l'installation.
- Avec groupe supplémentaire
inet
( 3003
), qui est nécessaire pour créer des sockets réseau et est attribué à toute application au moment de l'installation qui déclare android.permission.INTERNET
dans son AndroidManifest.xml . Pour plus de détails, voir Comment fonctionne le mappage des permissions d'Android avec les UID/GID ? .
- Avec groupe supplémentaire
everybody
( 9997
) qui est utilisé pour contrôler l'accès en lecture/écriture de l'application à l'adresse suivante /sdcard
. Pour plus de détails, voir Qu'est-ce que l'UID "u#_everybody" ? .
- Avec des groupes supplémentaires
<uid>_cache
(UID+10000) et all_<uid>
(UID+40000) pour que l'application puisse accéder à son cache, au code exécutable natif, etc. Mais ces éléments ne sont pas nécessairement nécessaires puisque nous n'exécutons pas l'application elle-même.
- En entrant dans l'espace de nom de l'application Termux (
com.termux
) qui est nécessaire pour le processus supgid 9997
pour travailler. Si l'application n'est pas en cours d'exécution (par exemple, si elle est exécutée à partir de adb shell
), supgid 1015
peut être utilisé pour obtenir un accès en écriture à /sdcard
mais ce n'est pas comme ça que l'application fonctionne.
- En abandonnant tous les Linux capacités (privilèges Root granulaires dans Efficace , Autorisé , Héritage , Délimitation y Ambiant ) ainsi que la mise en place
securebits
et l'attribut de contrôle du processus NO_NEW_PRIVS qui s'assure que l'application n'est pas en mesure d'élever les privilèges en faisant usage de setuid
ou les capacités du fichier.
- Avec blocage
syscalls
en appliquant seccomp-bpf filtre.
- Avec le contexte SELinux de l'application, qui est déterminé à l'installation/exécution sur la base du MMAC. ( 1 , 2 ) .
- En ajoutant le processus à des cgroups par exemple
cpuset
, memcg
etc. comme le fait le framework d'Android.
- Par attraper , blocage y en ignorant le même signaux comme le ferait l'application.
- En définissant l'environnement sur lequel il s'appuie. Par exemple, le bash de Termux ne s'exécutera pas sans
LD_LIBRARY_PATH
dont il a besoin pour la liaison dynamique.
Il n'y a pas un seul outil en ligne de commande disponible qui puisse faire tout ce sandboxing, il ne peut être réalisé entièrement que de manière programmatique (cf. Mini-prison ), ou peuvent utiliser plusieurs outils, par ex. nsjail
/ firejail
pour le réglage seccomp
filtres, runcon
pour modifier le contexte SELinux, capsh
pour modifier les DAC/capacités, nsenter
pour entrer dans l'espace de noms de montage, etc. setpriv
de util-linux
Le paquet peut faire le maximum :
~# uid=$(stat -c %u /data/data/com.termux)
~# pid=$(pidof -s com.termux)
~# label=$(cat /proc/$pid/attr/current)
~# export LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib
~# exec nsenter -t $pid -m setpriv --reuid $uid --regid $uid --groups 3003,9997 --bounding-set -all --selinux-label $label -- /system/bin/sh -c 'exec /data/data/com.termux/files/usr/bin/bash'
* nsenter
y setpriv
sont des applets busybox mais avec des fonctionnalités limitées. Pour aarch64
vous pouvez obtenir des binaires statiques ici : nsenter , setpriv .
Cependant, nous devons définir shell_exec
(étiquette de /system/bin/sh
) comme entrypoint
pour exécution par untrusted_app
contexte qui ne fait pas partie du stock sepolicy
(au moins sur Pie) :
~# supolicy --live 'allow untrusted_app shell_exec file entrypoint'
Exécuter /system/bin/sh
avant d'exécuter /data/data/com.termux/files/usr/bin/bash
est nécessaire car /data
La partition est montée avec nosuid
qui empêche la transition de contexte SELinux (de magisk
a untrusted_app
) ( 3 ) et vous obtenez une permission refusée. Vous pouvez envisager de monter /data
sans nosuid
pour sauter cette étape.
Pour la même raison --no-new-privs
y --selinux-label
ne peuvent pas être utilisés conjointement.
Tout cela se passe dans le monde natif, rien dans la pile Java. Nous n'avons donc aucun contrôle direct sur des choses comme autorisations du manifeste qui fonctionnent entièrement dans le cadre d'Android. Cependant, l'application de la permission manifeste est également basée sur les UIDs. ( 4 ) . Par exemple, si Termux a reçu android.permission.WRITE_EXTERNAL_STORAGE
le bash que nous exécutons avec l'UID de Termux sera aussi capable d'écrire sur /sdcard
.
D'après votre commentaire :
Je ne comprends pas comment cela est possible. Par exemple, considérez la sortie :
u0_a129 ~$ /sbin/su --context=u:object_r:app_data_file:s0:c512,c768 u0_a129 -c /system/bin/id
uid=10129(u0_a129) gid=10129(u0_a129) groups=10129(u0_a129) context=u:r:magisk:s0
u0_a129 ~$ /system/bin/id
uid=10129(u0_a129) gid=10129(u0_a129) groups=10129(u0_a129),3003(inet),9997(everybody),20129(u0_a129_cache),50129(all_a129),99909997(u999_everybody) context=u:r:untrusted_app_27:s0:c512,c768
D'après ce que j'ai compris, c'est ainsi que fonctionne le contrôle d'accès discrétionnaire d'Unix. Tout d'abord, il faut passer --context
à celui de Magisk /sbin/su
ne fait aucune différence comme expliqué ici :
l'option existe toujours pour la compatibilité CLI avec les applications conçues pour SuperSU. Cependant, l'option est silencieusement ignorée car elle n'est plus pertinente.
Donc le contexte n'a pas changé, comme vous pouvez le voir, c'est toujours u:r:magisk:s0
. Deuxièmement, Magisk su
n'est pas le véritable utilisateur du commutateur ( 5 ) il fournit une fonctionnalité minimale de la norme su
(celui que nous avons sur Linux). Pour plus de détails, voir Comment fonctionne Magisk ?
Dans votre première commande, il a défini l'UID, le GID et les groupes supplémentaires à l'UID que vous avez fourni. Vous n'avez pas demandé su
pour définir des groupes supplémentaires, ni l'un ni l'autre ne le peut.
Dans la deuxième commande, vous voyez l'UID, le GID, les groupes supplémentaires et le contexte SELinxu qui ont été définis par zygote
quand il a bifurqué sur le DVM/ART de l'application ( com.termux
dans le cas de Termux). Les groupes supplémentaires sont expliqués ci-dessus. 99909997
est également expliqué dans le lien donnée ci-dessus.