https://github.com/osquery/osquery logo
Title
t

terracatta

05/19/2020, 6:13 PM
@Stefano Bonicatti I am working on a new table that uses a macOS API that only returns data for the current user only. If osquery is running as a daemon, the current user is usually root, which causes the returned data to not be useful. So what I was thinking of doing was when I need to run my code, to fork the osquery process, then in the new process drop privileges into the specified user from the query context, run the query, and then use some kind of IPC mechanism to get the data back to the parent osquery process and then kill the child. It seems https://github.com/osquery/osquery/pull/6209 does some similar things. Do you think copying these patterns is the way to go or is there a better way in your opinion to accomplish the above?
Nevermind, this may be what I want instead https://github.com/osquery/osquery/pull/2624
s

Stefano Bonicatti

05/19/2020, 6:28 PM
Yeah, It would've required different performance characteristics also, especially with JOIN and index columns
t

terracatta

05/19/2020, 6:34 PM
Got it
t

theopolis

05/19/2020, 6:41 PM
I hope that works for your use cases. I can see the OS implementing something more than a euid check to determine if you can perform an action as a user.
t

terracatta

05/19/2020, 6:44 PM
I hope so too!
I will let you know either way
g

groob

05/19/2020, 7:54 PM
@theopolis I’ve found out the hard way that just dropping the euid per thread is not enough. on macOS a lot of these checks are relying on the launchagent context. you’ll get totally different behavior with sudo osquery vs with osquery in launchd
@terracatta I wasted two weeks on this with airdrop. Good luck 😛
t

terracatta

05/19/2020, 7:54 PM
lol, why was it a waste?
did it not work?
g

groob

05/19/2020, 7:54 PM
it did not
you basically need a second process that runs as a launchagent
and to be able to rpc to that process to get your information
t

terracatta

05/19/2020, 8:00 PM
so annoying
@groob in my testing, setuid / seteuid does actually work for NSUserDefaults when I run the binary as root against launchctl with
asuser 0
pthread_setugid_np
does not
g

groob

05/19/2020, 8:39 PM
yeah, so how are you going to implement that in osquery core?
t

terracatta

05/19/2020, 8:39 PM
oh yeah that's game over
lol
but launcher might be viable still
only way to do it in core is fork, drop, and IPC the info back to the parent
g

groob

05/19/2020, 8:44 PM
and it’s still problematic from the API because it’s leaky. You’d assume osquery returns all the info for all users, not just the currently logged in one.
but that’s a different issue
t

terracatta

05/19/2020, 8:44 PM
yeah that limitation just needs to be accepted
and documented
g

groob

05/19/2020, 8:44 PM
I think having an extension with a separate process and XPC between might work
t

terracatta

05/19/2020, 8:45 PM
honestly I think the only reason your PR you linked didn't work is you used CFPreferences vs NSUserDefaults
I will try it
g

groob

05/19/2020, 8:46 PM
come to think of it I have enough swift chops these days to implement a user “agent” that exposes some of these hard to check values. It would run as it’s own process and an extension can query the values from it
t

terracatta

05/19/2020, 8:47 PM
problem is now you have another binary to distribute to folks
g

groob

05/19/2020, 8:48 PM
yes
I’m going to wait and see how much more apple is going to wreck with 10.16
t

terracatta

05/19/2020, 8:52 PM
they never disappoint
t

theopolis

05/20/2020, 1:33 PM
Are you sure you tested setting euid/ruid enough? I would dtrace what is happening and see if you can isolate the auth failure. I’ve never investigated dropping a thread’s permissions completely (overwriting suid) but check if that works/is possible too
t

terracatta

05/20/2020, 1:52 PM
@theopolis here is the trivial program I am using to test this...
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
   pthread_setugid_np(501, 20)
   NSUserDefaults * userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"com.apple.sharingd"];
   NSDictionary * dict = [userDefaults dictionaryRepresentation];
   NSLog(@"%@", dict);
   return 0;
}
gcc -framework Foundation test.m -o test
and run it with
sudo launchctl asuser 0 ./test
I get the settings for UID 0 not 501. If instead of
pthread_setugid_np(501, 20)
I use
seteuid(501); setegid(20)
and run it with the same arguments, it logs the correct settings.
t

theopolis

05/20/2020, 3:47 PM
This is a long shot but can you call the macOS pthread API then spawn another thread, check your uid/gid, then try the user defaults request?
My hypothesis is you either need to call the normal setuid or create a thread while holding the desired credential, changing credentials then using the new credentials using the _np API might have unexpected behavior.
t

terracatta

05/20/2020, 5:26 PM
I'll give it a shot, and let you know