Closed stek29 closed 6 years ago
We should also have jailbreakd setuid the binary while we're at it, since setuid() doesn't work
Yup, that's what I've meant by "Add su command to jailbreakd" :)
#include <spawn.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "common.h"
int main(int argc, char *argv[], char *envp[]) {
if (argc < 2) {
fprintf(stderr, "usage: %s program args...\n", argv[0]);
return EXIT_FAILURE;
}
posix_spawnattr_t attr;
posix_spawnattr_init(&attr);
posix_spawnattr_setflags(&attr, POSIX_SPAWN_START_SUSPENDED|POSIX_SPAWN_SETEXEC);
calljailbreakd(getpid(), JAILBREAKD_COMMAND_ENTITLE_AND_SIGCONT_AFTER_DELAY);
int ret = posix_spawnp(NULL, argv[1], NULL, &attr, &argv[1], envp);
fprintf(stderr, "Failed: %d (%s)\n", ret, strerror(ret));
return ret;
}
If we have something like a su command for jailbreakd we could use it in posix_spawn: We have a list of setuid binaries on the system and if the binary which gets spawned is in that list we elevate privileges.
@littlelailo hardcoding a a list of binaries isn't really a good idea. A better solution would be to get the path of the PID that's to get setuid, and check if the file on disk has the setuid flag set
@coolstar Oh, I thought that some MACF policy would deny the execution of setuid binaries, but if they just start without higher privileges, this is of course the better solution. So we could do something like this to check if the binary is a setuid binary:
#include <sys/stat.h>
#include <stdbool.h>
bool is_setuid(char* path) {
struct stat sb;
if (stat(path, &sb) == -1) {
return false;
}
if (sb.st_mode & S_ISUID) {
return true;
}
return false;
}
The code is of course vulnerable to a race condition (basic TOCTOU), but I don't think this is a big problem.
Does it seem like a bad idea to let /Developer/usr/bin/debugserver always get elevated, without needing to use su? So that it can be spawned for non-get-task-allow
entitled processes via the Xcode/Instruments/etc UI. Of course I’d be concerned about an app reading data from another app via spawning debugserver. CFUserNotification could be used to display a prompt and block till there's a response (or it times out). Would make something similar to SuperSU possible without needing to inject a tweak into SpringBoard.
Current state of implementation:
OTTO:/bootstrap mobile$ ps aux | grep "\-sh"
mobile 301 0.0 0.1 1584208 1216 s000 R+ 3:33PM 0:00.01 grep \-sh
mobile 299 0.0 0.1 1594464 2304 s000 Ss 3:32PM 0:00.03 -sh
OTTO:/bootstrap mobile$ ./jailbreakd_client
Usage:
jailbreakd_client <pid> <1 | 2 | 5>
1 = entitle+platformize the target PID
2 = entitle+platformize the target PID and subsequently sent SIGCONT
5 = rootify the pid (su/sudo/setuid(0))
OTTO:/bootstrap mobile$ ./jailbreakd_client 299 5
OTTO:/bootstrap mobile$ ps aux | grep "\-sh"
root 305 0.0 0.1 1584208 1392 s000 R+ 3:33PM 0:00.01 grep \-sh
root 299 0.0 0.1 1594464 2304 s000 Ss 3:32PM 0:00.04 -sh
OTTO:/bootstrap mobile$
Now I will try to implement the setuid check in posix_spawn.
This took way longer then I thought it would take. Anyway now everything works (App was restarted manual after each kill):
OTTO:~ root# ps aux | grep "test"
root 711 0.0 0.1 1584208 1392 s000 R+ 1:02PM 0:00.01 grep test
mobile 709 0.0 1.0 1640672 20240 ?? Ss 1:02PM 0:00.22 /var/containers/Bundle/Application/<uid>/test_posix_spawn.app/test_posix_spawn
OTTO:~ root# chmod +s /var/containers/Bundle/Application/<uid>/test_posix_spawn.app/test_posix_spawn
OTTO:~ root# kill -9 709
OTTO:~ root# ps aux | grep "test"
root 713 0.0 1.1 1641120 22208 ?? Ss 1:02PM 0:00.24 /var/containers/Bundle/Application/<uid>/test_posix_spawn.app/test_posix_spawn
root 715 0.0 0.1 1584288 1424 s000 R+ 1:02PM 0:00.01 grep test
OTTO:~ root# chmod -s /var/containers/Bundle/Application/<uid>/test_posix_spawn.app/test_posix_spawn
OTTO:~ root# kill -9 713
OTTO:~ root# ps aux | grep "test"
mobile 717 0.0 1.0 1641776 20128 ?? Ss 1:03PM 0:00.21 /var/containers/Bundle/Application/<uid>/test_posix_spawn.app/test_posix_spawn
root 719 0.0 0.1 1584288 1408 s000 R+ 1:03PM 0:00.01 grep test
OTTO:~ root#
Of course this does not work for anything which isn't going through launchd or xpc_proxy. So when you run a setuid binary over ssh (logged in as mobile) it won't elevate, there you need to elevate using jailbreakd_client's rootify command.
I will now test everything and removed my debug code. Pull request: #81
Nah, there's still no su binary.
oh lol
thought that added it for some reason
So the su binary should do the following(?):
Because I would like to implement this, but I want to make sure, that you're ok with my idea on how to implement it.
Yup, I think that's ok.
Update: the su binary is now working:
OTTO:~ root# ls -la /bootstrap/
total 348
drwxr-xr-x 17 root admin 544 Jan 31 21:25 .
drwxrwxr-t 19 root admin 608 Jan 31 21:25 ..
drwxr-xr-x 8 mobile staff 256 Jan 31 21:25 Library
-rwxr-xr-x 1 mobile staff 896 Dec 23 19:21 README
-rwxr-xr-x 1 mobile staff 52176 Jan 31 21:25 amfid_payload.dylib
drwxr-xr-x 53 mobile staff 1696 Jan 16 21:36 bin
-rw-r--r-- 1 mobile staff 453 Dec 22 04:09 buildlist.sh
drwxr-xr-x 4 mobile staff 128 Dec 20 02:42 etc
-rwxr-xr-x 1 mobile staff 53088 Jan 31 21:25 inject_criticald
-rwxr-xr-x 1 mobile staff 77216 Jan 31 21:25 jailbreakd
-rwxr-xr-x 1 mobile staff 50672 Jan 31 21:25 jailbreakd_client
-rwxr-xr-x 1 mobile staff 52976 Jan 31 21:25 pspawn_payload.dylib
drwxr-xr-x 9 mobile staff 288 Dec 25 00:39 sbin
-rwsr-xr-x 1 root wheel 51376 Jan 31 21:25 su
drwxr-xr-x 4 root admin 128 Jan 27 10:52 test
-rw-r--r-- 1 root admin 810 Jan 31 21:25 unjailbreak.sh
drwxr-xr-x 9 mobile staff 288 Jan 25 21:55 usr
====== (started process in other terminal)
OTTO:~ root# ps aux | grep "/3"
root 278 0.0 0.1 1584208 1216 s000 S+ 9:27PM 0:00.01 grep /3
root 274 0.0 0.1 1583968 1232 s001 S+ 9:27PM 0:00.00 ./test/3
root 273 0.0 0.1 1584992 1856 s001 S+ 9:27PM 0:00.02 ./su ./test/3
OTTO:~ root#
Other terminal:
OTTO:/bootstrap mobile$ ./su ./test/3
Call up to jbd. This may take some time...
Spawn process now...
But I was not able to get my head around the UserNotification thing. So looking into this is the next step and after that I will make a PR.
Looks good!
@littlelailo btw, @summertriangle-dev was working with XPC jailbreakd on his fork. you might want to check it out.
Works 🎉 One question @stek29 I need the value kCFBooleanTrue, but I wasn't able to find the right header file. Could you help? And one more question: how long should I wait till I let the request time out? Now I need to port this to the jbd lib and then I will open a pr.
@littlelailo
❯ rg kCFBooleanTrue /System/Library/Frameworks/CoreFoundation.framework
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers/CFNumber.h
21:const CFBooleanRef kCFBooleanTrue;
We can use su from GNU coreutils 8.18 (its been removed from coreutils after that version, but we should be fine with just su being older source)
@coolstar So we won't go for the CFUserNotification approach?
@littlelailo I think whole CFUserNotification thing should have it's own issue with discussion: about tweak/sandbox injection skipping, about SU notification, about safe mode (which IMO should show a notification which can be opened from status bar and not the app activating on each unlock)