C cannot endors another user permissions using setresuid - c

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

Related

Problems with readlink and set uid

I'm having trouble getting setuid to work as hoped (chmod 3755).
I'm trying to implement, using C language, my own version of psgrep (or pgrep) for a very specific need. In order to accomplish this, I need to get the value of the link at /proc/[pid]/exe for every listed [pid]
To demonstrate the issue, I made this tiny program: (proof.c)
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char procFilename[] = "/proc/1/exe" ;
char pointsTo[80] ;
int rc ;
memset(pointsTo, 0x00, sizeof(pointsTo)) ;
rc = readlink(procFilename, pointsTo, sizeof(pointsTo)) ;
if ( rc < 0 ) {
perror("Trying to read /proc/1/exe link") ;
}
else {
printf("%s points to %s.\n", procFilename, pointsTo) ;
}
}
In the same folder, I exeucte:
gcc -o proof proof.c
sudo chown root:root proof
sudo chmod 3755 proof
Now, here are the execution results:
> ./proof
Trying to read /proc/1/exe link: Permission denied
> sudo ./proof
/proc/1/exe points to /usr/lib/systemd/systemd.
> ls -l proof
-rwxr-sr-t 1 root root 16888 Feb 16 14:06 proof
As I understand it, the chmod and chown combination should have gotten me past the permission error, but obviously I am missing something.
When I searched stackoverflow for "sticky-bit problems" there were no good matches (though a surprising number of people expect setuid to work with scripts). One problem about 2.6 kernel didn't seem to fit either. Anyway, what might I be missing?

Can I get a different UID than EUID and GID than EGID in a command?

I have a program that gets its own UID, EUID, GID, EGID, and I want to get UID!=EUID and GID!=EGID.
I've tried changing the owner and group of the program file, but I'm always getting the same results.
Here is the c code:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
char cad[128];
pid_t pid;
pid = getpid();
char s1[] = "ps -p ";
char s2[] = " -o cmd,pid,ppid,uid,euid,gid,egid,pri,stat";
char spid[42];
sprintf(spid, "%d", (int)pid);
char result[2048];
strcpy(result, s1);
strcat(result, spid);
strcat(result, s2);
sprintf(cad,"Program %s started.\n",argv[0]);
write(1,cad,strlen(cad));
system(result);
read(0,cad,1);
sprintf(cad,"Program %s ended.\n",argv[0]);
write(1,cad,strlen(cad));
exit(0);
}
The commands I've tried are:
$ sudo chown 2000 filename
$ sudo chgrp 2000 filename
$ sudo chmod u+r,g+x filename
And then executing the compiled program. Always getting:
Program ./pgm1_1_1 started.
CMD PID PPID UID EUID GID EGID PRI STAT
./pgm1_1_1 18216 17683 1000 1000 1000 1000 19 S+
You've not set the SUID and SGID bits in the permissions:
sudo chmod ug+s filename
Or, doing the permissions setting all in one, you can use either of these:
sudo chmod 6755 filename # Numeric permissions (octal)
sudo chmod a=rx,u+w,ug+s filename # Symbolic permissions
You should run ls -l filename after you've finished the permissions setting. With the SUID and SGID bits set, you should see something like:
-rwsr-sr-x 1 2000 2000 8712 May 8 00:18 filename
where the two s values are crucial in the permissions. You might have names where I get to see the UID and GID numbers.

setuid() returns 0 but has no effect

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.

Effective UID doesn't behave as expected

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 . )

unsuccessfully call external shell script as non-root user

I want A user to do some jobs as B user. It's OK if B is root, but non-root user failed. Here are basic codes:
root.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
setuid( 0 );
system( "/tmp/script_of_root.sh" );
return 0;
}
script_of_root.sh:
#!/bin/sh
echo $RANDOM >> /tmp/file_of_root
playback:
$ cd /tmp
$ cc root.c -o root
$ su -
# chown root.root /tmp/root
# chmod 4755 /tmp/root
# exit
$ ./root
After executing "./root", file "/tmp/file_of_root" will be updated. But if I apply the same thing to a non-root user, it doesn't work. Codes:
foobar.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
setuid( 1001 ); // uid of user "foobar"
system( "/tmp/script_of_foobar.sh" );
return 0;
}
script_of_foobar.sh:
#!/bin/sh
echo $RANDOM >> /tmp/file_of_foobar
playback:
$ cd /tmp
$ cc foobar.c -o foobar
$ su -
# chown foobar.users /tmp/foobar
# chmod 4755 /tmp/foobar
# exit
$ ./foobar
If I run "./foobar" as other normal user(not "foobar" itself), it's gonna be error:
/tmp/script_of_foobar.sh: line 2: file_of_foobar: Permission denied
I am totally confused. Why the second scenario not working?
Best regards.
The setuid call in foobar.c will only succeed if you are root, or your effective UID is 1001.
So. If you're not root, setuid(1001) will fail, and you won't have the required rights to overwrite the file owned by "foobar".
From the output it looks like your non-root user is able to execute script_of_foobar.sh, but unable to write to /tmp/file_of_foobar. Are the permissions on /tmp possibly off? I believe it should be set to 1777.

Resources