I have the following code:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char* argv[]) {
printf("uid=%u euid=%u\n", getuid(), geteuid());
printf("%d = setuid(euid)\n", setuid(geteuid()));
printf("uid=%u euid=%u\n", getuid(), geteuid());
}
Compiled and run this way:
val#particle:/tmp $ sudo gcc foo.c
val#particle:/tmp $ sudo chown dev-misc:dev-misc a.out
val#particle:/tmp $ sudo chmod u+s a.out
val#particle:/tmp $ ./a.out
uid=1000 euid=1006
0 = setuid(euid)
uid=1000 euid=1006
Why does the uid remain unchanged? And why does setuid report success? (according to the man page, 0 means success)
setuid() sets the effective user ID, not the real process ID. From the manual:
setuid() sets the effective user ID of the calling process. If the
effective UID of the caller is root (more precisely: if the caller
has the CAP_SETUID capability), the real UID and saved set-user-ID
are also set.
To be able to change real user ID, the process must have effective user ID set to 0. Since, it's not the case in your example, it doesn't change. setuid() succeeds because you are just setting it to the same effective user ID the process already has.
Related
I wrote the following code expecting to spawn a /bin/sh from another user.
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp)
{
setresgid(getegid(), getegid(), getegid());
setresuid(geteuid(), geteuid(), geteuid());
execve("/bin/sh", argv, envp);
return 0;
}
I then changed the owner to match with my target user and changed permissions (too much, I know)
chown usertarget:globalgroup ./shell
chmod 777 ./shell
chmod +s ./shell
ls -lah shell
Everything is fine according to me. However, It keeps opening a shell as my current user, not the target one.
I already tried to hardcode the userid of my target user and a few other things (setuid function, ...) but nothing seems to work...
Anyone has an idea or anything that could help me investigate this problem ?
EDIT #1
baseuser#machine:/tmp/tata$ ls -lah shell2
-rwsrwsrwx 1 targetuser globalgroup 7.2K Aug 18 18:21 shell2
baseuser#machine:/tmp/tata$ id
uid=1507(baseuser) gid=1314(globalgroup) groups=1314(globalgroup),100(users)
baseuser#machine:/tmp/tata$ ls -lah shell2
-rwsrwsrwx 1 targetuser globalgroup 7.2K Aug 18 18:21 shell2
baseuser#machine:/tmp/tata$ ./shell2
====== WELCOME USER ======
baseuser#machine:/tmp/tata$ id -a
uid=1507(baseuser) gid=1314(globalgroup) groups=1314(globalgroup),100(users)
baseuser#machine:/tmp/tata$
Well in facts, the parition was mounted with nosuid option. This can be checked through mount command
So I got this code below from here. However when I follow the commands:
sudo chown root:root a.out
sudo chmod u+s a.out
It still won't run with effective uid to 0.
This is the code:
#define _POSIX_C_SOURCE 200112L // Needed with glibc (e.g., linux).
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void report (uid_t real) {
printf ("Real UID: %d Effective UID: %d\n", real, geteuid());
}
int main (void) {
uid_t real = getuid();
report(real);
seteuid(real);
report(real);
return 0;
}
The output is:
Real UID: 1000 Effective UID: 1000
Real UID: 1000 Effective UID: 1000
Where I supposed it should have been:
Real UID: 1000 Effective UID: 0
Real UID: 1000 Effective UID: 1000
The getuid function returns the real user id only. The real user id of user process is still 1000. The 1000 is stored in the real variable.
So, while calling of seteuid function you again sets the 1000 as the effective user id.But actually you have to set the 0 in that place. So only the effective user id doesn't changed.
Try the below it will works fine.
#define _POSIX_C_SOURCE 200112L // Needed with glibc (e.g., linux).
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void report (uid_t real) {
printf ("Real UID: %d Effective UID: %d\n", real, geteuid());
}
int main (void) {
uid_t real = getuid();
report(real);
seteuid(0);
report(real);
return 0;
}
Apparently as #MarkPlotnick said.
cd to the directory where that a.out is. Run df . to get the mount
point. Run mount | grep themountpoint and see what the filesystem type
and mount options are.
If there is something saying nosuid then you need to remount that part of filesystem without the nosuid flag.
This website here gives a good explanation about how to do that.
Code
I wrote the following c program to print the real and effective uid:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
void main() {
printf("real uid: %d\n", (int) getuid());
printf("effective uid: %d\n", (int) geteuid());
}
I compiled it using gcc:
jazz#kryptonite beyond_basics $ gcc -o uid_demo.out uid_demo.c
Afterwards I changed owner and permissions as following:
jazz#kryptonite beyond_basics $ sudo chown root:root uid_demo.out
jazz#kryptonite beyond_basics $ sudo chmod u+s uid_demo.out
Result
Now I got:
jazz#kryptonite beyond_basics $ ll uid_demo.out
-rwsr-xr-x 1 root root 8712 Sep 8 18:12 uid_demo.out*
When running the program I get the following result:
jazz#kryptonite beyond_basics $ ./uid_demo.out
real uid: 1000
effective uid: 1000
Question
I would expect the effective uid to be 0.
Can anyone explain why it is not?
Thanks
It is surprising, isn't it?
It's worth checking the mount options on your filesystem - it may have been mounted with the nosuid option. To inspect the options, try running the mount command, or cat /proc/mounts.
(I'm sure you know which filesystem you are in, but for completeness, if you are cd'ed there, as per your example, you can use df . )
This sample suid program
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
void main() {
int ret;
printf("uid=%d, euid=%d\n", getuid(), geteuid());
ret = setuid(1000);
printf("uid=%d, euid=%d\n", getuid(), geteuid());
}
has 'noemi' (id=1001) as owner:
sarah-$ logname
sarah
sarah-$ ls -l p.bin
-rwsr-xr-x 1 noemi noemi 7028 17 dic 10.30 p.bin
If started from user 'sarah' (id=1000) euid changes to 1000
Why? p.bin changes only uid (this should have no effect, since uid was 1000 when p.bin was started by 'sarah'):
sarah-$ ./p.bin
uid=1000, euid=1001
uid=1000, euid=1000
sarah-$
I am using Debian 6 64 bit.
Please help me understand.
Thank you
Check man 2 setuid:
setuid() sets the effective user ID of the calling process. If the effective UID of the caller
is root, the real UID and saved set-user-ID are also set.
So, as you already have observed, when you are executing setuid() as regular user it will only change the effective user id.
Why does a process that has gone into seccomp mode always get killed on exit?
$ cat simple.c
#include <stdio.h>
#include <stdlib.h>
#include <linux/prctl.h>
int main( int argc, char **argv )
{
printf("Starting\n");
prctl(PR_SET_SECCOMP, 1);
printf("Running\n");
exit(0);
}
$ cc -o simple simple.c
$ ./simple || echo "Returned $?"
Starting
Running
Killed
Returned 137
From the man page, under PR_SET_SECCOMP, the only allowed system calls are read, write, exit, and sigreturn.
When you call exit(0) in the standard library (in recent Linux), you call the exit_group system call, not exit. This is not allowed, so you get a SIGKILL.
(You can see this if you strace the process...)