0

I am running C++ program from user with sudo access rights. Binary was started with ./binName command.

From it i can execute sudo ls with popen function - this is working fine. So i though that i can open some privileged files with open function, but it's return -1 with errno= 13:Permission denied.

So then i though that i need to forcly set my euid with seteuid but it's return -1 with errno= 13:Permission denied

When i start program with sudo ./binName all working fine and i can open any file with open function. What i am doing wrong?

#include <stdio.h>
#include <vector>
#include <cstdint>
#include <cstring>
#include <string>
#include <fcntl.h>
#include <unistd.h>

#define Log(fmt, ...) printf("%s | " fmt, __FUNCTION__, ##__VA_ARGS__)

bool OpenPath(const std::string& path) {
    if (path.empty()) return false;

    const int f = open(path.c_str(), O_RDWR);
    if (f == -1){
        Log("[!] Unable to open %s, errno= %d:%s\n", path.c_str(), errno, strerror(errno));
        return false;
    }

    close(f);
    return true;
}

bool ReadFromStream(const char *command, std::vector<uint8_t> &output)
{
    FILE *fp = popen(command, "r");
    if (!fp)
    {
        Log("[!] Error: Unable to popen\n");
        return false;
    }

    char str[512];
    while (!feof(fp))
    {
        if (fgets(str, sizeof(str), fp))
        {
            const int size = strlen(str);
            output.insert(output.end(), str, str + size);
        }
    }

    pclose(fp);
    return !output.empty();
}

bool HasRights() {
    const __uid_t uid = getuid();
    const __uid_t gid = geteuid();

    bool elevated = uid == 0 || uid != gid;

    Log("uid= %d, gid= %d, elevated= %d\n", uid, gid, elevated);

    if (elevated && OpenPath("/usr/bin/ls")) // it's just a test path
        return true;

    std::vector<uint8_t> buffer;
    if (ReadFromStream("sudo -n ls", buffer)) {
        const std::string str(buffer.begin(), buffer.end());
        if (str != "sudo: a password is required")
        {
            if (seteuid(0) == -1) {
                Log("[!] Unable seteuid, errno= %d:%s\n", errno, strerror(errno));
            }
            return OpenPath("/usr/bin/ls"); // it's just a test path
        }
    }
    return false;
}

int main(int argc, char **argv)
    const auto hasRights = HasRights();
    Log("hasRights= %d\n", hasRights);

    return 0;
}

output without sudo rights = ./binName

HasRights | uid= 1000, gid= 1000, elevated= 0
HasRights | [!] Unable seteuid, errno= 1:Operation not permitted
OpenPath | [!] Unable to open /usr/bin/ls, errno= 13:Permission denied
test | hasRights= 0

output with sudo rights = sudo ./binName

HasRights | uid= 0, gid= 0, elevated= 1
test | hasRights= 1

output when sudo timeout expired = ./binName

HasRights | uid= 1000, gid= 1000, elevated= 0
sudo: a password is required
test | hasRights= 0
SLI
  • 713
  • 11
  • 29
  • 3
    Please provide a [mcve], like e.g. a list of steps what you do and a small C++ program. I for one don't know precisely what you did. – Ulrich Eckhardt Jan 25 '21 at 18:46
  • 1
    You can't use `sudo` to give a running program root privileges. It can only start a new program with root privileges. – that other guy Jan 25 '21 at 19:19
  • @that other guy, sure i know that, my question is how can i do that from C++ without using sudo command – SLI Jan 25 '21 at 19:33
  • @SLI `sudo` does this by having the executable owned by root with the setuid bit set. This makes it always start with root privileges. If your goal is to read a privileged file, you can instead run `sudo cat file` and then read from the pipe to indirectly read from the file. – that other guy Jan 25 '21 at 19:39
  • @that other guy, so are no ways to elevate my self from C++ code when i was started from user that currently has sudo access rights? – SLI Jan 25 '21 at 19:41
  • 1
    @SLI - If your program needs to elevate rights, you'll need to have the setuid bit on the program, then you can use `seteuid`. Being able to escalate privileges in an arbitrary program would be a security risk. – Stephen Newell Jan 25 '21 at 19:45
  • @Stephen Newell, thank you – SLI Jan 25 '21 at 19:57
  • Unrelated: `while (!feof(fp))` [is a potential bug.](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – user4581301 Jan 25 '21 at 22:13
  • @user4581301, thanks – SLI Jan 25 '21 at 23:28

0 Answers0