Shellcode as payload for buffer overflow (or other) exploits executed as root? - security

When I use shellcode such as the ones provided here* as payload to some vulnerable program, how is the shell executed as root? I am asking about how the privileges are elevated to root? The shellcode doesn't seem to call setuid or anything to change user.
* http://www.tenouk.com/Bufferoverflowc/Bufferoverflow5.html

Those examples include the following:
mov $70, %al #setreuid is syscall 70
So they're using the setreuid(2) syscall, which sets both the real and effective user IDs of the process:
int setreuid(uid_t ruid, uid_t euid);

In order to execute shellcode you need a vulnerability like a buffer overflow. The shellcode has all of the rights as the running process. So if you exploit a binary that is setuid root like the passwd command or otherwise running as root such as the cupsd daemon process then the attacker will have root access. The kernel can also suffer from a buffer overflow, and root access can be obtained this way as well.

first you need to giving the program as root privileges (use chown and chmod as root). and you need setreuid() for your payload. that's would give you root, if you can exploit the program by other user.

Of course, if your vuln program has an owner root and your shellcode have a setuid(0) syscall, you can execute /bin/sh as root

Related

Why the set-uid operation can't be used in an excutable file?

When learning the system security in the ubuntu 20.04 on the VMware, I tried the set-uid operation and found the fllowing question:
With the excutable file catcall compiled by the source code caltcall.c:
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char* argv[]){
char *cat = "/bin/cat";
if(argc < 2){
printf("please type a file name.\n");
return 1;
}
char *command = malloc(strlen(cat) + strlen(argv[1] + 2));
sprintf(command, "%s %s",cat, argv[1]);
system(command);
return 0;
}
I complete the set-uid operation through the following codes:
$ sudo chown root catcall
$ sudo chmod 4755 catcall
When excuting the excutable file catcall, I thought I can see the content of the file /etc/shadow, for the 'catcall' has been set to the Set-Uid programme.
But the operation is denied when trying to access the etc/shadow:
/bin/cat: /etc/shadow: Permission denied
Why did the set-uid operation failed?
Each process actually has two user ids, a real uid and an effective uid, see Difference between Real User ID, Effective User ID and Saved User ID. Normally they are equal. Setting the setuid bit causes the effective uid to be set to the owner of the binary upon exec, but the real uid remains unchanged, and will normally still be the uid of the user who actually ran the program.
So when your program starts, the effective uid will be root and the real uid will be dim_shimmer. Now you have chosen to try to start your program via system(), which executes the specified command using the shell. However, many shells have a security feature where they compare the real and effective uid, and if they are not equal, they set the effective uid equal to the real uid. (For instance, this avoids a disaster in case the sysadmin accidentally does chmod +s /bin/sh). I suspect that's what's happening here. So by the time your cat command runs, your real and effective uid are both dim_shimmer again, and that user does not have permission to read /etc/shadow.
If you run your cat command using execl instead (or one of its relatives), so as to bypass the shell, then I suspect you'll find that it works.

Difference between EUID and UID?

EUID is not the same as UID. At what context are these both are used in the script?
I tried to get the values by echo "UID is $UID and EUID is $EUID", but only space came as output. My machine runs Ubuntu 12.04 LTS. Seen at some sites that this is usually used to check whether it is root user and all but not able to get proper difference.
They're different when a program is running set-uid. Effective UID is the user you changed to, UID is the original user.
UID is the ID of the user that executed the program.
EUID (Effective UID) is the user ID the process is executing. Usually both are equal, unless using a program with SetUID to for example increase your privileges. A common case where UID and EUID are different would be executing sudo.
EUID and UID variables only work on bash, not in dash (in Debian based distros as Ubuntu sh is usually a symlink to dash).
If you are running the script interactively you might not have bash configured as your default shell, run bash before trying.
If you are running it from console:
bash script.sh
If you are running it using its path (for example ./script.sh) ensure the first line of the script is:
#!/bin/bash
And not:
#!/bin/sh
For a more generic way to do it -that works on any shell- check: https://askubuntu.com/questions/15853/how-can-a-script-check-if-its-being-run-as-root
In that post the command id is mentioned, where:
id -u # is the EUID
id -u -r # is the UID

Linux, the only way to GAIN root access is executing a setuid-root file?

Is my assumption true, that on Unix/Linux, the only way to GAIN root access is to execute a setuid-root file?
In other words, the system calls setuid(), setgid() are all about DROPPING privileges?
Please note that my question is not about exploits.
That's true. The only way for a non-root process (assuming it's running a non-setuid program) to become root is to exec a setuid program. If it's running a set-uid root program, then its effective uid is root and real uid is whoever ran it. It can then do setuid(0) to make its real uid 0.

In Linux, does the location of an executable affect how the setuid bit is interpreted?

In a Linux system, does the permissions of the directory in which a setuid program resides affect how the kernel launches the process? The reason I ask is that when I compiled an identical setuid program in two different directories, it only actually assumed the user permissions in one directory. I compiled it in /tmp and /home/flag03 where flag03 is the user account that I am attempting to gain access to. When executed from /tmp it did not escalate privileges as expected, but it worked under /home.
Some background on the problem:
I'm working on level 03 of exploit-exercises.com/nebula. The exercise requires that you gain access to a flag03 user account. The exercise is setup so that the flag03 user is periodically running a cronjob which will allow you to execute a script in a specific directory. My plan was to write a simple bash script which will compile a setuid program that itself launches a bash shell, and then set the setuid bit with chmod +s. The idea is that when the setuid program is compiled, it is compiled by user flag03 via the cronjob. Once this newly compiled program is executed, it will launch a shell as user flag03, and that is the goal.
Here is the simple setuid program (l3.c, based on levels 1 + 2):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char **argv, char **envp)
{
uid_t uid;
gid_t gid;
uid = geteuid();
gid = getegid();
setresuid(uid,uid,uid);
setresgid(gid,gid,gid);
printf("uid: %d\n", getuid());
printf("gid: %d\n", getgid());
system("/bin/bash");
return 0;
}
In order for this to work, a bash script compiles the program as user flag03 and then chmods the setuid bit.
#!/bin/bash
#gcc -o /tmp/l3 /tmp/l3.c
#chmod +s,a+rwx /tmp/l3
gcc -o /home/flag03/l3 /tmp/l3.c
chmod +s,a+rwx /home/flag03/l3
The executable generated in /tmp does not escalate privileges as expected, but the one generated in /home/flag03 works as expected.
NOTE I just created a new bash script to move the version of the setuid program that was compiled in /tmp to /home/flag03, and then reset the setuid bit. When executed from there, that version worked as well. So it appears to me that the permissions of the directory in which the setuid program resides has some kind of impact with how the process is launch. Maybe this is related to /tmp being a somewhat "special" directory?
Thanks for any interest in this long-winded question!
If the filesystem is mounted with the nosuid option, the suid bit will be ignored when executing files located there. As I understand it, /tmp is usually a separate filesystem (often tmpfs) mounted with the nosuid option. The motivation for this configuration is preventing a compromised account that has no writable storage except /tmp (e.g. nobody) from being able to produce suid binaries, which may be used in certain elaborate multi-step attacks to elevate privilege.

Can dmidecode command be invoked successfully by SUID program in Linux?

OS is Linux SuSE 2.6.16.60-0.21-smp
I have one executable bin file (name is bmu) which has been configured SUID, as shown in below
-rwsr-sr-x 1 root root 14968899 2012-03-29 10:35 bmu
And this program invoke dmidecode inside.
Operation will be ok if it was run by root, but dmidecode invoked will return null if the program was run by non-root user.
What is the reason of this problem and how to fix it?
Edit: Added code and description from comment:
read_fp = popen("dmidecode | grep 'Product Name'", "r");
/* ...... */
chars_read = fread(buffer, sizeof(char), BUFSIZ-1, read_fp);
Return of read_fp is not null, but length of buffer is 0 which there should be some value.
The problem was solved in an unsafe way.
It is not enough to add SUID in the program bmu, dmidecode should also be.
-rwsr-sr-x 1 root root 59504 2006-06-16 22:08 /usr/sbin/dmidecode
The dmidecode program needs access to /dev/mem which ordinary users doesn't have permission for. The most common fix to such a problem is either to do as you already do and make the program SUID, or to add the user to the kmem group (the group owning /dev/mem).

Resources